Hacker News new | past | comments | ask | show | jobs | submit login

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.



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.


First of all, that place is where the reader macros go, so the spot is already taken.

Second of all, notwithstanding interference with reader macros, then no, it isn't completely trivial unless what you're suggesting is just pointless string substitution, which would also make e.g. 1(2 3) be equal to (1 2 3).

If what you're suggesting is having an enforced hard split between lists and function/macro invocation, that pretty much just makes everything harder to do with no perceivable gain, other than looking a bit more like C-based languages. It's a bit like enforcing that any strings that are parsed as numbers somewhere in the source code must be defined using "..." while strings that aren't must use '...' instead.

The entire point is that you can manipulate code as data structures. You can rewrite the rules of the language by returning data structures. There's no reason to make this more complex.


Homoiconicity in Lisp means that it is written on top of the data syntax.

Sure you can put other parsers in front, which might just convert a different notation into Lisp data. The difference is then, that the primitive datastructure itself has a different syntax. In Lisp we use the syntax of the primitive data notation (-> s-expressions) to encode both data AND code.


Try replacing the + with a more complicated expression. ((if t + -) 1 2 3) and (if t + -) (1 2 3). In your notation it is much harder to determine which expressions are intended to be evaluated.


(+ 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.


sure it is

  (paris berlin london)  
is a data structure, which knows nothing about Lisp. It's just a nested list.

  paris(berlin london)
does not make any sense as a list of symbols. Why is paris written outside of the list?

Lisp chooses to write programs as nested lists of symbols.

If you start to define a specific syntax which violates the simple syntax for nested lists, then the code is no longer read by reading a simple data expression.


I think you're wrong if (+ 2 3) means apply the + function with the 2 3 arguments then (Paris Berlin London) means apply the Paris function with the Berlin London arguments..

AFAIK if you want a list either you use (list a b c) or you use '(a b c) which I find less regular than +(1 2) or (1 2) which is equal to list(1 2)


What it means is entirely contextual.

Often, it will be interpreted to be a function call or a macro invocation in the eval step (the E in REPL).

You can sidestep this behaviour using the ' reader macro (i.e. quote) as you mentioned yourself. Quoting disables this behaviour for the form that the reader macro applies to. Reader macros occur in the R step (i.e. before the E in REPL).

It is a list data structure. There are many examples of lists which are never interpreted as function calls in Lisp, since macros run before evaluation and can change the default behaviour, e.g. in

    (defun increment (x) (+ x 1))
the (x) is not a function invocation, it's a list of named function parameters.


Remember: the specific feature of a typical Lisp is that it is written as s-expressions. S-expressions are a notation for data (similar to XML, JSON, ...). This notation is independently useful for all kinds of purposes - like a list of city names: (paris berlin london).

But the specific feature of Lisp is this: code is data and data can be code. Some use the word homocionic -> the program is written in its own data syntax. S-expressions are the data syntax used by Lisp and the programs are written as s-expressions.

> (+ 2 3) means apply the + function with the 2 3 arguments

Depending on the context (a b c) can have different meanings. As a list it is a list of three items. As a top-level item it is a function call. In (let (a b c) ...) it means a list of variables.

Lisp is based on s-expressions. S-expressions is a simple syntax for data:

an symbolic expression is:

  a symbol: foo, bar, 1, 2 paris, +, -, delta, bear, G1345

  an empty list: NIL or ()

  a non-empty list: ( s-expressionn1 ... s-expression-n)
That's basically it.

Lisp has three functions to work with those: READ, PRINT and EVAL. READ reads a textual s-expression to data, PRINT takes data and prints it as an s-expression, EVAL takes data and evaluates it.

Thus the toplevel of Lisp is something like

  (loop (print (eval (read))))
It reads a Lisp expression in form of an s-expression, evaluates it and prints the result.

> AFAIK if you want a list either you use (list a b c) or you use '(a b c) which I find less regular than +(1 2) or (1 2) which is equal to list(1 2)

(a b c) is a list. It's an s-expression. It is valid data. It's only valid Lisp, if A is an operator.

(quote (a b c)) is also a nested list AND a valid Lisp program.

But READ reads all kinds of nested lists, not just Lisp programs. It does that, because S-expressions are a general data syntax.

Compare that with most other programming languages. Their programs are not written on top of a general data-structure notation like nested lists, nested vectors, nested tables, ...


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

e.g. APL




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: