Scheme is derivate of Lisp. A programming language with even less syntax than Tcl itself. (but special forms and the like...? RS)
wdb: I strongly disagree that Scheme has less syntax than Tcl! Reason: the symbols have a value per se. Tcl has no symbols as $varname is just a shortcut for [set varname] where varname is just a constant, and the procedure addressed by set carries all the semantics. In Tcl, the command list unknown returns unknown because it is a constant. In Scheme, (list unknown) throws an error unless a symbol unknown is defined. If you want to list an unknown symbol, indeed, you need the special form (quote unknown) resp. its shortcut 'unknown.
proc quote x {
set x
}(Thank you, RS, for the hint with the combinator Identity!)
One interesting difference is that setting of (only global?) variables and function definition both are done with define, which creates a lambda if its first element is a list. Just for experimenting, here's how to have that in Tcl:
proc define {what how} {
if {[llength $what] == 1} {
uplevel 1 set $what [list $how]
} else {
proc [lindex $what 0] [lrange $what 1 end] $how
}
}% define x 42
42
% define {+ x y} {expr {$x+$y}}
% + $x $x
84This prevents us from having spaces in variable names (not a big problem), but presents the function name and arguments in one list, similar to how it will later be called - people sometimes wonder why we define proc foo {x y} {..} but call it foo $x $y...
silas 2018-11-14: LISP has the quote operator ('), as described above, but also has the backquote operator (`) that does what (in Scheme parlance) is called quasi-quotation. It will not eval anything unless lists followed by commas. Take the following Scheme code as an example:
(define (nl) (display "\n")) (define x 10) (define v '(display x)) (display v) (nl) (eval v) (nl) (define a 20) (define y `(display ,(+ a 10))) (display y) (nl) (eval y) (nl) ; Output is: ; (display x) ; 10 ; (display 30) ; 30
In Tcl I've stumbled upon situations where I needed something similar. Usually people use eval "..." and escape \$ and [ when don't want it to be evaluated, but it can lead to more or less unreadable code. I wrote a small method called xset that works just like set, but replaces variables that start with @:
proc xset {var body} {
# Look for own @ identifiers in $body
set my_identifiers [regexp -inline -all {@[[:alpha:]]+} $body]
set my_identifiers [lsort -unique $my_identifiers]
set map_list [list]
# Builds the map_list variable
foreach my_ident $my_identifiers {
set ident [string map [list "@" ""] $my_ident]
upvar 1 $ident x
# If upvar'ed variable does not exist, raise an error.
if {[catch {lappend map_list $my_ident $x}]} {
set raw_name [string map [list "@" ""] $my_ident]
return -code error \
-errorinfo "can't read $raw_name: no such variable"
}
}
# Make substitutions, set and return $body.
upvar 1 $var x
set body [string map $map_list $body]
set x $body
return $body
}And example to that would be:
set one 1
xset test {
set one "test"
set a $one
set b @one
}
puts $test
# outputs:
# set one "test"
# set a $one
# set b 1How would you implement quasi-quotation in Tcl?