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.
(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 84
This 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 1
How would you implement quasi-quotation in Tcl?