top | item 34624625

(no title)

amanwithnoplan | 3 years ago

But why (+ 1 2 3) and not +(1 2 3) since the head is special? Or (1 2 3 +) so nested trees are built bottom up?

discuss

order

simongray|3 years ago

If it's +(1 2 3) then the language is no longer homoiconic and you will lose the primary leverage of being a Lisp. The fact that Lisp code consists entirely of Lisp data literals (code as data) is what enables Lisp macros and the superior REPL experience.

distcs|3 years ago

Can you elaborate what about +(1 2 3) makes it not homoiconic? Isn't it trivial for a hypothetical Lisp implementation to treat +(1 2 3) as the list [+, 1, 2, 3]?

Not sure if I am missing something. This is an honest question.

paldepind2|3 years ago

(+ 1 2 3) vs +(1 2 3) is just a small syntactic difference and has no bearing on whether the language is homo-iconic or not. The translation from code to data is equally trivial for both syntaxes.

pasc1878|3 years ago

There are languages where this can be written +/ 1 2 3

e.g. APL

sokoloff|3 years ago

So that the function to be applied could itself come from executing code.

  ((if (condition) ‘+ ‘*) 2 3)
If for some (toy, in this case) reason you wanted to sometimes add and sometimes multiply.

lisper|3 years ago

Lisp syntax is not required for this. There is no reason that you could not write:

    (if (condition) '+ '*) (2 3)
and have that mean a conditional function call on the arguments 2 and 3. In fact, many traditional-syntax languages allow you to do that, e.g.:

    Python 3.8.9 (default, Mar 30 2022, 13:51:16) 
    >>> def f(x): return x+1
    ... 
    >>> def g(x): return x+2
    ... 
    >>> (f if 1 else g)(4)
    5
No, the real reason you want (f x y) rather than f(x y) is so you can parse it with no lookahead.

It is actually possible to extend Lisp's syntax to allow f(x y) using the hack that if there is no whitespace between a symbol and an open-paren then treat that like a function call, i.e. you can tweak the Lisp parser so that:

    (list f(x y) f (x y))
will read as

    (list (f x y) f (x y))
and so kinda sorta do the Right Thing if you like traditional function call syntax. But that is pretty hacky and fragile.

lisper|3 years ago

Because parsing +(1 2 3) requires lookahead. You want to be able to type X into a REPL and get back the value of X, but you can't do that if there is a possibility that an open paren after the X will change its semantics into a function call.

Also, what should be the result of:

    (defvar f ...)
    (defun f (x) ...)
    (length (list f (g x) f(g x)))

?