Python syntax in Lisp and Scheme

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Raffael Cavallaro

    Re: Python syntax in Lisp and Scheme

    In article <y8vnhkcy.fsf@c cs.neu.edu>, Joe Marshall <jrm@ccs.neu.ed u>
    wrote:
    [color=blue]
    > The problem with this is that you've essentially outlawed MAP.
    >
    > (map 'list (make-adder offset) some-list)
    >
    > The problem with this is that MAKE-ADDER is no less a lambda in drag,
    > and it isn't even local.[/color]

    I think you misunderstand me. I haven't outlawed map. I've simply asked
    that it be used in a _named_ function or macro that expresses _what_ is
    being done, not _how_. For example:

    (defgeneric add-offset (some-sequence some-offset))

    (defmethod add-offset ((some-list list) some-offset)
    (map 'list #'(lambda (x) (+ x some-offset)) some-list))

    (defmethod add-offset ((some-vector vector) some-offset)
    (map 'vector #'(lambda (x) (+ x some-offset)) some-vector))


    And the client code looks like your example:

    (add-offset my-list current-offset) or

    (add-offset my-vector vector-offset) etc.

    Also see my reply to Thant Tessman entitled "Express What, not How."

    Comment

    • Kaz Kylheku

      Re: Python syntax in Lisp and Scheme

      Matthias Blume <find@my.addres s.elsewhere> wrote in message news:<m1k777n2i 2.fsf@tti5.uchi cago.edu>...[color=blue]
      > kaz@ashi.footpr ints.net (Kaz Kylheku) writes:
      >[color=green]
      > > Marcin 'Qrczak' Kowalczyk <qrczak@knm.org .pl> wrote in message news:<pan.2003. 10.13.21.26.56. 715704@knm.org. pl>...[color=darkred]
      > > > On Mon, 13 Oct 2003 13:51:22 -0700, Kaz Kylheku wrote:
      > > >
      > > > > Secondly, it would be unoptimizeable. The result of evaluating a
      > > > > lambda expression is an opaque function object. It can only be called.
      > > >
      > > > This is not true. When the compiler sees the application of a lambda,
      > > > it can inline it and perform further optimizations, fusing together
      > > > its arguments, its body and its context.[/color]
      > >
      > > Kindly keep in mind the overall context of the discussion, which is
      > > HOF's versus macros. The closures being discussed are ones passed down
      > > into functions. Those closures typically cannot be inlined, except
      > > under very special circumstances taken advantage of by a compiler with
      > > very smart global optimizations.[/color]
      >
      > If a macro works in a particular situation, then any equivalent HOF
      > can be inlined there as well. Granted, not all compilers will
      > actually do so, but the possibility trivially exists. This does not
      > depend on "very smart" global optimizations.[/color]

      That is a case of bringing all of the function into the present
      context so it can be mixed with the closures manually created there.

      A macro controls how much material is inlined and how much isn't.

      A macro can have its own binary interface between the expanded
      material and some material in a library that is associated with the
      macro.

      The macro decides what forms need to be made into a closure that is
      passed to the library and which are not.

      These considerations are important, because in the Lisp world,
      programs are dynamically updated while they are running. There are
      versioning issues, like keeping new versions of a macro's library
      compatible with existing macro-expansions, which won't be re-expanded
      and re-compiled when the new code is loaded into an existing
      application.

      Comment

      • Marcin 'Qrczak' Kowalczyk

        Re: Express What, not How.

        On Tue, 14 Oct 2003 22:09:44 +0000, Raffael Cavallaro wrote:
        [color=blue]
        > A theme of this whole thread is the difference between writing _what_
        > something does, and _how_ it does it. The higher up the ladder of
        > abstraction we go, the more we want to express _what_ is being done. We
        > leave the _how_ defined elsewhere, to be consulted only as needed.[/color]

        Sometimes a function is so simple that its body is more clear than any
        name. A name is an extra level of indirection. You must follow it to be
        100% sure what the function means, or to understand what does it really
        mean that it does what it's named after. The code also gets longer - not
        only more verbose but the structure of the code gets more complex with
        more interdependent parts. When you have lots of short functions, it's
        harder to find them. There are many names to invent for the writer and
        many names to rememner for a reader. Function headers are administrative
        stuff, it's harder to find real code among abstractions being introduced
        and used.

        Why do you insist on naming *functions*? You could equally well say that
        every list should be named, so you would see its purpose rather than its
        contents. Perhaps every number should be named, so you can see what it
        represents rather than its value. You could say that each statement of
        a compound statement should be moved to a separate function, so you can
        see what it does by its name, not how it does it by its contents. It's
        all equally absurd.

        A program should balance named and unnamed objects. Both are useful,
        there is a continuum between cases where one or the other is more clear
        and it's subjective in border cases, but there is place for unnamed
        functions - they are not that special. Most high level languages have
        anonymous functions for a reason.

        --
        __("< Marcin Kowalczyk
        \__/ qrczak@knm.org. pl
        ^^ http://qrnik.knm.org.pl/~qrczak/

        Comment

        • Jock Cooper

          Re: Python syntax in Lisp and Scheme

          "Terry Reedy" <tjreedy@udel.e du> writes:[color=blue]
          > The default-parameter hack which substituted for closures made lambdas
          > then more awkward, but I believe they were mostly just as useful as
          > today as callbacks and as HOF args. In any case, closures were
          > introduced over two years ago in 2.1, and your original statement says
          > 'is', not 'used to be some years ago'.[/color]

          Isn't it true though that the lambda can only contain a single expression
          and no statements? That seems to limit closures somewhat.

          Comment

          • james anderson

            Re: Express What, not How.



            Marcin 'Qrczak' Kowalczyk wrote:[color=blue]
            >
            > On Tue, 14 Oct 2003 22:09:44 +0000, Raffael Cavallaro wrote:
            >[color=green]
            > > A theme of this whole thread is the difference between writing _what_
            > > something does, and _how_ it does it. The higher up the ladder of
            > > abstraction we go, the more we want to express _what_ is being done. We
            > > leave the _how_ defined elsewhere, to be consulted only as needed.[/color]
            >
            > Sometimes a function is so simple that its body is more clear than any
            > name. ... Function headers are administrative
            > stuff, it's harder to find real code among abstractions being introduced
            > and used.
            >
            > Why do you insist on naming *functions*? ... It's
            > all equally absurd.[/color]

            years and years ago, perchance, the same person who introduced me to
            referential transparency also went to great lengths to acquaint me with the
            benefits of internal define.
            [color=blue]
            >
            > A program should balance named and unnamed objects. Both are useful,
            > there is a continuum between cases where one or the other is more clear
            > and it's subjective in border cases, but there is place for unnamed
            > functions - they are not that special. Most high level languages have
            > anonymous functions for a reason.
            >[/color]

            please post the longest lambda calculus definition which you would like to
            point to as an exemplar of coding clarity - an exercise, publication,
            production code, whatever. i'm just wondering if you're serious about all of this.

            ....

            Comment

            • David Eppstein

              Re: Python syntax in Lisp and Scheme

              In article <m3r81f1lu9.fsf @jcooper02.sage pub.com>,
              Jock Cooper <jockc@mail.com > wrote:
              [color=blue]
              > "Terry Reedy" <tjreedy@udel.e du> writes:[color=green]
              > > The default-parameter hack which substituted for closures made lambdas
              > > then more awkward, but I believe they were mostly just as useful as
              > > today as callbacks and as HOF args. In any case, closures were
              > > introduced over two years ago in 2.1, and your original statement says
              > > 'is', not 'used to be some years ago'.[/color]
              >
              > Isn't it true though that the lambda can only contain a single expression
              > and no statements? That seems to limit closures somewhat.[/color]

              It limits lambdas. It doesn't limit named functions. Unlike lisp, a
              Python function definition can be nested within a function call, and the
              inner function can access variables in the outer function's closure.

              --
              David Eppstein http://www.ics.uci.edu/~eppstein/
              Univ. of California, Irvine, School of Information & Computer Science

              Comment

              • David Eppstein

                Re: Python syntax in Lisp and Scheme

                In article <eppstein-434779.17173814 102003@news.ser vice.uci.edu>,
                David Eppstein <eppstein@ics.u ci.edu> wrote:
                [color=blue][color=green]
                > > Isn't it true though that the lambda can only contain a single expression
                > > and no statements? That seems to limit closures somewhat.[/color]
                >
                > It limits lambdas. It doesn't limit named functions. Unlike lisp, a
                > Python function definition can be nested within a function call, and the
                > inner function can access variables in the outer function's closure.[/color]

                To clarify, by "unlike lisp" I meant only that defun doesn't nest (at
                least in the lisps I've programmed) -- of course you could use flet, or
                bind a variable to a lambda, or whatever.

                --
                David Eppstein http://www.ics.uci.edu/~eppstein/
                Univ. of California, Irvine, School of Information & Computer Science

                Comment

                • Raffael Cavallaro

                  Re: Express What, not How.

                  In article <pan.2003.10.14 .23.19.11.73387 9@knm.org.pl>,
                  Marcin 'Qrczak' Kowalczyk <qrczak@knm.org .pl> wrote:

                  [color=blue]
                  > Sometimes a function is so simple that its body is more clear than any
                  > name. A name is an extra level of indirection. You must follow it to be
                  > 100% sure what the function means, or to understand what does it really
                  > mean that it does what it's named after.[/color]

                  Your argument is based on the assumption that whenever people express
                  _what_ a function does, they do so badly, with an inappropriate name.

                  We should choose our mode of expression based on how things work when
                  used correctly, not based on what might happen when used foolishly. We
                  don't write novels based on how they might be misread by the
                  semi-litterate.

                  Anonymous functions add no clarity except to our understaning of
                  _implementation _, i.e., _how_ not _what_. Higher level abstractions
                  should express _what_. Implementation details should remain separate,
                  both for clarity of exposition, and for maintanence and change of
                  implementation.
                  [color=blue]
                  > The code also gets longer[/color]

                  No, it gets shorter, because you don't repeat your use of the same
                  abstraction over and over. You define it once, then reference it by name
                  everywhere you use it.
                  [color=blue]
                  > - not
                  > only more verbose but the structure of the code gets more complex with
                  > more interdependent parts.[/color]

                  No, there are _fewer_ interdependent parts, because the parts that
                  correspond to the anonymous function bodies are _completely gone_ from
                  the main exposition of what is happening. These formerly anonymous
                  function bodies are now elswhere, where they will only be consulted when
                  it is necessary to modify them.

                  You seem to take the view that client code can't trust the interfaces it
                  uses, that you have to see how things are implemented to make sure they
                  do what they represent to do.

                  This is a very counterproducti ve attitude. Code should provide high
                  level abstractions, and clients of this code should be able to tell what
                  it does just by looking at the interface, and maybe a line of
                  documentation. It shouldn't be necessary to understand the internals of
                  code one uses just to use it. And it certainly isn't necessary to
                  include the internals of code one uses where one is using it (i.e.,
                  anonymous functions). That's what named functions and macros are for.
                  Inlining should be done by compilers, not programmers.

                  Anonymous functions are a form of unnecessary information overload. If I
                  don't need to see how something works right here, in this particular
                  context, then don't put its implementation here. Just refer to it by
                  name.
                  [color=blue]
                  > When you have lots of short functions, it's
                  > harder to find them. There are many names to invent for the writer and
                  > many names to rememner for a reader.[/color]

                  Which is why names should be descriptive. Then, there's little to
                  remember. I don't need to remember what add-offset does, nor look up
                  it's definition, to understand its use in some client code. Anonymous
                  functions are sometimes used as a crutch by those who can't be bothered
                  to take the time to attend to the social and communicative aspects of
                  programming. Ditto for overly long function bodies. How to express
                  intent to human readers is just as important as getting the compiler to
                  do what you want. These same programmers seem enamored of
                  crack-smokingly short and cryptic identifier and function names, as if
                  typing 10 characters instead of 3 is the real bottleneck in modern
                  software development. (Don't these people know how to touch type?)


                  [color=blue]
                  > Function headers are administrative
                  > stuff, it's harder to find real code among abstractions being introduced
                  > and used.[/color]


                  Seemingly to you, the only "real code" is low level implementation. In
                  any non-trivial software, however, the "real code" is the interplay of
                  high level abstractions. At each level, we craft a _what_ from some less
                  abstract _how_, and the _what_ we have just defined, is, in turn used as
                  part of the _how_ for an even higher level of abstraction or
                  functionality.

                  [color=blue]
                  > Why do you insist on naming *functions*? You could equally well say that
                  > every list should be named, so you would see its purpose rather than its
                  > contents.[/color]

                  I think this concept is called variable bindings ;^)

                  [color=blue]
                  > Perhaps every number should be named, so you can see what it
                  > represents rather than its value.[/color]

                  Actually, they are _already_ named. The numerals we use _are_ names, not
                  numbers themselves. I'm surprised you aren't advocating the use of
                  Church Numerals for all numerical calculation.
                  [color=blue]
                  > You could say that each statement of
                  > a compound statement should be moved to a separate function, so you can
                  > see what it does by its name, not how it does it by its contents. It's
                  > all equally absurd.[/color]

                  In the Smalltalk community the rule of thumb is that if a method body
                  gets to be more than a few lines, you've failed to break it down into
                  smaller abstractions (i.e., methods).
                  [color=blue]
                  > A program should balance named and unnamed objects. Both are useful,
                  > there is a continuum between cases where one or the other is more clear
                  > and it's subjective in border cases, but there is place for unnamed
                  > functions - they are not that special. Most high level languages have
                  > anonymous functions for a reason.[/color]

                  Yes, but they should live inside the bodies of named functions. Not lie
                  exposed in the middle of higher level abstractions. Please also see my
                  reply to Joe Marshall/Prunesquallor a few posts up in this thread.

                  Comment

                  • David Mertz

                    Re: Python syntax in Lisp and Scheme

                    |> Isn't it true though that the lambda can only contain a single
                    |> expression and no statements? That seems to limit closures somewhat.

                    David Eppstein <eppstein@ics.u ci.edu> wrote previously:
                    |It limits lambdas. It doesn't limit named functions. Unlike lisp, a
                    |Python function definition can be nested within a function call, and the
                    |inner function can access variables in the outer function's closure.

                    I don't really know Lisp, so I could be wrong. But my understanding is
                    that CL has a 'let' special form that works fine within a function
                    definition. In particular, you should be able to define inner functions
                    by binding a name to a lambda, using 'let'.

                    So there's nothing really special about the fact that Python (or
                    Haskell, ML, etc) can nest function definition. Of course, Haskell's
                    'let' and 'where' are quite wonderful... even better, syntaxwise, than
                    Python's nested 'def's.

                    Yours, David...

                    P.S. On the prior poster's misunderstandin g: Lambdas in Python are
                    actually completely general. There is nothing you cannot express using
                    a single expression, even side effects--it just gets ugly doing it.
                    Basically, just like in CL, a list or tuple is a single expression, and
                    it evaluates its elements in predictable left-to-right order... you can
                    work out the rest of the ugly details from that fact. Or you can look
                    at my articles on "FP in Python"--however, my intent in those is NOT to
                    enable obfuscated Python, but to point to actual useful techniques.
                    It's a fine line though.

                    --
                    ---[ to our friends at TLAs (spread the word) ]--------------------------
                    Echelon North Korea Nazi cracking spy smuggle Columbia fissionable Stego
                    White Water strategic Clinton Delta Force militia TEMPEST Libya Mossad
                    ---[ Postmodern Enterprises <mertz@gnosis.c x> ]--------------------------


                    Comment

                    • james anderson

                      Re: Python syntax in Lisp and Scheme



                      David Eppstein wrote:[color=blue]
                      >
                      > In article <eppstein-434779.17173814 102003@news.ser vice.uci.edu>,
                      > David Eppstein <eppstein@ics.u ci.edu> wrote:
                      >[color=green][color=darkred]
                      > > > Isn't it true though that the lambda can only contain a single expression
                      > > > and no statements? That seems to limit closures somewhat.[/color]
                      > >
                      > > It limits lambdas. It doesn't limit named functions. Unlike lisp, a
                      > > Python function definition can be nested within a function call, and the
                      > > inner function can access variables in the outer function's closure.[/color]
                      >
                      > To clarify, by "unlike lisp" I meant only that defun doesn't nest (at
                      > least in the lisps I've programmed) -- of course you could use flet, or
                      > bind a variable to a lambda, or whatever.[/color]

                      ? which lisps have you been using?

                      i do not observe the spec for defun
                      (http://www.lispworks.com/reference/H...dy/m_defun.htm)
                      to place any restrictions on its context. anscillary discussion introduces the
                      issue of compile-time side-effects, eg whether the definition of the function
                      is known to exist for the purpose of error-checking, but there are no
                      constraints apparent to this reader on where the form may appear.

                      to wit


                      ? (defun function1 (a)
                      (defun function2 (b) (+ a b)))
                      FUNCTION1
                      ? (function1 2)
                      FUNCTION2
                      ? (function2 3)
                      5
                      ? (function1 5)
                      FUNCTION2
                      ? (function2 3)
                      8
                      ? (defun function* (a list)
                      (apply #'+ (mapcar (defun function2 (b) (+ a b)) list)))
                      FUNCTION*
                      ? (function* 1 '(1 2 3))
                      9
                      ?

                      that is, both the invocation for side-effect and for the returned value appear
                      to have the intended effect. on the other hand, it's not clear why one would
                      want to do this, so perhaps you mean something else?

                      ....

                      Comment

                      • Pascal Bourguignon

                        Re: Python syntax in Lisp and Scheme


                        prunesquallor@c omcast.net writes:[color=blue]
                        > [...]
                        > I thought that whitespace was significant to Python.
                        >
                        > My computer does not display whitespace. I understand that most
                        > computers do not. There are few fonts that have glyphs at the space
                        > character.
                        >
                        > Since having the correct amount of whitespace is *vital* to the
                        > correct operation of a Python program, it seems that the task of
                        > maintaining it is made that much more difficult because it is only
                        > conspicuous by its absence.[/color]

                        :-)

                        That remembers me that when the languages had significant spaces, the
                        programming was done with forms, sheets of physical paper preprinted
                        with empty spaces:


                        |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                        1 7 12

                        |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                        1 7 12

                        |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                        1 7 12

                        |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                        1 7 12

                        |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                        1 7 12

                        |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                        1 7 12

                        |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                        1 7 12

                        |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                        1 7 12

                        and you could then fill the blanks and have the significant spaces and
                        columns nicely visualized.

                        I assume python editors now show this kind of form as a background
                        bitmap, don't they.

                        --
                        __Pascal_Bourgu ignon__

                        Do not adjust your mind, there is a fault in reality.

                        Comment

                        • prunesquallor@comcast.net

                          Re: Python syntax in Lisp and Scheme

                          Pascal Bourguignon <spam@thalassa. informatimago.c om> writes:
                          [color=blue]
                          > prunesquallor@c omcast.net writes:[color=green]
                          >> [...]
                          >> I thought that whitespace was significant to Python.
                          >>
                          >> My computer does not display whitespace. I understand that most
                          >> computers do not. There are few fonts that have glyphs at the space
                          >> character.
                          >>
                          >> Since having the correct amount of whitespace is *vital* to the
                          >> correct operation of a Python program, it seems that the task of
                          >> maintaining it is made that much more difficult because it is only
                          >> conspicuous by its absence.[/color]
                          >
                          > :-)
                          >
                          > That remembers me that when the languages had significant spaces, the
                          > programming was done with forms, sheets of physical paper preprinted
                          > with empty spaces:
                          >
                          >
                          > |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                          > 1 7 12
                          >
                          > |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                          > 1 7 12
                          >
                          > |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                          > 1 7 12
                          >
                          > |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                          > 1 7 12
                          >
                          > |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                          > 1 7 12
                          >
                          > |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                          > 1 7 12
                          >
                          > |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                          > 1 7 12
                          >
                          > |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|_|_| _|_|_|_|_|_|_|_ |_|_|_|_|_|
                          > 1 7 12
                          >
                          > and you could then fill the blanks and have the significant spaces and
                          > columns nicely visualized.
                          >
                          > I assume python editors now show this kind of form as a background
                          > bitmap, don't they.[/color]

                          The Lisp Machine had a visual Hollerith editor.

                          Comment

                          • Brian McNamara!

                            Re: Express What, not How.

                            Raffael Cavallaro <raffaelcavalla ro@junk.mail.me .not.mac.com> once said:[color=blue]
                            > Marcin 'Qrczak' Kowalczyk <qrczak@knm.org .pl> wrote:[color=green]
                            >> Sometimes a function is so simple that its body is more clear than any
                            >> name. A name is an extra level of indirection. You must follow it to be
                            >> 100% sure what the function means, or to understand what does it really
                            >> mean that it does what it's named after.[/color]
                            >
                            >Your argument is based on the assumption that whenever people express
                            >_what_ a function does, they do so badly, with an inappropriate name.[/color]
                            ....[color=blue]
                            >Anonymous functions add no clarity except to our understaning of
                            >_implementatio n_, i.e., _how_ not _what_. Higher level abstractions
                            >should express _what_. Implementation details should remain separate,
                            >both for clarity of exposition, and for maintanence and change of
                            >implementation .[/color]

                            I am in total agreement with Marcin. What you (Raffael) say here
                            sounds simply like dogma, rather than practical advice for constructing
                            software.

                            As a short practical example of what I'm saying, consider code like

                            -- I am translating this from another language; apologies if I have
                            -- screwed up any of the Haskell details
                            nat :: Parser Int
                            nat = do {c <- digit; return charToInt c}
                            `chainl1` (return \x y -> 10*x+y)

                            The code here parses natural numbers; it does do by parsing individual
                            digit characters, translating the digit characters into the
                            corresponding integers, and then combining the digit-integers into the
                            overall number.

                            If I understand you correctly, you would insist I write something like

                            nat :: Parser Int
                            nat = do {c <- digit; return charToInt c}
                            `chainl1` combineDigits
                            where combineDigits = return \x y -> 10*x+y

                            In my opinion, the code here is worse than the original.
                            "combineDig its" (or whatever we might choose to name it) is a one-time
                            function. It is not going to be reused (it's local to "nat"; moving it
                            to a more-top-level scope would just cause more problems finding a good
                            name for it).

                            Introducing a name for this function does nothing more than clutter the
                            code. The name provides no extra understanding. Of course the
                            function is "combining digits"! If the programmer is using chainl1, he
                            already knows that

                            chainl1 :: Parser a -> Parser (a->a->a) -> Parser a
                            -- parses a series of items separated by left-associative operators
                            -- which are used to combine those items

                            and he can infer "combining digits" just by seeing the call to chainl1
                            and inspecting its left argument.

                            [color=blue]
                            >Anonymous functions are a form of unnecessary information overload. If I
                            >don't need to see how something works right here, in this particular
                            >context, then don't put its implementation here. Just refer to it by
                            >name.[/color]

                            There are more functional abstractions than there are reasonable names.

                            Forcing programmers to name every abstraction they'll ever encounter is
                            tantamount to forcing them to memorizing a huge vocabulary of names for
                            these abstractions. Perhaps you can remember the precise meanings of
                            ten-thousand function names off the top of your head. I, on the other
                            hand, can probably recall only a hundred or so. Thus, I must write,
                            e.g.

                            zipWith (\x y -> (x+y,x-y)) list1 list2

                            rather than

                            zipWith makePairOfSumAn dDifference list1 list2

                            By only naming the most reusable abstractions (and, ideally, selecting
                            a set which are mostly orthogonal to one another), we provide a "core
                            vocabulary" which captures the essential basis of the domain. Lambda
                            then takes us the rest of the way. In my opinion, a core vocabulary of
                            named functions plus lambda is better than a separate name for every
                            abstraction. In natural language, such a scheme would be considered
                            double-plus-un-good, but in programming, I think it lends itself to the
                            simplest and most precise specifications.


                            I agree with your one of your overall theses, which is that we should
                            focus on the "what" rather than the "how". Where our opinions diverge,
                            however, is that I think sometimes the best way to communicate an
                            abstraction is to show the "how" inline, rather than creating a new
                            name in an attempt to capture the "what".

                            --
                            Brian M. McNamara lorgon@acm.org : I am a parsing fool!
                            ** Reduce - Reuse - Recycle ** : (Where's my medication? ;) )

                            Comment

                            • Ken Shan

                              Re: Express What, not How.

                              Raffael Cavallaro <raffaelcavalla ro@junk.mail.me .not.mac.com> wrote in article <raffaelcavalla ro-7597B0.20420614 102003@netnews. attbi.com> in comp.lang.funct ional:[color=blue]
                              > In article <pan.2003.10.14 .23.19.11.73387 9@knm.org.pl>,
                              > Marcin 'Qrczak' Kowalczyk <qrczak@knm.org .pl> wrote:[color=green]
                              > > Why do you insist on naming *functions*? You could equally well say that
                              > > every list should be named, so you would see its purpose rather than its
                              > > contents.[/color]
                              > I think this concept is called variable bindings ;^)[/color]

                              Yes, but what Marcin is talking about outlawing anonymous variables, so
                              for example you can't write

                              amount_due = sum(item_prices ) * (1 + tax_rate)

                              in his hypothetical programming language down the slippery slope (or is
                              it up the slippery slope?), but must write

                              subtotal = sum(item_prices )
                              tax_multiplier = 1 + tax_rate
                              amount_due = subtotal * tax_multiplier

                              just as programmers did before FORTRAN.

                              I would go one step further and point out that even in the code above,
                              there are still unnamed things whose functionality is possibly unclear.
                              These things are source code locations to which computations return,
                              aka continuations. For instance, what is the purpose of executing this
                              code above? The purpose is not to go through a bunch of arithmetic
                              operations for fun, but to compute the amount due.

                              def compute_amount_ due:
                              subtotal = sum(item_prices )
                              tax_multiplier = 1 + tax_rate
                              amount_due = subtotal * tax_multiplier

                              There, clearer already. But what is the purpose of having the subtotal?
                              It is to add the tax to get the amount due.

                              def compute_amount_ due:
                              sum(item_prices , add_tax_for_amo unt_due)

                              def add_tax_for_amo unt_due(subtota l):
                              tax_multiplier = 1 + tax_rate
                              amount_due = subtotal * tax_multiplier

                              What is the purpose of computing the tax_multiplier? To multiply with
                              the subtotal in order to get the amount due. (I assume a Python-ish
                              syntax with partial function application (currying) here.)

                              def add_tax_for_amo unt_due(subtota l):
                              add(1, tax_rate, subtotal_and_ta x_multiplier_to _amount_due(sub total))

                              def subtotal_and_ta x_multiplier_to _amount_due(sub total, tax_multiplier) :
                              amount_due = subtotal * tax_multiplier

                              But what's the purpose of having the amount due at all? Maybe it is to
                              print a bill:

                              def subtotal_and_ta x_multiplier_to _amount_due(sub total, tax_multiplier) :
                              multiply(subtot al, tax_multiplier, print_bill_with _amount_due)

                              def print_bill_with _amount_due(amo unt_due):
                              ...
                              [color=blue][color=green]
                              > > Perhaps every number should be named, so you can see what it
                              > > represents rather than its value.[/color]
                              > Actually, they are _already_ named. The numerals we use _are_ names, not
                              > numbers themselves. I'm surprised you aren't advocating the use of
                              > Church Numerals for all numerical calculation.[/color]

                              Functions are _already_ named as well. The lambda expressions we use
                              _are_ names, not functions themselves.
                              [color=blue][color=green]
                              > > You could say that each statement of
                              > > a compound statement should be moved to a separate function, so you can
                              > > see what it does by its name, not how it does it by its contents. It's
                              > > all equally absurd.[/color]
                              >
                              > In the Smalltalk community the rule of thumb is that if a method body
                              > gets to be more than a few lines, you've failed to break it down into
                              > smaller abstractions (i.e., methods).[/color]

                              So perhaps we should have the programming language outlaw anonymous
                              functions that are more than 4 lines long...

                              --
                              Edit this signature at http://www.digitas.harvard.edu/cgi-bin/ken/sig
                              "The first rule of politics: The ballots don't make the vote. The count
                              makes the vote." -- Boss Tweed in Gangs of New York

                              Comment

                              • Rainer Deyke

                                Re: Express What, not How.

                                One of the most compelling arguments for anonymous functions comes from
                                Smalltalk, where the 'if' statement is implemented as a higher order method.
                                The equivalent in Python would look something like this:

                                class true_class:
                                def if_true(self, fn): return fn()
                                def if_false(self, fn): pass

                                class false_class:
                                def if_true(self, fn): pass
                                def if_false(self, fn): return fn()

                                true = true_class()
                                false = false_class()

                                (x == 0).if_true(anon ymous_code_bloc k)

                                Sure, Python already has an 'if' statement. That does not mean that there
                                are no other control structures worth implementing as HOFs.

                                However, I think I can make an even stronger case for anonymous functions
                                from my own code, which is littered with lambda expressions such as 'lambda:
                                1', 'lambda: 0', and 'lambda: None'. Giving those mini functions individual
                                names would be an atrocity, and even a factory function that returns these
                                mini functions would only hurt readability.


                                --
                                Rainer Deyke - rainerd@eldwood .com - http://eldwood.com


                                Comment

                                Working...