Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Call by Reference

88 views
Skip to first unread message

Andreas Leitgeb

unread,
Oct 19, 2007, 7:15:32 AM10/19/07
to
Actually, it's a trivial thing, but I wonder how others judge it:

proc newproc {name arglist body} {
set newbody ""
foreach arg $arglist {
set argname [lindex $arg 0]
if {[string match "&*" $argname]} {
set lbarearg [list [string range $argname 1 end]]
append newbody "upvar 1 \[set [list $argname]\] $lbarearg\n"
}
}
proc $name $arglist $newbody$body
}

The effect of this would be that if you define a procedure such:
newproc foo {&x y} { lappend x $y }
foo mylist bar; set mylist ;# --> bar
It would do the upvar'ing automatically.

Now, I even think this would be cool as a general feature in any
procedure, but despite its low likelyhood of breaking existing code
it's strictly an incompatible change, so probably something to save
up for 9.0 (at which point the added upvar wouldn't necessary show
up in [info body] explicitly, and even bytecode could be optimized,
and tools like nagelfar could then easily recognize the situation, too).

What do you think about it?

keithv

unread,
Oct 19, 2007, 8:07:15 AM10/19/07
to

Jan Kandziora

unread,
Oct 19, 2007, 4:30:19 PM10/19/07
to
Andreas Leitgeb schrieb:

>
> What do you think about it?
>
Sure it make things shorter, terse. It will lead Tcl down the Perl path,
where programs tend to become write-only.

No kidding, I think a fully fledged (and fast!) "macro" command, which
evaluates it's contents in the scope of the calling procedure -- besides
from variables defined some way inside the macro -- is more useful.

I my Tcl coding (so far some megabytes) I seldom had mixed call by
reference/call by value procs. Usually, all the parameters are passed by
value. The few times it's by reference, I like the idea of having an
explicit "upvar" with a big fat comment block above it.

Kind regards

Jan


Andreas Leitgeb

unread,
Oct 20, 2007, 3:44:50 AM10/20/07
to
keithv <kve...@gmail.com> wrote:
> On Oct 19, 7:15 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at> wrote:
>> proc newproc {name arglist body} {
>> set newbody ""
>> foreach arg $arglist {
>> set argname [lindex $arg 0]
>> if {[string match "&*" $argname]} {
>> set lbarearg [list [string range $argname 1 end]]
>> append newbody "upvar 1 \[set [list $argname]\] $lbarearg\n"
>> }
>> }
>> proc $name $arglist $newbody$body
>> }

Ok, so the idea is old (didn't know that), but I think my version
is more robust against noise-named parameternames than any of those
on wiki so far. :-)

Anyway, noone on the wiki pages really discussed feasibility of getting
the effect into 9.0's normal proc. This was actually the point of my
posting.

Alexandre Ferrieux

unread,
Oct 20, 2007, 4:39:25 AM10/20/07
to
On Oct 20, 9:44 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
>

> Anyway, noone on the wiki pages really discussed feasibility of getting
> the effect into 9.0's normal proc. This was actually the point of my
> posting.

Not sure I'd like it in normal proc, 9.0 or 12.0.
Two reasons:

(1) Orthogonality. This is just syntactic sugar for [upvar].
Redundancy in the core primitives is not a desirable thing when
there's no strong incentive.

(2) Efficiency of pure-Tcl solution. Since it is a "compile-time"
tweaking of a proc's body, the performance hit is minimal (it only
slows down the registering of the function, not its execution). So the
pure-Tcl solution is simply the best way of doing it. Just put it on
the wiki.

But personally, I like simplicity, and just a bit of naming discipline
and one extra line does it too:

proc f {x y va vb} {
upvar $va a $vb b
...
}

-Alex

Andreas Leitgeb

unread,
Oct 20, 2007, 5:09:46 AM10/20/07
to
Jan Kandziora <j...@gmx.de> wrote:
> Andreas Leitgeb schrieb:
>> What do you think about it?

> Sure it make things shorter, terse. It will lead Tcl down the Perl path,
> where programs tend to become write-only.

Oh, no. I think you're overdoing here, waving the "perl-path"-
warning-banner.

> No kidding, I think a fully fledged (and fast!) "macro" command, which
> evaluates it's contents in the scope of the calling procedure -- besides
> from variables defined some way inside the macro -- is more useful.

This surely isn't always desired where upvar-for-call-by-reference
pattern is used. I welcome the macro-idea but it's got nothing
to do with this here.

> I my Tcl coding (so far some megabytes) I seldom had mixed call by
> reference/call by value procs.

Just because the new mechanism would make it simple to do it, doesn't
mean, that one would deliberately make the argument list more chaotic
than necessary. Also, there is no urge to refrain from explicit upvar.
The incompatibility would only hit people, whose procedure have a
&var parameter, and then use "var" as a normal non-linked local
variable. Even repeating the upvar does *not* hurt!

> Usually, all the parameters are passed by value. The few times it's
> by reference,

And it's good to see this already in the parameter list, when a
parameter is intended to be only used for passing a variable name.

Currently, everyone has his own way of flagging such parameters,
like _list, listn, listVar, listName, vlist, nlist,... but generally
not &list, because it is too clumsy to pass that to upvar ($&list
doesn't work and ${&list} is really too much line-noise).

With that change, people would tend to use &list out of sheer
creative laziness (since it saves the explicit upvar), and once
it's established, var-parameters are seen at first glance, with
no need to look into the procedure's body for upvars.

> I like the idea of having an
> explicit "upvar" with a big fat comment block above it.

Big fat comment-blocks are still hard to decipher for static-analysis-
tools like e.g. nagelfar.

Andreas Leitgeb

unread,
Oct 20, 2007, 5:17:56 AM10/20/07
to
Alexandre Ferrieux <alexandre...@gmail.com> wrote:
>> Anyway, noone on the wiki pages really discussed feasibility of getting
>> the effect into 9.0's normal proc. This was actually the point of my
>> posting.

> (1) Orthogonality. This is just syntactic sugar for [upvar].
I never mind tcl-experience to be even more sweetened :-)

It's more than just syntactic sugar. It's also a "guide" to
consistent reference-parameter-naming, for overall improved
readability (even of other's code).

> Redundancy in the core primitives is not a desirable thing when
> there's no strong incentive.

Right, but I find the incentive strong :-)
(Admittedly not quite as strong as for {*}-syntax, but still)

> (2) Efficiency of pure-Tcl solution. Since it is a "compile-time"
> tweaking of a proc's body, the performance hit is minimal

Performance wasn't my primary objective this time.

