Python syntax in Lisp and Scheme

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Hans Nowak

    #91
    Re: Python syntax in Lisp and Scheme

    Grzegorz Chrupa?a wrote:
    [color=blue]
    > As an example of how subjective this can be, most of the features you
    > mention as too complex for Python to support are in fact standard in Scheme
    > (true lexical scope, implicit return, no expression/statement distinction)
    > and yet Scheme is widely regarded as one of the simplest programming
    > languages out there, more so than Python.[/color]

    Scheme, as a language, is arguably simpler than Python... it takes a few core
    concepts and rigorously applies them everywhere. This makes the Scheme
    language definition simpler than Python's. However, whether *programming in
    Scheme* is simpler than *programming in Python* is a different issue
    altogether. To do everyday things, should you really have to grok recursion,
    deeply nested expressions, anonymous functions, complex list structures, or
    environments? Of course, Python has all this as well (more or less), but they
    usually don't show up in Python 101.

    --
    Hans (hans@zephyrfal con.org)
    Memimpin Angin Perubahan Teknologi




    Comment

    • Terry Reedy

      #92
      Re: Python syntax in Lisp and Scheme


      "Grzegorz Chrupaƅ,a" <grzegorz@pithe kos.net> wrote in message
      news:bln1uh$9ti $1@news.ya.com. ..[color=blue]
      > As an example of how subjective this can be, most of the features[/color]
      you[color=blue]
      > mention as too complex for Python to support are in fact standard in[/color]
      Scheme[color=blue]
      > (true lexical scope, implicit return, no expression/statement[/color]
      distinction)
      [color=blue]
      > Another problem with simplicity is that introducing it in one place[/color]
      may[color=blue]
      > increase complexity in another place. [typos corrected][/color]

      [Python simplicity=>com plexity example (scopes) snipped]

      [I am leaving the reduced newsgroup list as is. If anything I write
      below about Lisp does not apply to Scheme specificly, my aplogies in
      advance.]

      There is a basic Lisp example that some Lispers tend to gloss over, I
      think to the ultimate detriment of promoting that more people
      understand and possibly use Lisp (in whatever version).

      Specifically, the syntactic simplification of unifying functions and
      statements as S-expressions aids, is made possible by, and comes at
      the cost of semantic complexificatio n of the meaning of 'function
      call' (or S-expression evaulation).

      The 'standard' meaning in the languages I am previously familiar with
      (and remember) is simple and uniform: evaluate the argument
      expressions and somehow 'pass' the resulting values to the function to
      be matched with the formal parameters. The only complication is in
      the 'how' of the passing.

      Lisp (and possibly other languages I am not familiar with) adds the
      alternative of *not* evaluating arguments but instead passing them as
      unevaluated expressions. In other words, arguments may be
      *implicitly* quoted. Since, unlike as in Python, there is no
      alternate syntax to flag the alternate argument protocol, one must, as
      far as I know, memorize/learn the behavior for each function. The
      syntactic unification masks but does not lessen the semantic
      divergence. For me, it made learning Lisp (as far as I have gotten)
      more complicated, not less, especially before I 'got' what going on.

      In Python, one must explicitly quote syntactic function arguments
      either with quote marks (for later possible eval()ing) or 'lambda :'
      (for later possible calling). Inplicit quoting requires the alternate
      syntax of either operator notation ('and' and 'or'-- but these are
      exceptional for operators) or a statement. Most Python statements
      implicitly quote at least part of the construct. (A print statement
      implicitly stringifies its object values, but this too is special
      handling.)

      Question: Python has the simplicity of one unified assignment
      statement for the binding of names, attributes, slot and slices, and
      multiples thereof. Some Lisps have the complexity of different
      functions for different types of targets: set, setq, putprop, etc.
      What about Scheme ;-?

      Terry J. Reedy


      Comment

      • Steve VanDevender

        #93
        Re: Python syntax in Lisp and Scheme

        "Terry Reedy" <tjreedy@udel.e du> writes:
        [color=blue]
        > Lisp (and possibly other languages I am not familiar with) adds the
        > alternative of *not* evaluating arguments but instead passing them as
        > unevaluated expressions. In other words, arguments may be
        > *implicitly* quoted. Since, unlike as in Python, there is no
        > alternate syntax to flag the alternate argument protocol, one must, as
        > far as I know, memorize/learn the behavior for each function. The
        > syntactic unification masks but does not lessen the semantic
        > divergence. For me, it made learning Lisp (as far as I have gotten)
        > more complicated, not less, especially before I 'got' what going on.[/color]

        What you're talking about are called "special forms" and are definitely
        not functions, and are used when it is semantically necessary to leave
        something in an argument position unevaluated (such as in 'cond' or
        'if', Lisp 'defun' or 'setq', or Scheme 'define' or 'set!').
        Programmers create them using the macro facilities of Lisp or Scheme
        rather than as function definitions. There are only a handful of
        special forms one needs to know in routine programming, and each one has
        a clear justification for being a special form rather than a function.

        Lisp-family languages have traditionally held to the notion that Lisp
        programs should be easily representable using the list data structure,
        making it easy to manipulate programs as data. This is probably the
        main reason Lisp-family languages have retrained the very simple syntax
        they have, as well as why there is not different syntax for functions
        and special forms.
        [color=blue]
        > Question: Python has the simplicity of one unified assignment
        > statement for the binding of names, attributes, slot and slices, and
        > multiples thereof. Some Lisps have the complexity of different
        > functions for different types of targets: set, setq, putprop, etc.
        > What about Scheme ;-?[/color]

        Scheme has 'define', 'set!', and 'lambda' for identifier bindings (from
        which 'let'/'let*'/'letrec' can be derived), and a number of mutation
        operations for composite data types: 'set-car!'/'set-cdr!' for pairs,
        'vector-set!' for mutating elements of vectors, 'string-set!' for
        mutating strings, and probably a few others I'm forgetting.

        --
        Steve VanDevender "I ride the big iron" http://jcomm.uoregon.edu/~stevev
        stevev@hexadeci mal.uoregon.edu PGP keyprint 4AD7AF61F0B9DE8 7 522902969C0A7EE 8
        Little things break, circuitry burns / Time flies while my little world turns
        Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes

        Comment

        • Jason Creighton

          #94
          Re: Python syntax in Lisp and Scheme

          On Sat, 04 Oct 2003 17:02:41 GMT
          Alex Martelli <aleax@aleax.it > wrote:
          [color=blue][color=green]
          > > As Paul Graham says (<URL:http://www.paulgraham. com/icad.html>):[color=darkred]
          > >> or even
          > >>
          > >> def foo(n):
          > >> lambda i: n += i[/color][/color]
          >
          > And this touches on yet another point of the Zen of Python:
          > explicit is better than implicit. Having a function
          > implicitly return the last expression it computes would
          > violate this point (and is in fact somewhat error-prone,
          > in my experience, in the several languages that adopt
          > this rule).[/color]

          I don't mean to start a flamewar....ah, who am I kidding, of *course* I
          mean to start a flamewar. :-)

          I just wish the Zen of Python (try "import this" on a Python interpreter
          for those who haven't read it.) would make it clearer that "Explicit is
          better than implicit" really means "Explicit is better than implicit _in
          some cases_"

          Look here:
          [color=blue][color=green][color=darkred]
          >>> [x*x for x in [1,2,3]][/color][/color][/color]
          [1, 4, 9]

          Good grief! How could someone who doesn't understand list comprehensions
          *ever* read and understand this? We'd better do it the explicit way:'
          [color=blue][color=green][color=darkred]
          >>> ary = []
          >>> for x in [1,2,3]:[/color][/color][/color]
          .... ary.append(x*x)
          ....[color=blue][color=green][color=darkred]
          >>> ary[/color][/color][/color]
          [1, 4, 9][color=blue][color=green][color=darkred]
          >>>[/color][/color][/color]

          *Much* better! Now you don't have to understand list comprehensions to
          read this code!

          </sarcasm>

          Of course, nobody is going to seriously suggest that list
          comprehensions be removed from Python. (I hope). The point here is that,
          for any level of abstraction, you have to understand how it works. (I
          think) what the author of "The Zen of Python" (Tim Peters) means when
          he says "Explicit is better than implicit" is "Don't do weird crazy
          things behind the programmer's back, like automatically have varibles
          initialized to different datatypes depending on how they are used, like
          some programming language we could mention."

          I agree with most of the rest of "The Zen of Python", except for the
          "There should be one-- and preferably only one --obvious way to do it."
          bit. I think it should be "There should be one, and preferably only one
          , *easy* (And it should be obvious, if we can manage it) way to do it."

          For instance, let us take the ternary operator. Ruby has at least two
          constructs that will act like the ternary operator.

          if a then b else c end

          and

          a ? b : c

          The "if a then b else c end" bit works because of Ruby's "return value is
          last expression" policy.

          In a recent thread in comp.lang.ruby, you (Alex Martelli) said:

          But for the life of me I just can't see why, when one has
          "if a then b else c end" working perfectly as both an expression
          and a control statement, one would WANT to weigh down the language
          with an alternative but equivalent syntax "a?b:c".

          <end quote>

          The reason I would want to weigh down the language with an alternative
          syntax is because sometimes a ? b : c is the *easy* way to do it.
          Sometimes you don't want do say:

          obj.method(arg1 , (if boolean then goober else lala end))

          Sometimes you just want to be able to say:

          obj.method(arg1 , arg2, boolean ? goober : lala)

          But the Python folks seems to like having only one way to write
          something, which I argee with, so long as we have at least one easy way
          to write something.

          So there is a balance to be struck here. Some people like the way Python
          does things; some people do not. This is why we all hate each other. :-)

          No, really, that's why we have different languages.
          [color=blue]
          > In Ruby, the spaces of methods and data are separate (i.e.,
          > most everything is "an object" -- but, differently from
          > Python, methods are not objects in Ruby), and I do not
          > think, therefore, that you can write a method that builds
          > and returns another method, and bind the latter to a name --
          > but you can return an object with a .call method, a la:
          >
          > def outer(a) proc do |b| a+=b end end[/color]

          I would probably define this as;

          def outer(a)
          proc { |b| a+=b }
          end

          I prefer the { } block syntax for one-line blocks like that. And I don't
          like stick a whole function definition on one line like that. Makes it
          harder to read, IMHO.
          [color=blue]
          > x = outer(23)
          > puts x.call(100) # emits 123
          > puts x.call(100) # emits 223
          >
          > [i.e., I can't think of any way you could just use x(100)
          > at the end of such a snippet in Ruby -- perhaps somebody
          > more expert of Ruby than I am can confirm or correct...?][/color]

          I will go on a little ego trip here and assume I'm more of a Ruby expert
          than you are. :-)

          Yes, you are pretty much correct. There are some clever hacks you could
          do, but for the most part, functional objects in Ruby come without
          sugar.

          Jason Creighton

          Comment

          • Oren Tirosh

            #95
            Re: Python syntax in Lisp and Scheme

            On Fri, Oct 03, 2003 at 04:02:13AM -0700, Mark Brady wrote:
            ....[color=blue]
            > have been helped by python. I learned python then got interested in
            > it's functional side and ended up learning Scheme and Common Lisp. A
            > lot of new Scheme and Common Lisp developers I talk to followed the
            > same route. Python is a great language and I still use it for some
            > things.[/color]

            Python is a gateway drug to much more dangerous stuff. Just say no to
            functions as first-class objects. Before you know it you will be
            snorting a dozen closing parentheses in a row.

            Oren

            Comment

            • Rene van Bevern

              #96
              Re: Python syntax in Lisp and Scheme

              On Sat, 04 Oct 2003 13:11:49 +0100, David Rush <drush@aol.ne t> wrote:[color=blue]
              > Emacs. I've noticed over the years that people don't really get Emacs
              > religion until they've started hacking elisp. I know that the frustration
              > of having almost-but-not-quite the behavior I wanted on top of having all
              > that source code was a powerful incentive for me to learn Lisp. Of course
              > my apreciation of Emacs only increased as I went...[/color]

              hm. i really like LISP, but still don't get through emacs. After i
              learned a bit LISP i wanted to try it again, and again i failed ;) i
              know vim from the in- and out- side and just feel completely lost in
              emacs.

              i also like vim with gtk2 support more. not because of menu or toolbar,
              which are usually switched off in my config, but because of antialiased
              letters. I just don't like coding with bleeding eyes anymore ;)

              *to me* vim just looks and feels much more smooth than emacs, so i don't
              think that hacking LISP influences the choice of the editor much. it of
              course makes people *try* Emacs because of its LISP support.

              Rene

              Comment

              • Bengt Richter

                #97
                Re: Python syntax in Lisp and Scheme

                On Sat, 04 Oct 2003 19:48:54 GMT, Alex Martelli <aleax@aleax.it > wrote:
                [color=blue]
                >Bengt Richter wrote:
                > ...[color=green]
                >> I like the Bunch class, but the name suggests vegetables to me ;-)[/color]
                >
                >Well, I _like_ vegetables...
                >[color=green]
                >> BTW, care to comment on a couple of close variants of Bunch with
                >> per-object class dicts? ...
                >>
                >> def mkNSC(**kwds): return type('NSC', (), kwds)()[/color]
                >
                >Very nice (apart from the yecchy name;-).
                >[color=green]
                >> or, stretching the one line a bit to use the instance dict,[/color][/color]
                ^^^^^^^^^^^^^^^ ^^^^^^^^^[color=blue][color=green]
                >>
                >> def mkNSO(**kwds): o=type('NSO', (), {})(); o.__dict__.upda te(kwds);
                >> return o[/color]
                >
                >I don't see the advantage of explicity using an empty dict and then
                >updating it with kwds, vs using kwds directly.[/color]
                ^^-- not the same dict, as you've probably thought of by now, but
                glad to see I'm not the only one who misread that ;-)

                I.e., as you know, the contents of the dict passed to type is used to update the fresh class dict.
                It's not the same mutable dict object, (I had to check)
                [color=blue][color=green][color=darkred]
                >>> d={'foo':'to check id'}
                >>> o = type('Using_d', (),d)()
                >>> d['y']='a y value'
                >>> o.__class__.__d ict__.keys()[/color][/color][/color]
                ['__dict__', '__module__', 'foo', '__weakref__', '__doc__']

                (If d were serving as class dict, IWT y would have shown up in the keys).

                and also the instance dict is only a glimmer in the trailing ()'s eye
                at the point the kwd dict is being passed to type ;-)
                [color=blue][color=green][color=darkred]
                >>> def mkNSC(**kwds): return type('NSC', (), kwds)()[/color][/color][/color]
                ...[color=blue][color=green][color=darkred]
                >>> def mkNSO(**kwds): o=type('NSO', (), {})(); o.__dict__.upda te(kwds); return o[/color][/color][/color]
                ...[color=blue][color=green][color=darkred]
                >>> class Bunch(object):[/color][/color][/color]
                ... def __init__(self, **kw): self.__dict__.u pdate(kw)
                ...[color=blue][color=green][color=darkred]
                >>> for inst in [mk(x=mk.__name_ _+'_x_value') for mk in (mkNSC, mkNSO, Bunch)]:[/color][/color][/color]
                ... cls=inst.__clas s__; classname = cls.__name__
                ... inst.y = 'added %s instance attribute y'% classname
                ... print '%6s: instance dict: %r' %(classname, inst.__dict__)
                ... print '%6s class dict keys: %r' %('', cls.__dict__.ke ys())
                ... print '%6s instance attr x: %r' %( '', inst.x)
                ... print '%6s instance attr y: %r' %( '', inst.y)
                ... print '%6s class var x : %r' %( '', cls.__dict__.ge t('x','<x not there>'))
                ... print
                ...
                NSC: instance dict: {'y': 'added NSC instance attribute y'}
                class dict keys: ['__dict__', 'x', '__module__', '__weakref__', '__doc__']
                instance attr x: 'mkNSC_x_value'
                instance attr y: 'added NSC instance attribute y'
                class var x : 'mkNSC_x_value'

                NSO: instance dict: {'y': 'added NSO instance attribute y', 'x': 'mkNSO_x_value' }
                class dict keys: ['__dict__', '__module__', '__weakref__', '__doc__']
                instance attr x: 'mkNSO_x_value'
                instance attr y: 'added NSO instance attribute y'
                class var x : '<x not there>'

                Bunch: instance dict: {'y': 'added Bunch instance attribute y', 'x': 'Bunch_x_value' }
                class dict keys: ['__dict__', '__module__', '__weakref__', '__doc__', '__init__']
                instance attr x: 'Bunch_x_value'
                instance attr y: 'added Bunch instance attribute y'
                class var x : '<x not there>'

                Note where x and y went. So NSC is nice and compact, but subtly different. E.g.,
                [color=blue][color=green][color=darkred]
                >>> nsc = mkNSC(x='really class var')
                >>> nsc.x[/color][/color][/color]
                'really class var'[color=blue][color=green][color=darkred]
                >>> del nsc.x[/color][/color][/color]
                Traceback (most recent call last):
                File "<stdin>", line 1, in ?
                AttributeError: 'NSC' object attribute 'x' is read-only

                (Is that's a new message with 2.3?)
                [color=blue][color=green][color=darkred]
                >>> del nsc.__class__.x
                >>> nsc.x[/color][/color][/color]
                Traceback (most recent call last):
                File "<stdin>", line 1, in ?
                AttributeError: 'NSC' object has no attribute 'x'

                NS was for Name Space, and C vs O was for Class vs obj dict initialization ;-)

                Regards,
                Bengt Richter

                Comment

                • Kenny Tilton

                  #98
                  Re: Flat-schmat! [was Re: Python syntax in Lisp and Scheme]



                  Andrew Dalke wrote:
                  [color=blue]
                  > Still have only made slight headway into learning Lisp since the
                  > last discussion, so I've been staying out of this one. But
                  >
                  > Kenny Tilton:
                  >[color=green]
                  >>Take a look at the quadratic formula. Is that flat? Not. Of course
                  >>Python allows nested math (hey, how come!), but non-mathematical
                  >>computation s are usually trees, too.[/color]
                  >
                  >
                  > Since the quadratic formula yields two results, ...[/color]

                  I started this analogy, didn't I? <g>

                  I expect most[color=blue]
                  > people write it more like
                  >
                  > droot = sqrt(b*b-4*a*c) # square root of the discriminate
                  > x_plus = (-b + droot) / (4*a*c)
                  > x_minus = (-b - droot) / (4*a*c)[/color]

                  Not?:

                  (defun quadratic (a b c)
                  (let ((rad (sqrt (- (* b b) (* 4 a c)))))
                  (mapcar (lambda (plus-or-minus)
                  (/ (funcall plus-or-minus (- b) rad) (+ a a)))
                  '(+ -))))

                  :)
                  [color=blue]
                  >
                  > possibly using a temp variable for the 4*a*c term, for a
                  > slight bit better performance.[/color]

                  Well it was a bad example because it does require two similar
                  calculations which can be done /faster/ by pre-computing shared
                  components. But then the flattening is about performance, and the
                  subject is whether deeply nested forms are in fact simpler than
                  flattened sequences where the algorithm itself would be drawn as a tree.
                  So the example (or those who stared at it too hard looking for
                  objections <g>) distracted us from that issue.
                  [color=blue]
                  > But isn't that flattening *exactly* what occurs in math. Let me pull
                  > out my absolute favorite math textbook - Bartle's "The Elements
                  > of Real Analysis", 2nd ed.[/color]

                  Oh, god. I tapped out after three semesters of calculus. I am in deep
                  trouble. :)
                  [color=blue]
                  >
                  > I opened to page 213, which is in the middle of the book.
                  >
                  > 29.1 Definition. If P is a partition of J, then a Riemann-Stieltjes sum
                  > of f with respect to g and corresponding to P = (x_0, x_1, ..., x_n) is a
                  > real
                  > number S(P; f, g) of the form
                  >
                  > n
                  > S(P; f, g) = SIGMA f(eta_k){g(x_k) - g(x_{k-1})}
                  > k = 1
                  >
                  > Here we have selected number eta_k satisying
                  >
                  > x_{k-1} <= eta_k <= x_k for k = 1, 2, ..., n
                  >
                  > There's quite a bit going on here behind the scenes which are
                  > the same flattening you talk about. For examples: the definiton
                  > of "partition" is given elsewhere, the notations of what f and g
                  > mean, and the nomenclature "SIGMA"[/color]

                  <snip another good example>
                  [color=blue]
                  > In both cases, the equations are flattened. They aren't pure trees
                  > nor are they absolutely flat. Instead, names are used to represent
                  > certain ideas -- that is, flatten them.[/color]

                  No! Those are like subroutines; they do not flatten, they create call
                  trees, hiding and encapsulating the details of subcomputations .

                  We do precisely the same in programming, which is part of why flattening
                  can be avoided. When any local computation gets too long, there is
                  probably a subroutine to be carved out, or at least I can take 10 lines
                  and give it a nice readable name so I can avoid confronting too much
                  detail at any one time. But I don't throw away the structure of the
                  problem to get to simplicity.
                  [color=blue]
                  > .. You judge the Zen of Python
                  > using the Zen of Lisp.[/color]

                  Hmmm, Zen constrained by the details of a computing language. Some
                  philosophy! :) What I see in "flat is better" is the mind imposing
                  preferred structure on an algorithm which has its own structure
                  independent of any particular observer/mind.

                  I am getting excellent results lately by always striving to conform my
                  code to the structure of the problem as it exists independently of me.
                  How can I know the structure independently of my knowing? I cannot, but
                  the problem will tell me if I screw up and maybe even suggest how I went
                  wrong. I make my code look like my best guess at the problem, then if I
                  have trouble, I try a different shape. I do not add bandaids and patches
                  to force my first (apparently mistaken) ideas on the problem. When the
                  problem stops resisting me, I know I have at least approximated its
                  shape. Often there is a "pieces falling into place" sensation that gives
                  me some confidence.

                  Lisp has both SETF and "all forms return a value", so it does not
                  interfere in the process. In rare cases where the functional paradigm is
                  inappropriate, I can run thru a sequence of steps to achieve some end.
                  Lisp stays out of the way.

                  Python (I gather from what I read here) /deliberately/ interferes in my
                  attempts to conform my code to the problem at hand, because the
                  designers have decreed "flat is better". Python rips a tool from my
                  hands without asking if, in some cases (I would say most) it might be
                  the right tool (where an algorithm has a tree-like structure).

                  I do not think that heavy-handedness can be defended by saying "Oh, but
                  this is not Lisp." It is just plain heavy-handed.

                  kenny

                  "Be the ball."
                  - Caddy Shack




                  Comment

                  • Shriram Krishnamurthi

                    #99
                    Re: Python syntax in Lisp and Scheme

                    "Terry Reedy" <tjreedy@udel.e du> writes:
                    [color=blue]
                    > Lisp (and possibly other languages I am not familiar with) adds the
                    > alternative of *not* evaluating arguments but instead passing them as
                    > unevaluated expressions. In other words, arguments may be
                    > *implicitly* quoted. Since, unlike as in Python, there is no
                    > alternate syntax to flag the alternate argument protocol, one must, as
                    > far as I know, memorize/learn the behavior for each function. The
                    > syntactic unification masks but does not lessen the semantic
                    > divergence. For me, it made learning Lisp (as far as I have gotten)
                    > more complicated, not less, especially before I 'got' what going on.[/color]

                    I'm sorry -- you appear to be hopelessly confused on this point. I
                    can't comment on the dark corners of Common Lisp, but I do know all of
                    those corners of Scheme. Scheme is a true call-by-value language.
                    There are no functions in Scheme whose arguments are not evaluated.
                    Indeed, neithen a function definition, nor an argument location, has
                    the freedom to "not evaluate" an argument. We can reason about this
                    quite easily: the language provides no such syntactic annotation, and
                    the evaluator (as you might imagine) does not randomly make such a
                    choice. Therefore, it can't happen.

                    It is possible that you had a horribly confused, and therefore
                    confusing, Scheme instructor or text.
                    [color=blue]
                    > Question: Python has the simplicity of one unified assignment
                    > statement for the binding of names, attributes, slot and slices, and
                    > multiples thereof. Some Lisps have the complexity of different
                    > functions for different types of targets: set, setq, putprop, etc.[/color]

                    Again, you're confused. SET, SETQ, etc are not primarily binding
                    operators but rather mutation operators. The mutation of identifiers
                    and the mutation of values are fundamentally different concepts.

                    Shriram

                    Comment

                    • A.M. Kuchling

                      Re: Flat-schmat!

                      On Sun, 05 Oct 2003 12:27:47 GMT,
                      Kenny Tilton <ktilton@nyc.rr .com> wrote:[color=blue]
                      > Python (I gather from what I read here) /deliberately/ interferes in my
                      > attempts to conform my code to the problem at hand, because the
                      > designers have decreed "flat is better". Python rips a tool from my
                      > hands without asking if, in some cases (I would say most) it might be
                      > the right tool (where an algorithm has a tree-like structure).[/color]

                      Oh, for Pete's sake... Python is perfectly capable of manipulating tree
                      structures, and claiming it "rips a tool from my hand" is simply silly.

                      The 19 rules are general principles that encapsulate various principles of
                      Python's design, but they're not hard-and-fast rules to be obeyed like a
                      legal code, and their meanings are unspecified. I have seen the "flat is
                      better than nested" rule cited against creating too many submodules in a
                      package, against nesting loops too deeply, against making code too dense.
                      You can project any meaning onto them you wish, much like Perlis's epigrams
                      or Zen koans.

                      --amk

                      Comment

                      • Terry Reedy

                        Re: Python syntax in Lisp and Scheme


                        "Steve VanDevender" <stevev@hexadec imal.uoregon.ed u> wrote in message
                        news:874qyodvc7 .fsf@localhost. efn.org...[color=blue]
                        > "Terry Reedy" <tjreedy@udel.e du> writes:
                        >[color=green]
                        > > Lisp (and possibly other languages I am not familiar with) adds[/color][/color]
                        the[color=blue][color=green]
                        > > alternative of *not* evaluating arguments but instead passing them[/color][/color]
                        as[color=blue][color=green]
                        > > unevaluated expressions. In other words, arguments may be
                        > > *implicitly* quoted. Since, unlike as in Python, there is no
                        > > alternate syntax to flag the alternate argument protocol, one[/color][/color]
                        must, as[color=blue][color=green]
                        > > far as I know, memorize/learn the behavior for each function. The
                        > > syntactic unification masks but does not lessen the semantic
                        > > divergence. For me, it made learning Lisp (as far as I have[/color][/color]
                        gotten)[color=blue][color=green]
                        > > more complicated, not less, especially before I 'got' what going[/color][/color]
                        on.[color=blue]
                        >
                        > What you're talking about are called "special forms"[/color]

                        Perhaps by you and by Schemers generally, and perhaps even by modern
                        Common Lispers (I have no idea) but not by Winston and Horn in LISP
                        (1st edition, now into 3rd): "Appendix 2: Basic Lisp Functions ... A
                        FSUBR takes a variable number of arguments which may not be
                        evaluated.", which goes on to list AND, COND, DEFUN, PROG, etcetera,
                        along with normal SUBR and LSUBR (variable arg number) arg-evaluating
                        functions.
                        [color=blue]
                        > and are definitely not functions,[/color]

                        That is *just* what I thought, though I mentally used the word
                        'psuedofunction '.
                        [color=blue]
                        > and are used when it is semantically necessary to leave
                        > something in an argument position unevaluated (such as in 'cond' or
                        > 'if', Lisp 'defun' or 'setq', or Scheme 'define' or 'set!').[/color]

                        Once I understood this, I noticed that the special forms mostly
                        correspond to Python statements or special operators, which have the
                        same necessity.

                        ....[color=blue]
                        > Lisp-family languages have traditionally held to the notion that[/color]
                        Lisp[color=blue]
                        > programs should be easily representable using the list data[/color]
                        structure,[color=blue]
                        > making it easy to manipulate programs as data.[/color]

                        This is definitely a plus. One of my current interests is in
                        meta-algorithms that convert between recursive and iterative forms of
                        expressing 'repetition with variation' (and not just tail recursion).
                        Better understanding Lisp has help my thinking about this.

                        Terry J. Reedy


                        Comment

                        • Terry Reedy

                          Re: Python syntax in Lisp and Scheme


                          "Shriram Krishnamurthi" <sk@cs.brown.ed u> wrote in message
                          news:w7dk77jq26 d.fsf@cs.brown. edu...
                          [color=blue]
                          >"Terry Reedy" <tjreedy@udel.e du> writes:[color=green]
                          >> Lisp (and possibly other languages I am not familiar with) adds the
                          >> alternative of *not* evaluating arguments but instead passing them[/color][/color]
                          as[color=blue][color=green]
                          >> unevaluated expressions.[/color][/color]
                          [color=blue]
                          > I'm sorry -- you appear to be hopelessly confused on this point.[/color]

                          Actually, I think I have just achieved clarity: the one S-expression
                          syntax is used for at least different evaluation protocols -- normal
                          functions and special forms, which Lispers have also called FSUBR and
                          FEXPR *functions*. See the post by Steve VanDevender and my response
                          thereto.
                          [color=blue]
                          > There are no functions in Scheme whose arguments are not evaluated.[/color]

                          That depends on who defines 'function'. As you quoted, I said Lisp
                          (in general) and not Scheme specifically. I repeat my previous note:
                          "If anything I write below about Lisp does not apply to Scheme
                          specificly, my aplogies in advance."
                          [color=blue]
                          > It is possible that you had a horribly confused, and therefore
                          > confusing, Scheme instructor or text.[/color]

                          I will let you debate this with LISP authors Winston and Horn. I also
                          read the original SICP (several years ago, and have forgotten some
                          details) and plan to look at the current version sometime.

                          Terry J. Reedy


                          Comment

                          • prunesquallor@comcast.net

                            Re: Python syntax in Lisp and Scheme

                            "Terry Reedy" <tjreedy@udel.e du> writes:
                            [color=blue]
                            > "Shriram Krishnamurthi" <sk@cs.brown.ed u> wrote in message
                            > news:w7dk77jq26 d.fsf@cs.brown. edu...
                            >[color=green]
                            >>"Terry Reedy" <tjreedy@udel.e du> writes:[color=darkred]
                            >>> Lisp (and possibly other languages I am not familiar with) adds the
                            >>> alternative of *not* evaluating arguments but instead passing them[/color][/color]
                            > as[color=green][color=darkred]
                            >>> unevaluated expressions.[/color][/color]
                            >[color=green]
                            >> I'm sorry -- you appear to be hopelessly confused on this point.[/color]
                            >
                            > Actually, I think I have just achieved clarity: the one S-expression
                            > syntax is used for at least different evaluation protocols -- normal
                            > functions and special forms, which Lispers have also called FSUBR and
                            > FEXPR *functions*. See the post by Steve VanDevender and my response
                            > thereto.[/color]

                            There used to be FEXPR and FSUBRs in MacLisp, but Common Lisp never
                            had them. They had flags that indicated that their arguments were not
                            to be evaluated, but were otherwise `normal' functions.

                            The problem with FEXPRs is when you pass them around as first-class
                            values. Then it is impossible to know if any particular fragment of
                            code is going to be evaluated (in fact, it can dynamically change).
                            Needless to say, this presents problems to the compiler.

                            It generally became recognized that macros were a better solution.

                            So FSUBRs, which were primitives that did not evaluate their arguments
                            have been superseded by `special forms', which are syntactic constructs.

                            FEXPRs, which were user procedures that did not evaluate their
                            arguments have been superseded by macros.

                            Macros and special forms are generally not considered `functions'
                            because they are not first-class objects.
                            [color=blue]
                            > I will let you debate this with LISP authors Winston and Horn. I also
                            > read the original SICP (several years ago, and have forgotten some
                            > details) and plan to look at the current version sometime.[/color]

                            The original Winston and Horn book came out prior to SICP, which
                            itself came out prior to the creation of Common Lisp.


                            Comment

                            • Kenny Tilton

                              Re: Flat-schmat!



                              A.M. Kuchling wrote:
                              [color=blue]
                              > On Sun, 05 Oct 2003 12:27:47 GMT,
                              > Kenny Tilton <ktilton@nyc.rr .com> wrote:
                              >[color=green]
                              >>Python (I gather from what I read here) /deliberately/ interferes in my
                              >>attempts to conform my code to the problem at hand, because the
                              >>designers have decreed "flat is better". Python rips a tool from my
                              >>hands without asking if, in some cases (I would say most) it might be
                              >>the right tool (where an algorithm has a tree-like structure).[/color]
                              >
                              >
                              > Oh, for Pete's sake... Python is perfectly capable of manipulating tree
                              > structures, and claiming it "rips a tool from my hand" is simply silly.[/color]

                              Well then I am glad I did not say it! :)

                              I am talking about coding up an algorithm, not manipulating a tree of
                              data. An example is:

                              (my-function ;; takes three parameters, which follow
                              (this-function x yz) ;; p1
                              (case x (:left 1)(:right -1)) ;;p2
                              (if (some-other-function 'z)
                              42
                              'norwegian-blue)) ;; p3

                              where my-function gets passed the first two computations plus either 42
                              or 'norwegian-blue, ie, the value returned by the IF form.

                              Looks simple to me. But IIUC (I may not!) in Python IF is a statement,
                              so that would not work too well. I need an artificial extra statement to
                              satisfy an artifical rule.

                              kenny

                              Comment

                              • Russell Wallace

                                Re: Python syntax in Lisp and Scheme

                                On 03 Oct 2003 18:51:38 +0100, Alexander Schmolck <a.schmolck@gmx .net>
                                wrote:
                                [color=blue]
                                >I'd be interested to hear your reasons. *If* you take the sharp distinction
                                >that python draws between statements and expressions as a given, then python's
                                >syntax, in particular the choice to use indentation for block structure, seems
                                >to me to be the best choice among what's currently on offer (i.e. I'd claim
                                >that python's syntax is objectively much better than that of the C and Pascal
                                >descendants[/color]

                                I'll claim C's syntax is objectively better - it has a clean
                                definition whereas Python's hasn't. Python isn't even consistent - it
                                uses whitespace some of the time and delimiters some of the time; if
                                it stuck to the decision to use whitespace it might be a bit less
                                repellent. Also Python's syntax has a whole category of pitfalls that
                                C's lacks.

                                In truth, though, my reason for being unwilling to use Python for
                                anything other than throwaway scripting isn't based on objective
                                criteria, it's based on a visceral revulsion - it just _feels_ wrong.
                                If Python feels right to you, then you should by all means use it.

                                --
                                "Sore wa himitsu desu."
                                To reply by email, remove
                                the small snack from address.

                                Comment

                                Working...