merits of Lisp vs Python

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • metawilm@gmail.com

    Re: CLPython (was Re: merits of Lisp vs Python)

    Paul Rubin wrote:
    I thought it was of some interest though I'm a little surprise by the
    choice of CL rather than Scheme as a target.
    In many aspects Python is a subset of CL. In CLPython, exceptions are
    Lisp conditions with a custom metaclass (strictly spoken not portable
    CL), Python (meta)classes are CLOS classes, methods are implemented
    using hashtables and functions and CLOS generic functions, strings and
    numbers have direct equivalents, hash tables implement dicts, Python
    functions are funcallable CLOS instances, tuples and lists are Lisp
    lists and vectors, generators are closures. Thus a great part of
    implementing CLPython consisted of connecting already existing dots. I
    found that quite amazing.
    I'm still not sure about the mapping of Python strings to Lisp strings.
    What happens with the following in CLPython?
    >
    a = 'hello'
    a[0] = 'H' # attempt to change first letter to upper case
    As CLPython mirrors Python semantics, this results in a TypeError. The
    internal representation of an immutable Python string is a mutable Lisp
    string, but there is no way you can actually modify it from within
    CLPython.

    Now in some cases modifying strings is dangerous (e.g. when stored in
    an instance dict to represent an attribute), but in other cases it can
    be completely safe. And modifying strings is a normal Lisp feature, so
    it sounds strange to disallow it at all times. Maybe there should be a
    way for the user to declare that he knows what he is doing, and does
    not want the Python implementation to be "crippled" w.r.t. the host
    language. Normally you start the CLPython interpreter using (repl);
    maybe something like this would allow dangerous statements:

    (let ((*strict-python-semantics* nil))
    (repl))

    Oh, and there is actually one way to modify Python strings in the
    interpreter, namely using Lisp commands:

    PYTHON(12): (repl)
    [CLPython -- type `:q' to quit, `:help' for help]
    >>s = "abc"
    'abc'
    >> (setf (aref _ 0) #\x)
    #\x
    >>s
    'xbc'
    >>type(s)
    #<class PY-STRING @ #x10575342>
    >>type(s) == str
    1
    >>s
    'xbc'
    >> (inspect _)
    A NEW simple-string (3) "xbc" @ #x11548f6a
    0-The character #\x [#x0078]
    1-The character #\b [#x0062]
    2-The character #\c [#x0063]
    [1i] PYTHON(13): :ptl
    >>>

    Comment

    • Neil Cerutti

      Re: merits of Lisp vs Python

      On 2006-12-15, André Thieme
      <address.good.u ntil.2006.dec.2 2@justmail.dewr ote:
      In Lisp it is like an IF and represents exactly what we think.
      IF in Lisp:
      (if expr
      (then-part)
      (else-part))
      >
      nif in Lisp:
      (nif expr
      (positive-part)
      (zero-part)
      (negative-part))
      >
      It looks as if it were a construct directly built into Lisp. If
      one wants one could even add some additional syntax, so that it
      looks like:
      (nif expr
      positive:
      (foo1)
      (foo2)
      zero:
      (foo3)
      negative:
      (foo4))
      >
      If you regard that idea nonsense then I suggest you to not use
      Rubys if-statement anymore. But instead program your own
      version "RubyIF" so that in future you have to pass all code
      inside blocks to your RubyIF function. If you *really* think
      that the Lisp savings are not worth it, then you would begin
      with my suggestion today.
      I don't know how to build a house. It doesn't make me want to
      live in a cave. ;-)

      --
      Neil Cerutti
      The third verse of Blessed Assurance will be sung without musical
      accomplishment. --Church Bulletin Blooper

      Comment

      • =?ISO-8859-1?Q?Andr=E9_Thieme?=

        Re: merits of Lisp vs Python

        greg schrieb:
        >Adding parentheses ... all this is a
        >burden specific to Python.
        >
        As opposed to Lisp, where all you have to do is
        use parentheses... oh, er...
        Lisp has no parens. An editor could support a mode where code
        is displayed in written in trees. There wouldn't be a single
        paren.

        >By the way, you guys seem fixate on the parentheses of Lisp without
        >having the experience
        >
        I don't know about the other Pythonistas in this
        discussion, but personally I do have experience with
        Lisp, and I understand what you're saying. I have
        nothing against Lisp parentheses, I just don't agree
        that the Lisp way is superior to the Python way in
        all respects, based on my experience with both.
        Lisp is not superior in all respects. As soon you decide to use a
        language you decide against other features.
        Python is especially strong as a scripting language as that is the
        domain of it.


        André
        --

        Comment

        • William James

          Re: merits of Lisp vs Python

          André Thieme wrote:
          William James schrieb:
          >
          def nif num, pos, zero, neg
          send( num>0 ? pos : (num==0 ? zero : neg) )
          end
          >
          btw, your nif body is built out of 13 tokens, so more
          complicated than the Python version.
          >

          André
          --
          def nif num, *args
          send args[ 1 + (0 <=num) ]
          end

          Comment

          • =?ISO-8859-1?Q?Andr=E9_Thieme?=

            Re: merits of Lisp vs Python

            William James schrieb:
            André Thieme wrote:
            >William James schrieb:
            >>
            >>def nif num, pos, zero, neg
            >> send( num>0 ? pos : (num==0 ? zero : neg) )
            >>end
            >btw, your nif body is built out of 13 tokens, so more
            >complicated than the Python version.
            >>
            >>
            >André
            >--
            >
            def nif num, *args
            send args[ 1 + (0 <=num) ]
            end

            send
            |
            |
            [ ]
            / \
            / \
            / \
            args +
            / \
            / \
            1 ()
            |
            |
            <=>
            / \
            / \
            0 num

            Okay, 9. Now it is at the complexity level of the Lisp
            and Python example.
            But how would a call to nif look like?
            I hope it doesn't involve an extra operator to group the
            args into a list or tuple. That would add more complexity to
            each call - so one should better have a slightly more complex
            nif because that exists only one time.

            And can this nif now handle any input values, such as strings
            or function objects?

            The <=is called cmp in Python.
            In Lisp it is called signum. The Lisp function has in general the
            advantage that it keeps type information.
            While Pythons cmp returns either -1, 0 or 1 the Lisp version can
            also return -1.0 and 1.0 and also complex numbers:
            (signum #C(10 4)) = #C(0.9284767 0.37139067)


            André
            --

            Comment

            • William James

              Re: merits of Lisp vs Python

              André Thieme wrote:
              Paul Rubin schrieb:
              André Thieme <address.good.u ntil.2006.dec.2 2@justmail.dewr ites:
              >and the Lisp version has only 9:
              >nth, 1+, truncate, signum, num, list, pos, zero, neg
              >
              Oh come on, you have to count the parentheses too.
              >
              We could define hundreds of way how to count tokens.
              But see the program as a tree:
              >
              nth
              / \
              / \
              / \
              1+ list
              | / | \
              | / | \
              truncate pos zero neg
              |
              |
              signum
              |
              |
              num
              >
              And I didn't count the indentation level and \n in Python code.
              Why should I? They are editor commands.
              >
              >
              Anyway, token count doesn't mean much, you have to instead go by the
              user's cognitive effort in dealing with the prefix notation etc.,
              >
              How complicated ss it to say "cmp(a, b)" compared to "a cmp b"?
              After a few days writing Lisp code your brain specializes on that
              style. Arabian countries write from right to left. They seem to have
              no problem to use what they know.
              I admit that I am used to write +, -, * and / infix, because I were
              trained in that thinking since day 1 in school.
              In our example program there was only 1+ compared to ".. + 1" which
              looks "alien" to untrained people.
              If a program uses extensive math we can get syntax for Lisp that is
              even more pleasant to read than Pythons:
              17a + x³-x²
              >
              >
              >
              which isn't purely a matter of token count. And if (+ 2 3) were
              really as easy to read as 2+3, mathematics would have been written
              that way all along.
              >
              Mathmaticians invented prefix notation and they use it regularily.
              They inventey operators that wrap around their arguments, as one can
              see here: http://www.mathe-trainer.com/formel/?SN=&t=1
              >
              Or think of indices, etc.
              >
              >
              >
              >TypeError: 'str' object is not callable
              >I don't know how I can fix that. Maybe you could tell me.
              >
              >>>lazy_nif(0 , lambda: "p", lambda: "z", lambda: "n")
              >
              Yes, that works. And that's why I wanted to make it a macro.
              Now you are essentially doing what I did in my first Lisp version.
              While this works it is farer away from what we think.
              >
              (nif 0 "p" "z" "n")
              (nif 0 #'p #'z #'n)
              are exactly what one thinks.
              For this reason "if" is implemented as a keyword in Python.
              It allows you to give code as a block instead of embedding it into
              a lambda or a def (which even needs a name).
              >
              >
              And we might go further (again with an easy Graham example).
              See this typical pattern:
              >
              result = timeConsumingCa lculation()
              if result:
              use(result)
              >
              We need this ugly temporary variable result to refer to it.
              If we could use the anaphor[1] "it" that could make situations like
              these more clean.
              >
              Imagine Python would have an "anaphoric if", "aif". Then:
              >
              aif timeConsumingCa lculation():
              use(it)
              >
              Many Lispers might have this as a macro in their toolbox after some
              time of coding or after reading Graham.
              A short three-liner in Lisp and I can really say:
              >
              (aif (timeConsumingC alculation)
              (use it))
              >
              How would you solve this in Python?
              You could embed it inside a lambda and must somehow make the
              variable "it" visible in it, because in the context of aif this
              "it" gets bound to the result.
              In Ruby:

              def aif val
              yield val if val
              end

              def complex_calc n
              if n % 2 == 1
              n**n
              else
              nil
              end
              end

              aif( complex_calc( 9 ) ) {|x| puts "hello, #{x}"}
              aif( complex_calc( 8 ) ) {|x| puts "hello, #{x}"}

              --- output -----
              hello, 387420489

              Comment

              • William James

                Re: merits of Lisp vs Python

                André Thieme wrote:
                William James schrieb:
                André Thieme wrote:
                William James schrieb:
                >
                >def nif num, pos, zero, neg
                > send( num>0 ? pos : (num==0 ? zero : neg) )
                >end
                btw, your nif body is built out of 13 tokens, so more
                complicated than the Python version.
                >
                >
                André
                --
                def nif num, *args
                send args[ 1 + (0 <=num) ]
                end
                >
                >
                send
                |
                |
                [ ]
                / \
                / \
                / \
                args +
                / \
                / \
                1 ()
                |
                |
                <=>
                / \
                / \
                0 num
                >
                Okay, 9. Now it is at the complexity level of the Lisp
                and Python example.
                But how would a call to nif look like?
                A call is unchanged:

                [0, 2.5, -8].map{|x| nif x, :p, :z, :n}

                I hope it doesn't involve an extra operator to group the
                args into a list or tuple. That would add more complexity to
                each call - so one should better have a slightly more complex
                nif because that exists only one time.
                >
                And can this nif now handle any input values, such as strings
                or function objects?
                It handles only symbols.
                I suppose this can handle anything ...

                p = proc {
                puts "very positive"
                "positive" }
                z = proc {
                puts "no no"
                "zero" }
                n = proc {
                puts "very negative"
                "negative" }
                def nif num, *args
                args[ 1 + (0 <=num) ].call
                end

                [0, 2.5, -8].map{|x| nif x, p, z, n}
                puts [0, 2.5, -8].map{|x| nif x,
                proc{'zero'}, proc{'plus'}, proc{'minus'}}

                .... if you wrap everything in a proc (lambda).

                Comment

                • =?ISO-8859-1?Q?Andr=E9_Thieme?=

                  Re: merits of Lisp vs Python

                  mikael.jansson@ gmail.com schrieb:
                  William James schrieb:
                  >>How would you solve this in Python?
                  >>You could embed it inside a lambda and must somehow make the
                  >>variable "it" visible in it, because in the context of aif this
                  >>"it" gets bound to the result.In Ruby:
                  >def aif val
                  > yield val if val
                  >end
                  >>
                  >def complex_calc n
                  > if n % 2 == 1
                  > n**n
                  > else
                  > nil
                  > end
                  >end
                  >>
                  >aif( complex_calc( 9 ) ) {|x| puts "hello, #{x}"}
                  >aif( complex_calc( 8 ) ) {|x| puts "hello, #{x}"}
                  >>
                  >--- output -----
                  >hello, 387420489
                  >>
                  Okay, so it's certainly _doable_. I think the question is more if it's
                  usable. Regular if:s don't like that in Ruby/Python/similar, and adding
                  such a construct would mean extending the syntax.
                  >
                  In Lisp, all (well, almost) functions are equal, so an (if ...) would
                  look the same like the (aif ...). I think that's the point here.
                  Exactly that is the point.
                  *Of course* it is doable.
                  And what William shows us is maybe one of the best solutions
                  in Ruby. He used advanced abstractions that made it possible.
                  The thing with most (if not all) programming languages other than Lisp
                  is: these abstractions are leaky.
                  They have a low level knowledge leak. Users of aif need to know how to
                  pass in arguments. As you see he had do embed the code that needs execution
                  into a block (anon function) and then use this special syntax for x.


                  André
                  --

                  Comment

                  • Slawomir Nowaczyk

                    Re: merits of Lisp vs Python

                    On Fri, 15 Dec 2006 17:21:12 +0100
                    André Thieme <address.good.u ntil.2006.dec.2 2@justmail.dewr ote:

                    #And we might go further (again with an easy Graham example).
                    #See this typical pattern:
                    #>
                    #result = timeConsumingCa lculation()
                    #if result:
                    # use(result)
                    #>
                    #We need this ugly temporary variable result to refer to it.
                    #If we could use the anaphor[1] "it" that could make situations like
                    #these more clean.
                    #>
                    #Imagine Python would have an "anaphoric if", "aif". Then:
                    #>
                    #aif timeConsumingCa lculation():
                    # use(it)

                    I would spell the above like this:

                    def timeConsumingCa lculation():
                    pass
                    def useit(it):
                    pass

                    def aif(first,secon d):
                    res = first()
                    if res:
                    second(res)

                    aif(timeConsumi ngCalculation,u seit)

                    Sure, it requires me to define function useit instead of embedding the
                    code in aif call, but that has never been a problem for me: in reality,
                    the code I would want to execute would be complex enough to warrant it's
                    own function anyway. Of course, YMMV.

                    --
                    Best wishes,
                    Slawomir Nowaczyk
                    ( Slawomir.Nowacz yk@cs.lth.se )

                    Real programmers can write assembly code in any language.

                    Comment

                    • William James

                      Re: merits of Lisp vs Python

                      André Thieme wrote:
                      mikael.jansson@ gmail.com schrieb:
                      William James schrieb:
                      >>How would you solve this in Python?
                      >>You could embed it inside a lambda and must somehow make the
                      >>variable "it" visible in it, because in the context of aif this
                      >>"it" gets bound to the result.In Ruby:
                      >def aif val
                      > yield val if val
                      >end
                      >>
                      >def complex_calc n
                      > if n % 2 == 1
                      > n**n
                      > else
                      > nil
                      > end
                      >end
                      >>
                      >aif( complex_calc( 9 ) ) {|x| puts "hello, #{x}"}
                      >aif( complex_calc( 8 ) ) {|x| puts "hello, #{x}"}
                      >>
                      >--- output -----
                      >hello, 387420489
                      >>
                      Okay, so it's certainly _doable_. I think the question is more if it's
                      usable. Regular if:s don't like that in Ruby/Python/similar, and adding
                      such a construct would mean extending the syntax.
                      >
                      In Lisp, all (well, almost) functions are equal, so an (if ...) would
                      look the same like the (aif ...). I think that's the point here.
                      >
                      Exactly that is the point.
                      *Of course* it is doable.
                      And what William shows us is maybe one of the best solutions
                      in Ruby. He used advanced abstractions that made it possible.
                      The thing with most (if not all) programming languages other than Lisp
                      is: these abstractions are leaky.
                      They have a low level knowledge leak. Users of aif need to know how to
                      pass in arguments. As you see he had do embed the code that needs execution
                      into a block (anon function) and then use this special syntax for x.
                      >
                      >
                      André
                      --
                      I may have tried too hard. The simpler way is usually better.
                      No aif() is needed:

                      if x = complex_calc( 9 )
                      puts "hello, #{x}"
                      end

                      Comment

                      • Paul Rubin

                        Re: merits of Lisp vs Python

                        André Thieme <address.good.u ntil.2006.dec.2 2@justmail.dewr ites:
                        And I didn't count the indentation level and \n in Python code.
                        Why should I? They are editor commands.
                        No they're part of Python syntax. A change in indent level is
                        recognized by Python's lexical scanner as a token and you should count
                        it. You wouldn't count the indent and \n separately though.
                        Anyway, token count doesn't mean much, you have to instead go by the
                        user's cognitive effort in dealing with the prefix notation etc.,
                        >
                        How complicated ss it to say "cmp(a, b)" compared to "a cmp b"?
                        It gets worse when the expressions are nested.
                        Imagine Python would have an "anaphoric if", "aif". Then:
                        >
                        aif timeConsumingCa lculation():
                        use(it)
                        Well, it's not really in the Pythonic style to add obscurity like
                        that, but you could certainly write something like:

                        def aif(func):
                        it = func()
                        if it: use(it)

                        aif(timeConsumi ngCalculation)
                        So in some languages that support functional programming one needs
                        to do extra work to get lazyness, while in Haskell one gets extra
                        work if one doesn't want it. But maybe someone can correct me here...
                        In Lisp one could build some features to get lazyness as well.
                        I think that is essentially correct. But it's not so easy to do extra
                        work to get Haskell-like laziness in languages that don't have it, not
                        because laziness itself is difficult, but non-lazy languages usually
                        end up giving up referential transparency.


                        Comment

                        • Paul Rubin

                          Re: merits of Lisp vs Python

                          André Thieme <address.good.u ntil.2006.dec.2 2@justmail.dewr ites:
                          Lisp has no parens. An editor could support a mode where code
                          is displayed in written in trees. There wouldn't be a single paren.
                          But there would be even more tokens, the lines going between the nodes
                          in the trees, for example.

                          Comment

                          • Paul Rubin

                            Re: CLPython (was Re: merits of Lisp vs Python)

                            metawilm@gmail. com writes:
                            a = 'hello'
                            a[0] = 'H' # attempt to change first letter to upper case
                            >
                            As CLPython mirrors Python semantics, this results in a TypeError. The
                            internal representation of an immutable Python string is a mutable Lisp
                            string, but there is no way you can actually modify it from within CLPython.
                            How do you manage that? The compiler can't check. Is there some kind
                            of special dispatch on the assignment statement instead of turning it
                            into a setf?

                            Comment

                            • =?ISO-8859-1?Q?Andr=E9_Thieme?=

                              Re: merits of Lisp vs Python

                              Paul Rubin schrieb:
                              André Thieme <address.good.u ntil.2006.dec.2 2@justmail.dewr ites:
                              >Lisp has no parens. An editor could support a mode where code
                              >is displayed in written in trees. There wouldn't be a single paren.
                              >
                              But there would be even more tokens, the lines going between the nodes
                              in the trees, for example.
                              These are painted by the editor.
                              I also don't count the number of pixels ouf of which a letter consists
                              as tokens. The nodes in the source tree can be one counting method
                              which a lot of people could accept.
                              For Python I also wouldn't count the number of spaces of indentation.


                              André
                              --

                              Comment

                              • Paul Rubin

                                Re: merits of Lisp vs Python

                                André Thieme <address.good.u ntil.2007.feb.0 5@justmail.dewr ites:
                                But there would be even more tokens, the lines going between the
                                nodes
                                in the trees, for example.
                                >
                                These are painted by the editor.
                                If you have to tell the editor where to put them, they are tokens.

                                Comment

                                Working...