> proc f {x y va vb} {
> upvar $va a $vb b

Congrats to the \infinity+1st style of ref-parameter naming.

Alexandre Ferrieux

unread,
Oct 20, 2007, 5:40:46 AM10/20/07
to
On Oct 20, 11:17 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> >

> > (2) Efficiency of pure-Tcl solution. Since it is a "compile-time"
> > tweaking of a proc's body, the performance hit is minimal
>
> Performance wasn't my primary objective this time.

Then why ask a core modification when a pure-script does it ?

> > proc f {x y va vb} {
> > upvar $va a $vb b
> Congrats to the \infinity+1st style of ref-parameter naming.

The point is not originality; it's conciseness and readability.
You'll have a hard time wedging a core change for (a) minimal
stylistic improvement and (b) zero performance gain (and (c) loss of
orthogonality).

-Alex


Andreas Leitgeb

unread,
Oct 20, 2007, 8:18:42 AM10/20/07
to
Alexandre Ferrieux <alexandre...@gmail.com> wrote:
> On Oct 20, 11:17 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
>> > (2) Efficiency of pure-Tcl solution. Since it is a "compile-time"
>> > tweaking of a proc's body, the performance hit is minimal
>> Performance wasn't my primary objective this time.
> Then why ask a core modification when a pure-script does it ?

Because it would allow to write scripts in a favourable way.
(That's what I strictly believe it would)

All these "I write a procedure to override some builtin"-tips
are cool for playing, or for doing things that other languages
call "instrumentation", but it's not a way to improve the
language itself (as seen by a new programmer).

The current thing is not a dodekalogue change, but only a change
in the proc command, of which I try to convince that it is
desirable enough to make it available without first having to
overwrite proc.

>> > proc f {x y va vb} {
>> > upvar $va a $vb b
>> Congrats to the \infinity+1st style of ref-parameter naming.
> The point is not originality;

I think it is. The point is, that everyone uses different
more or less consistent schemes for referential parameters,
and in the end you always need to look into the body for
occurrances of upvar.

upvar is a very intrusive tool, since it allows to access
arbitrary variables in arbitrary caller scopes.
Having to use this sledgehammer for every half-inch nail
is something I'd like to change, and I think that by sugar-
coating the harmless usage for references, all the remaining
uses of upvar can be better reviewed, as is the case with
{*} and the other sledgehammer "eval".

My view on this is mostly biased towards how I think
tcl-script would look better, and the language be more
attractive. This is a question of weighing simpler scripts
against simpler (in the sense of less-featured) language.

pro1: clearer scripts (ref-parms are more evident)
pro2: less use of sledgehammer-tools, where a typo
can create hard-to-find bugs

con1: yet another feature to the language (actually "proc")
con2: (very remote) possibility of incompatibility.

Alexandre Ferrieux

unread,
Oct 20, 2007, 2:02:14 PM10/20/07
to
On Oct 20, 2:18 pm, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:

> This is a question of weighing simpler scripts
> against simpler (in the sense of less-featured) language.

Yeah. Less-featured like Lisp with its poor CAR and CDR as only list-
manipulation primitives and everything else in the library.

You might be surprised that on the wiki, people are interested in the
minimal set of primitives necessary to build the rest:

http://wiki.tcl.tk/15051

Others (or the same ;-) also seek minimality of code for its own sake

http://wiki.tcl.tk/1363

But of course you're free to prefer polishing the surface, so that the
language becomes "attractive".

-Alex

Andreas Leitgeb

unread,
Oct 20, 2007, 5:50:41 PM10/20/07
to
Alexandre Ferrieux <alexandre...@gmail.com> wrote:
> On Oct 20, 2:18 pm, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
>> This is a question of weighing simpler scripts
>> against simpler (in the sense of less-featured) language.
>
> Yeah. Less-featured like Lisp with its poor CAR and CDR as only list-
> manipulation primitives and everything else in the library.

How many programmers are there who restrict themselves to CAR and CDR ?
Anyway, they already do have lisp, and won't switch to tcl, even if we
cut away everything down to [car ...] and [cdr ...].

> You might be surprised that on the wiki, people are interested in the
> minimal set of primitives necessary to build the rest:
> http://wiki.tcl.tk/15051
> Others (or the same ;-) also seek minimality of code for its own sake
> http://wiki.tcl.tk/1363

They build on old versions, anyway, so it doesn't matter if we make
the newer versions a smoother place for programmers rather than for
minimizers and language theoretics.

> But of course you're free to prefer polishing the surface, so that the
> language becomes "attractive".

Yes, indeed that's my goal. - I guess not only my own.

Alexandre Ferrieux

unread,
Oct 20, 2007, 6:39:24 PM10/20/07
to
On Oct 20, 11:50 pm, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:

> Alexandre Ferrieux <alexandre.ferri...@gmail.com> wrote:
>
> > Yeah. Less-featured like Lisp with its poor CAR and CDR as only list-
> > manipulation primitives and everything else in the library.
>
> How many programmers are there who restrict themselves to CAR and CDR ?
> Anyway, they already do have lisp, and won't switch to tcl, even if we
> cut away everything down to [car ...] and [cdr ...].

You're not getting it, eh ? Nobody's talking about *restricting* to
CAR/CDR;
Instead it's all about keeping in mind the boundary between primitives
and non-primitives.
In Lisp zillions of list-handling functions have been defined, but in
Lisp, not in C...

Why does this matter ? Because only the C part ever has to be ported,
profiled, optimized, in a platform-dependent way (which is time-
consuming).

> > You might be surprised that on the wiki, people are interested in the
> > minimal set of primitives necessary to build the rest:
> > http://wiki.tcl.tk/15051
> > Others (or the same ;-) also seek minimality of code for its own sake
> > http://wiki.tcl.tk/1363
>
> They build on old versions, anyway, so it doesn't matter if we make
> the newer versions a smoother place for programmers rather than for
> minimizers and language theoretics.

Oh sure, you're turning to a bright future with only 3GHz quad-cores,
right ?
Small devices are uninteresting ?

A massive Tcl for the masses -- scary...

-Alex

tom.rmadilo

unread,
Oct 20, 2007, 9:06:45 PM10/20/07
to
On Oct 19, 4:15 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:

I got somewhat bored trying to figure out the best way to express the
basic flaw in this idea. So I gave up and decided to select a random
week of John Baez physics blog. And a nice analogy was right there, so
I thought I'd quote it:

From: http://math.ucr.edu/home/baez/week200.html

You see, in logic there are many levels of what you might call
"strength" or "expressive power", ranging from wimpy languages that
don't let you say very much and deduction rules that don't let you
prove very much, to ultra-powerful ones that let you do all sorts of
marvelous things. Near the bottom of this hierarchy there's the
"propositional calculus" where we only get to say things like

((P implies Q) and (not Q)) implies (not P)

Further up there's the "first-order predicate calculus", where we get
to say things like

for all x (for all y ((x = y and P(x)) implies P(y)))

Even further up, there's the "second-order predicate calculus" where
we get to quantify over predicates and say things like

for all x (for all y (for all P (P(x) iff P(y)) implies x = y))

Etcetera...

And, while you might think it's always best to use the most powerful
form of logic you can afford, this turns out not to be true!

One reason is that the more powerful your logic is, the fewer
categories can contain models of theories expressed in this logic.
This point may sound esoteric, but the underlying principle should be
familiar. Which is better: a hand-operated drill, an electric drill,
or a drill press? A drill press is the most powerful. But I forgot to
mention: you're using it to board up broken windows after a storm. You
can't carry a drill press around, so now the electric drill sounds
best. But another thing: this is in rural Ghana! With no electricity,
now the hand-operated drill is your tool of choice.

In short, there's a tradeoff between power and flexibility.
Specialized tools can be powerful, but they only operate in a limited
context. These days we're all painfully aware of this from using
computers: fancy software only works in a fancy environment!

.........


Andreas Leitgeb

unread,
Oct 21, 2007, 3:53:45 AM10/21/07
to
Alexandre Ferrieux <alexandre...@gmail.com> wrote:
> On Oct 20, 11:50 pm, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
>> Alexandre Ferrieux <alexandre.ferri...@gmail.com> wrote:
> You're not getting it, eh ?

I do get it, but I interpret it differently.
It's not as if I suggested adding an encyclopedia into the core.
Instead I suggested, what I think is a really smallish change, with
a nice effect on scripters' experience.

I'd rather have a fundamental discussion about whether
proc addfoo {&list} {lappend list "foo"}
would be a generally good feature or not. I think it
is, you seem to disagree.

> Instead it's all about keeping in mind the boundary between primitives
> and non-primitives.

Ok, lots of tcl's features are implemented in C, although they could
have been implemented in tcl, like e.g. bignums. Of course, for
bignums, speed is some issue, but it means that *some* tradeoff
is made between minimality of "C-implemented" core and practical aspects.

Anyway, discussion isn't yet about implementation, maybe the
implementation of that feature could even be done in pure tcl.

> Oh sure, you're turning to a bright future with only 3GHz quad-cores,

You know that todays' embedded platforms are faster than what appeared
as a "wow!"-hardware about ten years ago?
Tcl8.5 no longer exists for MacOS pre-X (which I personally found a
pity), so your scenario is quite likely to happen sooner or later,
anyway. And it isn't even accellerated by a change in dealing with
a proc's parameters.

Andreas Leitgeb

unread,
Oct 21, 2007, 4:06:47 AM10/21/07
to
tom.rmadilo <tom.r...@gmail.com> wrote:
>> What do you think about it?
> I got somewhat bored trying to figure out the best way to express the
> basic flaw in this idea. So I gave up ...
> [quote from John Baez follows]

> And, while you might think it's always best to use the most powerful
> form of logic you can afford, this turns out not to be true!

So far I agree. But I find it irrelevant here.

> This point may sound esoteric, but the underlying principle should be
> familiar. Which is better: a hand-operated drill, an electric drill,
> or a drill press?

My suggestion is about creasing the handoperated drill that we have
for easier drive.

Joe English

unread,
Oct 21, 2007, 10:47:27 AM10/21/07
to
Andreas Leitgeb wrote:
>
>I do get it, but I interpret it differently.
>It's not as if I suggested adding an encyclopedia into the core.
>Instead I suggested, what I think is a really smallish change, with
>a nice effect on scripters' experience.
>
>I'd rather have a fundamental discussion about whether
> proc addfoo {&list} {lappend list "foo"}
>would be a generally good feature or not. [...]

My two cents: that's not a bad idea.

(Not yet convinced that it's a *good* idea, but am pretty
sure it's at least not a *bad* one :-)

Besides the advantages you've mentioned (not using the
sledgehammer of [upvar] to crack the nut of pass-by-name
parameters, improved perspicuity, etc.), this would also
be useful for syntax-checkers: having seen the definition
[proc addfoo {&list} {...}], they would be able to know
to flag calls like [addfoo $list] as potential errors.


--Joe English

Alan Anderson

unread,
Oct 21, 2007, 7:06:11 PM10/21/07
to
In article <slrnfhm1c...@gamma.logic.tuwien.ac.at>,
Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at> wrote:

> I'd rather have a fundamental discussion about whether
> proc addfoo {&list} {lappend list "foo"}
> would be a generally good feature or not. I think it
> is, you seem to disagree.

I don't see the point in adding such a feature to the core. If you want
to do it yourself, nobody is stopping you, and indeed several people are
willing to help you come up with good ways to implement it. But there
doesn't seem to be a compelling reason to add an unobvious piece of
syntax just to avoid having to put an upvar command somewhere in the
code.

Bruce Hartweg

unread,
Oct 22, 2007, 2:13:39 AM10/22/07
to

OK, second reference of the "sledgehammer" of upvar to crack
nut of pass by reference. But to me it looks a lot more like
using a phillips screwdriver to drive a phillips screw. What
numerous other big problems is upvar used for tha is not pass
by reference? (or more literally pass by name)

Bruce

dav...@dedasys.com

unread,
Oct 22, 2007, 2:45:35 AM10/22/07
to
On Oct 21, 4:47 pm, jengl...@flightlab.com (Joe English) wrote:
> Andreas Leitgeb wrote:
>
> >I do get it, but I interpret it differently.
> >It's not as if I suggested adding an encyclopedia into the core.
> >Instead I suggested, what I think is a really smallish change, with
> >a nice effect on scripters' experience.
>
> >I'd rather have a fundamental discussion about whether
> > proc addfoo {&list} {lappend list "foo"}
> >would be a generally good feature or not. [...]
>
> My two cents: that's not a bad idea.
>
> (Not yet convinced that it's a *good* idea, but am pretty
> sure it's at least not a *bad* one :-)

+1 - I've been considering something like this for Hecl.

Do you guys think this 'abstraction' would leak, or not? Are people
going to be able to get it without having to go back and read up on
upvar anyway?

Alexandre Ferrieux

unread,
Oct 22, 2007, 2:46:31 AM10/22/07
to
On Oct 21, 4:47 pm, jengl...@flightlab.com (Joe English) wrote:
>
> Besides the advantages you've mentioned (not using the
> sledgehammer of [upvar] to crack the nut of pass-by-name
> parameters, improved perspicuity, etc.), this would also

Besides the drawback already mentioned (redundancy), which in itself
is nonnegliglible, it is also opening the (nearly) virgin space of
"special things" in Tcl. To somebody discovering Tcl, which the move
apparently targets, I'm not convinced that a description like

There are two kinds of arguments: those passed by value and those
by name

adds much clarity to a language where otherwise Everything Is A String
(Value, including var names).

Now, I do respect the nostalgy of lower level languages from which the
"&" notation is extracted, but if a given application is so much
asking for the feature, then (1) maybe it's a hint that it would
deserve some refactoring, and (2) adding Andreas's exemplary pure-Tcl
implementation to the head of the script looks like the best
solution...

> be useful for syntax-checkers: having seen the definition
> [proc addfoo {&list} {...}], they would be able to know
> to flag calls like [addfoo $list] as potential errors.

Yes but the same syntax-checkers can already spot "upvars" at the
beginning of the body, which should cover 99% of cases.

-Alex

suchenwi

unread,
Oct 22, 2007, 4:35:32 AM10/22/07
to
On 20 Okt., 10:39, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
wrote:

> But personally, I like simplicity, and just a bit of naming discipline
> and one extra line does it too:
>
> proc f {x y va vb} {
> upvar $va a $vb b
> ...
> }
Warning, however: it is more robust to always specify the upvar level
(typically 1). Consider:
proc f {_x y} {
upvar $_x x
set x $y
}
88 % f 1 2
wrong # args: should be "upvar ?level? otherVar localVar ?otherVar
localVar ...?"

This may have been a pilot error by the caller, or intended - the
caller wants a variable called "1" (which makes sense e.g. when
emulating sh/awk scripts).


Gerald W. Lester

unread,
Oct 22, 2007, 8:55:45 AM10/22/07
to
Joe English wrote:
> Andreas Leitgeb wrote:
>> I do get it, but I interpret it differently.
>> It's not as if I suggested adding an encyclopedia into the core.
>> Instead I suggested, what I think is a really smallish change, with
>> a nice effect on scripters' experience.
>>
>> I'd rather have a fundamental discussion about whether
>> proc addfoo {&list} {lappend list "foo"}
>> would be a generally good feature or not. [...]
>
> My two cents: that's not a bad idea.
>
> (Not yet convinced that it's a *good* idea, but am pretty
> sure it's at least not a *bad* one :-)
>
> Besides the advantages you've mentioned (not using the
> sledgehammer of [upvar] to crack the nut of pass-by-name

Joe, this address pass-by-reference *not* pass-by-name.

> parameters, improved perspicuity, etc.), this would also
> be useful for syntax-checkers: having seen the definition
> [proc addfoo {&list} {...}], they would be able to know
> to flag calls like [addfoo $list] as potential errors.

What if "$list" contained the name of a variable that was built up from
pieces (e.g. the parameters to a trace callback)?

If we are going to do special syntax for pass-by-reference (so people can
not have to learn the upvar command -- not sure why it is being referred to
as a "sledgehammer") do we also introduce special syntax for pass-by-name
so people do have to use uplevel?


--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+

Donal K. Fellows

unread,
Oct 22, 2007, 12:16:18 PM10/22/07
to
Gerald W. Lester wrote:
> What if "$list" contained the name of a variable that was built up from
> pieces (e.g. the parameters to a trace callback)?

That's a rarer case, and syntax checkers are known to be not perfect.
Which is why they'd only be able to issue a warning in that case
anyway.

Donal.

Andreas Leitgeb

unread,
Oct 22, 2007, 12:17:36 PM10/22/07
to
Bruce Hartweg <bruce...@hartweg.us> wrote:

> Joe English wrote:
>> Besides the advantages you've mentioned (not using the
>> sledgehammer of [upvar] to crack the nut of pass-by-name
>> parameters, ...

>
> OK, second reference of the "sledgehammer" of upvar to crack
> nut of pass by reference. But to me it looks a lot more like
> using a phillips screwdriver to drive a phillips screw. What
> numerous other big problems is upvar used for tha is not pass
> by reference? (or more literally pass by name)

What makes upvar a sledgehammer is, that the name of the variable
you link from "outside" does not need to have been passed in through
a parameter, nor does it need to be from caller's stackframe.

It doesn't even need to be a previously existing variable.

It's power could be compared to java's "reflection" (which is also
a sledgehammer, but much less idly used.)

Don't misunderstand me, it's a powerful feature that tcl shouldn't
miss, but which would be good if simple tcl-scripts wouldn't need
just to achieve simple tasks like call-by-varname.

Andreas Leitgeb

unread,
Oct 22, 2007, 12:34:43 PM10/22/07
to
dav...@dedasys.com <dav...@dedasys.com> wrote:
> On Oct 21, 4:47 pm, jengl...@flightlab.com (Joe English) wrote:
>> Andreas Leitgeb wrote:
>> >I'd rather have a fundamental discussion about whether
>> > proc addfoo {&list} {lappend list "foo"}
>> >would be a generally good feature or not. [...]

>> My two cents: that's not a bad idea.
>> (Not yet convinced that it's a *good* idea, but am pretty
>> sure it's at least not a *bad* one :-)
>
> +1 - I've been considering something like this for Hecl.

I think, that feature of hecl is still somewhat different, from
what we're discussing here. (I think to remember faintly your
description of hecl-references in threads years ago)

The feature I proposed is indeed nothing more than syntactic sugar
for the common task of using upvar to "convert" the value of a
parameter to what looks like a local variable.

The caller of such a procedure would still pass the variable-name
as a string; the only new thing being different is that the upvar
is called *transparently* with a certain set of arguments that
reduces risk of typos in the arguments to current explicit upvar.

> Are people going to be able to get it without having to go
> back and read up on upvar anyway?

That's indeed a good question.
Those C & C++ people surely will understand it instantly, but
what about all others? It depends on what description we come
up with to document it. That might just refer to upvar, or
describe the special effect of the transparent upvar that
actually happens.

I'm also aware, that not being able to explain the new feature to
newbies (especially those without C/C++ background) would be a real
showstopper for this feature.

tom.rmadilo

unread,
Oct 22, 2007, 12:48:50 PM10/22/07
to
On Oct 21, 1:06 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:

> tom.rmadilo <tom.rmad...@gmail.com> wrote:
> > This point may sound esoteric, but the underlying principle should be
> > familiar. Which is better: a hand-operated drill, an electric drill,
> > or a drill press?
>
> My suggestion is about creasing the handoperated drill that we have
> for easier drive.

So the idea didn't sink in? We already have exactly what you want in
Tcl. You are confusing Tcl with other languages, and you are focusing
on something you see as a problem without understanding how Tcl has
solved this issue. Worse is it that your solution completely changes
the clean syntax. Whenever you start referencing how other languages
do xyz, just remember: Tcl isn't those other languages, thank goodness
for that.

Here is the basic concept: don't encode information into variable
names or any names in Tcl. Don't encode type information, don't encode
things that you think exist in Tcl (which don't). Strings don't become
variable names until they are used as variable names

You may think this is off base, but consider several commands: lappend
and linsert. Lappend take the name of a list, but linsert takes the
actual list. Your suggestion would be that lappend would change so
that you would do [lappend &mylist a b c]. Otherwise you have a major
distinction between pass by ref and by name. Then we could move on to
the array functions [array get &myarray]. Wow, that looks so cool. If
you don't require this, then you have two different ways of writing
commands. Or maybe you think there should be a difference between
procs (defined by proc) and commands? I don't.

You might try looking at namespaces if you don't like upvar. It is
just like a named stack/level. And it maintains state for you.

Also, there are no *small* syntax changes. You are doubling the number
of ways to pass information.

Andreas Leitgeb

unread,
Oct 22, 2007, 1:03:48 PM10/22/07
to
Alexandre Ferrieux <alexandre...@gmail.com> wrote:
> Besides the drawback already mentioned (redundancy), which in itself
> is nonnegliglible, it is also opening the (nearly) virgin space of
> "special things" in Tcl.

If it gets implemented such that the upvar's are generated
into the body (and thus visible in [info body ...]) then it's
not a "special thing in tcl", but rather a special thing in the
predefined command "proc".
If it's done really transparently, then yes, then it is a
"tcl special thing"

> To somebody discovering Tcl, which the move
> apparently targets, I'm not convinced that a description like
> There are two kinds of arguments: those passed by value and those by name

For a newbie, the concept of linking outside variables into the current
stackframe isn't a breeze, either. Rather than confronting them with the
whole generality of upvar (of which they'd hardly ever need anything
than "upvar 1 $parameter lclvar ..."), the distinction between normal
and '&'-padded parameter names is likely indeed a breeze.

"
Normally, parameters are passed by value.
If a procedure takes a parameter whose name starts with a '&',
like &par, then it is meant to pass in the variable as such.
Inside the procedure, par is then linked to a caller's variable
whose name was given for &par in the call to the procedure.
For general information about linking variables, see command "upvar".
"

> Now, I do respect the nostalgy of lower level languages from which the
> "&" notation is extracted, but if a given application is so much
> asking for the feature, then (1) maybe it's a hint that it would
> deserve some refactoring, and (2) adding Andreas's exemplary pure-Tcl
> implementation to the head of the script looks like the best
> solution...

The point is not, whether a single application is asking for it, but
whether it will be decided that "Tcl" should be like that.

>> be useful for syntax-checkers: having seen the definition
>> [proc addfoo {&list} {...}], they would be able to know
>> to flag calls like [addfoo $list] as potential errors.
> Yes but the same syntax-checkers can already spot "upvars" at the
> beginning of the body, which should cover 99% of cases.

Do they?

tom.rmadilo

unread,
Oct 22, 2007, 1:13:27 PM10/22/07
to
On Oct 22, 9:34 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:

> The feature I proposed is indeed nothing more than syntactic sugar
> for the common task of using upvar to "convert" the value of a
> parameter to what looks like a local variable.

One other problem is that upvar allows you to use a local name for a
variable. Otherwise your procedure would never be able to take the
name of certain passed in names. That is why upvar is define as:

upvar ?level? otherVar myVar ?otherVar myVar ...?

Also, you have to consider the case where the proc is supposed to
create the variable in the caller's space. The correct way to do that
is to pass in a name. [Upvar a b] is saying more than pass by
reference, it is saying create/reference a one level up and link it to
b right here.

But the weird thing is that this only aids the developer. Once the
proc is written, who cares how it works? Instead, you impose a burdon
on users of your procedures to remember to use or not use an &. That
requires them to either read the documentation or look at the proc
body.

Andreas Leitgeb

unread,
Oct 22, 2007, 1:13:59 PM10/22/07
to
Gerald W. Lester <Gerald...@cox.net> wrote:
> Joe English wrote:
>> Andreas Leitgeb wrote:
>>> I'd rather have a fundamental discussion about whether
>>> proc addfoo {&list} {lappend list "foo"}
>>> would be a generally good feature or not. [...]
>> Besides the advantages you've mentioned (not using the
>> sledgehammer of [upvar] to crack the nut of pass-by-name
>
> Joe, this address pass-by-reference *not* pass-by-name.

Sorry, wrong. it is still pass-by-name. It's just that the
upvar happens transparently/automatically, then.

> What if "$list" contained the name of a variable that was built up from
> pieces (e.g. the parameters to a trace callback)?

That's one of the special cases, where you have to control that
particular tool directly. (e.g. if it knows about pedefined commands
like lappend, calling lappend with a $varName is just the same situation)

> If we are going to do special syntax for pass-by-reference (so people can
> not have to learn the upvar command -- not sure why it is being referred to
> as a "sledgehammer") do we also introduce special syntax for pass-by-name
> so people do have to use uplevel?

For the "sledgehammer", see my re-Subject-ed subthread.

I don't understand how uplevel gets into this discussion.
I don't have any plans for sugar-coating uplevel in any near future,
but wouldn't exclude that possibility for all future :-)

Andreas Leitgeb

unread,
Oct 22, 2007, 1:34:36 PM10/22/07
to
Sorry, I think you grossly misunderstood the proposal.

tom.rmadilo <tom.r...@gmail.com> wrote:
> One other problem is that upvar allows you to use a local name for a
> variable. Otherwise your procedure would never be able to take the
> name of certain passed in names. That is why upvar is define as:
> upvar ?level? otherVar myVar ?otherVar myVar ...?

% proc addfoo {&var} {append var "foo"}
% addfoo bar
foo
%
As you see, the only place where variable names are then given is,
that the local variable inside the procedure has the name of the
parameter-name (minus the &). This does not look like a big
restriction to me. There is no relation to the name of the
caller's local variable!

I snipped the rest, because I think it's void. If you check
above example, you'll likely agree.

It's really about passing names, which are then automatically upvar'ed.

Andreas Leitgeb

unread,
Oct 22, 2007, 1:40:45 PM10/22/07
to
tom.rmadilo <tom.r...@gmail.com> wrote:
> Your suggestion would be that lappend would change so
> that you would do [lappend &mylist a b c].

No, this *is not* my suggestion, and I really wouldn't
even want that for tcl!

I've posted examples of both proc-definition and usage
of my proposal almost every other post, so please reread
one of them, and discuss them, not some rubbish that I
would never suggest for tcl.

PS: what you describe is actually hecl's way, which is good
for hecl, but would be bad for tcl :-)

Bruce Hartweg

unread,
Oct 22, 2007, 1:42:07 PM10/22/07
to
Andreas Leitgeb wrote:
> Bruce Hartweg <bruce...@hartweg.us> wrote:
>> Joe English wrote:
>>> Besides the advantages you've mentioned (not using the
>>> sledgehammer of [upvar] to crack the nut of pass-by-name
>>> parameters, ...
>> OK, second reference of the "sledgehammer" of upvar to crack
>> nut of pass by reference. But to me it looks a lot more like
>> using a phillips screwdriver to drive a phillips screw. What
>> numerous other big problems is upvar used for tha is not pass
>> by reference? (or more literally pass by name)
>
> What makes upvar a sledgehammer is, that the name of the variable
> you link from "outside" does not need to have been passed in through
> a parameter, nor does it need to be from caller's stackframe.
>
> It doesn't even need to be a previously existing variable.
>

I know you *can* do them, but hard coding variable names in other scopes
is not a great idea, so I think if you look at existing code that the
large majority of it's usage is for pass by name, a small instance
of variable aliasing (within same scope, global scope, or fully
namespace scope) and extremely rare abuse case of someone doing
something tricky.

so I still think it is the right tool for the job - yes you can use a
screwdriver to punch a hole in the wall, or whack a nail, or pry
something apart, but it's still a screwdriver, and driving screws
is it's primary job.


Bruce

Gerald W. Lester

unread,
Oct 22, 2007, 1:52:10 PM10/22/07
to
Andreas Leitgeb wrote:
> Gerald W. Lester <Gerald...@cox.net> wrote:
>> Joe English wrote:
>>> Andreas Leitgeb wrote:
>>>> I'd rather have a fundamental discussion about whether
>>>> proc addfoo {&list} {lappend list "foo"}
>>>> would be a generally good feature or not. [...]
>>> Besides the advantages you've mentioned (not using the
>>> sledgehammer of [upvar] to crack the nut of pass-by-name
>> Joe, this address pass-by-reference *not* pass-by-name.
>
> Sorry, wrong. it is still pass-by-name. It's just that the
> upvar happens transparently/automatically, then.

I'm sorry I do not follow.

Upvar is used to implement pass-by-reference semantics.

Uplevel is used to implement pass-by-name semantics.

What does upvar have to do with pass-by-name semantics?

Andreas Leitgeb

unread,
Oct 22, 2007, 2:04:05 PM10/22/07
to
Bruce Hartweg <no.sp...@nowhere.org> wrote:
>> What makes upvar a sledgehammer is, that the name of the variable
>> you link from "outside" does not need to have been passed in through
>> a parameter, nor does it need to be from caller's stackframe.
>>
>> It doesn't even need to be a previously existing variable.
I forgot something:
The fact that the variable doesn't necessarily exist, is not in itself
bad, but it means that typos in the parameter list of upvar may even
more easily go unnoticed and instead cause some spurious variables to be
unexpectedly created somewhere.

> so I still think it is the right tool for the job - yes you can use a
> screwdriver to punch a hole in the wall, or whack a nail, or pry
> something apart, but it's still a screwdriver, and driving screws
> is it's primary job.

I find this other parable more apt:
An axe or chainsaw can be used for cutting wood, even of larger diameters.
For small twigs there exist better tools (twig cutters) with a lower
risk of anyone getting hurt, and the effort is also smaller...
The pass-by-name is just a small twig, compared to linking variables
from somewhere else.

Andreas Leitgeb

unread,
Oct 22, 2007, 2:16:32 PM10/22/07
to
Gerald W. Lester <Gerald...@cox.net> wrote:
> I'm sorry I do not follow.
> Upvar is used to implement pass-by-reference semantics.
I see, you see this from a different (can't say wrong)
point of view, so I'll try to clarify:

upvar:
% proc foo {vx} { upvar 1 $vx x; lappend x 42 }
% foo lclVar
In my eyes, *this* is call-by-*name*.

new feature:
% proc foo {&x} { lappend x 42 }
% foo lclVar
In my eyes, *this*, too, is call-by-*name*.

uplevel:
% proc foo {vx} { uplevel 1 [list lappend $vx 42] }
% foo lclVar
In my eyes, *this*, too, is call-by-*name*.

We're talking about the "passing" of information to the
procedure, not what happens inside the procedure.


Andreas Leitgeb

unread,
Oct 22, 2007, 2:22:58 PM10/22/07
to

I forgot to mention, that by "call-by-reference" I understand a
general concept known across many languages, which in tcl is done
as call-by-name, in absence of a reference-type. So in the
tcl-context I consider them equivalent, whereas e.g. in Hecl
context it's something different, and even more so in Java context
(where call-by-name means using reflection, and the name refers to
a method's name rather than a variable's name)


Darren New

unread,
Oct 22, 2007, 2:46:21 PM10/22/07
to
Bruce Hartweg wrote:
> I know you *can* do them, but hard coding variable names in other scopes
> is not a great idea,

I've used upvar in at least two "unusual" situations that I didn't pass
the names down.

1) When getting invoked as a CGI or as an SMTP handler, I had a routine
that would take all the variables from the headers (user-agent, or
subject:, for example) and create variables prefixed with SMTP_ or HTTP_
in the caller, for easy access:
access_headers
if {[info exists HTTP_content_length]} {
[read $in $HTTP_content_length]
}
if {[info exists SMTP_reply_to]} {
set destination $SMTP_reply_to
} else {
set destination $SMTP_from
}
Not unlike the way PHP used to work, except PHP was dumb enough not to
use a distinct namespace for such variables, so it turned into a headache.

2) When making a complex event-driven mechanism (as in, each event had
the possibility of doing something rather complex), I used it to suck
the parent's locals (from a distinct list) into each child in the chain,
as it prevented the use of globals that had to be cleaned up when the
transaction finished. Some of the routines were nested a number of
layers deep, and needed things like the name and password, the customer
ID, the transaction to be performed, a number of different "joins" from
database tables, instantiations of and interactions with COM objects,
shopping carts full of stuff being bought, and so on. Nowadays, passing
a [dict] full of stuff around might work better, but at the time, having
a list of names of arrays where things were stored and just sharing them
across stack frames made sense.

--
Darren New / San Diego, CA, USA (PST)
Remember the good old days, when we
used to complain about cryptography
being export-restricted?

Darren New

unread,
Oct 22, 2007, 2:53:25 PM10/22/07
to
Andreas Leitgeb wrote:
> Sorry, wrong. it is still pass-by-name.

Um, no. Call-by-name is distinctly different than call-by-reference.

proc foo {&thing &stuff} {set think 42; return $stuff}

set topthing 13
set stuff(13) "Is 13"
set stuff(42) "Is 42"
foo topthing stuff($topthing)

What does that return?

If it returns "Is 42", then it's call by name. If it returns "Is 13",
it's call by reference. You could *make* it pass-by-name, by putting
braces around the passed-by-name arguments and calling uplevel inside
foo, but upvar is pass by reference, not by name.

These words *do* have technical meanings. It's not a question of what it
means in your eyes. :-)

peter....@gmail.com

unread,
Oct 22, 2007, 3:02:19 PM10/22/07
to
On Oct 22, 7:03 pm, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:

> Alexandre Ferrieux <alexandre.ferri...@gmail.com> wrote:
>
> >> be useful for syntax-checkers: having seen the definition
> >> [proc addfoo {&list} {...}], they would be able to know
> >> to flag calls like [addfoo $list] as potential errors.
> > Yes but the same syntax-checkers can already spot "upvars" at the
> > beginning of the body, which should cover 99% of cases.
>
> Do they?

I can't speak for other syntax checkers but Nagelfar detects
standard upvar usage to figure out call-by-name. The tricky thing
when detecting that is to figure out if the variable is an input and/
or
an output. Such syntax wouldn't give much help there.

/Peter

Andreas Leitgeb

unread,
Oct 22, 2007, 3:34:35 PM10/22/07
to
Darren New <dn...@san.rr.com> wrote:
> [call-by-name or call-by-reference]

> These words *do* have technical meanings. It's not a question of what it
> means in your eyes. :-)

Ok, so if I say "call-by-name" it will be misunderstood by language
theorists (supported by http://en.wikipedia.org/wiki/Evaluation_strategy)

If instead I call it "call-by-reference" some others misunderstand me
as wishing to call "lappend &var elem ..." (which of course I *don't*!)

So I take it as how it makes most sense for tcl, which is:
either I call by value, with a "$var" on caller's side
or I call by reference/name, with just "var"
caller and callee must of course agree in their interpretation
of the argument, otherwise it won't work ...

What is described on the wiki-page as "call by name" would be very
clumsy to do in tcl. Also, tcl has no reference type as such, so
passing a *name* of a variable (to be effectively upvar'ed) is
as near to other languages' *references* as we can get in Tcl.

Can we now stop splitting hairs on these technical terms?
If I see someone asking about "call by reference", and see him
speculating about "lappend &var elem", then obviously he has
a different meaning of that term in mind, so "call-by-name"
might get him back on track on what this thread is about.

Gerald W. Lester

unread,
Oct 22, 2007, 3:40:32 PM10/22/07
to

I guess maybe the definitions have changed since the late 70s and early 80s.
Back then call-by-name was only implemented in algol 68 and refered to
being able to pass in a code block to a procedure that was then excuted in
the current scope.

As in:

proc RepeatUntilLoop {body condition} {
while {1} {
uplevel $body
if {[uplevel [list expr $condition]]} {
break
}
}
}

set x 100
RepeatUntilLoop {
puts $x
incr x -1
} {$x > 0}

Andreas Leitgeb

unread,
Oct 22, 2007, 3:43:10 PM10/22/07
to
Darren New <dn...@san.rr.com> wrote:
> Bruce Hartweg wrote:
>> I know you *can* do them, but hard coding variable names in other scopes
>> is not a great idea,
>
> I've used upvar in at least two "unusual" situations that I didn't pass
> the names down.

I hope you didn't post this in defense of "upvar". I don't mean to
harm it, just reduce it's usage to where it's really needed, like
in your examples.

Use twig cutters for twigs, and chainsaws for bigger wood.
Should I change the subject to chainsaw instead of sledgehammer?

tom.rmadilo

unread,
Oct 22, 2007, 4:30:53 PM10/22/07
to
Okay, now I am totally confused. In Tcl the name of a variable (or
proc) _is_ a reference. Somewhere behind the scenes the name points to
a hash entry. This benefits the caller, because they don't have to ask
for the pointer, they already have it. Also, Tcl requires that you ask
for the value of the reference when you want to use the value:
$name...the dollar operator returns the value of a reference.

Maybe this is why this idea is confusing me. In C you use the &
operator in client code, because you are asking the called function to
use your memory location. The client code sets up the memory, or at
least knows that it is setup, and then asks the caller to put
something in it, or maybe update it in place. But there are many
different reasons for this, which simply do not exist in Tcl. In other
words, & and * exist in C, but in Tcl we have $ to replace the *
operator. The & operator isn't needed.

The fact that in Tcl you can directly address any variable or proc by
name, or use the same name in different contexts to address different
procs is a good thing. Upvar is just one way to address a variable in
another context, and if developers are having trouble using it,
hopefully they will keep their code locked away until they can type in
a few extra lines of code.

Also, these upvar statements are very helpful documentation. It is
common to place them at the top of a proc body because they are
important, they are a major feature of Tcl programming. Hiding away
important features may seem cool, but it ain't. And, again, if
developers can't figure this out, just wait 'til they try to debug
their broken code. Suddently the hidden magic isn't such a great
thing.

So this is not syntactic sugar, but syntactic molasses.

Darren New

unread,
Oct 22, 2007, 5:00:26 PM10/22/07
to
Andreas Leitgeb wrote:
> Darren New <dn...@san.rr.com> wrote:
>> Bruce Hartweg wrote:
>>> I know you *can* do them, but hard coding variable names in other scopes
>>> is not a great idea,
>> I've used upvar in at least two "unusual" situations that I didn't pass
>> the names down.
>
> I hope you didn't post this in defense of "upvar".

I feel upvar is a useful tool. If you can't handle it, don't use it. :-)

I'm simply pointing out that there are places it's useful that aren't
"call by reference" that I wouldn't call "hacky" either. Or at least not
*too* hacky - the bit of looking upwards for events was pretty hacky. ;-)

I certainly would think it would be a bad move to say you could *only*
use it for pass-by-reference.

Bryan Oakley

unread,
Oct 22, 2007, 5:08:54 PM10/22/07
to
Darren New wrote:
> Andreas Leitgeb wrote:
>> Darren New <dn...@san.rr.com> wrote:
>>> Bruce Hartweg wrote:
>>>> I know you *can* do them, but hard coding variable names in other
>>>> scopes
>>>> is not a great idea,
>>> I've used upvar in at least two "unusual" situations that I didn't
>>> pass the names down.
>>
>> I hope you didn't post this in defense of "upvar".
>
> I feel upvar is a useful tool. If you can't handle it, don't use it. :-)
>
> I'm simply pointing out that there are places it's useful that aren't
> "call by reference" that I wouldn't call "hacky" either. Or at least not
> *too* hacky - the bit of looking upwards for events was pretty hacky. ;-)
>

