Why don't people like lisp?

Darius ddarius at hotpop.com
Fri Oct 24 03:57:56 EDT 2003


Joe Marshall <jrm at ccs.neu.edu> wrote in message news:<fzhkexxp.fsf at ccs.neu.edu>...
> "Andrew Dalke" <adalke at mindspring.com> writes:
> 
> > As an example, here's a quick hack of a way to parse a simple
> > stack-based language and make a native Python function out
> > of it....
> 
> [code elided]
> 
> Let's take on something more complicated.  A lot more complicated.
> 
> Suppose I am solving problems that are best expressed
> non-deterministically, and I need a domain language that has the
> following non-deterministic constructs:
> 
> EITHER --
>         Used as a mechanism to combine expressions
>         non-deterministically as in
> 
>         Whatever the syntax, EITHER introduces a choice-point.  It
>         begins by attempting evaluation of the first subexpression.
>         If that subexpression returns a value, EITHER returns that
>         value.  If the subexpression `fails', EITHER attempts to
>         evaluate the next subexpression.  The first subexpression
>         to produce a value is the value of the whole expression.
>         If all subexpressions `fail', then the EITHER form itself
>         `fails'.
> 
> FAIL  --
>         Causes an expression to `fail'.  This means that control is
>         immediately returned to the nearest enclosing EITHER form
>         (backtracking) which will then proceed to attempt to evaluate
>         the next subexpression.  If the current subexpression is the
>         last form in the enclosing EITHER, the EITHER form propagates
>         the failure up to the next enclosing EITHER.
>  
> ALL-VALUES --
>         Used to collect all possible values returned by a
>         non-deterministic expression.  If all possible choice-points
>         in the expression yield failure, then ALL-VALUES
>         deterministically returns an empty collection.  Thus failures
>         cannot propagate past an ALL-VALUES form.
> 
> ONE-VALUE --
>         Returns the first possible value returned by a non-deterministic
>         expression, or some sort of distinguished token if no value
>         can be found.  Also blocks propagation of `failure'.
> 
> 
> Since I am unsure of the entire details of the problem I am solving, I
> also wish to have these forms integrated into a reasonably complete
> computer language.  Obviously this new language will have syntactic
> differences from anything other language (via the introduction of
> these forms), but by and large, the subexpressions of this new
> language ought to be something familiar.
> 
> So if we extended Lisp, for example, I could write:
>
> (defun an-integer-between (low high)
>   (if (> low high)
>       (fail)
>       (either low (an-integer-between (+ low 1) high))))
> 
> (defun pythagorean-triples (n)
>   (all-values
>     (let ((opposite (an-integer-between 1 n))
>           (adjacent (an-integer-between 1 n))
>           (hypotenuse (an-integer-between 1 n)))
>       (if (= (+ (* opposite opposite)
>                 (* adjacent adjacent))
>              (* hypotenuse hypotenuse))
>           (list opposite adjacent hypotenuse)
>           (fail)))))

pythagoreanTriples n =
    [ (opposite,adjacent,hypotenuse) |
        opposite   <- [1..n],
        adjacent   <- [1..n],
        hypotenuse <- [1..n],
        opposite^2 + adjacent^2 == hypotenuse^2]

{- or with alternative syntax
pythagoreanTriples n = do
    opposite   <- [1..n]
    adjacent   <- [1..n]
    hypotenuse <- [1..n]
    guard (opposite^2 + adjacent^2 == hypotenuse^2)
    return (opposite,adjacent,hypotenuse)
-}

> and (pythagorean-triples 10)
> would return ((3 4 5) (4 3 5) (6 8 10) (8 6 10))

*Main> pythagoreanTriples 10
[(3,4,5),(4,3,5),(6,8,10),(8,6,10)]

pythagoreanTriples n =
    [ (opposite,adjacent,hypotenuse) |
        let ns = [1..n],
        opposite   <- ns,
        adjacent   <- ns,
        hypotenuse <- ns,
        opposite^2 + adjacent^2 == hypotenuse^2 ]

behaves better... Don't try this with the Lisp.

I wonder if something along the lines of,
[ (x,y) | 
    range <- rangeOfRanges, 
    x     <- range, 
    y     <- range ] 
works with the Lisp version and does the Right Thing, namely give:
[(1,1),(1,2),(2,1),(2,2),(3,3),(3,4),(4,3),(4,4)] when rangeOfRanges
is (either (either 1 2) (either 3 4)) or something to that affect
([[1,2],[3,4]] was used to get the above numbers).

> on the other hand, if we extended Python, I could write:

Oops!  Wrong language.  Also forgot to extend the language. *sigh* I
can't do anything right.
 
> This is a tricky problem, but one approach in Lisp is to make
> ALL-VALUES and EITHER be rather complicated macros.
> 
> The advantage of doing this is that the rest of the language, LET,
> DEFUN, *, +, conditionals, strings, CLOS, i.e. everything, is pretty
> much intact.  Since I know that Lisp is a `reasonably complete'
> substrate, I don't have to worry about designing and parsing an entire
> non-deterministic language.  I can just graft my extension on to
> something people will be familiar with.
> 
> Yes, I know that adding non-determinism to the language is going to
> mean a change in how people would program (how could it not?!) but
> I'm attempting to *minimize* the intellectual burden by making the
> non-deterministic language very similar to one that already exists.
> 
> How would one approach this in Python?  If Python had macros, then
> one could take exactly the same approach as Lisp.  What does a Pythonista
> do when encountering a problem like this?  (I'm actually curious,
> not raising rhetorical questions.  I assume that there is *something*
> one would do, but not being a python hacker, I don't know what it is.)

(posted mostly for my own amusement though I am interested in how the
rangeOfRanges example is handled)




More information about the Python-list mailing list