References touch upon one of the ways in which Tcl is different from many other languages. What could be called the "standard model" for complex data structures is that:
- all values are atomic (scalar), structure (complexity) comes from how they are stored.
L:=[1,t,t^2]; f:=unapply(L,t);creates a function f such that f(2) returns [1,2,4], but
v:=vector([1,t,t^2]); g:=unapply(v,t);creates a function g which returns the vector [1,t,t^2] no matter what you give it. In order to get g work in the same way as f, you need to dereference v before handing it to unapply.
g:=unapply(eval(v),t);As for TclRef, does it obey the idiom that everything is a string? What happens if someone goes
eval lappend refs [linsert $otherRefs 0 [newRef xxx]]will the things appended to $refs still be references? (Sure, it is silly to do it that way, and in Tcl 8.5 there is {*}, but for Tcl values it should work! If it doesn't then the ability to embed values in scripts has been severely limited.)
davidw Everything is not a string in Tcl. Files and namespaces come to mind right away. In my years on this planet, I have developed a healthy skepticism about "every" and "any". Usually (not every time;-) they are wrong.
Discussion moved here from Why adding Tcl calls to a C/C++ application is a bad idea:davidw - And this is still an area where Python has us beat:
- Python has one, reasonably good OO system
- Python objects are GC'ed, making them easier to use in scripts. Tcl objects must be destroyed by the programmer.
- Python has references, which are also useful for doing data structures.
?: Some arguments are not correct
- XOTcl is better object system than Python. Tcl is flexible to write OO-Systems (see snit)
- In XOTcl not all object need to be explicit destroyed (without GC). There are subobjects and volatile objects that are destroyed automatic.
Artur Trzewik In fact XOTcl Objects names are references. Objects are referenced by their names. I do not see big difference amoung
C Point *point = Alloc(sizeof(Point)); Free(point); C++ Point *point = new Point(); delete point; C# Point point = new Point(); point = null; Smalltalk | point | point := Point new. point := nil. XOTcl set point [Point new] $point destroy set point [Point new -volatile] # if object sould life only in current blockIn all cases point is such kind of reference to object (structure) of type Point.Memento By using of OO in Tcl we not need really any additional references.About GC in OO-Tcl. I program this language about several years and after big period with Smalltalk programming I would also like GC in Tcl. But till now I do not very miss GC in XOTcl. There are techniques like volatile objects and subobjects that make destroing of many objects very simple. The C++ problems with forgotten objects (dangling objects) do not occurs in XOTcl. On the other side. Releasing objects (destroying) are very important period of object life-time that should be controlled by program. I have seen many problems with smalltalk memory handling because the programmer have forgotten to do this magic ( point := nil.) in some global references. Also with GC you have to care about object releasing and you do not have full control about it.It is also interesting to see some C++-programmers arguments agains GC.
davidw - XOTcl looks ok, but it's not available in ActiveTcl or the default starkit setup and there are no books about it. Even the .deb's have been pulled (I might be convinced to work on fixing at least that...). This is the problem with not having one standard thing.Also, the 'volatile' objects, from what I see on the docs, depend on living in a particular Tcl procedure. I don't want that, I want something that goes away when nothing else references it.The object system may be 'better' than python's or ruby's or something else, but for the new user, the situation looks like a mess. It's something I think we'll have to face up to if we want to program in this "Tcl is the controlling application" style, and promote it to the world at large.
Lars H: IMO, references are evil. I cannot recall a single case where using references would have simplified a programming task or would have lead to a better solution. Indeed, I do not know of any problem where the asymptotic complexity is smaller in a computing model with references than it is in current Tcl (i.e., without references). But feel free to enlighten me if you have an example.davidw: The classic example of having references/OO/GC make life easier is the http package. It requires you to do a 'cleanup', because otherwise it will never be GC'ed.jcw - Another example is when you want to create Tcl commands and nest them yet clean up automatically. The Vkit is a vector engine page goes into an example and tries to find a solution, but it really applies to a lot of problem domains, let's say matrices:
set a [$matrix invert] set b [$a transpose] set c [$b invert] $c printI'd like to write:
[[[$matrix invert] transpose] invert] printAnd have everything clean up after use, i.e. the Tcl commands. That's where Python's "matrix.invert().transpose().invert().print()" makes life a lot easier. Even C++'s constructors/destructors with temporaries support such an idiom, with automatic cleanup.Lars H: The catch in both examples is that they are of idioms that require references rather than actual problems (i.e., something which is solved with an algorithm) that need them. HTTP communication is, as I understand it, completely stateless -- hence there should be no need to create anything that needs to be GC'ed. I find the matrix example almost preposterous. Matrices are data, so why should they ever be make commands? What is wrong with
print [invert [transpose [invert $matrix]]]?RS: The former form can be read from left to right to indicate the temporal order of the nested methods, while the latter requires the reader to read from right to left, as usual with nested functions (and APL), but less in Western cultures...jcw - Lars, you say "matrices are data" - I see them as objects. Instances of a class, in OO terms (as in Python, C++, Smalltalk). An example which interests me more than matrices btw, is relational algebra [2]. If you brush aside examples where Tcl commands are used as objects, and with it the issue of object cleanup, so be it. Your example uses a namespace to identify operators and apply them to data, the OO model takes objects and makes them respond to methods/messages. Polymorphism, encapsulation - you're free to not care about that, of course.Lars H: Well, I suppose I the OO hype must have missed me, because I tend not to see things as objects, and since this furthermore seems to save me a lot of trouble I'm only glad for it. Polymorphism does not require referenced objects.I can agree that the "object on which a method is acting" view is sometimes appropriate, and I have on some occations suggested using it, but matrix arithmetic does hardly lend itself to that view. When all operations create new things from old then it isn't objects you're working with, but values! The Ratcl you refer to looks like a very striking example of this -- is there anything (apart from your preferences with respect to syntax) that prevent you from implementing views as Tcl values? (And you can of course have any syntax you like, if you just bite the bullet and create a proper little language.)jcw - State.
Peter da Silva: The problem with the idea that "references are evil" is that Tcl is full of references. $foo is following a reference to the value of foo. [foo] is following a reference to the procedure called foo. The only difference is that in Tcl there are no exposed "unnamed" references, and all dereferencing operations are symbol table lookups. But Tcl post 8.0 is no longer really an "everything is a string" language, it's an "everything can be made to look like a string" language. So there's no reason not to have unnamed references, they can be efficiently thrown around and shimmered into some unique token (eg ::ref::array_40AB65003) when they're used in a string context.Lars H: The controversial thing about references is whether you should be allowed to modify referenced data. Right now, if you have some value, you have precisely that value and no other part of the program is allowed to change it when you're not looking. This is not the case in languages with explicit references to things. (RS: ..and Tcl's "value security" is a great help for coders who know it. In fact, TOOT shows a way to "pure-value OO", where methods take one value and return another, but don't mutate a thing in place - that's transparently done with variable assignment only.)Also, the "everything can be made to look like a string" claim is a bit too weak. It's rather "everything can be fully encoded as a string".Peter da Silva: Everything can be fully encoded as a string, but that doesn't mean you don't have references: there are still references encoded as a string that are distinct from the fully encoded form.
proc refproc {ref} { upvar 1 $ref ary puts $ary(3) set ary(4) four } proc valproc {val} { array set ary $val puts $ary(3) set ary(4) four } array set name {1 one 2 two 3 three} valproc [array get name] refproc nameThe question shouldn't be "should Tcl have references", the question is "should Tcl have anonymous references". Tcl code is full little symbol generators to convert references into text that can be manipulated. So you get little generated names like "file5" that should really be the "stringized" version of anonymous references. For most programs they'd never get converted to a string or looked up in a symbol table, except that a text string is the only way you have to refer to a structured or opaque object.I was talking to Karl about this the other day and we both wish we had done a better job on arrays, but there's lots of other opaque objects that really should be moved out of the namespace. There's two different kinds of string conversions you really need to be able to apply to them, too. One that gives you a token that you can use in the current context, and one that can describe them, like the difference between "arrayname" and "array get arrayname".Anyway, I agree that pointer-style references are generally to be avoided, but there are other kinds of references that Tcl uses only clumsily right now.
See Also edit
- linked lists
- Tcl references in Tcl
- TclRef
- an implementation of references for Tcl