I know I should stay out of this, but...

I use upvar a lot, too, outside the context of "call by reference". I'm
not sure if that matters in this debate or not but figured I might as
well toss my hat into the ring.

I write pseudo-OO code all the time that looks roughly like this:

proc ::myclass::constructor {id args} {
...
interp alias {} $id {} ::myclass::proxy $id
upvar #0 ::myclass::data_$id data
array set data $args
...
}

proc ::myclass::proxy {id args} {
upvar #0 ::myclass::data_$id data
...
}

I find it to be tremendously useful to create lightweight objects
without having to load an OO extension, though I'll gladly abandon this
technique when OO makes it into the core.


--
Bryan Oakley
http://www.tclscripting.com

Alexandre Ferrieux

unread,
Oct 22, 2007, 5:17:54 PM10/22/07
to
On Oct 22, 7:03 pm, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> Alexandre Ferrieux <alexandre.ferri...@gmail.com> wrote:
> > Besides the drawback already mentioned (redundancy), which in itself
> > is nonnegliglible, it is also opening the (nearly) virgin space of
> > "special things" in Tcl.
>
> If it gets implemented such that the upvar's are generated
> into the body (and thus visible in [info body ...]) then it's
> not a "special thing in tcl", but rather a special thing in the
> predefined command "proc".
> If it's done really transparently, then yes, then it is a
> "tcl special thing"

