3 ms·
If I am reading this right, TCL's approach is neither FEXPRs nor Lisp's macros -- instead, it is a very concise "quote" command and "uplevel" command which is s
by theamk 5y ago
If I am reading this right, TCL's approach is neither FEXPRs nor Lisp's macros -- instead, it is a very concise "quote" command and "uplevel" command which is something I have not seen widely used in any other language.
In the lisp terms, imagine a language with no macros and with immediate evaluation ("applicatives" in the Kernel-speak). And no special forms either, except for syntax-level quote command. This means that, for example, for "if" you have to quote the code parameters to make sure they are not evaluated too early:
(if var '(print '(hello world)) nil)
the naive implementation has an obvious problem with variable scope, which you solve with "uplevel" command which evaluates expression in caller's scope. So there really is no difference in the data vs code, syntax-wise -- the first quote in the example above defines the "code" while second one defines "data", and only the function implementation knows how each argument will be used.
And that's how you build a language with homoiconicity and macro-like facilities, but without FEXPRs or applicatives or special syntax. Granted, it has plenty of downside, but it's still a very interesting approach.
- bsder 5y agoIn my opinion, there are two big things that Kernel brings to the table: 1) Arguments are not automatically evaluated before being passed to the underlying "operative" in Kernel-speak. This is important because it obviates the need for the macro machinery. This is fairly similar to Tcl. 2) Environments are first-class in Kernel. This is important because you can now constrain the scope explicitly. Do I want to evaluate this in the defining context (lexical scope)? Do I want to evaluate this in the calling context (dynamic scope)? Do I want to evaluate this is global or initial scope? All of these things are possible because environments are a thing that can be passed around. The downside is that this level of mutability seems to constrain the ability to pre-compile things. One of the "problems" that I would consider Tcl to have is that certain "atoms" don't self-evaluate. There's really no good reason for why you have to write: % if 1 {expr 2} else {expr 3} instead of % if 1 2 else 3 And no good reason why you can't write: % + 1 2 3 instead of % expr 1 + 2 3 This seems like going gratuitously out of the way to avoid "looking like Lisp" which was in its down phase by 1990.
- mst 5y agoNote that Tcl 8.5 added a mathop package https://www.tcl.tk/man/tcl8.5/TclCmd/mathop.html https://www.tcl.tk/man/tcl8.5/TclCmd/mathop.html which means you absolutely can write [+ 1 2] now if you import the relevant procs.