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.
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"
> 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.
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.
> 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 :-)
Sorry, I think you grossly misunderstood the proposal.
tom.rmadilo <tom.rmad...@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.
tom.rmadilo <tom.rmad...@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 :-)
Andreas Leitgeb wrote: > Bruce Hartweg <bruce-n...@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.
Andreas Leitgeb wrote: > Gerald W. Lester <Gerald.Les...@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?
-- +--------------------------------+---------------------------------------+ | Gerald W. Lester | |"The man who fights for his ideals is the man who is alive." - Cervantes| +------------------------------------------------------------------------+
Bruce Hartweg <no.spam....@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 <a...@gamma.logic.tuwien.ac.at> wrote: > Gerald W. Lester <Gerald.Les...@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.
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)
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?
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. :-)
-- Darren New / San Diego, CA, USA (PST) Remember the good old days, when we used to complain about cryptography being export-restricted?
> >> 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.
Darren New <d...@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. :-)
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.
Andreas Leitgeb wrote: > Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at> wrote: >> Gerald W. Lester <Gerald.Les...@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.
> 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}
-- +--------------------------------+---------------------------------------+ | Gerald W. Lester | |"The man who fights for his ideals is the man who is alive." - Cervantes| +------------------------------------------------------------------------+
Darren New <d...@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?
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.
Andreas Leitgeb wrote: > Darren New <d...@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.
-- Darren New / San Diego, CA, USA (PST) Remember the good old days, when we used to complain about cryptography being export-restricted?
Darren New wrote: > Andreas Leitgeb wrote: >> Darren New <d...@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.
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.
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.
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*.
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 <jengl...@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 :-)