No. I was talking from the newbie's point of view: learning about the
(few) different species dwelling the Tcl world. Adding "&", even
though it is clearly a limited-range 'macro' to all of us old Tclers,
may be seen from the outside as yet another species irreductible to
others. That bothers me, as I remember myself in the language-choosing
stage, looking for the smallest and most orthogonal set of
primitives...

> "
> Normally, parameters are passed by value.
> If a procedure takes a parameter whose name starts with a '&',
> like &par, then it is meant to pass in the variable as such.
> Inside the procedure, par is then linked to a caller's variable
> whose name was given for &par in the call to the procedure.
> For general information about linking variables, see command "upvar".
> "

Ouch. When a newcomer, just introduced to $abc "abc" {abc} and still
uncertain about them, encounters the above paragraph, I won't blame
him for turning to Colorized Forth at full speed.

-Alex

tom.rmadilo

unread,
Oct 22, 2007, 6:53:59 PM10/22/07
to
On Oct 22, 2:17 pm, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
wrote:

> Ouch. When a newcomer, just introduced to $abc "abc" {abc} and still
> uncertain about them, encounters the above paragraph, I won't blame
> him for turning to Colorized Forth at full speed.


Hopefully most will appreciate the fact that language development is
not directed at newcomers. Personally I am amazed at the compact
number of commands and the simple syntax. Adding syntax so that
newcomers can avoid a few lines of code doesn't help anyone.
Experienced developers will want a single way of doing things, even if
it is in their own code, so using a shortcut, then needing to avoid
the situations where the shortcut doesn't work is really moronic for
anyone interested in writing understandable code.

