S.M Mukarram Nainar
05/29/2020, 12:38 AMKartik Agaram
Doug Moen
05/29/2020, 2:27 AMKonrad Hinsen
05/29/2020, 4:56 AMKartik Agaram
Doug Moen
05/29/2020, 1:56 PM>>> 2 + 2
4
>>> "foo" ++ "bar"
"foobar"
>>> [1,2,3] ++ [4,5,6]
[1,2,3,4,5,6]
The above REPL session shows a language where numbers, strings and lists print as constructor expressions.
I don't think this requirement is in conflict with simplicity and malleability. However, Lisp dialects (languages with S-expression syntax) do not meet this requirement for lists, although they meet it for numbers and strings. For example, quoting from the Wart paper,
1 + 1
⇒ 2
'(1 2 3)
⇒ (1 2 3)
Philip Wadler wrote about how this causes problems for teaching Lisp to undergraduates:
The difference between (1 2 3) and (quote (1 2 3)) is subtle, and it inevitably confuses students. In particular, it plays havoc with the substitution model of evaluation.From "A critique of Abelson and Sussman -or- Why calculating is better than scheming" https://www.cs.kent.ac.uk/people/staff/dat/miranda/wadler87.pdf
wtaysom
05/29/2020, 5:02 PMKonrad Hinsen
05/29/2020, 5:15 PMdef foo
foo bar
foo bar
(assuming this is legal syntax?) That's where edge cases tend to get messy in various indentation-based proposals I have seen.Konrad Hinsen
05/29/2020, 5:17 PMKartik Agaram
def (foo)
prn 1
prn 2
Now (foo)
prints:
1
2
---
The price to pay is a distinction between standard identifiers and infix operator identifiers. OK, but what are those rules? Is it by character class, as in Smalltalk? Some characters are only allowed in infix identifiers, and others only in standard identifiers? With mixing forbidden? Then... how do you handle the creation of synthetic identifiers in macros? Stuff like Lisp's gensym.Yeah, disjoint character classes. The major restriction is that you can't use
-
in variables, which is a bitter pill to swallow. (Mu gave up Lisp to get back -
🙂)
I don't follow the gensym question. Wart expands $x
inside macros to something like x1234
. But it doesn't support infix operators. Is that what you're wondering? It never occurred to me to create new infix operators inside macros.Doug Moen
05/29/2020, 6:56 PM[a,b,c]
syntax for constructing lists, is that you can replace any of the list elements with a subexpression that denotes the same value. This property goes by several names: compositional semantics, composable syntax, "the substitution model of evaluation".
The corresponding syntax in Lisp is (list a b c)
. So, print '(a b c)
as (list 'a 'b 'c)
. But that's very verbose compared to the usual alternative. In Lisp culture, (quote a)
is so important that it is abbreviated as 'a
, but there is no abbreviation for (list a b c)
. So let's make an abbreviation, and use [a b c]
as an abbreviation for (list a b c)
. So now we print '(a b c)
as ['a 'b 'c]
.Kartik Agaram
> (list 1 2 3)
'(1 2 3)
> (list 1 2 (list 3 4))
'(1 2 (3 4))
I have ambivalent feelings about this 'feature', though.Konrad Hinsen
05/30/2020, 7:24 AM(let ((fn (make-symbol "foo-bar")))
`(eval (progn (defun ,fn () nil)
(,fn)))
This must raise an error at some point - but where? Do you disallow making mixed symbols? Using them as function names? Calling the misnamed function?
My point is that in a language with Lisp-style meta-programming, any constraint on syntax percolates down to lower layers, with hard to foresee consequences. And that's why s-expressions are so hard to replace, in my opinion.Konrad Hinsen
05/30/2020, 7:31 AM[ ... ]
as an alternative for '( ... )
and use it in printing. That leaves symbols requiring an explicit quote. But with the new list syntax, you have also broken homoiconicity a bit. Suppose you construct a list which you then turn into code by feeding it to eval
: your list constructor now has a different aspect than code written by hand.Kartik Agaram
make-symbol
(or sym
in Wart), you have to also refer to it the same way.
(eval `(def (foo a b) (let ,(sym "a-b") 34 ,(sym "a-b"))))
(foo 8 9)
=> 34 # args are ignored
Does this seem like a big problem? I've learned to expect that metaprogramming is a sharp tool that can get one in trouble.Doug Moen
05/30/2020, 2:55 PMDoug Moen
05/30/2020, 3:02 PMeval
. When I suggested how to fix Lisp, @Konrad Hinsen replied that "you have broken homoiconicity a bit". So this is a tradeoff in syntax design. Lisp syntax is designed to make metaprogramming easier, at the expense of making ordinary, non-metaprogramming more difficult.Konrad Hinsen
05/30/2020, 6:43 PMKartik Agaram
a-b
. Construction happens after the read phase. Infix expansion happens during the read phase.Konrad Hinsen
05/30/2020, 6:44 PMKonrad Hinsen
05/30/2020, 6:45 PMKartik Agaram
Konrad Hinsen
05/30/2020, 6:56 PM2 + 3 + 4 + 4
, which is parsed left-to-right. The net outcome is that you can read expressions as if they used traditional maths rules, but you don't need to remember precedence rules. And due to the same-operator exception, the number of parentheses remains very reasonable.Kartik Agaram
Doug Moen
05/30/2020, 7:59 PMKonrad Hinsen
05/31/2020, 5:58 PMS.M Mukarram Nainar
05/31/2020, 11:48 PMKonrad Hinsen
06/01/2020, 7:57 AMS.M Mukarram Nainar
06/01/2020, 10:00 AMS.M Mukarram Nainar
06/01/2020, 10:01 AMKartik Agaram
Konrad Hinsen
06/02/2020, 1:47 AMDavid Piepgrass
06/10/2020, 7:43 PMKonrad Hinsen
06/11/2020, 8:27 AM