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 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?