Personally I get pissed off at myself when I use different names for
the same thing in different procs. So the trend is to notice these
inconsistent usages and remove them.

Any useful body of code would therefor trend to remove your partial
solution to a more general solution so that code appears consistent.
Simply looking at one or two procs as an example is totally pointless.
Consistency is much more important than shortcut code. This is the
disease of languages like C, where you can skip certain syntax
requirements under certain conditions. It helps nobody in the long
run.

It is obviously even more important for an interpreted language to
have strict syntax than a compiled language, but even compiled
languages are aided by this. Remember that the most difficult
operation is parsing and compiling. Adding anything to this is a HUGE
change. If you don't appreciate this, then bone up on the problem.

The basic problem here is that us programmers have a tendency to think
that because something is easy for us, it will be easy for a computer
program. For whatever reason, it is much easier for humans to adapt
than programs. This 'distinction' should be used to simplify the
language, not make it more complicated: software is as dumb as you can
get, much dumber that I am. So my suggestion is that when syntax is
involved, think first of the poor interpreter, not the super smart
computer science major. Eventually everything has to be explained to
this poor ignorant chunk of code.


Joe English

unread,
Oct 23, 2007, 12:34:36 AM10/23/07
to
Bruce Hartweg wrote:

>OK, second reference of the "sledgehammer" of upvar to crack
>nut of pass by reference. But to me it looks a lot more like
>using a phillips screwdriver to drive a phillips screw. What
>numerous other big problems is upvar used for tha is not pass
>by reference? (or more literally pass by name)

