Python syntax in Lisp and Scheme

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Alex Martelli

    Re: Python syntax in Lisp and Scheme

    Daniel P. M. Silva wrote:
    ...[color=blue]
    > You still can't add new binding constructs or safe parameterizatio ns like
    > a with_directory form:
    >
    > with_directory( "/tmp", do_something())
    >
    > Where do_something() would be evaluated with the current directory set to
    > " tmp" and the old pwd would be restored afterward (even in the event of
    > an exception).[/color]

    Right: you need to code this very differently, namely:
    with_directory( "/tmp", do_something)
    *deferring* the call to do_something to within the with_directory
    function. Python uses strict evaluation order, so if and when you
    choose to explicitly CALL do_something() it gets called,

    So, I would code:

    def with_directory( thedir, thefunc, *args, **kwds):
    pwd = os.getcwd()
    try: return thefunc(*args, **kwds)
    finally: os.chdir(pwd)

    this is of course a widespread idiom in Python, e.g. see
    unittest.TestCa se.assertRaises for example.

    The only annoyance here is that there is no good 'literal' form for
    a code block (Python's lambda is too puny to count as such), so you
    do have to *name* the 'thefunc' argument (with a 'def' statement --
    Python firmly separates statements from expressions).
    [color=blue]
    > Last year -- I think at LL2 -- someone showed how they added some sort of
    > 'using "filename": ' form to Python... by hacking the interpreter.[/color]

    A "using" statement (which would take a specialized object, surely not
    a string, and call the object's entry/normal-exit/abnormal-exit methods)
    might often be a good alternative to try/finally (which makes no provision
    for 'entry', i.e. setting up, and draws no distinction between normal
    and abnormal 'exits' -- often one doesn't care, but sometimes yes). On
    this, I've seen some consensus on python-dev; but not (yet?) enough on
    the details. Consensus is culturally important, even though in the end
    Guido decides: we are keen to ensure we all keep using the same language,
    rather than ever fragmenting it into incompatible dialects.

    [color=blue]
    > Some people use Python's hooks to create little languages inside Python
    > (eg. to change the meaning of instantiation), which are not free of
    > problems:
    >
    > class Object(object):
    > def __init__(this, *args, **kwargs):[/color]

    [invariably spelt as 'self', not 'this', but that's another issue]
    [color=blue]
    > this.rest = args
    > this.keys = kwargs
    >
    > def new_obj_id(coun t=[0]):
    > count[0] = count[0] + 1
    > return count[0]
    >
    > def tag_obj(obj, id):
    > obj.object_id = id
    > return obj
    >
    > def obj_id(obj): return obj.object_id
    >
    > type.__setattr_ _(Object, "__new__", staticmethod(la mbda type, *args:
    > tag_obj(object. __new__(type), new_obj_id())))[/color]
    ...[color=blue]
    > # forgot to check for this case...
    > print Object(foo="bar ")[/color]

    It's not an issue of "checking": you have written (in very obscure
    and unreadable fashion) a callable which you want to accept (and
    ignore) keyword arguments, but have coded it in such a way that it
    in fact refuses keyword arguments. Just add the **kwds after the
    *args. This bug is not really related to "little languages" at all:
    you might forget to specify arguments which you do want your callable
    to accept and ignore in a wide variety of other contexts, too.

    A small but important help to avoid such mistakes is to express
    your intentions more readably. Let's suppose the 'Object' class is
    externally defined (so we don't want change its metaclass, which would
    be a more usual approach in Python), that we know it does not
    implement a significant __new__ nor __slots__, and that we want to add
    to it the "tag all objects on creation" feechur, which must use/support
    the also-existing and specified functions new_obj_id (for generating
    new ids), tag_obj (to set them) and obj_id (to access them) -- each
    of these specs is significant (we'd probably code differently if any
    or all of them were changed).

    Given all this, the normal way to code this functionality in Python
    would be something like:

    def tagging_new(cls , *args, **kwds):
    new_object = object.__new__( cls)
    new_id = new_obj_id()
    return tag_obj(new_obj ect, new_id)
    Object.__new__ = staticmethod(ta gging_new)

    The use of "type.__setattr __(Object, "__new__", staticmethod(la mbda ..."
    in lieu of the elementarily simple "Object.__n ew__ = staticmethod(.. ."
    would be quite peculiar. The use of a complicated lambda instead of
    a simple def also decreases readability (and thus makes mistakes
    such as forgetting that the new __new__ must also accept and ignore
    **kwds more likely). Another helpful idiom is to name the first arg
    of staticmethod's as 'cls', NOT 'type' (which would cause confusion
    with the builtin 'type', often needed in similar contexts).

    Moreover, it is possible that the auxiliary functions new_obj_id and
    tag_obj were not externally specified, but, rather, coded ad hoc just
    to enable the new __new__ to be written as a lambda (i.e., within the
    strictures of Python's lambda -- just one expression, no statements).

    If that is the case, then they might also be easily refactored out, e.g.:

    class Tagger(object):
    def __init__(self):
    self.next_id = 0
    def tag_new(self, cls, *args, **kwds):
    new_object = object.__new__( cls)
    self.next_id += 1
    new_object.obje ct_id = self.next_id
    return new_object
    tagging_new = Tagger().tag_ne w
    Object.__new__ = staticmethod(ta gging_new)

    How best to subdivide the task "tag a new object" is debatable (since
    a new tag should never be generated except during tagging, I do prefer
    to have the generation of the tag and the affixion of the tag to an
    object as inseparable -- but in some cases one might surely prefer to
    have them separate from the __new__ so as to be able to tag already
    existing objects -- that would, of course, be easy to achieve). But
    the point is that the preferred way in Python to package up some state
    (particularly mutable state) and some behavior is within a class; the
    use of a mutable default argument in new_obj_id is non-idiomatic -- it
    seems better to make a class for the purpose. This has the advantage
    of grouping related state and behavior in ways that any Pythonista
    will immediately recognize (the general advantage of using any given
    language's idiomatic approach: by doing what readers expect you to do,
    you make your code more readable than by being original and creative).

    I have extracted the tag_new method of an instance of Tagger and
    named it tagging_new in the assumption that we may want to then use
    the SAME tagsequence for other classes as well (and may prefer to
    avoid doing so by e.g. "OtherClass.__n ew__ = Object.__new__" ). If
    that is not the case, then merging the last two lines into

    Object.__new__ = staticmethod(Ta gger().tag_new)

    would probably be preferable.


    Alex

    Comment

    • Pascal Costanza

      Re: Python syntax in Lisp and Scheme

      Terry Reedy wrote:[color=blue]
      > "Pascal Costanza" <costanza@web.d e> wrote in message
      > news:blu4q0$156 8$1@f1node01.rh rz.uni-bonn.de...
      >[color=green]
      >>What about dealing with an arbitrary number of filters?[/color]
      >
      >
      > [macro snipped]
      >
      > What about it? Using macros for somewhat simple functions stikes me
      > as overkill.[/color]

      You're right. The use of with-collectors makes it more appropriate to
      express it as a macro, but of course, one can use a simple function when
      you don't stick to with-collectors.
      [color=blue]
      >[color=green]
      >>An example:
      >>[color=darkred]
      >> > (predicate-collect '(-5 -4 -3 -2 -1 0 1 2 3 4 5)[/color]
      >> (function evenp)
      >> (lambda (n) (< n 0))
      >> (lambda (n) (> n 3)))
      >>(-4 -2 0 2 4)
      >>(-5 -3 -1)
      >>(5)
      >>(1 3)[/color]
      >
      >
      > In Python:
      >
      > def multisplit(seq, *preds):
      > predn = len(preds)
      > bins = [[] for i in range(predn+1)]
      > predpends = [(p,b.append) for (p,b) in zip(preds,bins)]
      > rpend = bins[predn].append
      > for item in seq:
      > for pred,pend in predpends:
      > if pred(item):
      > pend(item)
      > break
      > else: rpend(item)
      > return bins
      >
      > multisplit(rang e(-5,6), lambda i: not i%2, lambda i: i<0, lambda i:
      > i>3)
      >
      > [[-4, -2, 0, 2, 4], [-5, -3, -1], [5], [1, 3]][/color]

      For the sake of completeness, here is the Lisp version:

      (defun predicate-collect (list &rest predicates)
      (let ((table (make-hash-table))
      (preds (append predicates
      (list (constantly t)))))
      (dolist (elem list)
      (loop for pred in preds
      until (funcall pred elem)
      finally (push elem (gethash pred table))))
      (mapcar (lambda (pred)
      (nreverse (gethash pred table)))
      preds)))


      ? (predicate-collect
      '(-5 -4 -3 -2 -1 0 1 2 3 4 5)
      (function evenp)
      (lambda (n) (< n 0))
      (lambda (n) (> n 3)))

      ((-4 -2 0 2 4) (-5 -3 -1) (5) (1 3))


      Pascal

      Comment

      • Pascal Costanza

        Re: Python syntax in Lisp and Scheme

        Carlo v. Dango wrote:
        [color=blue]
        >[color=green]
        >> I'd humbly suggest that if you can't see *any* reason why someone
        >> would prefer Lisp's syntax, then you're not missing some fact about
        >> the syntax itself but about how other language features are supported
        >> by the syntax.[/color]
        >
        >
        > sure, but it seems like noone was able to let CLOS have
        > (virtual) inner classes,
        > methods inside methods,
        > virtual methods (yeah I know about those stupid generic functions :),
        > method overloading,[/color]

        + Inner classes only make sense when the language requires you to put
        method definitions inside of class definitions. It doesn't make a lot of
        sense to put a class definition inside another class when it only
        consists of field definitions, as is the case in CLOS. (Except for
        having the benefit of additional namespaces, but namespaces are handled
        differently in Common Lisp.)

        + So what you want is method definitions inside of other methods. Of
        course, this is possible. Here is a little toy example that sketches how
        you can achieve this:

        (defclass person ()
        ((name :accessor name :initarg :name)
        (address :accessor address :initarg :address)))

        (defun make-out-method (person)
        (with-slots (name address) person
        (defmethod out ((p (eql person)))
        (format t "Name: ~A; address: ~A~%" name address))))

        (defvar *pascal* (make-instance 'person :name "Pascal" :address "Bonn"))

        (make-out-method *pascal*)

        (out *pascal*)

        => Name: Pascal; address: Bonn

        + All methods in CLOS are virtual. What do you mean?

        + Method overloading is a way to have static dispatch, and this doesn't
        fit well with a dynamic language. (Apart from that, static dispatch is a
        source for some nasty bugs.)

        What you probably really mean here is that there are some strict
        compatibility requirements wrt the lambda lists of methods that belong
        to the same generic function. I don't think Common Lispers have serious
        issues with these requirements.

        In general, dynamic type checking in Common Lisp makes these things much
        easier than you might think in case you have only considered statically
        typed languages so far.
        [color=blue]
        > A decent API (I tried playing with it.. it doesn't even have a freaking
        > date library as standard ;-p[/color]

        No language with an official standard (ANSI, ISO, etc.) defines
        everything you might ever need in its standard. That's simply not
        possible. Standardized languages rely on vendor support, and more often
        than not, community-driven de-facto standards emerge.

        Single-vendor languages follow a totally different approach in this
        regard. You are comparing apples and oranges here.

        One can have a debate about language standards vs. single-vendor
        languages, but that's a different issue altogether.

        Baseline: If you are looking for a decent date library, check out what
        Common Lisp vendors have to offer and/or what is available from third
        parties.
        [color=blue]
        > Yes I agree with the compile time macro expansion is a nice thing.
        > However, if I want to do some serious changes to the structure of
        > objects and classes (i.e. create a new kind of objects) then I have to
        > spend a long time finding out how the CLOS people hacked together their
        > representation of classes, methods, method call etc... it has been far
        > easier for me to just do some small changes using __getattribute_ _ and
        > metaclasses in python. So in that respect Im not really sure the macro
        > idea is advantageous for other than 'straight away' macros...[/color]

        Are you sure that you are not confusing macros and the CLOS MOP here?
        (Your remarks are too general to be able to comment on this.)
        [color=blue]
        > yes this mail is provocative.. please count slowly to 10 before replying
        > if you disagree with my point of view (and I know Pascal will disagree
        > ;-) ... not that I ever seen him angry ;-)[/color]

        grrr

        ;)


        Pascal

        Comment

        • Andreas Rossberg

          Re: Python syntax in Lisp and Scheme

          Dirk Thierbach wrote:[color=blue]
          >
          > you can use macros to
          > do everything one could use HOFs for (if you really want).[/color]

          Really? What about arbitrary recursion?

          --
          Andreas Rossberg, rossberg@ps.uni-sb.de

          "Computer games don't affect kids; I mean if Pac Man affected us
          as kids, we would all be running around in darkened rooms, munching
          magic pills, and listening to repetitive electronic music."
          - Kristian Wilson, Nintendo Inc.

          Comment

          • Dirk Thierbach

            Re: Python syntax in Lisp and Scheme

            james anderson <james.anderson @setf.de> wrote:
            [color=blue][color=green][color=darkred]
            >> > is the[re] no advantage to being able to do either - or both - as the
            >> > occasion dictates?[/color][/color][/color]

            Of course it's good to be able to do either. And Lisp macros are a
            powerful tool, and it's good to have it when you need it. But it's
            somewhat annoying to frequently read grossly exaggerated claims like
            "lots of things you can do with Lisp macros are impossible to do in
            any other language" when you can do a good part of these things even in
            Lisp without macros.
            [color=blue][color=green]
            >> The interesting part is that most Lisp'ers don't seem
            >> to use them, or even to know that you can use them, and use macros instead.[/color][/color]
            [color=blue]
            > while the first assertion might well be born out by a statistical
            > analysis of, for example, open-source code, i'm curious how one
            > reaches the second conclusion.[/color]

            I don't have statistical evidence, this is just my personal
            impression. On the one hand, there are the above claims, on the other
            hand, I see code that would (IMHO) much more simple and elegant with
            HOFs, but instead imperative assignment is used, or macros. So I then
            I have the impression that the programmer doesn't really know how to
            use HOFs, otherwise he would have used them. Maybe that's wrong and
            they all do that on purpose, or because they don't like HOFs (like you
            seem to do), but somehow this is difficult to imagine.
            [color=blue][color=green]
            >> The advantage of HOFs over macros is simplicity: You don't need additional
            >> language constructs[/color][/color]
            [color=blue]
            > when did common-lisp macros become an "additional language construct"?[/color]

            It's "additional " in the sense that you can write programs without it,
            and that different Lisp dialects use a different syntax and semantics
            for macros. HOFs on the other hand are pure lambda calculus, and every
            functional language has them.
            [color=blue][color=green]
            >> (which may be different even for different Lisp
            >> dialects, say), and other tools (like type checking) are available for
            >> free; and the programmer doesn't need to learn an additional concept.[/color][/color]
            [color=blue]
            > doesn't that last phrase contradict the previous one?[/color]

            I don't see any contradiction; maybe you can be more explicit?
            [color=blue]
            > i do admit to infrequent direct use of higher-order functions. one
            > reason is that there is little advantage to articulating the
            > creation of functions which have dynamic extent only,[/color]

            Why? The whole point (or one of them) of functional languages is that
            functions are first class, and you can easily use them (and you
            frequently do) in 'map', 'fold', or more complicated HOFs. It's simple,
            elegant, reusable, type-safe, and avoids unecessary state. A definition
            like

            sum = foldr (+) 0

            in Haskell is a lot better than doing an explicit loop. If you don't
            use HOFs at all, then IMHO you're not doing proper functional
            programming.
            [color=blue]
            > so in my use, most hof's are manifest through a macro
            > interface. it's the same distaste i have about inner and anonymous
            > java classes.[/color]

            I don't like inner and anonymous classes either: They're just a clumsy
            substitute for anonymous functions, and they have too much syntactic
            garbage associated with them.
            [color=blue]
            > the other reason is that when i moved from scheme to lisp, in the
            > process of porting the code which i carried over, it occurred to me
            > that much of what i was using higher-order functions for could be
            > expressed more clearly with abstract classes and appropriately
            > defined generic function method combinations.[/color]

            Sometimes it is more convenient to use other forms of parametrization
            (like classes). Sometimes HOFs are more natural. It really depends on
            the concrete example. And of course 'classes' or similar language
            features are independent from macros, and many languages provide them,
            even if they don't have macros.

            - Dirk

            Comment

            • Bruce Lewis

              algebra/prefix/infix (was: Python syntax in Lisp and Scheme)

              Pascal Bourguignon <spam@thalassa. informatimago.c om> writes:
              [color=blue]
              > Most probably, you would write a macro named WITH-INFIX and thus
              > automatically scope the infix part:
              >
              > (with-infix 1 / x + 1 / ( x ^ 3 ) + 1 / ( x ^ 5 ) )[/color]

              How about a with-algebraic macro? Someone mentioned that Python uses a
              nice algebraic syntax. That would obviously be different from the infix
              syntax you illustrated. With infix syntax, it takes some examination to
              notice that the above expression is the sum of three fractions. You
              have to think about operator precedence and everything. With algebraic
              syntax you could see it at a glance:

              1 1 1
              ----- + ----- + -----
              3 5
              x + 1 x x


              Of course, prefix notation would also make it obvious at a glance that
              you have the sum of three fractions:

              (+ (/ 1 (+ x 1))
              (/ 1 (expt x 3))
              (/ 1 (expt x 5)))

              You're already pretty close to algebraic syntax once you upgrade from
              infix to prefix notation. But that actual algebraic syntax must be
              really cool in Python. Isn't there some math tool out there that also
              does it?

              When Python programmers put algebraic formulas in their code, does it
              mess up the indentation at all? I'm curious exactly how it works.

              Comment

              • Alex Martelli

                Re: Python syntax in Lisp and Scheme

                Doug Tolton wrote:
                ...[color=blue]
                > Alex, this is pure un-mitigated non-sense.[/color]

                Why, thanks! Nice to see that I'm getting on the nerves of _some_
                people, too, not just having them get on mine.
                [color=blue]
                > Python's Metaclasses are
                > far more dangerous than Macro's. Metaclasses allow you to globally
                > change the underlying semantics of a program.[/color]

                Nope: a metaclass only affects (part of the semantics of) the
                classes that instantiate it. No "globally" about it. When I
                write a class I can explicity control what metaclass it uses,
                or inherit it. E.g., by writing 'class My(object):', with no
                explicit metaclass, I ensure type(my)==type( object). The type
                of the built-in named 'object' is the built-in named 'type'
                (which most custom metaclasses subclass), which is also the
                type of most other built-in types (numbers, strings, list,
                tuple, dict, functions, methods, module, file, ...). I.e.,
                your assertion is pure un-mitigated FUD.
                [color=blue]
                > Macros only allow you
                > to locally change the Syntax.[/color]

                "Locally"? Not globally? Care to explain? Each 'invocation'
                (expansion) of a macro must occur in a particular locus, sure,
                but isn't the _point_ of (e.g.) defining a 'loop-my-way' macro
                that every occurrence of 'loop-my-way' is such an expansion?

                As for that mention of "the Syntax" AS IF somehow contrasted
                with the "underlying semantics" just before, don't even bother
                to try explaining: one example of macros' wonders offered by a
                particularly vocal and emotional advocate was a macro
                'with-condition-maintained' that was somehow supposed to make
                whatever alterations might be needed in the control program of
                a reactor in order to regulate temperature -- and it was
                passed that code as three calls to functions (or expansions
                of macros) NOT defined inside it, so how it could possibly
                work "only...locally ", when to do anything at all it MUST
                necessarily find, "expand", and alter the local instantiations
                of those functions (or macros)...?!

                If that's an example of "only allow you to locally change
                the syntax", what would be an example of *EVEN DEEPER
                AND MORE PERVASIVE* changes ?!
                [color=blue]
                > Your comparison is spurious at best.[/color]

                What "my comparison" are you blabbering about? My text that
                you quoted, and called "pure un-mitigated non-sense", had no
                "comparison s", neither my own nor others'. I see YOU attempting
                to draw some "comparison " (eminently spurious, to be sure)
                between metaclasses and macros...

                [color=blue]
                > Your argument simply shows a serious mis-understanding of Macros.
                > Macros as has been stated to you *many* times are similar to
                > functions. They allow a certain type of abstraction to remove
                > extraneous code.[/color]

                Yeah, right. Kindly explain that 'with-condition-maintained'
                example and the exhalted claims made and implied for it, then.

                [color=blue]
                > Based on your example you should be fully campaigning against
                > Metaclasses, FP constructs in python and Functions as first class
                > objects. All of these things add complexity to a given program,[/color]

                "FUD" and "nonsense" (with or without a hyphen) would be serious
                understatements in an attempt to characterize *THIS*. *HOW* do
                "functions as first class objects" perform this devilish task of
                "adding complexity to a given program", for example?! The extra
                complexity would be in rules trying to FORBID normal usage of an
                object (passing as argument, returning as value, appending to a
                list, ...) based on the object's type. There is obviously no
                complexity in saying "_WHATEVER_ x happens to stand for, you
                can correctly call somelist.append (x)" [passing x as argument to
                a method of the somelist which appends x to the list], for example.
                The added complexity would come if you had to qualify this with
                "UNLESS ..." for whatever value of ``...''.
                [color=blue]
                > however they also reduce the total number of lines. Reducing program
                > length is to date the only effective method I have seen of reducing
                > complexity.[/color]

                For some (handwaving-defined) "appropriat e" approach to measuring
                "length" (and number of lines is most definitely not it), it is ONE
                important way. But you're missing another crucial one, which is
                the count of interactions, actual and potential, between "parts"
                of the program -- the key reason why global effects do not in fact
                effectively reduce complexity, but rather bid fair to increase it,
                even though they might often "reduce the total [[length]]", is
                exactly this. E.g., if large parts of my program needed all kinds
                of comparisons between strings (including comparison-related
                functionality such as hashing) to be case-insensitive, it might
                make my program 'shorter' if I could set case insensitivity as
                the global default -- but it might easily mess up totally unrelated
                and otherwise stable modules that rely on the usual case sensitive
                operations, causing weird, hard-to-trace malfunctionings . I've
                mentioned my youthful APL experiences: with its quad-IO to globally
                set index origin for arrays, and its quad-I forget what to globally
                set comparison tolerance in all comparisons between floating point
                numbers, APL was a prime example of this (among other things,
                reusability-destroying) global-effects risk. Sure, it was cool
                and made my program shorter to be able to check if "a < b" and
                have this IMPLICITLY mean "to within N significant digits" (or
                whatever) -- but it regularly broke other otherwise-stable modules
                and thus destroyed reuse. Not to mention the mind-boggling effects
                when a<b, a>b and a=b can ALL be 'true' at once thanks to the
                "to within N significant digits" IMPLICIT proviso...

                Complexity is not just program length, and reducing program length
                not the only important thing in reducing complexity. Removing
                *repetition* (boilerplate), sure, that's nice -- and if there was
                a way to constrain macros to ONLY do that (as opposed to ending up
                with examples such as 'with-condition-maintained', see above) I
                would be very interested in seeing it. I doubt there is one, though.

                [color=blue]
                > If you truly believe what you are saying, you really should be
                > programming in Java. Everything is explicit, and most if not all of[/color]

                Hmmm, one wonders -- are you a liar, or so totally ignorant of what
                you're talking about that you don't even KNOW that one of Java's
                most "cherished" features is that the "self." is just about ALWAYS
                implicit...? Anyway, in my text which you quoted and characterized
                as "pure un-mitigated non-sense" I was speaking of UNIFORMITY as
                a plus -- and Java's use of { } for example ensures NON-uniformity
                on a lexical plane, since everybody has different ideas about where
                braces should go:-).

                But I've NEVER argued in favour of boilerplate, of repetitiousness .
                I think that the occasional error that you can catch by forcing
                redundancy is generally outweighed by all the errors that just
                would not be there if the language let me state things "once, and
                only once". So, for example, when I write
                x = 23
                I most definitely don't WANT to have to redundantly state that,
                by the way, there is a variable x, and, whaddyaknow, x refers
                to an integer. As to whether it makes more sense to later let
                the same name x in the same scope refer to OTHER objects (of
                the same type; or, of any type) -- I still don't know; maybe
                a single-assignment kind of functional language would in fact be
                preferable, or maybe Python's relaxed attitude about re-bindings
                is best, or maybe something in-between, allowing re-bindings but
                only within a single type's items (for "re-bindings" you may
                choose to read "assignment s" if you wish, I'm not trying to
                reopen THAT particular lexical flamewar for further debate;-).

                So far, I'm pretty happy with Python's permissive approach to
                mutation and re-binding, but I notice I don't mind (differently
                from many others) the inability to re-bind SOME references
                (e.g., items of tuples, or lexically-outer names) -- and in
                Haskell or ML I don't recall ever feeling confined by the
                inability to have the same name refer to different values at
                successive times (in the same scope). [I _do_ recall some
                unease at being unable to mutate "large" data structures, as
                opposed to rebinding simple names, so it's not as if I can
                claim any natural affinity for the functional [immutable-data]
                approach to programming -- I just wonder if perhaps the current
                widespread _emphasis_ on rebinding and mutation may not be a
                TAD overdone -- but, enough for this aside].

                I do, of course, truly believe in what I'm saying -- what
                WOULD have stopped me from taking up any of a zillion different
                languages, instead of Python, when I started studying it
                about four years ago? Indeed, my opportunities for making
                money, and the audience for my books, would be vaster if I
                had stuck with what I was mainly using at work then (mostly C++,
                some Java, VB, Perl), my academic respectability higher if I
                had stuck with Haskell or some ML. But while I don't mind
                money, nor fans, I care most about other values -- and the
                amount to which "Python fits my brain" and makes me most
                comfortable and productive meets and exceeds all claims I had
                heard to this effect, PLUS, I have experiential proof (enough
                to convince me personally, if nobody else:-) that it's just
                as comfortable and productive for many others, from programming
                newbies to highly experienced professionals. Sure, Java would
                let me program my cellphone (which currently doesn't support
                Python) -- oh well, I'll have to eschew that crucial pursuit
                for a while longer now...


                Alex

                Comment

                • Marco Antoniotti

                  Re: Python syntax in Lisp and Scheme



                  David Mertz wrote:[color=blue]
                  > My answer sucked in a couple ways.
                  >
                  > (1) As Bengt Ricther pointed out up-thread, I should have changed David
                  > Eppstein's names 'filter' and 'iter' to something other than the
                  > built-in names.
                  >
                  > (2) The function categorize_comp ose() IS named correctly, but it doesn't
                  > DO what I said it would. If you want to fulfill ALL the filters, you
                  > don't to compose them, but... well, 'all()' them:
                  >
                  > | def categorize_join tly(preds, it):
                  > | results = [[] for _ in len(preds)]
                  > | for x in it:
                  > | results[all(filters)(x)].append(x)
                  > | return results
                  >
                  > Now if you wonder what the function 'all()' does, you could download:
                  >
                  > http://gnosis.cx/download/gnosis/util/combinators.py
                  >
                  > But the relevant part is:
                  >
                  > from operator import mul, add, truth
                  > apply_each = lambda fns, args=[]: map(apply, fns, [args]*len(fns))
                  > bools = lambda lst: map(truth, lst)
                  > bool_each = lambda fns, args=[]: bools(apply_eac h(fns, args))
                  > conjoin = lambda fns, args=[]: reduce(mul, bool_each(fns, args))
                  > all = lambda fns: lambda arg, fns=fns: conjoin(fns, (arg,))
                  >
                  > For 'lazy_all()', look at the link.
                  >
                  > See, Python is Haskell in drag.[/color]

                  Come on. Haskell has a nice type system. Python is an application of
                  Greespun's Tenth Rule of programming.

                  Cheers
                  --
                  Marco



                  [color=blue]
                  >
                  > Yours, David...
                  >
                  > --
                  > Keeping medicines from the bloodstreams of the sick; food from the bellies
                  > of the hungry; books from the hands of the uneducated; technology from the
                  > underdeveloped; and putting advocates of freedom in prisons. Intellectual
                  > property is to the 21st century what the slave trade was to the 16th.
                  >[/color]

                  Comment

                  • Marco Antoniotti

                    Re: Python syntax in Lisp and Scheme



                    Carlo v. Dango wrote:
                    [color=blue]
                    >[color=green]
                    >> I'd humbly suggest that if you can't see *any* reason why someone
                    >> would prefer Lisp's syntax, then you're not missing some fact about
                    >> the syntax itself but about how other language features are supported
                    >> by the syntax.[/color]
                    >
                    >
                    > sure, but it seems like noone was able to let CLOS have
                    > (virtual) inner classes,
                    > methods inside methods,
                    > virtual methods (yeah I know about those stupid generic functions :),
                    > method overloading,[/color]

                    From what you are saying it is obvious that you do not know what you
                    are talking about.

                    True, you do not have "inner" classes, but that has never stopped
                    anybody from writing good code. As for your comments on methods and
                    generic functions it is obvious that you do not know what multiple
                    dispatching is (yes, there is an ugly hacked up Python library to do
                    that floating around; I do not know if it will make it it 3.0), so you
                    comment looses value immediately.
                    [color=blue]
                    > A decent API (I tried playing with it.. it doesn't even have a freaking
                    > date library as standard ;-p[/color]


                    Apart form the fact that the language has GET-UNIVERSAL-TIME,
                    DECODE-UNIVERSAL-TIME etc etc, you can get a nice and portable (across
                    all n > 1.8 CL implementations ) date parsing library at




                    [color=blue]
                    >
                    > Yes I agree with the compile time[/color]

                    The term "compile" should already make you think.
                    [color=blue]
                    > macro expansion is a nice thing.
                    > However, if I want to do some serious changes to the structure of
                    > objects and classes (i.e. create a new kind of objects) then I have to
                    > spend a long time finding out how the CLOS people hacked together their
                    > representation of classes, methods, method call etc... it has been far
                    > easier for me to just do some small changes using __getattribute_ _ and
                    > metaclasses in python. So in that respect Im not really sure the macro
                    > idea is advantageous for other than 'straight away' macros...[/color]

                    And how exactly does CLOS forbid you to do the same? You can do that
                    using accessor, reader and writer generic functions (ooops, I forgot
                    that you do not know enough about them :) ) If that is not enough, the
                    CLOS Metaobject Protocol is available in practically all major CL
                    implementations (and that is more than the 1.8 Python implementations
                    out there). And it seems to me that
                    [color=blue]
                    >
                    > yes this mail is provocative.. please count slowly to 10 before replying
                    > if you disagree with my point of view (and I know Pascal will disagree
                    > ;-) ... not that I ever seen him angry ;-)[/color]


                    I counted until 42 :)

                    Cheers
                    --
                    Marco


                    Comment

                    • Doug Tolton

                      Re: Python syntax in Lisp and Scheme

                      On Wed, 08 Oct 2003 14:22:43 GMT, Alex Martelli <aleax@aleax.it >
                      wrote:
                      [color=blue]
                      >Doug Tolton wrote:
                      > ...[color=green]
                      >> Alex, this is pure un-mitigated non-sense.[/color]
                      >
                      >Why, thanks! Nice to see that I'm getting on the nerves of _some_
                      >people, too, not just having them get on mine.[/color]

                      Yes, this discussion is frustrating. It's deeply frustrating to hear
                      someone without extensive experience with Macros arguing why they are
                      so destructive. Particularly to hear the claim the Macros make it
                      impossible to have large teams work on a project, and at the same time
                      supporting features in python that make it far more difficult to share
                      code between people. (ie, white space delimiting, the ability to
                      rebind interenals, Metaclasses). Personally I'm not against any of
                      these features, however they all suffer from serious potential
                      drawbacks.[color=blue]
                      >[color=green]
                      >> Python's Metaclasses are
                      >> far more dangerous than Macro's. Metaclasses allow you to globally
                      >> change the underlying semantics of a program.[/color]
                      >
                      >Nope: a metaclass only affects (part of the semantics of) the
                      >classes that instantiate it. No "globally" about it. When I
                      >write a class I can explicity control what metaclass it uses,
                      >or inherit it. E.g., by writing 'class My(object):', with no
                      >explicit metaclass, I ensure type(my)==type( object). The type
                      >of the built-in named 'object' is the built-in named 'type'
                      >(which most custom metaclasses subclass), which is also the
                      >type of most other built-in types (numbers, strings, list,
                      >tuple, dict, functions, methods, module, file, ...). I.e.,
                      >your assertion is pure un-mitigated FUD.
                      >[/color]
                      Please explain to me how according to your logic, a semantic change to
                      the language is good, but a syntactic change is bad. Your logic is
                      extremely confusing to me. On the one hand you think Macro's are bad
                      because I can define a construct such as
                      (do-something-useful-here
                      arg1
                      arg2
                      arg3)
                      which operates according to all the regular semantic rules. In fact
                      there is even an explicit construct that will show me *exactly* what
                      this code is doing. Yet you apparently think using Metaclasses to
                      change the underlying semantics is somehow ok, because you can check
                      to see if it's built-in? So are you saying that using only built-in
                      constructs are good to use? If someone else gives you a class to use
                      which uses Metaclasses to change how it operates for some reason or
                      another, are you ok with that? What if they need to re-bind some of
                      the builtins to do something? Because you can't prevent that in python
                      either. In fact any piece of python code that runs on your system
                      could do that, yet you are ok with that?
                      [color=blue][color=green]
                      >> Macros only allow you
                      >> to locally change the Syntax.[/color]
                      >
                      >"Locally"? Not globally? Care to explain? Each 'invocation'
                      >(expansion) of a macro must occur in a particular locus, sure,
                      >but isn't the _point_ of (e.g.) defining a 'loop-my-way' macro
                      >that every occurrence of 'loop-my-way' is such an expansion?[/color]
                      yes, but the point is that if I just wrote 'loop-my-way', it doesn't
                      change existant code in unexpected ways. It only affects new code
                      that is written using 'loop-my-way'. Whereas re-binding the buildins
                      *will* change existant code.[color=blue]
                      >
                      >As for that mention of "the Syntax" AS IF somehow contrasted
                      >with the "underlying semantics" just before, don't even bother
                      >to try explaining: one example of macros' wonders offered by a
                      >particularly vocal and emotional advocate was a macro
                      >'with-condition-maintained' that was somehow supposed to make
                      >whatever alterations might be needed in the control program of
                      >a reactor in order to regulate temperature -- and it was
                      >passed that code as three calls to functions (or expansions
                      >of macros) NOT defined inside it, so how it could possibly
                      >work "only...locally ", when to do anything at all it MUST
                      >necessarily find, "expand", and alter the local instantiations
                      >of those functions (or macros)...?!
                      >[/color]
                      I'm not going to attempt to explain with-condition-maintained, as you
                      are clearly ignoring the general idea in favor of nitpicking
                      non-essential details of a hypothetical construct. When you descend
                      to the statements you have made about that construct, it's no longer
                      worth continuing discussion of it.

                      That's my exact problem though, your statements continually brand you
                      as ignorant of what macros are and how they operate on a fundamental
                      level, yet for some reason you feel qualified to extol their evils as
                      if you actually have significant experience with them.
                      [color=blue]
                      >If that's an example of "only allow you to locally change
                      >the syntax", what would be an example of *EVEN DEEPER
                      >AND MORE PERVASIVE* changes ?!
                      >[/color]
                      No idea what you are talking about here.
                      [color=blue][color=green]
                      >> Your comparison is spurious at best.[/color]
                      >
                      >What "my comparison" are you blabbering about? My text that
                      >you quoted, and called "pure un-mitigated non-sense", had no
                      >"comparisons ", neither my own nor others'. I see YOU attempting
                      >to draw some "comparison " (eminently spurious, to be sure)
                      >between metaclasses and macros...[/color]
                      The only reason you think it's spurious is because of your
                      fundamentally flawed conception of Macros.[color=blue]
                      >
                      >[color=green]
                      >> Your argument simply shows a serious mis-understanding of Macros.
                      >> Macros as has been stated to you *many* times are similar to
                      >> functions. They allow a certain type of abstraction to remove
                      >> extraneous code.[/color]
                      >
                      >Yeah, right. Kindly explain that 'with-condition-maintained'
                      >example and the exhalted claims made and implied for it, then.[/color]
                      I thought you didn't want it explained to you? If you are serious
                      about wanting to know what the *point* of the code snippet was, then
                      I'll explain it. If on the other hand you are going to make some
                      ridiculous argument about how with-condition-maintained isn't in fact
                      hooked to any control room circuitry, then forget it.[color=blue]
                      >
                      >[color=green]
                      >> Based on your example you should be fully campaigning against
                      >> Metaclasses, FP constructs in python and Functions as first class
                      >> objects. All of these things add complexity to a given program,[/color]
                      >
                      >"FUD" and "nonsense" (with or without a hyphen) would be serious
                      >understatement s in an attempt to characterize *THIS*. *HOW* do
                      >"functions as first class objects" perform this devilish task of
                      >"adding complexity to a given program", for example?! The extra
                      >complexity would be in rules trying to FORBID normal usage of an
                      >object (passing as argument, returning as value, appending to a
                      >list, ...) based on the object's type. There is obviously no
                      >complexity in saying "_WHATEVER_ x happens to stand for, you
                      >can correctly call somelist.append (x)" [passing x as argument to
                      >a method of the somelist which appends x to the list], for example.
                      >The added complexity would come if you had to qualify this with
                      >"UNLESS ..." for whatever value of ``...''.
                      >[/color]
                      Hmm...what if using a class with Metaclasses behaves in a totally
                      non-standard way? What if a function re-binds the builtins? What if
                      they over use FP constucts and nest 50 maps and filters? Are you ok
                      with all of these things? They are certainly more confusing than
                      Macros. To make the statement that *any* technology can't be abused
                      is foolish. To make that claim implies there is no correct usage,
                      only usage. In other words if there is no correct way to use
                      Metaclasses or re-bind builtins then any way that someone sees fit to
                      do it *is* the right way. We all know that is a ridiculous claim.
                      Macros are like any other sufficiently powerful technology. If they
                      aren't used right, they will complicate a program not simplify it.

                      I believe the crux of our difference is that you don't want to give
                      expressive power because you believe it will be misused. I on the
                      other hand want to give expressive power because I believe it could be
                      used correctly most of the time. For the times when it's not, well
                      that's why I have debugging skills. Sadly not eveyone uses looping
                      the way I would, but using my brain I can figure out what they are
                      doing.[color=blue][color=green]
                      >> however they also reduce the total number of lines. Reducing program
                      >> length is to date the only effective method I have seen of reducing
                      >> complexity.[/color]
                      >
                      >For some (handwaving-defined) "appropriat e" approach to measuring
                      >"length" (and number of lines is most definitely not it), it is ONE[/color]

                      Both from my experience and Fred Brooks it's the only actual way I've
                      seen of measuring the time it will take to write a program.
                      [color=blue]
                      >important way. But you're missing another crucial one, which is
                      >the count of interactions, actual and potential, between "parts"
                      >of the program -- the key reason why global effects do not in fact
                      >effectively reduce complexity, but rather bid fair to increase it,
                      >even though they might often "reduce the total [[length]]", is
                      >exactly this.[/color]

                      I understand this point very well. That's why I believe in building
                      layered software, and using good high order constructs to acheive
                      this. As I've said before, your statements reveal your fundamental
                      mis-understanding of the way Macro's work. To support Metaclasses,
                      classes, functions, first order functions etc as tools to support this
                      concept while at the same time reviling macros is simply showing an
                      un-educated bias about Macros. I wouldn't be suprised to hear you
                      respond with some argument about how you've read the writings by
                      people who have used Macros (as you've done in the past), but I
                      believe you do not have sufficient understanding to make the claims
                      you are making. If you really understood macros, I don't believe you
                      would be making such statements.
                      [color=blue]
                      > E.g., if large parts of my program needed all kinds
                      >of comparisons between strings (including comparison-related
                      >functionalit y such as hashing) to be case-insensitive, it might
                      >make my program 'shorter' if I could set case insensitivity as
                      >the global default -- but it might easily mess up totally unrelated
                      >and otherwise stable modules that rely on the usual case sensitive
                      >operations, causing weird, hard-to-trace malfunctionings . I've
                      >mentioned my youthful APL experiences: with its quad-IO to globally
                      >set index origin for arrays, and its quad-I forget what to globally
                      >set comparison tolerance in all comparisons between floating point
                      >numbers, APL was a prime example of this (among other things,
                      >reusability-destroying) global-effects risk. Sure, it was cool
                      >and made my program shorter to be able to check if "a < b" and
                      >have this IMPLICITLY mean "to within N significant digits" (or
                      >whatever) -- but it regularly broke other otherwise-stable modules
                      >and thus destroyed reuse. Not to mention the mind-boggling effects
                      >when a<b, a>b and a=b can ALL be 'true' at once thanks to the
                      >"to within N significant digits" IMPLICIT proviso...
                      >[/color]

                      Well that was a long winded digression into something that is
                      completely un-related to Macros. Seems like a good argument why
                      re-binding the buildins is bad though
                      ..[color=blue]
                      >Complexity is not just program length, and reducing program length
                      >not the only important thing in reducing complexity. Removing
                      >*repetition* (boilerplate), sure, that's nice -- and if there was
                      >a way to constrain macros to ONLY do that (as opposed to ending up
                      >with examples such as 'with-condition-maintained', see above) I
                      >would be very interested in seeing it. I doubt there is one, though.
                      >[/color]
                      I agree that reducing complexity is the goal. I disagree that you can
                      *ever* guarantee a high order construct is always used correctly
                      though.[color=blue]
                      >[color=green]
                      >> If you truly believe what you are saying, you really should be
                      >> programming in Java. Everything is explicit, and most if not all of[/color]
                      >
                      >Hmmm, one wonders -- are you a liar, or so totally ignorant of what
                      >you're talking about that you don't even KNOW that one of Java's
                      >most "cherished" features is that the "self." is just about ALWAYS
                      >implicit...? Anyway, in my text which you quoted and characterized
                      >as "pure un-mitigated non-sense" I was speaking of UNIFORMITY as
                      >a plus -- and Java's use of { } for example ensures NON-uniformity
                      >on a lexical plane, since everybody has different ideas about where
                      >braces should go:-).
                      >[/color]
                      Where braces should go is a trivial issues. However if braces is an
                      issue that seriously concerns you then I can see why macros are giving
                      you a heart attack.
                      [color=blue]
                      >But I've NEVER argued in favour of boilerplate, of repetitiousness .
                      >I think that the occasional error that you can catch by forcing
                      >redundancy is generally outweighed by all the errors that just
                      >would not be there if the language let me state things "once, and
                      >only once". So, for example, when I write
                      > x = 23
                      >I most definitely don't WANT to have to redundantly state that,
                      >by the way, there is a variable x, and, whaddyaknow, x refers
                      >to an integer. As to whether it makes more sense to later let
                      >the same name x in the same scope refer to OTHER objects (of
                      >the same type; or, of any type) -- I still don't know; maybe
                      >a single-assignment kind of functional language would in fact be
                      >preferable, or maybe Python's relaxed attitude about re-bindings
                      >is best, or maybe something in-between, allowing re-bindings but
                      >only within a single type's items (for "re-bindings" you may
                      >choose to read "assignment s" if you wish, I'm not trying to
                      >reopen THAT particular lexical flamewar for further debate;-).
                      >
                      >So far, I'm pretty happy with Python's permissive approach to
                      >mutation and re-binding, but I notice I don't mind (differently
                      >from many others) the inability to re-bind SOME references
                      >(e.g., items of tuples, or lexically-outer names) -- and in
                      >Haskell or ML I don't recall ever feeling confined by the
                      >inability to have the same name refer to different values at
                      >successive times (in the same scope). [I _do_ recall some
                      >unease at being unable to mutate "large" data structures, as
                      >opposed to rebinding simple names, so it's not as if I can
                      >claim any natural affinity for the functional [immutable-data]
                      >approach to programming -- I just wonder if perhaps the current
                      >widespread _emphasis_ on rebinding and mutation may not be a
                      >TAD overdone -- but, enough for this aside].
                      >
                      >I do, of course, truly believe in what I'm saying -- what
                      >WOULD have stopped me from taking up any of a zillion different
                      >languages, instead of Python, when I started studying it
                      >about four years ago? Indeed, my opportunities for making
                      >money, and the audience for my books, would be vaster if I
                      >had stuck with what I was mainly using at work then (mostly C++,
                      >some Java, VB, Perl), my academic respectability higher if I
                      >had stuck with Haskell or some ML. But while I don't mind
                      >money, nor fans, I care most about other values -- and the
                      >amount to which "Python fits my brain" and makes me most
                      >comfortable and productive meets and exceeds all claims I had
                      >heard to this effect, PLUS, I have experiential proof (enough
                      >to convince me personally, if nobody else:-) that it's just
                      >as comfortable and productive for many others, from programming
                      >newbies to highly experienced professionals. Sure, Java would
                      >let me program my cellphone (which currently doesn't support
                      >Python) -- oh well, I'll have to eschew that crucial pursuit
                      >for a while longer now...
                      >
                      >[/color]
                      The ironic thing is that I'm not bashing Python. I really like
                      python. It's a great language. I think we both use Python and Lisp
                      (for me) for the same reasons. If I wanted a higher paying job I'd be
                      using Java. I have aspirations to write books as well, I agree that
                      Python and Lisp aren't the biggest markets, and yet I use them because
                      they fit my brain also.

                      What I am in point of fact upset by is your constant barrage against
                      Macros. I feel that your stance is based on ignorance and
                      mis-information. You certainly don't have significant first hand
                      exposure to Lisp style Macros or you wouldn't be making statements
                      that were so obviously incorrect. Why don't you seriously try to
                      learn them? If you don't care to, why argue about them so much? I
                      haven't seen anyone bring up (I could've missed it) putting Macro's
                      into Python again. I personally don't think Macros would work very
                      well in Python, at least not as well as they do in Lisp. So
                      understanding that I'm not pushing for Macro's in python, why are you
                      so vehement against them? Are you on campaign to get Macros out of
                      Lisp?

                      Doug
                      Doug Tolton
                      (format t "~a@~a~a.~a " "dtolton" "ya" "hoo" "com")

                      Comment

                      • Dirk Thierbach

                        Re: Python syntax in Lisp and Scheme

                        Andreas Rossberg <rossberg@ps.un i-sb.de> wrote:[color=blue]
                        > Dirk Thierbach wrote:[/color]
                        [color=blue][color=green]
                        >> you can use macros to do everything one could use HOFs for (if you
                        >> really want).[/color][/color]

                        I should have added: As long as it should execute at compile time, of
                        course.
                        [color=blue]
                        > Really? What about arbitrary recursion?[/color]

                        I don't see the problem. Maybe you have an example? I am sure the
                        Lisp'ers here can come up with a macro solution for it.

                        - Dirk

                        Comment

                        • David Rush

                          Re: Python syntax in Lisp and Scheme

                          On Wed, 08 Oct 2003 15:31:21 GMT, Doug Tolton <doug@nospam.co m> wrote:[color=blue]
                          > On Wed, 08 Oct 2003 14:22:43 GMT, Alex Martelli <aleax@aleax.it >[color=green]
                          >> Doug Tolton wrote:
                          >> ...[color=darkred]
                          >>> Alex, this is pure un-mitigated non-sense.[/color]
                          >>
                          >> Why, thanks! Nice to see that I'm getting on the nerves of _some_
                          >> people, too, not just having them get on mine.[/color]
                          >
                          > Yes, this discussion is frustrating. It's deeply frustrating to hear
                          > someone without extensive experience with Macros arguing why they are
                          > so destructive.[/color]

                          You know I think that this thread has so far set a comp.lang.* record for
                          civilitiy in the face of a massively cross-posted language comparison
                          thread. I was even wondering if it was going to die a quiet death, too.

                          Ah well, We all knew it was too good to last. Have at it, lads!

                          Common Lisp is an ugly language that is impossible to understand with
                          crufty semantics

                          Scheme is only used by ivory-tower academics and is irerelevant to real
                          world programming

                          Python is a religion that worships at the feet of Guido vanRossum
                          combining the syntactic flaws of lisp with a bad case of feeping
                          creaturisms taken from languages more civilized than itself

                          There. Is everyone pissed off now?

                          david rush
                          --
                          Taking bets on how many more messages before Godwin's law kicks in...

                          Comment

                          • Daniel P. M. Silva

                            Re: Python syntax in Lisp and Scheme

                            <posted & mailed>

                            Alex Martelli wrote:
                            [color=blue]
                            > Daniel P. M. Silva wrote:
                            > ...[color=green]
                            >> You still can't add new binding constructs or safe parameterizatio ns like
                            >> a with_directory form:
                            >>
                            >> with_directory( "/tmp", do_something())
                            >>
                            >> Where do_something() would be evaluated with the current directory set to
                            >> " tmp" and the old pwd would be restored afterward (even in the event of
                            >> an exception).[/color]
                            >
                            > Right: you need to code this very differently, namely:
                            > with_directory( "/tmp", do_something)
                            > *deferring* the call to do_something to within the with_directory
                            > function. Python uses strict evaluation order, so if and when you
                            > choose to explicitly CALL do_something() it gets called,
                            >
                            > So, I would code:
                            >
                            > def with_directory( thedir, thefunc, *args, **kwds):
                            > pwd = os.getcwd()
                            > try: return thefunc(*args, **kwds)
                            > finally: os.chdir(pwd)
                            >
                            > this is of course a widespread idiom in Python, e.g. see
                            > unittest.TestCa se.assertRaises for example.
                            >
                            > The only annoyance here is that there is no good 'literal' form for
                            > a code block (Python's lambda is too puny to count as such), so you
                            > do have to *name* the 'thefunc' argument (with a 'def' statement --
                            > Python firmly separates statements from expressions).[/color]

                            That was my point. You have to pass a callable object to with_directory,
                            plus you have to save in that object any variables you might want to use,
                            when you'd rather say:

                            x = 7
                            with_directory( "/tmp",
                            print "well, now I'm in ", os.getpwd()
                            print "x: ", x
                            x = 3
                            )
                            [color=blue][color=green]
                            >> Last year -- I think at LL2 -- someone showed how they added some sort of
                            >> 'using "filename": ' form to Python... by hacking the interpreter.[/color]
                            >
                            > A "using" statement (which would take a specialized object, surely not
                            > a string, and call the object's entry/normal-exit/abnormal-exit methods)
                            > might often be a good alternative to try/finally (which makes no provision
                            > for 'entry', i.e. setting up, and draws no distinction between normal
                            > and abnormal 'exits' -- often one doesn't care, but sometimes yes). On
                            > this, I've seen some consensus on python-dev; but not (yet?) enough on
                            > the details. Consensus is culturally important, even though in the end
                            > Guido decides: we are keen to ensure we all keep using the same language,
                            > rather than ever fragmenting it into incompatible dialects.[/color]

                            The point is that the language spec itself is changed (along with the
                            interpreter in C!) to add that statement. I would be happier if I could
                            write syntax extensions myself, in Python, and if those extensions worked
                            on CPython, Jython, Python.Net, Spy, etc.
                            [color=blue]
                            >
                            >[color=green]
                            >> Some people use Python's hooks to create little languages inside Python
                            >> (eg. to change the meaning of instantiation), which are not free of
                            >> problems:
                            >>
                            >> class Object(object):
                            >> def __init__(this, *args, **kwargs):[/color]
                            >
                            > [invariably spelt as 'self', not 'this', but that's another issue]
                            >[color=green]
                            >> this.rest = args
                            >> this.keys = kwargs
                            >>
                            >> def new_obj_id(coun t=[0]):
                            >> count[0] = count[0] + 1
                            >> return count[0]
                            >>
                            >> def tag_obj(obj, id):
                            >> obj.object_id = id
                            >> return obj
                            >>
                            >> def obj_id(obj): return obj.object_id
                            >>
                            >> type.__setattr_ _(Object, "__new__", staticmethod(la mbda type, *args:
                            >> tag_obj(object. __new__(type), new_obj_id())))[/color]
                            > ...[color=green]
                            >> # forgot to check for this case...
                            >> print Object(foo="bar ")[/color]
                            >
                            > It's not an issue of "checking": you have written (in very obscure
                            > and unreadable fashion) a callable which you want to accept (and
                            > ignore) keyword arguments, but have coded it in such a way that it
                            > in fact refuses keyword arguments. Just add the **kwds after the
                            > *args. This bug is not really related to "little languages" at all:
                            > you might forget to specify arguments which you do want your callable
                            > to accept and ignore in a wide variety of other contexts, too.[/color]

                            I think changing the meaning of __new__ is a pretty big language
                            modification...

                            - Daniel

                            Comment

                            • Alexander Schmolck

                              Re: Python syntax in Lisp and Scheme

                              Pascal Bourguignon <spam@thalassa. informatimago.c om> writes:
                              [color=blue]
                              > Well, I would say that kanji is badly designed, compared to latin
                              > alphabet. The voyels are composed with consones (with diacritical
                              > marks) and consones are written following four or five groups with
                              > additional diacritical marks to distinguish within the groups. It's
                              > more a phonetic code than a true alphabet.[/color]

                              Huh? You seem to be confused (BTW French is misleading here: it's vowels and
                              consonants in English). *Kanji* are not phonetic, you seem to be talking about
                              *kana*. And the blanket claim that Japanese spelling in kana is badly designed
                              compared to say, English orthography seems really rather dubious to me.

                              'as

                              Comment

                              • Marco Antoniotti

                                Re: Python syntax in Lisp and Scheme



                                Dirk Thierbach wrote:
                                [color=blue]
                                > james anderson <james.anderson @setf.de> wrote:
                                >[color=green]
                                >>Matthias Blume wrote:[/color]
                                >
                                >[color=green][color=darkred]
                                >>>Most of the things that macros can do can be done with HOFs with just
                                >>>as little source code duplication as with macros. (And with macros
                                >>>only the source code does not get duplicated, the same not being true
                                >>>for compiled code. With HOFs even executable code duplication is
                                >>>often avoided -- depending on compiler technology.)[/color][/color]
                                >
                                >[color=green]
                                >>is the no advantage to being able to do either - or both - as the
                                >>occasion dictates?[/color]
                                >
                                >
                                > I can't parse this sentence, but of course you can also use HOFs in Lisp
                                > (all flavours). The interesting part is that most Lisp'ers don't seem
                                > to use them, or even to know that you can use them, and use macros instead.
                                >
                                > The only real advantage of macros over HOFs is that macros are guaranteed
                                > to to executed at compile time. A good optimizing compiler (like GHC
                                > for Haskell) might actually also evaluate some expressions including
                                > HOFs at compile time, but you have no control over that.
                                >
                                >[color=green]
                                >>i'd be interested to read examples of things which are better done
                                >>with HOF features which are not available in CL.[/color]
                                >
                                >
                                > HOFs can of course be used directly in CL, and you can use macros to
                                > do everything one could use HOFs for (if you really want).
                                >
                                > The advantage of HOFs over macros is simplicity:[/color]

                                As R^nRS shows, simplicity leads to language specs without useful things
                                (like records/struct) in them.

                                You want to make things simple, not any simpler (was it Einstein who
                                said that?)
                                [color=blue]
                                > You don't need additional
                                > language constructs (which may be different even for different Lisp
                                > dialects, say),[/color]

                                As we well know, there is now one dominant Lisp, which is Common by
                                name. (No. ELisp does not count as you do (require 'cl) in your .emacs
                                file) This argument is moot.
                                [color=blue]
                                > and other tools (like type checking) are available for
                                > free;[/color]

                                Yes. Type Checking is in CMUCL/SBCL.
                                [color=blue]
                                > and the programmer doesn't need to learn an additional concept.[/color]

                                The programmer needs to learn to use the tool at its best. If your tool
                                is limited you just have to learn less.

                                Cheers
                                --
                                Marco

                                Comment

                                Working...