From: Joerg-Cyril Hoehle
Subject: no need for macros in tcl because it's all FEXPR?
Date: 
Message-ID: <qkp3dyqhwdg.fsf@tzd.dont.telekom.spam.de.me>
Hello,

I'm trying to understand why people can claim they need no macros in
tcl and yet they can create every control structure they feel a need
for, and how they can claim they appreciate tcl's regularity in this
context.

This makes me think that the execution of procedures in tcl is similar
to Lisp's old, old (the Seventies) FEXPR: in contrast to an EXPR as
created with DEFUN (or DE or whatever the name) which gets all
arguments evaluated, the code written by the user inside a DF would
get all the arguments unevaluated and manipulate them itself.

As the manipulation happened at run-time, this wouldn't work without
EVAL.  Access to variables then was easy because of dynamic binding.

(DF PLUS args	; + with any number of arguments
  (cond ((zerop (length args)) 0)
	((= 1 (length args)) (EVAL (car args)))
	(t (built-in-binary+-SUBR
	    (EVAL (car args))
	    (EVAL (cons 'PLUS (cdr args)))))))

It's only some time later that people realized that macros were a much
superior mechanism for implementing control structures, declarative
contructs and all other things.  The separation of compile and
run-time only then became easy, benefited to lexical variables and
many other areas, the FAQ became an entry "you very probably did wrong
if you think you need EVAL", etc.

Any tcl knowledgeable people in this Lisp group care to explain?

Thanks,
	Jorg Hohle
Telekom Research Center -- SW-Reliability

From: Tim Bradshaw
Subject: Re: no need for macros in tcl because it's all FEXPR?
Date: 
Message-ID: <nkjd7xu2d0m.fsf@tfeb.org>
············@tzd.dont.telekom.spam.de.me (Joerg-Cyril Hoehle) writes:


> This makes me think that the execution of procedures in tcl is similar
> to Lisp's old, old (the Seventies) FEXPR: in contrast to an EXPR as
> created with DEFUN (or DE or whatever the name) which gets all
> arguments evaluated, the code written by the user inside a DF would
> get all the arguments unevaluated and manipulate them itself.
> 

I'm not a tcl person but this was exactly the understanding I got from
the recent discussion -- in TCL everything is a FEXPR and you call
EVAL when you need to.  In addition there may be some special syntax
(perhaps [..]?) which will call eval for you.  However (and TCL people
will correct me, no doubt) tcl does not actually have dynamic binding
--- or rather dynamic variable lookup -- instead you have this strange
upvar stuff which lets you peek up the binding stack yourself.

--tim
From: Ian Wild
Subject: Re: no need for macros in tcl because it's all FEXPR?
Date: 
Message-ID: <378DFF87.6F385855@cfmu.eurocontrol.be>
Tim Bradshaw wrote:
> 
> ············@tzd.dont.telekom.spam.de.me (Joerg-Cyril Hoehle) writes:
> 
> > This makes me think that the execution of procedures in tcl is similar
> > to Lisp's old, old (the Seventies) FEXPR: in contrast to an EXPR as
> > created with DEFUN (or DE or whatever the name) which gets all
> > arguments evaluated, the code written by the user inside a DF would
> > get all the arguments unevaluated and manipulate them itself.
> >
> 
> I'm not a tcl person but this was exactly the understanding I got from
> the recent discussion -- in TCL everything is a FEXPR and you call
> EVAL when you need to.  In addition there may be some special syntax
> (perhaps [..]?) which will call eval for you.  However (and TCL people
> will correct me, no doubt) tcl does not actually have dynamic binding
> --- or rather dynamic variable lookup -- instead you have this strange
> upvar stuff which lets you peek up the binding stack yourself.


I'm not sure I'm a Tcl person as such, but I've used both
it and Lisp enough to have a feel for what's going on.
Now let's see if I can write it down...

The parsing model is more-or-less the same as /bin/sh:
$ substitutes variables, whitespace separates tokens,
double quotes turn off the whitespace effect but allow
the $ effect.  The single-quote (turn off $ and space)
is spelled {} (curly brackets).  Backticks (command
substitution) is spelled [] (square brackets).

Execution is also much the same as in the shell, in
that once you've parsed the line into tokens you accuse the
first token of being a verb and make it take responsibility
for the others.  For example, in:

my_if {2 < 3} {
  set status OK
} else {
  set status "Oh dear ..."
}

the "my_if" procedure gets passed 4 args, the first
being the string "2 < 3", etc.

To be useful, "my_if" is going to try to evaluate
some of the curly-bracketted expressions, but, to
do it right it needs to be done in its *caller's*
context, not the local one.  For this it'll use the
"uplevel" command, which takes an expression and 
(optionally) a stack level.  One implementation
of "my_if" would be:

proc my_if {condition then_part dummy else_part} {
  if [uplevel $condition] {
    uplevel $then_part
  } else {
    uplevel $else_part
  }
}

As you can see, it's not quite a FEXPR ('cos the
dollar bit gets done too early), but nor is it
a macro (the evaluation is too late).

That's not quite enough to do *all* the usual
control flow operations, though.  Stuff like
"return", "break", and "continue" are implemented
as catchable exceptions, just like errors.  If
you need to, you can add your own:

proc my_break {} {
  return -code 3
}

Now "my_break" behaves just like "break" in
loops, switches, etc.  (Hmmm, I /think/
the number for "break" is 3...)