[upvar] can link a local variable to any other local variable
at any level in the call stack, or to a global variable in
any namespace.

It's most frequently used to link a local variable to a variable
in the caller's context, named in an argument to the procedure.
[upvar] is more powerful than it needs to be *for this particular use*.

--Joe English

Joe English

unread,
Oct 23, 2007, 1:04:07 AM10/23/07
to
Andreas Leitgeb wrote:

>Gerald W. Lester wrote:
>> I'm sorry I do not follow.
>> Upvar is used to implement pass-by-reference semantics.
>> [Uplevel is used to implement pass-by-name semantics.]
>> [What does upvar have to do with pass-by-name semantics?]

>
>I see, you see this from a different (can't say wrong)
>point of view, so I'll try to clarify:
> [...]

I suspect Gerald is thinking of the traditional formal
definitions of call-by-reference and call-by-name.
(The latter is a rather unusual calling convention
first seen in Algol 60 and not seen very often since then :-)

I was using the term "pass-by-name" in an informal sense,
meaning "you pass the name of a variable instead of its value."

But he's absolutely right: Tcl _always_ uses call-by-value;
to get call-by-reference, the callee uses [upvar 1]
and the caller passes a variable name; and to get call-by-name
semantics (in the Algol 60 sense), the callee uses [uplevel 1]
and the caller passes in a script.


--Joe English

Andreas Leitgeb

unread,
Oct 23, 2007, 2:02:09 AM10/23/07
to
Joe English <jeng...@flightlab.com> wrote:
> Andreas Leitgeb wrote:
>>Gerald W. Lester wrote:
>>> Upvar is used to implement pass-by-reference semantics.
...
> I suspect Gerald is thinking of the traditional formal
> definitions of call-by-reference and call-by-name.

Yes, after googling for "call-by-name" and then reading
a wikipedia article I now know what he referred to and I
accuse him of nitpicking, despite clearly understanding :-)

Andreas Leitgeb

unread,
Oct 23, 2007, 2:10:11 AM10/23/07
to
Darren New <dn...@san.rr.com> wrote:
> I certainly would think it would be a bad move to say you could *only*
> use it for pass-by-reference.

I agree on that.
The claim instead was, that upvar's usage for pass by reference/varname
could do with some sugar-coating, whereas all other uses of upvar would
of course remain unaffected.

davidn...@gmail.com

unread,
Oct 23, 2007, 3:43:39 AM10/23/07
to
> Hopefully most will appreciate the fact that language development is
> not directed at newcomers. Personally I am amazed at the compact
> number of commands and the simple syntax. Adding syntax so that
> newcomers can avoid a few lines of code doesn't help anyone.

