ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> tcl-core
tcl-core
Re: [TCLCORE] Variable access
by Neil Madden other posts by this author
May 13 2008 6:28AM messages near this date
[TCLCORE] Variable access | Re: [TCLCORE] Variable access
Hi Frédéric,

On 12 May 2008, at 23:48, Frédéric Bonnet wrote:
>  [...]
>  But first, I'd like to point out a misunderstanding. The discussion  
>  was
>  not around argument passing conventions, but around references in data
>  structures. So all the proposals around proc enhancements are a bit
>  off-topic, however interesting they might be. (Actually I planned to
>  make the same kind of proposal in Cloverfield). More on that below.

OK, I didn't get that from your original post.
[...]
> > Yes. "Everything is a string" is fundamentally incompatible with the
> > idea of strong references, as far as I can tell (i.e. it is
> > impossible to create a properly abstracted system of reference using
> > strings as references). Tcl_Obj internal rep hacks are not just prone
> > to failure, but also break EIAS.
> 
>  True. However Cloverfield tries to address this issue by providing  
>  a way
>  to serialize references more robustly. See the Tridekalogue for more
>  information:
> 
>  	http://wiki.tcl.tk/20643 (see [11.7])

How is it any more robust than a variable name? Surely you have  
exactly the same problems.

> > [...]
> > What then is the difference between these weak references and just
> > names? Are they looked up in a different context/namespace?
> 
>  There is no difference, only syntactic. Cloverfield introduces a whole
>  set of access methods for variable values, e.g. vector or map (list or
>  dict in Tcl lingo). However the parser can get in the way of the  
>  access
>  syntax. For example:
> 
>     # Same as puts [lindex $a 1 2 3]:
>     puts $a{1 2 3}
> 
>     # Fails because the parse splits a{1 2 3} at spaces and build 3  
>  words.
>     set a{1 2 3} 4
> 
>     # The above must be written using the weak reference syntax:
>     set @a{1 2 3} 4
> 
>  The original discussion revolved around whether to extend the  
>  parser so
>  that words must span across braces as a general rule (i.e. a{1 2 3} is
>  one word and not 3), or whether to require special syntax whenever
>  variables must be indexed.

This seems a separate discussion from the present one. Why not insist  
that variable names be single words (they almost always are), and  
then use ${a 1 2 3} or [set {a 1 2 3} 4]?

>  [..]
> 
>  However Tcl has no means of storing references outside of plain
>  variables. For example, one cannot build a structure that holds
>  references other than using variable names (which must be global in  
>  most
>  cases). This causes a number of problems in term of lifetime  
>  management
>  that OO system writers know too well. Cloverfield tries to address  
>  this
>  limitation.

I don't really understand what benefits these references have over  
just using unique globally-scoped variable names. Perhaps some  
examples would help. If I put a reference into a dict (map) and then  
send that over a socket, what gets serialised at the other end --  
does the reference get recreated, or just the current value at time  
of serialisation? i.e.

set d [dict create foo 12 bar $&jim]
puts $sock $d
... on other end ...
set d [read $sock]
set $&d(bar) ... ;# is that the right syntax?

