Python syntax in Lisp and Scheme

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Kaz Kylheku

    Re: Python syntax in Lisp and Scheme

    Matthias Blume <find@my.addres s.elsewhere> wrote in message news:<m1d6d9njk r.fsf@tti5.uchi cago.edu>...[color=blue]
    > Well, no, not really. You can define new syntactic forms in terms of
    > old ones, and the evaluation rules end up being determined by those of
    > the old ones. Again, with HOFs you can always get the same
    > effect -- at the expense of an extra lambda here and there in your
    > source code.[/color]

    A macro can control optimization: whether or not something is achieved
    by that extra lambda, or by some open coding.

    In the worst cases, the HOF solution would require the user to
    completely obfuscate the code with explicitly-coded lambdas. The code
    would be unmaintainable.

    Secondly, it would be unoptimizeable. The result of evaluating a
    lambda expression is an opaque function object. It can only be called.

    Consider the task of embedding one programming language into another
    in a seamless way. I want to be able to write utterances in one
    programming language in the middle of another. At the same time, I
    want seamless integration between them right down to the lexical
    level. For example, the embedded language should be able to refer to
    an outer variable defined in the host language.

    HOF's are okay if the embedded language is just some simple construct
    that controls the evaluation of coarse-grained chunks of the host
    language. It's not too much of an inconvenience to turn a few
    coarse-grained chunks into lambdas.

    But what if the parameters to the macro are not at all chunks of the
    source language but completely new syntax? What if that syntax
    contains only microscopic utterances of the host language, such as the
    mentions of the names of variables bound in surrounding host language?

    You can't put a lambda around the big construct, because it's not even
    written in the host language! So what do you do? You can use an escape
    hatch to code all the individual little references as host-language
    lambdas, and pepper these into the embedded language utterance. For
    variables that are both read and written, you need a reader and writer
    lambda. Now you have a tossed salad. And what's worse, you have poor
    optimization. The compiler for the embedded language has to work with
    these lambdas which it cannot crack open. It can't just spit out code
    that is integrated into the host language compile, where references
    can be resolved directly.
    [color=blue][color=green]
    > > This can only be accomplished with functions if you're
    > > willing to write a set of functions that defer evaluation, by, say
    > > parsing input, massaging it appropriately, and then passing it to the
    > > compiler. At that point, however, you've just written your own macro
    > > system, and invoked Greenspun's 10th Law.[/color]
    >
    > This is false. Writing your own macro expander is not necessary for
    > getting the effect. The only thing that macros give you in this
    > regard is the ability to hide the lambda-suspensions.[/color]

    That's like saying that a higher level language gives you the ability
    to hide machine instructions. But there is no single unique
    instruction sequence that corresponds to the higher level utterance.

    Macros not only hide lambdas, but they hide the implementation choice
    whether or not lambdas are used, and how! It may be possible to
    compile the program in different ways, with different choices.

    Moreover, there might be so many lambda closures involved that writing
    them by hand may destroy the clarity of expression and maintainability
    of the code.
    [color=blue]
    > To some people
    > this is more of a disadvantage than an advantage because, when not
    > done in a very carefully controlled manner, it ends up obscuring the
    > logic of the code. (Yes, yes, yes, now someone will jump in an tell
    > me that it can make code less obscure by "canning" certain common
    > idioms. True, but only when not overdone.)[/color]

    Functions can obscure in the same ways as macros. You have no choice.
    Large programs are written by delegating details elsewhere so that a
    concise expression can be obtained.

    You can no more readily understand some terse code that consists
    mostly of calls to unfamiliar functions than you can understand some
    terse code written in an embedded language build on unfamiliar macros.

    All languages ultimately depend on macros, even those functional
    languages that don't have user-defined macros. They still have a whole
    bunch of syntax. You can't define a higher order function if you don't
    have a compiler which recognizes the higher-order-function-defining
    syntax, and that syntax is nothing more than a macro that is built
    into the compiler which captures the idioms of programming with higher
    order functions!

    All higher level languages are based on syntax which captures idioms,
    and this is nothing more than macro processing.

    Comment

    • Kaz Kylheku

      Re: Python syntax in Lisp and Scheme

      gregm@cs.uwa.ed u.au wrote in message news:<blr1cq$bb 1$1@enyo.uwa.ed u.au>...[color=blue]
      > In comp.lang.funct ional Erann Gat <my-first-name.my-last-name@jpl.nasa.g ov> wrote:
      > : For example, imagine you want to be able to traverse a binary tree and do
      > : an operation on all of its leaves. In Lisp you can write a macro that
      > : lets you write:
      > : (doleaves (leaf tree) ...)
      > : You can't do that in Python (or any other langauge).
      >
      > My Lisp isn't good enough to answer this question from your code,
      > but isn't that equivalent to the Haskell snippet: (I'm sure
      > someone here is handy in both languages)
      >
      > doleaves f (Leaf x) = Leaf (f x)
      > doleaves f (Branch l r) = Branch (doleaves f l) (doleaves f r)[/color]

      You appear to be using macros here to define some entities. What if we
      took away the syntax which lets you write the above combination of
      symbols to achieve the associated meaning? By what means would you
      give meaning to the = symbol or the syntax (Leaf x)?

      Or give me a plausible argument to support the assertion that the =
      operator is not a macro. If it's not a macro, then what is it, and how
      can I make my own thing that resembles it?

      Comment

      • Category 5

        Re: Python syntax in Lisp and Scheme

        kaz@ashi.footpr ints.net (Kaz Kylheku) writes:
        [color=blue]
        > Lisp macros are part of the toolset that allow this translation itself
        > to be programmable. Thus you are not stuck with a fixed phrase
        > structure grammar with fixed semantics.
        >
        > Nearly every programming language has macros, it's just that most of
        > them have a hard-coded set of ``factory defined'' macros in the form
        > of a fixed set of production rules with rigidly defined semantics.[/color]

        Exactly so. But the average human mind clings viciously to rigid schema
        of all kinds in reflexive defence against the terrible uncertainties of
        freedom.

        To get someone with this neurological ailment to give up their preferred
        codification for another is very difficult. To get them to see beyond
        the limits of particular hardcoded schema altogether is practically
        impossible.

        This observation applies uniformly to programming and religion, but is
        not limited to them.

        --

        Comment

        • Marcin 'Qrczak' Kowalczyk

          Re: Python syntax in Lisp and Scheme

          On Mon, 13 Oct 2003 13:51:22 -0700, Kaz Kylheku wrote:
          [color=blue]
          > Secondly, it would be unoptimizeable. The result of evaluating a
          > lambda expression is an opaque function object. It can only be called.[/color]

          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.

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

          Comment

          • Raffael Cavallaro

            Re: Python syntax in Lisp and Scheme

            In article <pan.2003.10.13 .11.11.45.54187 9@knm.org.pl>,
            Marcin 'Qrczak' Kowalczyk <qrczak@knm.org .pl> wrote:
            [color=blue]
            > Note that Lisp and Scheme have a quite unpleasant anonymous function
            > syntax, which induces a stronger tension to macros than in e.g. Ruby or
            > Haskell.[/color]

            Actually, I think that any anonymous function syntax is undesirable. I
            think code is inerently more readable when functions are named,
            preferably in a descriptive fashion.

            I think it is the mark of functional cleverness that people's code is
            filled with anonymous functions. These show you how the code is doing
            what it does, not what it is doing.

            Macros, and named functions, focus on what, not how. HOFs and anonymous
            functions focus on how, not what. How is an implementation detail. What
            is a public interface, and a building block of domain specific languages.

            Comment

            • David C. Ullrich

              Re: Science is a human activity (was: Python syntax in Lisp and Scheme)

              On Mon, 13 Oct 2003 16:19:58 +0200, Michele Dondi
              <bik.mido@tisca linet.it> wrote:
              [color=blue]
              >On Sat, 11 Oct 2003 10:37:33 -0500, David C. Ullrich
              ><ullrich@math. okstate.edu> wrote:
              >[color=green]
              >>It's certainly true that mathematicians do not _write_
              >>proofs in formal languages. But all the proofs that I'm
              >>aware of _could_ be formalized quite easily. Are you
              >>aware of any counterexamples to this? Things that
              >>mathematician s accept as correct proofs which are
              >>not clearly formalizable in, say, ZFC?[/color]
              >
              >I am not claiming that it is a counterexample, but I've always met
              >with some difficulties imagining how the usual proof of Euler's
              >theorem about the number of corners, sides and faces of a polihedron
              >(correct terminology, BTW?) could be formalized. Also, however that
              >could be done, I feel an unsatisfactory feeling about how complex it
              >would be if compared to the conceptual simplicity of the proof itself.[/color]

              Well it certainly _can_ be formalized. (Have you any experience
              with _axiomatic_ Euclidean geometry? Not as in Euclid - no pictures,
              nothing that depends on knowing what lines and points really are,
              everything follows strictly logically from explictly stated axioms.
              Well, I have no experience with such a thing either, but I know
              it exists.)

              Whether the formal version would be totally incomprehensibl e
              depends to a large extent on how sophisticated the formal
              system being used is - surely if one wrote out a statement
              of Euler's theorem in the language of set theory, with no
              predicates except "is an element of" it would be totally
              incomprehensibl e. Otoh in a better formal system, for
              example allowing definitions, it could be just as comprehensible
              as an English version. (Not that I see that this question has
              any relevance to the existence of alleged philosophical
              inconsistencies that haven't been specified yet...)

              [color=blue]
              >Just a thought,
              >Michele[/color]

              *************** *********

              David C. Ullrich

              Comment

              • Greg Ewing (using news.cis.dfn.de)

                Re: Python syntax in Lisp and Scheme

                dewatf wrote:[color=blue]
                > 'virus' (slime, poison, venom) is a 2nd declension neuter noun and
                > technically does have a plural 'viri'.
                >
                > ... and also in latin 'viri' is
                > the nominative for 'men' which you do want to use a lot.[/color]

                So did Roman feminists use the slogan "All men are slime"?

                --
                Greg Ewing, Computer Science Dept,
                University of Canterbury,
                Christchurch, New Zealand


                Comment

                • Greg Ewing (using news.cis.dfn.de)

                  Re: Python syntax in Lisp and Scheme

                  Pascal Costanza wrote:[color=blue]
                  > Many programming languages require you to build a model upfront, on
                  > paper or at least in your head, and then write it down as source code.
                  > This is especially one of the downsides of OOP - you need to build a
                  > class hierarchy very early on without actually knowing if it is going to
                  > work in the long run.[/color]

                  I don't think that's a downside of OOP itself, but of statically
                  typed OO languages that make it awkward and tedious to rearrange
                  your class hierarchy once you've started on it.

                  Python's dynamic typing and generally low-syntactic-overhead
                  OO makes it quite amenable to exploratory OO programming, in my
                  experience.

                  --
                  Greg Ewing, Computer Science Dept,
                  University of Canterbury,
                  Christchurch, New Zealand


                  Comment

                  • Greg Ewing (using news.cis.dfn.de)

                    INDENT/DEDENT tokens considered hampering (Re: Code block literals)

                    Bengt Richter wrote:[color=blue]
                    > The thing is, the current tokenizer doesn't know def from foo, just that they're
                    > names. So either indenting has to be generated all the time, and the job of
                    > ignoring it passed on upwards, or the single keyword 'def' could be recognized
                    > by the parser in a bracketed context, and it would generate a synthetic indent token
                    > in front of the def name token as wide as if all spaces preceded the def, and then
                    > continue doing indent/dedent generation like for a normal def, until the def suite closed,
                    > at which point it would resume ordinary expression processing (if it was within brackets --
                    > otherwise is would just be a discarded expression evaluated in statement context, and
                    > in/de/dent processing would be on anyway. (This is speculative until really getting into it ;-)[/color]

                    I think there is a way of handling indentation that would make
                    changes like this easier to implement, but it would require a
                    complete re-design of the tokenizing and parsing system.

                    The basic idea would be to get rid of the indent/dedent tokens
                    altogether, and have the tokenizer keep track of the indent
                    level of the line containing the current token, as a separate
                    state variable.

                    Then parsing a suite would go something like

                    starting_level = current_indent_ level
                    expect(':')
                    expect(NEWLINE)
                    while current_indent_ level > starting_level:
                    parse_statement ()

                    The tokenizer would keep track of the current_indent_ level
                    all the time, even inside brackets, but the parser would
                    choose whether to take notice of it or not, depending on
                    what it was doing. So switching back into indent-based
                    parsing in the middle of a bracketed expression wouldn't
                    be a problem.

                    --
                    Greg Ewing, Computer Science Dept,
                    University of Canterbury,
                    Christchurch, New Zealand


                    Comment

                    • Matthew Danish

                      Re: Python syntax in Lisp and Scheme

                      On Wed, Oct 08, 2003 at 03:59:19PM -0400, David Mertz wrote:[color=blue]
                      > |Come on. Haskell has a nice type system. Python is an application of
                      > |Greespun's Tenth Rule of programming.
                      > Btw. This is more nonsense. HOFs are not a special Lisp thing. Haskell
                      > does them much better, for example... and so does Python.[/color]

                      Wow. The language with the limited lambda form, whose Creator regrets
                      including in the language, is ... better ... at HOFs?

                      You must be smoking something really good.

                      --
                      ; Matthew Danish <mdanish@andrew .cmu.edu>
                      ; OpenPGP public key: C24B6010 on keyring.debian. org
                      ; Signed or encrypted mail welcome.
                      ; "There is no dark side of the moon really; matter of fact, it's all dark."

                      Comment

                      • David Mertz

                        Re: Python syntax in Lisp and Scheme

                        Matthew Danish <mdanish@andrew .cmu.edu> wrote previously:
                        |On Wed, Oct 08, 2003 at 03:59:19PM -0400, David Mertz wrote:
                        |> |Come on. Haskell has a nice type system. Python is an application of
                        |> |Greespun's Tenth Rule of programming.
                        |> Btw. This is more nonsense. HOFs are not a special Lisp thing. Haskell
                        |> does them much better, for example... and so does Python.

                        |Wow. The language with the limited lambda form, whose Creator regrets
                        |including in the language, is ... better ... at HOFs?
                        |You must be smoking something really good.

                        I guess a much better saying than Greenspun's would be something like:
                        "Those who know only Lisp are doomed to repeat it (whenver they look at
                        another language)." It does a better job of getting at the actual
                        dynamic.

                        People who know something about languages that are NOT Lisp know that
                        there is EXACTLY ZERO relation between lambda forms and HOFs. Well, OK,
                        I guess you couldn't have playful Y combinators if every function has a
                        name... but there's little loss there.

                        In point of fact, Python could completely eliminate the operator
                        'lambda', and remain exactly as useful for HOFs. Some Pythonistas seem
                        to want this, and it might well happen in Python3000. It makes no
                        difference... the alpha and omega of HOFs is that functions are first
                        class objects that can be passed and returned. Whether they happen to
                        have names is utterly irrelevant, anonymity is nothing special.

                        Haskell could probably get rid of anonymous functions even more easily.
                        It won't, there's no sentiment for that among Haskell programmers. But
                        there is not conceptual problem in Haskell with replacing every lambda
                        (more nicely spelled "\" in that language) with a 'let' or 'where'.

                        Yours, David...

                        --
                        mertz@ _/_/_/_/ THIS MESSAGE WAS BROUGHT TO YOU BY: \_\_\_\_ n o
                        gnosis _/_/ Postmodern Enterprises \_\_
                        ..cx _/_/ \_\_ d o
                        _/_/_/ IN A WORLD W/O WALLS, THERE WOULD BE NO GATES \_\_\_ z e


                        Comment

                        • Matthew Kennedy

                          Re: Python syntax in Lisp and Scheme

                          Alex Martelli <aleaxit@yahoo. com> writes:

                          [...]
                          [color=blue]
                          >
                          > Without macros, when you see you want to design a special-purpose
                          > language you are motivated to put it OUTSIDE your primary language,
                          > and design it WITH its intended users, FOR its intended purposes, which
                          > may well have nothing at all to do with programming. You parse it with a
                          > parser (trivial these days, trivial a quarter of a century ago), and off you
                          > go.[/color]

                          ....and off I go. A parser for our new DSL syntax is one thing, but
                          now I'll need a compiler as well, a symbolic debugger understanding
                          the new syntax would be nice, and perhaps an interactive environment
                          (interpreter) would be helpful. If we get time (ha!), lets create an
                          tools to edit the new syntax.

                          Seems like a lot of work.

                          I think I'll stay within Lisp and build the language up to problem
                          just as Paul Graham describes in On Lisp[1]. That way I get all of
                          the above for free and in much less time.

                          Footnotes:
                          [1] http://www.paulgraham.com/onlisp.html


                          --
                          Now, my ENTIRE LIFE is flashing before my EYES as I park my DODGE
                          DART in your EXXON service area for a COMPLETE LUBRICATION!!

                          Comment

                          • prunesquallor@comcast.net

                            Re: Python syntax in Lisp and Scheme

                            Alexander Schmolck <a.schmolck@gmx .net> writes:
                            [color=blue]
                            > prunesquallor@c omcast.net writes:[color=green]
                            >> Suppose I cut just one arm of a conditional. When I paste, it is
                            >> unclear whether I intend for the code after the paste to be part of
                            >> that arm, part of the else, or simply part of the same block.[/color]
                            >
                            > Sorry, I have difficulties understanding what exactly you mean again.[/color]

                            Let me back up here. I originally said:
                            [color=blue][color=green]
                            >> Every line in a block doesn't encode just its depth relative to the
                            >> immediately surrounding context, but its absolute depth relative to
                            >> the global context.[/color][/color]

                            To which you replied:
                            [color=blue]
                            > I really don't understand why this is a problem, since its trivial to
                            > transform python's 'globally context' dependent indentation block structure
                            > markup into into C/Pascal-style delimiter pair block structure markup.[/color]
                            [color=blue]
                            > Significantly, AFAICT you can easily do this unambiguously and *locally*, for
                            > example your editor can trivially perform this operation on cutting a piece of
                            > python code and its inverse on pasting (so that you only cut-and-paste the
                            > 'local' indentation).[/color]

                            Consider this python code (lines numbered for exposition):

                            1 def dump(st):
                            2 mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime = st
                            3 print "- size:", size, "bytes"
                            4 print "- owner:", uid, gid
                            5 print "- created:", time.ctime(ctim e)
                            6 print "- last accessed:", time.ctime(atim e)
                            7 print "- last modified:", time.ctime(mtim e)
                            8 print "- mode:", oct(mode)
                            9 print "- inode/dev:", ino, dev
                            10
                            11 def index(directory ):
                            12 # like os.listdir, but traverses directory trees
                            13 stack = [directory]
                            14 files = []
                            15 while stack:
                            16 directory = stack.pop()
                            17 for file in os.listdir(dire ctory):
                            18 fullname = os.path.join(di rectory, file)
                            19 files.append(fu llname)
                            20 if os.path.isdir(f ullname) and not os.path.islink( fullname):
                            21 stack.append(fu llname)
                            22 return files

                            This code is to provide verisimilitude, not to actually run. I wish
                            to show that local information is insufficient for cutting and pasting
                            under some circumstances.

                            If we were to cut lines 18 and 19 and to insert them between lines
                            4 and 5, we'd have this result:

                            3 print "- size:", size, "bytes"
                            4 print "- owner:", uid, gid
                            18 fullname = os.path.join(di rectory, file)
                            19 files.append(fu llname)
                            5 print "- created:", time.ctime(ctim e)
                            6 print "- last accessed:", time.ctime(atim e)

                            Where we can clearly see that the pasted code is at the wrong
                            indentation level. It is also clear that in this case, the
                            editor could easily have determined the correct indentation.

                            But let us consider cutting lines 6 and 7 and putting them
                            between lines 21 and 22. We get this:

                            15 while stack:
                            16 directory = stack.pop()
                            17 for file in os.listdir(dire ctory):
                            18 fullname = os.path.join(di rectory, file)
                            19 files.append(fu llname)
                            20 if os.path.isdir(f ullname) and not os.path.islink( fullname):
                            21 stack.append(fu llname)
                            6 print "- last accessed:", time.ctime(atim e)
                            7 print "- last modified:", time.ctime(mtim e)
                            22 return files

                            But it is unclear whether the intent was to be outside the while,
                            or outside the for, or part of the if. All of these are valid:

                            15 while stack:
                            16 directory = stack.pop()
                            17 for file in os.listdir(dire ctory):
                            18 fullname = os.path.join(di rectory, file)
                            19 files.append(fu llname)
                            20 if os.path.isdir(f ullname) and not os.path.islink( fullname):
                            21 stack.append(fu llname)
                            6 print "- last accessed:", time.ctime(atim e)
                            7 print "- last modified:", time.ctime(mtim e)
                            22 return files

                            15 while stack:
                            16 directory = stack.pop()
                            17 for file in os.listdir(dire ctory):
                            18 fullname = os.path.join(di rectory, file)
                            19 files.append(fu llname)
                            20 if os.path.isdir(f ullname) and not os.path.islink( fullname):
                            21 stack.append(fu llname)
                            6 print "- last accessed:", time.ctime(atim e)
                            7 print "- last modified:", time.ctime(mtim e)
                            22 return files

                            15 while stack:
                            16 directory = stack.pop()
                            17 for file in os.listdir(dire ctory):
                            18 fullname = os.path.join(di rectory, file)
                            19 files.append(fu llname)
                            20 if os.path.isdir(f ullname) and not os.path.islink( fullname):
                            21 stack.append(fu llname)
                            6 print "- last accessed:", time.ctime(atim e)
                            7 print "- last modified:", time.ctime(mtim e)
                            22 return files

                            Now consider this `pseudo-equivalent' parenthesized code:

                            1 (def dump (st)
                            2 (destructuring-bind (mode ino dev nlink uid gid size atime mtime ctime) st
                            3 (print "- size:" size "bytes")
                            4 (print "- owner:" uid gid)
                            5 (print "- created:" (time.ctime ctime))
                            6 (print "- last accessed:" (time.ctime atime))
                            7 (print "- last modified:" (time.ctime mtime))
                            8 (print "- mode:" (oct mode))
                            9 (print "- inode/dev:" ino dev)))
                            10
                            11 (def index (directory)
                            12 ;; like os.listdir, but traverses directory trees
                            13 (let ((stack directory)
                            14 (files '()))
                            15 (while stack
                            16 (setq directory (stack-pop))
                            17 (dolist (file (os-listdir directory))
                            18 (let ((fullname (os-path-join directory file)))
                            19 (push fullname files)
                            20 (if (and (os-path-isdir fullname) (not (os-path-islink fullname)))
                            21 (push fullname stack)))))
                            22 files))

                            If we cut lines 6 and 7 with the intent of inserting them
                            in the vicinity of line 21, we have several options (as in python),
                            but rather than insert them incorrectly and then fix them, we have
                            the option of inserting them into the correct place to begin with.
                            In the line `(push fullname stack)))))', there are several close
                            parens that indicate the closing of the WHILE, DOLIST, LET, and IF,
                            assuming we wanted to include the lines in the DOLIST, but not
                            in the LET or IF, we'd insert here:
                            V
                            21 (push fullname stack))) ))

                            The resulting code is ugly:

                            11 (def index (directory)
                            12 ;; like os.listdir, but traverses directory trees
                            13 (let ((stack directory)
                            14 (files '()))
                            15 (while stack
                            16 (setq directory (stack-pop))
                            17 (dolist (file (os-listdir directory))
                            18 (let ((fullname (os-path-join directory file)))
                            19 (push fullname files)
                            20 (if (and (os-path-isdir fullname) (not (os-path-islink fullname)))
                            21 (push fullname stack)))
                            6 (print "- last accessed:" (time.ctime atime))
                            7 (print "- last modified:" (time.ctime mtime))))
                            22 files))

                            But it is correct.

                            (Incidentally inserting at that point is easy: you move the cursor over
                            the parens until the matching one at the beginning of the DOLIST begins
                            to blink. At this point, you know that you are at the same syntactic level
                            as the dolist.)
                            [color=blue][color=green][color=darkred]
                            >> >> The fact that the information is replicated, and that there is nothing
                            >> >> but programmer discipline keeping it consistent is a source of errors.[/color][/color][/color]

                            Let me expand on this point. The lines I cut are very similar to each
                            other, and very different from the lines where I placed them. But
                            suppose they were not, and I had ended up with this:

                            19 files.append(fu llname)
                            20 if os.path.isdir(f ullname) and not os.path.islink( fullname):
                            21 stack.append(fu llname)
                            6 print "- last accessed:", time.ctime(atim e)
                            7 print "- last modified:", time.ctime(mtim e)
                            22 print "- copacetic"
                            23 return files

                            Now you can see that lines 6 and 7 ought to be re-indented, but line 22 should
                            not. It would be rather easy to either accidentally group line seven with
                            line 22, or conversely line 22 with line 7.
                            [color=blue][color=green][color=darkred]
                            >> > Sure there is. Your editor and immediate visual feedback (no need to remember
                            >> > to reindent after making the semantic changes).[/color]
                            >>
                            >> `immediate visual feedback' = programmer discipline
                            >> Laxness at this point is a source of errors.[/color]
                            >
                            > You got it backwards.
                            > Not forgetting to press 'M-C-\' = programmer discipline.
                            > Laxness at this point is a source of errors.[/color]

                            Forgetting to indent properly in a lisp program does not yield
                            erroneous code.
                            [color=blue]
                            > And indeed, people *do* have to be educated not to be lax when editing lisp -
                            > newbies frequently get told in c.l.l or c.l.s that they should have reindented
                            > their code because then they would have seen that they got their parens mixed
                            > up.[/color]

                            This is correct. But what is recommended here is to use a simple tool to
                            enhance readability and do a trivial syntactic check.
                            [color=blue]
                            > OTOH, if you make an edit in python the result of this edit is immediately
                            > obvious -- no mismatch between what you think it means and what your computer
                            > thinks it means and thus no (extra) programmer discipline required.[/color]

                            Would that this were the case. Lisp code that is poorly indented will still
                            run. Python code that is poorly indented will not. I have seen people write
                            lisp code like this:

                            (defun factorial (x)
                            (if (> x 0)
                            x
                            (*
                            (factorial (- x 1))
                            x
                            )))

                            I still tell them to re-indent it. A beginner writing python in this manner
                            would be unable to make the code run.
                            [color=blue]
                            > Of course you need *some* basic level of discipline to not screw up your
                            > source code when making edits -- but for all I can see at the moment (and know
                            > from personal experience) it is *less* than what's required when you edit lisp
                            > (I have provided a suggested way to edit this particular example in emacs for
                            > python in my previous post -- you haven't provided an analoguous editing
                            > operation for lisp with an explanation why it would be less error-prone)).[/color]

                            Ok. For any sort of semantic error (one in which a statement is
                            associated with an incorrect group) one could make in python, there is
                            an analagous one in lisp, and vice versa. This is simply because both
                            have unambiguous parse trees.

                            However, there is a class of *syntactic* error that is possible in
                            python, but is not possible in lisp (or C or any language with
                            balanced delimiters). Moreover, this class of error is common,
                            frequently encountered during editing, and it cannot be detected
                            mechanically.

                            Consider this thought experiment: pick a character (like parenthesis
                            for example) go to a random line in a lisp file and insert four of them.
                            Is the result syntactically correct? No. Could a naive user find them?
                            Trivially. Could I program Emacs to find them? Sure.

                            Now go to a random line in a python file and insert four spaces. Is
                            the result syntactically correct? Likely. Could a naive user find
                            them? Unlikely. Could you write a program to find them? No.

                            Delete four adjacent parens in a Lisp file. Will it still compile? No.
                            Will it even be parsable? No.

                            Delete four adjacent spaces in a Python file. Will it still compile?
                            Likely.
                            [color=blue][color=green][color=darkred]
                            >> >> >> Yet the visual representation is not only identical between all of these, it
                            >> >> >> cannot even be displayed.
                            >> >> >
                            >> >> > I don't understand what you mean. Could you maybe give a concrete example of
                            >> >> > the information that can't be displayed?
                            >> >>
                            >> >> Sure. Here are five parens ))))) How much whitespace is there here:
                            >> >
                            >> > 10 spaces (which BTW I counted in emacs in just the same way that I'd count a
                            >> > similar number of parens) -- but what has counting random trailing whitespace
                            >> > got to do with anything?[/color]
                            >>
                            >> It is simply an illustration that there is no obvious glyph associated
                            >> with whitespace, and you wanted a concrete example of something that can't
                            >> be displayed.[/color]
                            >
                            > No, I didn't want just *any* example of something that can't be displayed; I
                            > wanted an example of something that can't be displayed and is *pertinent* to
                            > our discussion (based on the Quinean assumption that you wouldn't have brought
                            > up "things that can't be displayed" if they were completely besides the
                            > point).[/color]

                            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=blue]
                            > me:[color=green][color=darkred]
                            >> >> > People can't "read" '))))))))'.[/color][/color]
                            > [more dialog snipped][color=green]
                            >> I cannot read Abelson and Sussman's minds, but neither of them are
                            >> ignorant of the vast variety of computer languages in the world.
                            >> Nonetheless, given the opportunity to choose any of them for
                            >> exposition, they have chosen lisp. Sussman went so far as to
                            >> introduce lisp syntax into his book on classical mechanics.[/color]
                            >
                            > Well the version of SICM *I've* seen predeominantly seems to use (infixy) math
                            > notation, so maybe Sussman is a little less confident in the perspicuousness
                            > of his brainchild than you (also cf. Iverson)?[/color]

                            Perhaps you are looking at the wrong book. The full title is
                            `Structure and Interpretation of Classical Mechanics' by Gerald Jay
                            Sussman and Jack Wisdom with Meinhard E. Mayer, and it is published by
                            MIT Press. Every computational example in the book, and there are
                            many, is written in Scheme.

                            Sussman is careful to separate the equations of classical mechanics
                            from the *implementation * of those equations in the computer, the
                            former are written using a functional mathematical notation similar to
                            that used by Spivak, the latter in Scheme. The two appendixes give
                            the details. Sussman, however, notes ``For very complicated
                            expressions the prefix notation of Scheme is often better''
                            [color=blue]
                            > I don't personally think (properly formated) lisp reads that badly at all
                            > (compared to say C++ or java) and you sure got the word-seperators right. But
                            > to claim that using lisp-style parens are in better conformance with the
                            > dictum above than python-style indentation frankly strikes me as a bit silly
                            > (whatever other strengths and weaknesses these respective syntaxes might
                            > have).[/color]

                            And where did I claim that? You originally stated:
                            [color=blue]
                            > Still, I'm sure you're familiar with the following quote (with which I most
                            > heartily agree):
                            >
                            > "[P]rograms must be written for people to read, and only incidentally for
                            > machines to execute."
                            >
                            > People can't "read" '))))))))'.[/color]

                            Quoting Sussman and Abelson as a prelude to stating that parenthesis are
                            unreadable is hardly going to be convincing to anyone.
                            [color=blue][color=green]
                            >> Obviously the indentation.
                            >> But I'd notice the mismatch.[/color]
                            >
                            > (Hmm, you or emacs?)[/color]

                            Does it matter?
                            [color=blue][color=green]
                            >> If I gave you a piece of python code jotted down on paper that (as these
                            >> hypothetical examples usually are) for some reason was of vital importance
                            >> but I accidentally misplaced the indentation -- how would you know?[/color]
                            >
                            > Excellent point. But -- wait! Were it Lisp, how would I know that you didn't
                            > intend e.g.
                            >
                            > (if (bar watz) foo)
                            >
                            > instead of
                            >
                            > (if (bar) watz foo)[/color]

                            You are presupposing *two* errors of two different kinds here: the
                            accidental inclusion of an extra parenthesis after bar *and* the
                            accidental omission of a parenthesis after watz.

                            The kind of error I am talking about with Python code is a single
                            error of either omission or inclusion.
                            [color=blue]
                            > Moral: I really think your (stereoptypical ) argument that the possibility of
                            > inconsistency between "user interpretation" and "machine interpretation" of a
                            > certain syntax is a feature (because it introduces redundancy that can can be
                            > used for error detection) requires a bit more work.[/color]

                            I could hardly care less.

                            Comment

                            • prunesquallor@comcast.net

                              Re: Python syntax in Lisp and Scheme

                              Marcin 'Qrczak' Kowalczyk <qrczak@knm.org .pl> writes:
                              [color=blue]
                              > Note that Lisp and Scheme have a quite unpleasant anonymous function
                              > syntax, which induces a stronger tension to macros than in e.g. Ruby or
                              > Haskell.[/color]

                              Good grief!

                              Unpleasant is the inner classes needed to emulate anonymous functions
                              in Java.

                              Comment

                              • prunesquallor@comcast.net

                                Re: Python syntax in Lisp and Scheme

                                Raffael Cavallaro <raffaelcavalla ro@junk.mail.me .not.mac.com> writes:
                                [color=blue]
                                > In article <pan.2003.10.13 .11.11.45.54187 9@knm.org.pl>,
                                > Marcin 'Qrczak' Kowalczyk <qrczak@knm.org .pl> wrote:
                                >[color=green]
                                >> Note that Lisp and Scheme have a quite unpleasant anonymous function
                                >> syntax, which induces a stronger tension to macros than in e.g. Ruby or
                                >> Haskell.[/color]
                                >
                                > Actually, I think that any anonymous function syntax is undesirable. I
                                > think code is inerently more readable when functions are named,
                                > preferably in a descriptive fashion.[/color]

                                So it'd be even *more* readable if every subexpression were named as
                                well. Just write your code in A-normal form.
                                [color=blue]
                                > I think it is the mark of functional cleverness that people's code is
                                > filled with anonymous functions. These show you how the code is doing
                                > what it does, not what it is doing.[/color]

                                I disagree. This:

                                (map 'list (lambda (x) (+ x offset)) some-list)

                                is clearer than this:

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


                                Comment

                                Working...