Language development is aimed at humans, and should therefore try to
take into account how they work, with all their imperfections and
foibles. If you want an "advanced" language (according to most
language geek researcher types) that is not aimed at beginners, then
you should let Tcl be and use something like Lisp or Haskell.

I don't agree with this way of thinking though. One of the things
that I like about Tcl is that it is both powerful in the hands of
experts, and not so difficult that a beginner can't do useful things
with it, or start reading other people's code. That should be the
goal of a programming language - easy to learn, yet still powerful and
convenient for an expert.

> The basic problem here is that us programmers have a tendency to think
> that because something is easy for us, it will be easy for a computer
> program. For whatever reason, it is much easier for humans to adapt
> than programs. This 'distinction' should be used to simplify the
> language, not make it more complicated: software is as dumb as you can
> get, much dumber that I am. So my suggestion is that when syntax is
> involved, think first of the poor interpreter, not the super smart
> computer science major. Eventually everything has to be explained to
> this poor ignorant chunk of code.

You definitely want Lisp in that case;-) I don't agree, however.
Programming languages, even Lisp, are for people, not for computers.
As Simon Peyton Jones says, "syntax is a language's user interface",
and if you are going to be staring at it all day, you want it to be
easy to use and read. Computers keep getting faster and faster, so
spending a few cycles on something that dramatically improves a
language's readability is well worth it.

Andreas Leitgeb

unread,
Oct 23, 2007, 3:49:45 AM10/23/07
to
tom.rmadilo <tom.r...@gmail.com> wrote:
> Any useful body of code would therefor trend to remove your partial
> solution to a more general solution so that code appears consistent.
I don't understand this.

> Simply looking at one or two procs as an example is totally pointless.

I disagree to this.

> Consistency is much more important than shortcut code. This is the
> disease of languages like C, where you can skip certain syntax
> requirements under certain conditions. It helps nobody in the long
> run.

I quite strongly disagree to this. I think not always having to
write "unsigned" or "signed" for an int, and leaving out redundant
noise was, what made C an interesting language as opposed to
pascal, where you had to always do something with returned values,
and had to type long "begin end" instead of short "{}"

That said, one shouldn't of course overdo it, like the perl guys did.

I'm not targetting to make tcl a second C, but some of the non-obvious
magic-spells for common tasks are on my "Things I'd like to change in
Tcl"-list.

eval with [list]-protecting the non-expansive parts was #1 one on that
list. Thank $deity for {*}-syntax to get rid of *these* usages of eval.

Getting rid of those "upvar"s that are used for call-by-reference/name
of course has much smaller priority (even in my mind) than eval had.

> The basic problem here is that us programmers have a tendency to think
> that because something is easy for us, it will be easy for a computer
> program. For whatever reason, it is much easier for humans to adapt
> than programs.

This is not true for redundant repeating of words, as happens with
upvar and the variable names. This is one weak point for humans, who
have a tendency of adding non-deterministic typo-noise into repetitions.

> Eventually everything has to be explained to
> this poor ignorant chunk of code.

That step is called "implementation" :-)

davidn...@gmail.com

unread,
Oct 23, 2007, 3:51:22 AM10/23/07
to
On Oct 23, 8:02 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:

I agree. What most languages consider pass by reference is when the
reference refers to some value directly, rather than a key in a hash
table that can be used to get at the value. I don't recall how its
internals work, but I suppose upvar points the new variable name at
the old value, so I guess you could argue for that. However, in
practical terms, what you are passing to the proc that utilizes upvar
is the name - the key in the hash table, not the value - so I would
say that 'pass by name' is in some way a more accurate description.

Uwe Klein

unread,
Oct 23, 2007, 6:17:15 AM10/23/07
to
Bryan Oakley wrote:

> I know I should stay out of this, but...

In my aborted attempt to use itcl I used:

class xyz {
# state is an array
public variable state

constructor {args} {
upvar 0 state ::$this

}

}

xyz ::FirstObj
xyzz ::SecondObj

trace variable ::FirstObj(current) w {::SecondObj update }


to string objects together via traces.
( and then afair there is a bug in itcl or tcl
when taking down these objects)

uwe

Donal K. Fellows

unread,
Oct 23, 2007, 9:02:37 AM10/23/07
to
Uwe Klein wrote:
> constructor {args} {
> upvar 0 state ::$this
> }

I hope that didn't work; the second (non-level) argument to [upvar]
should always be a colon-free name.

Donal.

miguel

unread,
Oct 23, 2007, 9:10:58 AM10/23/07
to

I agree with "should" (see my Tip 276), but it does work in general.

% namespace eval a {}
% set x 1
1
% upvar 0 x a::y
% set a::y
1
% set x 2
2
% set a::y
2

Uwe's should however not work for a different reason: you cannot upvar a
namespace var to a proc-local variable:

% set x 1
1
% proc a {} {upvar 0 state ::x; set state 2}
% a
bad variable name "::x": upvar won't create namespace variable that
refers to procedure variable

Donal K. Fellows

unread,
Oct 23, 2007, 9:14:36 AM10/23/07
to
David Welton wrote:
> I don't recall how its
> internals work, but I suppose upvar points the new variable name at
> the old value, so I guess you could argue for that.

It actually points the new variable name at the old variable via an
indirection record.

Donal (I'll raise you one picked nit...)

Uwe Klein

unread,
Oct 23, 2007, 9:25:55 AM10/23/07
to
it works, and quite well at that ;-)
at least for the purpose intended.

And where is it stated that i can not upvar to a
fully qualified namespace path?

There are problems when the context is destroyed.

> Donal.

uwe


Message has been deleted

miguel

unread,
Oct 23, 2007, 9:51:08 AM10/23/07
to
Uwe Klein wrote:

> miguel wrote:
>
>> Uwe's should however not work for a different reason: you cannot upvar
>> a namespace var to a proc-local variable:
>>
>> % set x 1
>> 1
>> % proc a {} {upvar 0 state ::x; set state 2}
>> % a
>> bad variable name "::x": upvar won't create namespace variable that
>> refers to procedure variable
>
> the context is persistent as it is a variable in an object context.

Oops - sorry, missed that. I stand corrected.


>
> and it works in a namespace context too:
>
> % namespace eval XYZ {
> variable state
> set state(hallo) 12345
> upvar 0 state ::ZZZ
> }
> % array get ZZZ
> hallo 12345
>
>
> uwe

Bruce Hartweg

unread,
Oct 23, 2007, 11:01:52 AM10/23/07
to
tom.rmadilo wrote:

So my suggestion is that when syntax is
> involved, think first of the poor interpreter, not the super smart
> computer science major. Eventually everything has to be explained to
> this poor ignorant chunk of code.


this reminds me of some code I periodically have to look at
written long ago by a very smart guy- cool algorithms and such,
but completely unreadable, it was Fortran, used named blocks (which
overlapped on purpose) and the kicker was not only zero comments
but also zero whitespace - vertically *and* horizontally!

so he was optimizing the compile step!

Bruce

Uwe Klein

unread,
Oct 23, 2007, 11:07:16 AM10/23/07
to
Bruce Hartweg wrote:

> this reminds me of some code I periodically have to look at
> written long ago by a very smart guy- cool algorithms and such,
> but completely unreadable, it was Fortran, used named blocks (which
> overlapped on purpose) and the kicker was not only zero comments
> but also zero whitespace - vertically *and* horizontally!
>
> so he was optimizing the compile step!
>
> Bruce
>

some smarts smart, eh?

uwe

Bruce Hartweg

unread,
Oct 23, 2007, 11:32:20 AM10/23/07
to
yup. i think he saved money to by not needing a spacebar on his keyboard ;)

Bruce

PS
did i mention his functions had not only multiple exit points, but
multiple entry points? and purposely used the overlapping blocks
so that h[23] was the same exact memory as g[154] ?

now try to recode an that algorithm in C - or better yet, get handed
a C program that had a subtle bug, then be told that it was a port
of the ugly fortran and be asked to find the bug. 3 weeks of my life
I'll never get back.

Uwe Klein

unread,
Oct 23, 2007, 11:44:36 AM10/23/07
to
Bruce Hartweg wrote:

> did i mention his functions had not only multiple exit points, but
> multiple entry points?

I have to confess that I have done similar deeds to some
program for a PIC microcontroller.

>
> now try to recode an that algorithm in C - or better yet, get handed
> a C program that had a subtle bug, then be told that it was a port
> of the ugly fortran and be asked to find the bug. 3 weeks of my life
> I'll never get back.

unpaid work?

uwe, ducking

tom.rmadilo

unread,
Oct 23, 2007, 12:04:01 PM10/23/07
to