Does that work? I assume for that to work that the string rep of a  
reference must identify itself as a reference (e.g. the "{ref foo} 
bar" syntax), but then how do I get just the current value from a  
reference if $myref returns the reference?

If the calling conventions stuff is secondary, and the primary aim is  
to get garbage collected first-class references that can be stored in  
data structures, then surely Jim has already solved this problem?  
(http://wiki.tcl.tk/13847)

> 
> > 2.) Generalise the notion of what can be referred to by a Var to that
> > of a general "resource" -- i.e., not just Tcl_Objs, but also "opaque"
> > entities like commands, channels, objects, etc. This would allow for
> > finer control over the lifetime/scope of these resources (e.g. proc-
> > local commands or channels), and could be extended to encompass
> > things like general reference-counting of resources and perhaps even
> > a generalised serialisation framework (i.e. $foo means "attempt to
> > serialise the resource referred to by the var named foo").
> 
>  That's an interesting proposal. However it raises deep philosophical
>  questions about lifetime management of said resources. Other paradigms
>  are sometimes better suited (C++ RAII for example).

I don't think it does raise any deep philosophical issues, only  
practical ones. What I am suggesting is to allow the scope of various  
opaque things (objects, commands, aliases, channels etc) be allowed  
to be confined to smaller scopes than just global/namespace.  
Essentially, I am proposing something not too distant from RAII. For  
instance, you could have a proc-local XOTcl object:

proc foo {} {
    myclass create bar ...
    bar mymethod ...
} ;# bar is destroyed on proc exit (RAII)
proc foo varName {
    upvar 1 $varName bar
    myclass create bar ...
    bar method ...
} ;# bar is preserved in reference passed

Note that this means unifying command/var scopes (and others) -- at  
least, that's the nicest way of doing it. Of course, as you point  
out, this says nothing about storing resources/references inside data  
structures, but I don't think the solutions to this problem do any  
better than a global variable name.

Incidentally, are references in Cloverfield just first-class  
variables? I.e. do they refer to just Tcl_Objs, or can they also  
refer to the various opaque resources I mention above (e.g. XOTcl  
objects, channels etc)?

>  ==============================
>  [...]
>  With references, the caller can choose whether to pass by value (in a
>  purely functional way) or by reference:
> 
>     % set v1 {a b c}
>     % set v2 [linsert $v1 1 d]
>     a d b c
>     % set v1
>     a b c
>     % linsert $&v1 1 d
>     a d b c
>     % set v1
>     a d b c
> 
>  This eliminates the value/reference dichotomy that exists in current
>  Tcl. But as I said above, this is just a side effect. The primary  
>  intent
>  is to build complex structure patterns (with potential circularities).

As I pointed out before, eliminating this distinction at the level of  
implementation would need more than just a bit of extra syntax: each  
command would have to be written to be able to do sensible things  
when passed either a value or a reference. Could you show some  
example code of how a Cloverfield command that works in this way  
would be implemented in C (or point me towards the source if there is  
an implementation available)? I think that would help clarify what is  
intended.

This dichotomy itself isn't unique to Tcl. It is a simple use/mention  
distinction that is fundamental in most languages. You can either  
have different syntax for whether a variable is being used (i.e. the  
value retrieved) or mentioned: e.g. $foo vs foo or foo vs 'foo  
(Lisp), or you can make the distinction at a higher level in the  
syntax, e.g. foo = foo + 1 (C), where foo before the '=' (so-called  
"lvalue") is taken as a reference, and after is taken as a value, or  
you can use the "mention" syntax everywhere and then provide a  
function to retrieve the value: foo vs [set foo] (original Tcl). A  
final option (ML) is to provide only the "use" syntax (and therefore,  
only constants) and then provide a separate reference object type  
that has it's own use/mention distinction: !foo vs foo. Your proposal  
still has this distinction: $foo vs $&foo, so you haven't eliminated  
the dichotomy, but duplicated it! Rather than clarifying things, I  
think this will just make it much more confusing.

I personally *like* the fact that there is a clear distinction  
between commands that are purely functional (guaranteed not to  
produce side-effects, no matter what they are passed) and commands  
that are obviously effectful.

[...]

>  Neil Madden wrote:
> > How can $&foo syntax guarantee that a variable named foo exists any
> > more than upvar can?
> 
>  Twylite got it right:
> 
>  Twylite wrote:
> > Upvar can't.  Upvar links to the variable irrespective of whether it
> > exists or not.  If you try to dereference the local name and the  
> > given
> > variable doesn't exist in the caller's scope then you get an error.
>  [...]
> > Errors are handled in the right context, and the error is
> > thrown for the right context and with the right name.  And your  
> > proc can
> > treat the variable as a (local) parameter, while the caller gets to
> > determine if it should be passed by value or as a reference (in which
> > case changes made by the proc are available to the caller).
> >
> > Upvar means that errors are discovered in the proc when you  
> > dereference
> > the linked variable.  The programming error was when you passed in  
> > the
> > wrong variable name.  The error message you get (with upvar) is
> > misleading because it indicated the linked variable name in the proc,
> > not the name of the linked-to variable (which is in a different  
> > scope).

Right, so it doesn't guarantee anything at all. It just catches the  
error earlier and produces a nicer error message (which I showed can  
be done in Tcl now).

>  [...]
> 
>  Neil Madden wrote:
> >> set b alpha -> alpha
> >> set c [lappend b beta] -> alpha beta
> >> puts $b -> alpha beta
> >> puts $c -> alpha beta
> >>
> >> What if I need "alpha" and "alpha beta", i.e. the original $b and
> >> the final $c?
> >
> > Then use [linsert] instead of [lappend]:
> 
>  That's exactly the kind of things newcomers find confusing as hell in
>  Tcl, the fact that we need two sets of commands to carry on the same
>  operations. Granted, most of them come from all-reference  
>  languages, and
>    are understandably puzzled by Tcl's copy-on-write and pass-by-value,
>  but they rightly feel that Tcl's way of faking references with  
>  variable
>  names is bizarre at best.

They are not the same operations! Most other languages don't have  
this distinction as most operations are pass-by-reference and you  
have to do extra work to get a side-effect free version. So, in Java  
you'd write:

     myList.append(myElement)

in Tcl:

     lappend myList $myElement

What Java typically has no equivalent of is:

     linsert $myList end $myElement

and, indeed, you'd need a separate method to get this, even in the  
append case. Other languages provide only the side-effect free  
versions, and you have to go to extra lengths to mutate a variable  
(e.g. myList := !myList @ [myElement], in ML). So yes, people are  
confused to find a language that happily supports both ways of doing  
things, but I don't see how introducing yet another way could  
possibly make this any simpler.

Ideally, I would like the ML situation: names map to things  
(resources) and never change, and then you introduce a mutable  
reference type as a type of resource. For a language like Tcl I don't  
think this can work well on the level of values without doing serious  
abuse to EIAS, which is why I'd prefer to do it at the level of named  
things. This makes it hard to use with value data structures (lists/ 
dicts) etc, so the idea would be that those remain as purely- 
functional structures, and instead when you need a complex mutable  
structure you build it in an OO system, making use of better  
facilities for scoping such resources.

[...]
>  Neil Madden wrote:
> >> No - you're still missing one thing: with implicit upvar the proc
> >> controls the semantics (pass-by-value or pass-by-reference); with $&
> >> syntax the caller is in control.
> >
> > I didn't miss that. I strongly think that the proc should control the
> > semantics, as the proc has to implement them.
> 
>  In some cases, procs should be in control. In other cases the caller
>  should be. As of today Tcl provides no support for the second class of
>  problems.

What is wrong with the [foo -var bar] vs [foo $bar] option I  
described before?

> > The proc must always be written to know whether it is getting a value
> > or a variable reference. Otherwise allowing callers to pass in a var
> > will result in implementation-specific undefined side-effects being
> > performed on the variable.
> 
>  Unless it's done consistently and properly documented. The current
>  situation is no more consistent on this point, with its mixture of
>  pass-by-value and pass-by-name conventions.

It is! Everything is pass-by-value (pass-by-name is something else  
entirely). Some commands expect values directly for some arguments  
and variable names for other arguments. They never expect either for  
the same argument.

[...]

-- Neil
This message has been checked for viruses but the contents of an attachment
may still contain software viruses, which could damage your computer system:
you are advised to perform your own checks. Email communications with the
University of Nottingham may be monitored as permitted by UK legislation.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft 
Defy all challenges. Microsoft(R) Visual Studio 2008. 
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Tcl-Core mailing list
Tcl-Core@[...].net
https://lists.sourceforge.net/lists/listinfo/tcl-core
Thread:
fbonnet
fredericbonnet
Neil Madden
fbonnet
Neil Madden
fbonnet
Lars Hellstrom
fbonnet
Neil Madden
fredericbonnet
David Welton
fbonnet
David Welton
Larry McVoy
Alexandre Ferrieux
Andreas Leitgeb
fbonnet
Neil Madden
Donal K. Fellows
Alexandre Ferrieux
Larry McVoy
Neil Madden
Gustaf Neumann
Neil Madden
Larry McVoy
Neil Madden
Alexandre Ferrieux
fbonnet
Neil Madden
Alexandre Ferrieux
Donal K. Fellows
Larry McVoy
Alexandre Ferrieux
Donal K. Fellows
Alexandre Ferrieux

Privacy Policy | Email Opt-out | Feedback | Syndication
© 2004 ActiveState, a division of Sophos All rights reserved