So did anyone notice that I am the person advocating for more
whitespace and less obfuscation, or did that just fly right over your
head? Tcl could never have the problem being described here for
fortran because Tcl has simple rules for the interpreter. Adding an
additional redundant symbol that means the same but less than [upvar]
is the exact way code becomes difficult to read and maintain (and copy
and reuse).

Does anyone here really think that a fortran compiler/c compiler are
simple? And that is why you can write unreadable code? If the parsing
rules require you to write readable code, why is this a bad thing? An
& doesn't derive from any language I have seen, functions are not
defined with the address operator,instead the & is used by the caller
to get an address. In Tcl this is already done for you. The name is
the address. If you want to pass in a value, you use $ to
dereference. But in addition, [upvar] may create a variable, so it
isn't the same as other languages.

Neil Madden

unread,
Oct 23, 2007, 1:54:41 PM10/23/07
to
Gerald W. Lester wrote:
> Andreas Leitgeb wrote:
...
>> I forgot to mention, that by "call-by-reference" I understand a
>> general concept known across many languages, which in tcl is done
>> as call-by-name, in absence of a reference-type. So in the
>> tcl-context I consider them equivalent, whereas e.g. in Hecl
>> context it's something different, and even more so in Java context
>> (where call-by-name means using reflection, and the name refers to
>> a method's name rather than a variable's name)
>
> I guess maybe the definitions have changed since the late 70s and early
> 80s. Back then call-by-name was only implemented in algol 68 and
> refered to being able to pass in a code block to a procedure that was
> then excuted in the current scope.
>
> As in:
>
> proc RepeatUntilLoop {body condition} {
> while {1} {
> uplevel $body
> if {[uplevel [list expr $condition]]} {
> break
> }
> }
> }
>
> set x 100
> RepeatUntilLoop {
> puts $x
> incr x -1
> } {$x > 0}

Actually, it's slightly more than that. Call-by-name is a non-strict
evaluation strategy whereby a procedures arguments are not evaluated
before being passed to the procedure, but are instead directly
substituted in the body -- the argument is then evaluated as many times
as it is used in the procedure rather than once before the call. To
illustrate, in Tcl this would look like:

proc-by-name foo {a b} { ... }
foo $bar [expr {$bar+1}]

Here, when foo is called it is passed the literal strings "$bar" and
"[expr {$bar+1}]" which are substituted into the body. Clearly, this
isn't possible in Tcl without altering the interpreter itself. Instead,
Tcl is purely call-by-value, but provides convenient syntax for quoting
expressions ({braces}).

Upvar doesn't change this. You can implement call-by-reference in Tcl
simply because variable "references" are just strings.

-- Nei

Bruce Hartweg

unread,
Oct 23, 2007, 2:48:25 PM10/23/07
to
tom.rmadilo wrote:
> On Oct 23, 8:32 am, Bruce Hartweg <bruce-n...@hartweg.us> wrote:

>
> So did anyone notice that I am the person advocating for more
> whitespace and less obfuscation, or did that just fly right over your
> head?

Tom, that is why I put OT in the subject - because this is off topic.
I am not saying this is relevant at all to the discussion.

there was a comment about "think of the interpreter" instead of the
programmer. - it triggered the memory & even tho' it was a decade ago
I still occasionally vent.

Bruce

Bruce Hartweg

unread,
Oct 23, 2007, 2:51:44 PM10/23/07
to

nah, luckily i was paid - but what a pain. (FYI i couldn't find
any errors in the C port, but the fortran test code still ran,
so I massaged our data into a format the fortran code wanted and
ran it through the original and it should the same buggy results
for that data set. So I packed it up and sent it back to the
algorithm group. 2 more weeks pass and instead of a bug fix, I am
handed a completly differnt algorithm to re-implement in our code.
Luckily it was easier to read.)

Bruce

Andreas Leitgeb

unread,
Oct 23, 2007, 3:48:09 PM10/23/07
to
tom.rmadilo <tom.r...@gmail.com> wrote:
> ... And that is why you can write unreadable code? If the parsing

> rules require you to write readable code, why is this a bad thing?

Are you aware, that different people may have different ideas of
what is readable or unreadable? (of course there are large areas
of consense, but rumour says, some people even found perl readable :-)

> An & doesn't derive from any language I have seen,

Which just tells us, you haven't (yet) seen C++.
No big business. Knowing C++ surely isn't supposed to be
a prerequisite for working with/in tcl.
Here is an example, of how this feature is used in C++:
(the // is C++'s towards-end-of-line comment)

void foo(int& i) { i=42; } // function definition
...
int bar=0;
foo(bar); // no & here!
printf("%d\n",bar); // prints 42

Actually, I don't insist on using the "&" character for marking.
prefixing a "*" or "_" would also be fine for me, whereas "$"
would be quite a bad choice imho.

tom.rmadilo

unread,
Oct 23, 2007, 8:52:41 PM10/23/07
to
On Oct 23, 10:54 am, Neil Madden <n...@cs.nott.ac.uk> wrote:
> Actually, it's slightly more than that. Call-by-name is a non-strict
> evaluation strategy whereby a procedures arguments are not evaluated
> before being passed to the procedure, but are instead directly
> substituted in the body -- the argument is then evaluated as many times
> as it is used in the procedure rather than once before the call. To
> illustrate, in Tcl this would look like:

Hmmm, when you put it like that, it reminds me of the Tcl [for ] or
[while ]. When you put it like that, even 'proc' appears to be a
generalized call-by-name. Everything in Tcl looks like this if it is
in curly braces. Hmmmmmmmmm, so maybe the call-by-name thing is
signaled by curly braces.

Darren New

unread,
Oct 23, 2007, 10:42:35 PM10/23/07
to
tom.rmadilo wrote:
> An & doesn't derive from any language I have seen,

Well, PHP, but that's not an argument in favor... :-)
--
Darren New / San Diego, CA, USA (PST)
Remember the good old days, when we
used to complain about cryptography
being export-restricted?

Kaitzschu

unread,
Oct 24, 2007, 8:39:42 AM10/24/07
to
On Tue, 23 Oct 2007, Uwe Klein wrote:

> Donal K. Fellows wrote:
>> Uwe Klein wrote:
>>
>>> constructor {args} {
>>> upvar 0 state ::$this
>>> }
>>
>>
>> I hope that didn't work; the second (non-level) argument to [upvar]
>> should always be a colon-free name.
>>
> it works, and quite well at that ;-) at least for the purpose intended.
>
> And where is it stated that i can not upvar to a fully qualified
> namespace path?

That would be here:
http://sourceforge.net/tracker/index.php?func=detail&aid=1587442&group_id=10894&atid=360894

Miguel wants us to stop using [upvar] like this :)

--
-Kaitzschu
s="TCL ";while true;do echo -en "\r$s";s=${s:1:${#s}}${s:0:1};sleep .1;done

"Good thing programmers don't build bridges
[the same way as Kaitzschu writes code]."
--John Kelly in comp.lang.tcl

miguel

unread,
Oct 24, 2007, 9:22:25 AM10/24/07
to
Kaitzschu wrote:
> On Tue, 23 Oct 2007, Uwe Klein wrote:
>
>> Donal K. Fellows wrote:
>>> Uwe Klein wrote:
>>>
>>>> constructor {args} {
>>>> upvar 0 state ::$this
>>>> }
>>>
>>>
>>> I hope that didn't work; the second (non-level) argument to [upvar]
>>> should always be a colon-free name.
>>>
>> it works, and quite well at that ;-) at least for the purpose intended.
>>
>> And where is it stated that i can not upvar to a fully qualified
>> namespace path?


Where is it stated that you *can*?

If you look at the manpage, it says that upvar "arranges for one or more
local variables in the current procedure to refer to variables in an
enclosing procedure call or to global variables"

> That would be here:
> http://sourceforge.net/tracker/index.php?func=detail&aid=1587442&group_id=10894&atid=360894
>
>
> Miguel wants us to stop using [upvar] like this :)

Or else!!

My beef with that usage is:

(a) it is not documented (see above). That usage violates the "current
procedure" part (as does the usage outside proc bodies, but that one I
actually like :P). The current behaviour is more an implementation
accident than a design feature.

(b) it is "probably" not used a lot

(c) it reeks of "action at a distance" - the intention is clearer if I do eg
namespace eval ::a {upvar 0 ::x x}
than
upvar 0 ::x ::a::x

Now: I did write "IMO" in that RFE. I am perfectly willing to be shown
wrong in (b), and to receive "de gustibus non est disputandum" re (c).

The argumentation in my Tip 276 is a bit more general - I want to unify
criteria among all the variable linking commands.

Neil Madden

unread,
Oct 24, 2007, 11:13:53 AM10/24/07
to

Basically, yes. Strictly speaking, a PL theorist would probably say that
Tcl is still call-by-value in this case and just has a convenient
quotation syntax, similar to Lisp's (foo '(a b c)). I really like Tcl's
approach, as call-by-value is easy to understand, and learning when to
use braces is pretty straightforward.

-- Neil

0 new messages