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

TIP #111: Dictionary Values and Manipulators

23 views
Skip to first unread message

Donal K. Fellows

unread,
Oct 23, 2002, 12:45:00 PM10/23/02
to

TIP #111: DICTIONARY VALUES AND MANIPULATORS
==============================================
Version: $Revision: 1.1 $
Author: Donal K. Fellows <donal.k.fellows_at_man.ac.uk>
State: Draft
Type: Project
Tcl-Version: 8.5
Vote: Pending
Created: Saturday, 05 October 2002
URL: http://purl.org/tcl/tip/111.html
WebEdit: http://purl.org/tcl/tip/edit/111
Post-History:

-------------------------------------------------------------------------

ABSTRACT
==========

This TIP proposes adding a standard value format (and supporting
commands) to Tcl that implements a value-to-value mapping, just as
Tcl's list values can be regarded as implementing a number-to-value
mapping.

RATIONALE
===========

What is a dictionary? It is a translation from arbitrary values to
arbitrary values, often also known as an associative map. Many computer
languages, especially higher-level ones, have them as part of the
language or the standard library. It would be nice to have them in Tcl
too.

Now, I realise that Tcl already contains arrays which provide
dictionary functionality, but they are not quite the same thing. Tcl's
arrays are collections of variables indexable by name, and not
collections of values. This has some far-reaching implications; it is
possible to set traces on individual elements of the array, but it is
not possible to pass the array by value. However, one of the main
concerns is the sheer cost of arrays in terms of memory space; aside
from the hash table used as the core of the implementation (and the
representations of the keys and values, of course) there is a
substantial overhead for each array to support traces on the array as a
whole, plus a similar overhead _per element_ that stems from the fact
that elements are variables in their own right. By contrast, a
dictionary value should be a lot more frugal.

VALUE SYNTAX AND SEMANTICS
============================

Naturally, it is desirable for dictionary values to have human-readable
forms that are similar to those that currently exist. I propose using
_key value key value ..._ form with list-style quoting for keys and
values that contain characters that are significant to Tcl, which
should be immediately familiar to users of the [array get] and [array
set] commands. No special interpretation will be placed on the amount
of whitespace separating keys and values, just as with lists (indeed,
any list with an even number of elements can be regarded as a
dictionary.) For example, the following value represents a mapping from
selected languages to a possible program to invoke to compile them:

C gcc C++ g++ FORTRAN f77 Java javac

Empty dictionaries are those that contain no mappings from keys to
values. Any representation of an empty list will also be a
representation of an empty dictionary. There is no upper bound on the
number of items that a dictionary may hold.

It should be specially noted that dictionary values have copy-on-write
semantics just like lists. This means that if I hand a dictionary value
into a procedure as an argument, and that procedure updates the
variable containing that value, the value as seen by the caller will
not have changed. This is in complete contrast with arrays which cannot
(currently) be passed by value other than through using [array get] to
convert the array to a list form and [array set] to convert back again.

This specification does not state what order the keys and values are
listed in. That depends on the implementation.

COMMAND SYNTAX AND SEMANTICS
==============================

I propose that all operations that work with dictionary values (where
not done through adaptations of existing commands) will go through the
_dict_ command. The alternatives are "array" which is already in use,
"dictionary" which is rather long for what I believe will be a fairly
commonly used command, "alist" (association list) which is probably too
easy to confuse with existing commands, and "map" which is probably
better reserved for future use as something for applying an operation
to a list (or other collection of values.)

Most subcommands operate on either a dictionary value (_exists_, _for_,
_get_, _info_, _keys_, _remove_, _replace_, _size_, and _values_), or
on a variable containing a dictionary value (_append_, _incr_,
_lappend_, _set_, and _unset_).

Proposed subcommands:

dict create:
Make a dictionary.

dict create ?$key1 $value1 $key2 $value2 ...?

This will create a new dictionary from the given keys and values
and return it as the result. The command will take an even number
of arbitrary strings (or other objects, naturally) and will use
the first, third, fifth, etc. as keys and the second, fourth,
sixth, etc. as values. From the point of view of string
representations, this command will behave the same as the [list]
command with an even number of arguments. There is no restriction
on the possible representations of keys or values. It is legal to
call this command with no arguments at all, which creates an
empty dictionary.

dict get: Get value for given key.

dict get $dictionaryValue $key ?$key ...?

Given a dictionary value (first argument) and a key (second
argument), this will retrieve the value for that key. Where
several keys are supplied, the behaviour of the command shall be
as if the result of [dict get $dictVal $key] was passed as the
first argument to [dict get] with the remaining arguments as
second (and possibly subsequent) arguments. This facilitates
lookups in nested dictionaries. For example, the following two
commands are equivalent:

dict get $dict foo bar spong
dict get [dict get [dict get $dict foo] bar] spong

It is an error to attempt to retrieve a value for a key that is
not present in the dictionary.

dict replace:
Create a new dictionary that is a copy of an old one except with
some values different or some extra key/value pairs added.

dict replace $dictionaryValue ?$key $value ...?

This is very much the analogue of [lreplace], taking a dictionary
value as its first argument and then a list of key/value pairs.
The result of the command is a new dictionary value that is a
copy of the supplied dictionary other than that whenever a key is
one of those supplied to this command, the returned dictionary
will map that key to the associated value. It is legal for this
command to be called with no key/value pairs, but illegal for
this command to be called with a key but no value.

dict remove:
Create a new dictionary that is a copy of an old one except
without the key/value mappings whose keys are listed.

dict remove $dictionaryValue ?$key $key ...?

This operation does what [dict replace] can't do; removes keys
and values. The result of the command is a new dictionary value
that does not contain mappings for any of the keys listed; it is
not an error if either there are no keys listed, or if any of the
listed keys does not exist in the supplied dictionary.

dict set: Set value for given key in a dictionary in a variable.

dict set $dictionaryVar $key ?$key ...? $value

This operation takes the name of a variable containing a
dictionary value and places an updated dictionary value in that
variable containing a mapping from the given key to the given
value. In a manner analogous to [lset], where multiple keys are
present, they do indexing into nested dictionaries.

dict unset: Remove association for given key in a dictionary in a
variable.

dict unset $dictionaryVar $key ?$key ...?

This operation takes the name of a variable containing a
dictionary value and places an updated dictionary value in that
variable that does not contain a mapping for the given key. Where
multiple keys are present, this describes a path through nested
dictionaries to the mapping to remove. At least one key must be
specified.

dict keys: List all keys (with optional criteria matching) in
dictionary.

dict keys $dictionaryValue ?$globPattern?

Return a list of all keys in the given dictionary value. If a
pattern is supplied, only those keys that match it (according to
the rules of [string match]) will be returned. The returned keys
will be in an arbitrary implementation-specific order.

dict values:
List all values (with optional criteria matching) in the
dictionary.

dict values $dictionaryValue ?$globPattern?

Return a list of all values in the given dictionary value. If a
pattern is supplied, only those values that match it (according
to the rules of [string match]) will be returned. The returned
keys will be in an arbitrary implementation-specific order,
though where no pattern is supplied the _i_'th key returned by
[dict keys] will be the key for the _i_'th value returned by
[dict values] applied to the same dictionary value.

dict for: Iterate across all key/value mappings in the dictionary.

dict for {$keyVar $valueVar} $dictionaryValue $body

This takes three arguments, the first a pair of variable names
(for the key and value respectively of each mapping in the
dictionary), the second the dictionary value to iterate across,
and the third a script to be evaluated for each mapping with the
key and value variables set appropriately (in the manner of
[foreach].) The result of the command is an empty string. If any
evaluation of the body generates a _TCL_BREAK_ result, no further
pairs from the dictionary will be iterated over and the [dict
for] command will terminate successfully immediately. If any
evaluation of the body generates a _TCL_CONTINUE_ result, this
shall be treated exactly like a normal _TCL_OK_ result.

dict append:
Append a string to the value for a particular key in the
dictionary.

dict append $dictionaryVar $key ?$string ...?

This appends the given string (or strings) to the value that the
given key maps to in the dictionary value contained in the given
variable, writing the resulting dictionary value back to that
variable. Non-existent keys are treated as if they map to an
empty string.

dict incr: Increment the value for a particular key in the dictionary.

dict incr $dictionaryVar $key ?$increment?

This adds the given increment value (an integer that defaults to
1 if not specified) to the value that the given key maps to in
the dictionary value contained in the given variable, writing the
resulting dictionary value back to that variable. Non-existent
keys are treated as if they map to 0. It is an error to increment
a value for an existing key if that value is not an integer.

dict lappend:
Append an item to the list-value for a particular key in the
dictionary.

dict lappend $dictionaryVar $key ?$item ...?

This appends the given items to the list value that the given key
maps to in the dictionary value contained in the given variable,
writing the resulting dictionary value back to that variable.
Non-existent keys are treated as if they map to an empty list,
and it is legal for there to be no items to append to the list.
It is an error for the value that the key maps to to not be
representable as a list.

dict exists:
Test whether a mapping exists for a key.

dict exists $dictionaryValue $key ?$key ...?

This returns a boolean value indicating whether the given key (or
path of keys through a set of nested dictionaries) exists in the
given dictionary value. This returns a true value exactly when
[dict get] on that path will succeed.

dict size: Get the number of key/value mappings in a dictionary.

dict size $dictionaryValue

This returns the size of the dictionary, which will be exactly
half the value that [llength $dictionaryValue] would return. It
is an error to apply this command to a non-dictionary value.

dict info: Get implementation-specific information about the dictionary
value.

dict info $dictionaryValue

This returns information (intended for display to people) about
the given dictionary though the format of this data is dependent
on the implementation of the dictionary. For dictionaries that
are implemented by hash tables, it is expected that this will
return the string produced by _Tcl_HashStats()_.

OTHER RELATED CHANGES
=======================

There are a few other commands that change:

* [array set] will take a dictionary instead of (or as well as) a
list as its final argument.

* [array get] will return a dictionary.

* [string map] will take a dictionary instead of (or as well as) a
list as its map argument.

EXAMPLES
==========

Counting the number of unique words in a file and the number of times
each word occurs:

set f [open someFile.txt]
set contents [read $f]
close $f
foreach word [regexp -all -inline {\w+} $contents] {
dict incr count $word
}
puts "There are [dict size $count] unique words."
foreach word [lsort -dictionary [dict keys $count]] {
puts "${word}: [dict get $count $word] occurrences"
}

A localisable [string toupper] implementation:

set capital [dict create C [dict create]]
foreach c {abcdefghijklmnopqrstuvwxyz} {
dict set capital C $c [string toupper $c]
}
dict set capital en [dict get $capital C]
# ... and so on for other supported languages ...
set upperCase [string map [dict get $capital $env(LANG)] $string

COPYRIGHT
===========

This document has been placed in the public domain.

-------------------------------------------------------------------------

_These appendices are not formally part of the proposal and exist
merely to help understanding._

APPENDIX: IMPLEMENTATION NOTES
================================

Implement using hash tables (of course.) Need efficient ways to convert
to/from lists, perhaps making lists know what's going on underneath the
covers?

APPENDIX: FUTURE DIRECTIONS
=============================

Alternate implementations of mappings, like trees or disk-backed
databases?

-------------------------------------------------------------------------

TIP AutoGenerator - written by Donal K. Fellows

[[Send Tcl/Tk announcements to tcl-an...@mitchell.org
Announcements archived at http://groups.yahoo.com/group/tcl_announce/
Send administrivia to tcl-announ...@mitchell.org
Tcl/Tk at http://tcl.tk/ ]]

Zoran Vasiljevic

unread,
Oct 24, 2002, 4:04:58 AM10/24/02
to
"Donal K. Fellows" <donal.k...@man.ac.uk> wrote in message news:<pgpmoose.2002...@despot.non.net>...

> TIP #111: DICTIONARY VALUES AND MANIPULATORS

Are you aware that a dictionary implementation already
exists? It's a Frederic Bonnets "dictionary" package.

Cheers
Zoran

Donal K. Fellows

unread,
Oct 25, 2002, 6:00:11 AM10/25/02
to
Zoran Vasiljevic wrote:
>> TIP #111: DICTIONARY VALUES AND MANIPULATORS
> Are you aware that a dictionary implementation already
> exists? It's a Frederic Bonnets "dictionary" package.

No, I was not. Must have missed the announcement and/or forgotten about it.
Anyone care to do some kind of comparison of the two?

Donal.
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ donal....@man.ac.uk
-- Thanks, but I only sleep with sentient lifeforms. Anything else is merely
a less sanitary form of masturbation.
-- Alistair J. R. Young <avatar...@arkane.demon.co.uk>

Zoran Vasiljevic

unread,
Oct 25, 2002, 1:24:02 PM10/25/02
to
"Donal K. Fellows" <donal.k...@man.ac.uk> wrote in message news:<3DB9162B...@man.ac.uk>...

> Zoran Vasiljevic wrote:
> >> TIP #111: DICTIONARY VALUES AND MANIPULATORS
> > Are you aware that a dictionary implementation already
> > exists? It's a Frederic Bonnets "dictionary" package.
>
> No, I was not. Must have missed the announcement and/or forgotten about it.
> Anyone care to do some kind of comparison of the two?
>
> Donal.

I'm amazed!
This is another example that there is only one Truth!

Why?

The fact that you did not know about the existence of the
dictionary package and the fact that Frederic has already
implemented its dictionary some years ago, almost with 95%
correspondence to your TIP, I must conclude that this is
the final proof that there can be only one Truth!

For you, and others interested:

http://www.purl.org/NET/bonnet/pub/dictionary.tar.gz

It would be great to extend Tcl with more datatypes like
the one created by this package.

Cheers
Zoran

Mark Patton

unread,
Oct 27, 2002, 7:37:24 PM10/27/02
to
I think this is a great TIP. It would cleanly provide functionality
that has to be hacked together now. And finally an incr that treats a
non-existent var as 0!

I have a few minor nits to pick:

* I find "dict foreach" more readable than "dict for".

* "dict unset" without a key should clear out the dictionary

* "dict get" works on a dictionary value, while "dict set" works on
a dictionary var. I understand the rationale, but it just seems a bit
odd.

* The commands that operate on a dictionary variable handle their
arguments somehwhat inconsistently. The commands "dict set", "dict
unset", and "dict exists" take multiple key arguments while "key
incr", "key lappend", and "key append" take only one key argument. I
think all commands operating on a dictionary variable should accept
multiple key arguments. Unfortunately this conflicts with multiple
values being used to modify a dictionary value.
One solution would be to always specify a key with a list, but this
might be a little cumbersome

* The commands that take a glob pattern as an argument should also
handle regexps with a switch like "array names" does.

* It would be nice if there was a generic way to modify the numeric
value of
a dictionary key besides just incr. Perhaps there could be a command
"dict expr var ?key ...? expression" where expression would be a Tcl
expression containing an identifier for the key value. The identifier
could be substituted for the key value, the expression evaluated, and
then the result used to replace the key value. The NArray extension,
http://www.csua.berkeley.edu/~sls/narray/, has similar functionality.
This this is hard to implement, it's probably not worth it.


Also, had you considered an object based implementation? I usually
find them much more convenient for complex data types. Object based
interfaces are usually simpler and cleanly get rid of the "Am I
operating on a variable name or a value?" problem. This would mean
that a dictionary would no longer have the specified {key val ...}
string/list. The string rep would just be a key to the C Tcl_Obj
structure.

Compare

set d [dict create key val key2 val2]
dict get $d key
dict set d key3 val3
dict unset d key
dict keys $d

proc x {dict_var} {
upvar 1 $dict_var d
dict set d key value
foreach val [dict values $d] {
...
}

with

set d [dict create key val key2 val2]
dict get $d key
dict set $d key3 val3
dict unset $d key
dict keys $d

proc x {d} {
dict set $d key value
foreach val [dict values $d] {
...
}


Anyway I'm looking forward to getting this sort of functionality in
the Tcl core. Maybe I'll do a test implementation if I get a free
weekend.

As an aside I think Tcl needs real multi-dimensional arrays too. Hash
tables are a poor substitute when performance on large arrays is a
consideration.

Mark

Bruce Stephens

unread,
Oct 28, 2002, 5:48:37 AM10/28/02
to
mpa...@jhu.edu (Mark Patton) writes:

[...]

> Also, had you considered an object based implementation? I usually
> find them much more convenient for complex data types. Object based
> interfaces are usually simpler and cleanly get rid of the "Am I
> operating on a variable name or a value?" problem. This would mean
> that a dictionary would no longer have the specified {key val ...}
> string/list. The string rep would just be a key to the C Tcl_Obj
> structure.

[...]

> with
>
> set d [dict create key val key2 val2]
> dict get $d key
> dict set $d key3 val3
> dict unset $d key
> dict keys $d
>
> proc x {d} {
> dict set $d key value
> foreach val [dict values $d] {
> ...
> }

Why not go just a bit further?

set d [dict create key val key2 val2]

$d get key ;# Probably "$d set key" would be more Tcl-like
$d set key3 val3
$d unset key
$d keys

proc x {d} {
$d set key value
foreach val [$d values] {
...
}

[...]

Zoran Vasiljevic

unread,
Oct 28, 2002, 11:24:12 AM10/28/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote in message
> Why not go just a bit further?
>
> set d [dict create key val key2 val2]
> $d get key ;# Probably "$d set key" would be more Tcl-like
> $d set key3 val3
> $d unset key
> $d keys
>
> proc x {d} {
> $d set key value
> foreach val [$d values] {
> ...
> }
>
>

I'm not sure if "$d get key" gets compiled by the internal
bytecode compiler. Maybe Miguel can explain this?
I like the object-related approach. But, aren't we defeating
the bytecode compiler with that?

Cheers, Zoran

Mark Patton

unread,
Oct 28, 2002, 5:00:17 PM10/28/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote in message news:<87vg3m6...@cenderis.demon.co.uk>...

Sure. I like the object as command interface better than the slightly
more verbose form I proposed above too, but you can easily get the
latter from the former.

There are also a few other minor things to think about like name
clashes with already present commands. It would be nice if Tcl
provided facilities for anonymous procedures or some sort of general
support for these types of objects.

Mark

Donal K. Fellows

unread,
Oct 29, 2002, 5:17:03 AM10/29/02
to
Mark Patton wrote:
> I think this is a great TIP. It would cleanly provide functionality
> that has to be hacked together now. And finally an incr that treats a
> non-existent var as 0!

Yeah; that's annoyed me for ages! :^D

> I have a few minor nits to pick:
>

> * "dict unset" without a key should clear out the dictionary

Why not just use a new blank dictionary instead? (OK, there'd be some subtle
performance issues, but that's not necessarily something I'd want to expose
anyway.)

> * "dict get" works on a dictionary value, while "dict set" works on
> a dictionary var. I understand the rationale, but it just seems a bit
> odd.

Tcl's value semantics force this. I'd much rather maintain the value semantics
than make the API perfectly orthogonal.

> * The commands that operate on a dictionary variable handle their
> arguments somehwhat inconsistently. The commands "dict set", "dict
> unset", and "dict exists" take multiple key arguments while "key
> incr", "key lappend", and "key append" take only one key argument. I
> think all commands operating on a dictionary variable should accept
> multiple key arguments. Unfortunately this conflicts with multiple
> values being used to modify a dictionary value.
> One solution would be to always specify a key with a list, but this
> might be a little cumbersome

The problem is that keys can be arbitrary strings, including lists. Wherever it
was possible for me to determine clearly what arguments are keys and what are
not, I've allowed a path-like key scheme, but sometimes I've been unable to do
that.

> * The commands that take a glob pattern as an argument should also
> handle regexps with a switch like "array names" does.

Maybe...

> * It would be nice if there was a generic way to modify the numeric
> value of
> a dictionary key besides just incr. Perhaps there could be a command
> "dict expr var ?key ...? expression" where expression would be a Tcl
> expression containing an identifier for the key value. The identifier
> could be substituted for the key value, the expression evaluated, and
> then the result used to replace the key value. The NArray extension,
> http://www.csua.berkeley.edu/~sls/narray/, has similar functionality.
> This this is hard to implement, it's probably not worth it.

I'm going to turn this idea down on the principle that we don't really need the
[dict] command to be much bloatier than it already is; I really regard the
append, lappend and incr subcommands as being non-core functionality.

> Also, had you considered an object based implementation? I usually
> find them much more convenient for complex data types. Object based
> interfaces are usually simpler and cleanly get rid of the "Am I
> operating on a variable name or a value?" problem. This would mean
> that a dictionary would no longer have the specified {key val ...}
> string/list. The string rep would just be a key to the C Tcl_Obj
> structure.

Objects are something else. In particular, they have semantics that is in
effect call-by-reference as opposed to call-by-copy; if a procedure is passed an
object, it is still entirely feasable for the values in that object to be
changed by other code, whereas when it is passed a value, that value is always
exactly the same (though a new value may be assigned to the variable containing
the value, of course.)

I was deliberately after value semantics, not object semantics. Object-like
semantics are achieved by backing up the value semantics with a variable, so
that references are to the variable, not the value.

[...]


> Anyway I'm looking forward to getting this sort of functionality in
> the Tcl core. Maybe I'll do a test implementation if I get a free
> weekend.
>
> As an aside I think Tcl needs real multi-dimensional arrays too. Hash
> tables are a poor substitute when performance on large arrays is a
> consideration.

There were some interesting talks on this sort of thing at the Tcl conference.

-- US citizens? Remember, I rule the world in this scenario. They aren't
citizens of the US, unless that stands for United Stevenland.
-- Steven Odhner <ta...@primenet.com>

lvi...@yahoo.com

unread,
Oct 29, 2002, 11:51:35 AM10/29/02
to

According to Bruce Stephens <bruce+...@cenderis.demon.co.uk>:
:> set d [dict create key val key2 val2]
:> dict get $d key

:Why not go just a bit further?


:
: set d [dict create key val key2 val2]
: $d get key ;# Probably "$d set key" would be more Tcl-like


Exactly when, in Tcl, is an 'object' view of things better than a command
driven version?

For instance, should in a future version of Tcl, we change things to:

set a [list 1 2 other]

$a replace 1 3 [list a b c]

and similar things for strings, etc.?

--
Tcl - The glue of a new generation. <URL: http://wiki.tcl.tk/ >
Even if explicitly stated to the contrary, nothing in this posting
should be construed as representing my employer's opinions.
<URL: mailto:lvi...@yahoo.com > <URL: http://www.purl.org/NET/lvirden/ >

km...@socrates.berkeley.edu

unread,
Oct 29, 2002, 4:06:22 PM10/29/02
to
In article <apmean$l2m$4...@srv38.cas.org>, <lvi...@yahoo.com> wrote:
>
>According to Bruce Stephens <bruce+...@cenderis.demon.co.uk>:
>:> set d [dict create key val key2 val2]
>:> dict get $d key
>
>:Why not go just a bit further?
>:
>: set d [dict create key val key2 val2]
>: $d get key ;# Probably "$d set key" would be more Tcl-like
>
>
>Exactly when, in Tcl, is an 'object' view of things better than a command
>driven version?

Tcl is command driven, but Tk is object driven:
set w [text .t]
$w insert end "Hello, world\n"


Keith

Karl Lehenbauer

unread,
Oct 29, 2002, 7:31:18 PM10/29/02
to
lvi...@yahoo.com wrote:

> According to Bruce Stephens :


> :> set d [dict create key val key2 val2]
> :> dict get $d key
>
> :Why not go just a bit further?
> :
> : set d [dict create key val key2 val2]
> : $d get key ;# Probably "$d set key" would be more Tcl-like

Object style. Definitely.

> Exactly when, in Tcl, is an 'object' view of things better than a command
> driven version?

Almost always. I repudiate how files work, i.e. with handles. Files should
have been executable and have subcommands/methods for gets, puts, read,
seek,
tell, *configure*, etc. Then you're not creating top-level commands
(like gets,
puts, read, seek, tell and *fconfigure*) that operate on handles of the
correct
type. It is all about object-oriented and encapsulation versus a sort of
C-style. John tried to get me to understand this when I did files for
TclX 3 (Tcl didn't have files back then), but I didn't get it.

Think how much less work virtual filesystems would have been if Tcl's
files had always worked that way! (They pretty much wouldn't have
been needed except for directory handling (glob) and stuff "file" does.)

> For instance, should in a future version of Tcl, we change things to:
>
> set a [list 1 2 other]
>
> $a replace 1 3 [list a b c]
>
> and similar things for strings, etc.?

It's useful when it's useful, and it's not useful when it's not useful.
Itcl is a great
environment for prototyping stuff like this. I've tried writing a
really good general
purpose list object and I haven't really cracked the nut in the sense
that that
"$a replace 1 3..." business starts to break down when you actually try
to use it.

Karl Lehenbauer

unread,
Oct 29, 2002, 7:53:07 PM10/29/02
to
Donal K. Fellows wrote:

> TIP #111: DICTIONARY VALUES AND MANIPULATORS

In developing with Tcl and developing extensions to Tcl, etc, I've found
that
when the process includes iteratively prototyping and then trying to use
the code
in real-world-type situations... see if it works and if it's "right" or
not... you get
better extensions that are more useful and feel more "right."

A couple of examples come to mind: With the very first implementation of
files, you had to include the newline when calling "puts" (i.e. it
didn't implicitly
add a newline in standard operation.) Only by using it did I learn that you
wanted the newline 99% of the time and see that it should just do it by
default.

"upvar" is another example. It is super useful, used and abused. It is
the stepchild of
"uplevel", a great idea that is difficult to use. (The thought process
that led
to "upvar" came from trying to write "incr" in high-level Tcl using
"uplevel.")

A couple of examples from outside of Tcl are IP (versus OSI) and UNIX
(versus OS/360
or VMS or whatever).

Where I'm headed with this is, I don't think stuff like this TIP should
become
part of the standard until people have had a chance to try it and see if
it really
helps solve a problem or not. And in the act of that maybe they
discover, hey,
if we twiddled this this way, it becomes way more useful or way more general
purpose. Kind of like how stuff evolved in TclX and then the Tcl team at
Berkeley/Sun/Scriptics/Ajuba many of its best and most general purpose ideas
(arrays, files, sockets, clock support, etc), fixed it up a bit, and
made it part of the
standard.

The code had a chance to be used and evolve before they became a part of
the standard.

Or maybe we could put new stuff in but mark it experimental, where we
explicitly
say that we're making no commitment to supporting it or providing
compatibility
with the existing implementation in the future.

Comments?

Don Porter

unread,
Oct 29, 2002, 8:13:50 PM10/29/02
to
Karl Lehenbauer wrote:
> Almost always. I repudiate how files work, i.e. with handles. Files should
> have been executable and have subcommands/methods for gets, puts, read,
> seek,
> tell, *configure*, etc. Then you're not creating top-level commands
> (like gets,
> puts, read, seek, tell and *fconfigure*) that operate on handles of the
> correct
> type. It is all about object-oriented and encapsulation versus a sort of
> C-style. John tried to get me to understand this when I did files for
> TclX 3 (Tcl didn't have files back then), but I didn't get it.
>
> Think how much less work virtual filesystems would have been if Tcl's
> files had always worked that way! (They pretty much wouldn't have
> been needed except for directory handling (glob) and stuff "file" does.)

Apples and oranges, I think. What you call "files" above -- the handles
that come back from [open], [socket], and the things you can [puts] to
and [gets] and [read] from etc. are more precisely "channels", that is
implementations of the Tcl_Channel interface.

The VFS stuff in 8.4, however, generalizes "file systems" not files.
It's a completely different extension interface. There's some relation
between them, but not so much that I think a nice OO "channel"
representation would have made VFS significantly easier.

--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

Donal K. Fellows

unread,
Oct 30, 2002, 8:34:00 AM10/30/02
to
Mark Patton wrote:
> There are also a few other minor things to think about like name
> clashes with already present commands. It would be nice if Tcl
> provided facilities for anonymous procedures or some sort of general
> support for these types of objects.

This topic again? All it takes is a way to figure out when to get rid of the
command, and you can get (effectively) anonymous procedures really easily in Tcl
as it stands at the moment (it is pretty easy to write a procedure to pick a
command name that is not currently in use...)

OTOH, garbage collection in such situations is a major issue.

-- If that's dead, sign me up for necrophilia classes.
-- Mark Loy <ml...@iupui.edu>

lvi...@yahoo.com

unread,
Oct 30, 2002, 11:19:08 AM10/30/02
to

:Where I'm headed with this is, I don't think stuff like this TIP should
:become
:part of the standard until people have had a chance to try it and see if
:it really
:helps solve a problem or not.

Is there anything in TIP 111 that requires it to be implemented within
the core? Or is it proposed for the core not because of implementation
necessity, but from the idea that it would be invaluable to most?

I'm just thinking that perhaps it could initially be implemented as
an extension, tried out, etc. and then included along with Tcl
(or even integrated in the core if that improves speed, etc.) later.


Note that I'm not certain that I have envisioned a use for this
type of data structure, so perhaps I am missing some major aspect of
things.

Will Duquette

unread,
Oct 30, 2002, 7:04:21 PM10/30/02
to
On 29 Oct 2002 16:51:35 GMT, lvi...@yahoo.com wrote:

>Exactly when, in Tcl, is an 'object' view of things better than a command
>driven version?
>
>For instance, should in a future version of Tcl, we change things to:
>
>set a [list 1 2 other]
>
>$a replace 1 3 [list a b c]
>
>and similar things for strings, etc.?

In this case, absolutely not. Consider this:

% set a [list "set"]
set
% $a append foo
foo
% set a
set
% set append
foo

Object notation works well for objects managed by handles; it works
poorly for data values that translate naturally into strings.

As a side point, on the use of objects in general:

My programming maxim is that "complexity is conserved". Writing
large apps is all about managing that complexity so that it doesn't
kill you. I view objects as a mechanism for packaging up a bundle
of complexity and giving it nice pretty interface all tied to a nice
little handle. Then I can forget about the complexity.

In short, I need objects to package chunks of code. I don't really
want to have to use objects to solve problems at the level of
the individual line of code--having spent the summer doing Java,
the "everything has to be an object" paradigm can be really annoying.

Brett Schwarz

unread,
Oct 30, 2002, 8:25:08 PM10/30/02
to
Will Duquette wrote:

You took the words right out of my mouth...

Donal K. Fellows

unread,
Oct 31, 2002, 4:38:57 AM10/31/02
to
Karl Lehenbauer wrote:
[...]

> Where I'm headed with this is, I don't think stuff like this TIP should
> become part of the standard until people have had a chance to try it and see
> if it really helps solve a problem or not. And in the act of that maybe they
> discover, hey, if we twiddled this this way, it becomes way more useful or
> way more general purpose. Kind of like how stuff evolved in TclX and then
> the Tcl team at Berkeley/Sun/Scriptics/Ajuba many of its best and most
> general purpose ideas (arrays, files, sockets, clock support, etc), fixed it
> up a bit, and made it part of the standard.

I definitely think that some kind of experimental version will be necessary
before any attempt at integration (though I've hit the need for hash-values in
the past in my code, and hit a fairly substantial performance wall in the
process too, so I'd assert that the need for this sort of thing is there.) On
the other hand, I am very short of time for non-work things at the moment, so an
actual implementation (probably as an extension when it finally happens) is
likely to be a while off.

I published the TIP because I felt that functionality like this might be nice in
the core (there are integration aspects in the full nature of my idea that
preclude an extension, particularly things like the type of the results of
[array get]) and because I thought it would be nice to have some feedback on my
idea before I started coding anything.

Bob Techentin

unread,
Oct 31, 2002, 9:32:39 AM10/31/02
to
"Will Duquette" <William.H...@jpl.nasa.gov> wrote

> lvi...@yahoo.com wrote:
> >Exactly when, in Tcl, is an 'object' view of things better than
> >a command driven version?
> >
> >For instance, should in a future version of Tcl, we change
> >things to:
> >
> >set a [list 1 2 other]
> >$a replace 1 3 [list a b c]
>
> In this case, absolutely not. Consider this:
>
> % set a [list "set"]
> set
> % $a append foo
> foo
> % set a
> set
> % set append
> foo
>
> Object notation works well for objects managed by handles; it works
> poorly for data values that translate naturally into strings.


Eeek! Don't mix metaphores like that! :-) Object notation is not
the same as command or keyword substitution. I think I can expand on
Larry's 'object style' vs 'command style'.
'command style' (the way we do things now)

set a [list "never" "do" "your"]
set a [lreplace $a 0 0 "always"]
lappend a "best"
puts $a
always do your best

'object style' (which might be possible in the future)
set a [list "never" "do" "your"]
$a replace 0 0 "always"
$a append "best"
puts [$a]
always do your best


> In short, I need objects to package chunks of code.
> I don't really want to have to use objects to solve
> problems at the level of the individual line of code--having
> spent the summer doing Java, the "everything has to
> be an object" paradigm can be really annoying.

Amen. I'm not sure which style would work best for lists in the long
term, becuase I don't see a dramatic reduction in the amount of code
needed to manipulate the list.

Bob
--
Bob Techentin techenti...@NOSPAMmayo.edu
Mayo Foundation (507) 538-5495
200 First St. SW FAX (507) 284-9171
Rochester MN, 55901 USA http://www.mayo.edu/sppdg/


Will Duquette

unread,
Oct 31, 2002, 11:28:29 AM10/31/02
to
On Thu, 31 Oct 2002 08:32:39 -0600, "Bob Techentin"
<techenti...@mayo.edu> wrote:

Bob,

I'm not sure we're communicating. I understood completely what
Larry meant by object style; I was just demonstrating that to use
object style for lists means that the string representation of the
list needs to be a token (a command name) rather than a white space
delimited string as it is now. My code snippet above shows why--
if you don't represent the list as a token then you can't distinguish
between list objects and other strings. In the example above, is

set append foo

a command to assign "foo" to the variable "append", or a command
to append "foo" to the list currently containing one element, "set"?
Unless we completely change the nature of Tcl, it's the former.
Which means that to make lists objects, the shell dialog I show
above would need to look like this instead:

% set a [list "set"]

list1
% $a append foo
% set a
list1
% $a join
set foo

And suddenly lists are no longer strings, and again, lots of
Tcl code breaks.

>> In short, I need objects to package chunks of code.
>> I don't really want to have to use objects to solve
>> problems at the level of the individual line of code--having
>> spent the summer doing Java, the "everything has to
>> be an object" paradigm can be really annoying.
>
>Amen. I'm not sure which style would work best for lists in the long
>term, becuase I don't see a dramatic reduction in the amount of code
>needed to manipulate the list.

I agree; pure list manipulation code would be more or less the same.
But--I'm sure that the current style is better because if we adopt
the object style we lose the easy equivalence between lists and
strings. I don't see any way around that.

Will

lvi...@yahoo.com

unread,
Nov 4, 2002, 10:35:15 AM11/4/02
to

According to Bob Techentin <techenti...@mayo.edu>:
:I'm not sure which style would work best for lists in the long

:term, becuase I don't see a dramatic reduction in the amount of code
:needed to manipulate the list.


But I don't see the command vs object style of writing commands as being
a matter of reducing code - instead, it is, in my mind, a matter of
mindset and of stylistically determining how to extend the language.

Look at the arguments that have occured over the years about lrepace,
lindex, etc. vs a single list like command consolidating all the
operations under a single umbrella command.

lvi...@yahoo.com

unread,
Nov 4, 2002, 10:39:56 AM11/4/02
to

According to Will Duquette <William.H...@jpl.nasa.gov>:
:But--I'm sure that the current style is better because if we adopt

:the object style we lose the easy equivalence between lists and
:strings. I don't see any way around that.

One just has to make certain that objects know how to express their data
when asked for string data vs list data vs ... Then we make string commands
ask objects for their string representations... or at least make string
operations in the interpreter occur automagically.

Bob Techentin

unread,
Nov 4, 2002, 11:37:55 AM11/4/02
to
<lvi...@yahoo.com> wrote

>
> According to Will Duquette <William.H...@jpl.nasa.gov>:
> :But--I'm sure that the current style is better because if we adopt
> :the object style we lose the easy equivalence between lists and
> :strings. I don't see any way around that.
>
> One just has to make certain that objects know how to express their
data
> when asked for string data vs list data vs ... Then we make string
commands
> ask objects for their string representations... or at least make
string
> operations in the interpreter occur automagically.


Hmmmm. Intriguing. I hadn't thought of contrasting objects vs.
variables by their ability to easily morph into a string
representation. But that's the nub of the problem with passing arrays
by value. Tcl arrays just don't have a natural, transparent and
automatic string representation.

I think I understand how to create a Tcl_Obj with these
characteristics. You just have to make sure that the object knows how
to generate a string rep, and expect string commands to call
Tcl_GetString(). But I don't think that resolves the problem Will
points out.

For this new dictionary type suggested in Tip #111, you can create the
object easily, and the command interface (current style) is probably
going to be implemented with value semantics.

set a [dict create key1 val1 key2 val2]
set a [dict remove $a key1]
puts $a

But if you're going to support the object style interface (like you'd
get from Incr Tcl), then what should the interpreter substitute for
the object name? Or am I misunderstanding the issue?

set a [dict create key1 val1 key2 val2]
$a remove key1
puts $a ;# or should this be...
puts [$a stringRep]

Kristoffer Lawson

unread,
Nov 4, 2002, 3:02:48 PM11/4/02
to
Bob Techentin <techenti...@mayo.edu> wrote:

> Hmmmm. Intriguing. I hadn't thought of contrasting objects vs.
> variables by their ability to easily morph into a string
> representation. But that's the nub of the problem with passing arrays
> by value. Tcl arrays just don't have a natural, transparent and
> automatic string representation.

Well they don't have a transparent and automatic representation, but
that's really a kind of fault in Tcl. They could do:

array get a
=> {name Kris} {age 25} {location Finland}

Or whatever

--
/ http://www.fishpool.com/~setok/

Chang Li

unread,
Nov 4, 2002, 6:02:59 PM11/4/02
to

<lvi...@yahoo.com> wrote in message news:aq643j$spm$2...@srv38.cas.org...

>
>
> But I don't see the command vs object style of writing commands as being
> a matter of reducing code - instead, it is, in my mind, a matter of
> mindset and of stylistically determining how to extend the language.
>

I agree. Object style will make Tcl much clean and extensible.

Acturally "everything is string" has changed in Tcl. The internal Tcl is an
object-oriented system without inheritance. I acturally think Tcl as an
object
language with string as object presentation. The convenience and efficiency
of Tcl is its automatic conversion between string and objects. And the
object
representation of Tcl is consistence from Tcl to Tk.

Chang

Darren New

unread,
Nov 4, 2002, 10:55:45 PM11/4/02
to
lvi...@yahoo.com wrote:
> I'm just thinking that perhaps it could initially be implemented as
> an extension, tried out, etc. and then included along with Tcl
> (or even integrated in the core if that improves speed, etc.) later.

Looking it over, it looks like it's pretty straightforward to implement
in pure Tcl, as long as you don't mind inefficiencies. Shimmering
between lists and arrays in a pure-8.4 implementation is the only thing
that looks bad.

Another thing I noticed: Some of the routines take a list of keys as
multiple keys at the same level, and some of the routines take a list of
keys as a deep probe into nested structures.

That is,
[dict get $a one two three]
gives you one value, but
[dict remove $a one two three]
removes three.

I'm thinking that the ability to specify a path through a dictionary
would be very useful, for remove, replace, append, etc. Perhaps either a
special syntax for keys (say, one key is always a list, allowing things
like
[dict set {one two} val1 {one three} val2]
that set values in a directory two levels down) or having a -wide vs
-deep flag or something like that?

-- Darren

art morel

unread,
Nov 5, 2002, 11:53:22 AM11/5/02
to
Will Duquette <William.H...@jpl.nasa.gov> wrote in message news:<22s0su07hsm2bua5k...@4ax.com>...

I would like to be able to grab a script library/package that could be
implemented seperately in both tcl procedures and/or an object
orientated system such as itcl or all the others. Id like to define
the interface then be able to use whoevers package implements the
interface with their technology of choice. I haven't thought through
this very much but I think if we can cleanly define a interface, have
a standard so that many systems(snit,stoop,...) can be used to
implement the interface , and the interface User being able to handle
it(these drop in replacements), we will get more libraries of cool SW.

I have wrestled with a file buffer library for a little text editor of
mine. It started out as an library of routines to process/manage many
open buffers of text. It has lots of functions and was getting
unweildly. I next wrote it in itcl or base parts of it and it was much
slicker. I have not taken the time to integrate it into my old system
because it was not designed as a drop in replacement nor was the
application. Had I followed some standards I could have easily done
this. I suspect we all could get more code in our hands and offload
work to others if we some standards out there.

art

Will Duquette

unread,
Nov 5, 2002, 11:31:23 AM11/5/02
to
On 4 Nov 2002 15:39:56 GMT, lvi...@yahoo.com wrote:

>
>According to Will Duquette <William.H...@jpl.nasa.gov>:
>:But--I'm sure that the current style is better because if we adopt
>:the object style we lose the easy equivalence between lists and
>:strings. I don't see any way around that.
>
>One just has to make certain that objects know how to express their data
>when asked for string data vs list data vs ... Then we make string commands
>ask objects for their string representations... or at least make string
>operations in the interpreter occur automagically.

I don't think it's as simple as that. I'll go back to my example--
if lists are objects with methods, then what does this mean:

set append foo

Is this a command to assign "foo" to the variable "append", or is
this a command to append "foo" to the list currently consisting of
the single item "set"?

To me, one of the glories of Tcl is that not everything is an
object. I can use objects when I want to, but I don't have to.

Will

Larry Smith

unread,
Nov 5, 2002, 12:25:01 PM11/5/02
to
Bob Techentin wrote:

> Hmmmm. Intriguing. I hadn't thought of contrasting objects vs.
> variables by their ability to easily morph into a string
> representation. But that's the nub of the problem with passing arrays
> by value. Tcl arrays just don't have a natural, transparent and
> automatic string representation.

There is nothing stopping us from giving them one.

--
.-. .-. .---. .---. .-..-. | Wild Open Source Inc.
| |__ / | \| |-< | |-< > / | "Making the bazaar just a
`----'`-^-'`-'`-'`-'`-' `-' | little more commonplace."
home: www.smith-house.org | work: www.wildopensource.com

lvi...@yahoo.com

unread,
Nov 6, 2002, 9:56:01 AM11/6/02
to

According to Bob Techentin <techenti...@mayo.edu>:
: set a [dict create key1 val1 key2 val2]

: set a [dict remove $a key1]
: puts $a
:
:But if you're going to support the object style interface (like you'd
:get from Incr Tcl), then what should the interpreter substitute for
:the object name? Or am I misunderstanding the issue?
:
: set a [dict create key1 val1 key2 val2]
: $a remove key1
: puts $a ;# or should this be...
: puts [$a stringRep]


I guess I would expect puts $a to output a handle and that if I wanted
to see the entire dictionary, I would expect to have a get method
that would return the contents of the dictionary in the form that could
be used by create .

Peter.DeRijk

unread,
Nov 7, 2002, 8:21:47 AM11/7/02
to
art morel <a...@rain.org> wrote:
> I would like to be able to grab a script library/package that could be
> implemented seperately in both tcl procedures and/or an object
> orientated system such as itcl or all the others. Id like to define
> the interface then be able to use whoevers package implements the
> interface with their technology of choice. I haven't thought through
> this very much but I think if we can cleanly define a interface, have
> a standard so that many systems(snit,stoop,...) can be used to
> implement the interface , and the interface User being able to handle
> it(these drop in replacements), we will get more libraries of cool SW.

Do you mean something like http://rrna.uia.ac.be/interface/. I have currently
used it in to define the interface of tcldbi (http://rrna.uia.ac.be/dbi/)

--
Peter De Rijk der...@uia.ua.ac.be
<a href="http://rrna.uia.ac.be/~peter/">Peter</a>
To achieve the impossible, one must think the absurd.
to look where everyone else has looked, but to see what no one else has seen.

Donal K. Fellows

unread,
Nov 12, 2002, 5:16:45 AM11/12/02
to
Kristoffer Lawson wrote:
> Well they don't have a transparent and automatic representation, but
> that's really a kind of fault in Tcl. They could do:
> array get a
> => {name Kris} {age 25} {location Finland}

That's TclX keyed-list style. While it would be nice to have that as our scheme
(it has the advantage that the length of the list is identical to the number of
mappings) we're better off sticking with keeping [array get] returning (things
that look like) lists as they currently are (to promote backward-compatability
at the script level.)

-- The small advantage of not having California being part of my country would
be overweighed by having California as a heavily-armed rabid weasel on our
borders. -- David Parsons <o r c @ p e l l . p o r t l a n d . o r . u s>

Donal K. Fellows

unread,
Nov 12, 2002, 5:30:25 AM11/12/02
to
Darren New wrote:
> Looking it over, it looks like it's pretty straightforward to implement
> in pure Tcl, as long as you don't mind inefficiencies. Shimmering
> between lists and arrays in a pure-8.4 implementation is the only thing
> that looks bad.

Doing something intelligent about that is an implementation detail. ;^)

> Another thing I noticed: Some of the routines take a list of keys as
> multiple keys at the same level, and some of the routines take a list of
> keys as a deep probe into nested structures.

This is one of the things that I agonized over!

> That is,
> [dict get $a one two three]
> gives you one value, but
> [dict remove $a one two three]
> removes three.

The thing is that there's two categories of use that I want to support;
operations on multiple keys and operations on key paths. And I don't want to
force the use of [list] for single one-level keys!

I think I'm sort-of trying to aim for there to be two classes of operations:
those that operate on values (and where usually I go for supporting multiple
keys at the given level) and those that operate on variables containing values
(where I prefer paths, in part because there's a clearer notion of root.)

> I'm thinking that the ability to specify a path through a dictionary
> would be very useful, for remove, replace, append, etc. Perhaps either a
> special syntax for keys (say, one key is always a list, allowing things like
> [dict set {one two} val1 {one three} val2]
> that set values in a directory two levels down) or having a -wide vs
> -deep flag or something like that?

Some of these things just plain didn't seem feasable to me. The problem is that
path-construction in dictionaries is much messier than in lists; I've usually
preferred to keep the normal case simpler than to produce a solution for every
task thrown at it. (If the TIP gets accepted, other people will be able to
build on it with their own TIPs... ;^)

Bob Techentin

unread,
Nov 12, 2002, 10:30:04 AM11/12/02
to
"Donal K. Fellows" <donal.k...@man.ac.uk> wrote:

> Darren New wrote:
> > I'm thinking that the ability to specify a path through a
> > dictionary would be very useful, for remove, replace, append,
> > etc. Perhaps either a special syntax for keys (say, one key is
> > always a list, allowing things like [dict set {one two} val1 {one
> > three} val2] that set values in a directory two levels down) or
> > having a -wide vs -deep flag or something like that?
>
> Some of these things just plain didn't seem feasable to me. The
> problem is that path-construction in dictionaries is much messier
> than in lists; I've usually preferred to keep the normal case
> simpler than to produce a solution for every task thrown at it. (If
> the TIP gets accepted, other people will be able to build on it with
> their own TIPs... ;^)

Could you add a path specification command? WIthout worrying about
implementation - much as I ignore the implementation of Itcl's
[code] - I can imagine a syntax something like this:

[dict get $a one two three]

gives you a list of three values

[dict get $a [dict path one two three]]
gives you one value


[dict remove $a one two three]
removes three.

[dict remove $a [dict path one two three]]
removes one value

Darren New

unread,
Nov 12, 2002, 10:55:47 AM11/12/02
to
Bob Techentin wrote:
> [dict remove $a [dict path one two three]]
> removes one value

Good idea. What does this produce?

puts [dict path one two three]

I think that's the quandry. :-)

Kristoffer Lawson

unread,
Nov 12, 2002, 1:04:42 PM11/12/02
to
Donal K. Fellows <donal.k...@man.ac.uk> wrote:
> Kristoffer Lawson wrote:
>> Well they don't have a transparent and automatic representation, but
>> that's really a kind of fault in Tcl. They could do:
>> array get a
>> => {name Kris} {age 25} {location Finland}
>
> That's TclX keyed-list style. While it would be nice to have that as our scheme
> (it has the advantage that the length of the list is identical to the number of
> mappings) we're better off sticking with keeping [array get] returning (things
> that look like) lists as they currently are (to promote backward-compatability
> at the script level.)

Oops, you're right. I was actually referring to the [array get] style.
The point really is that we do have a way of describing arrays as values
that can be passed back and forth between commands. All we need is for a
syntactically nice way to do that automagically, which could also
probably handle it faster than [array get] and [array set].

--
/ http://www.fishpool.com/~setok/

art morel

unread,
Nov 13, 2002, 1:08:03 AM11/13/02
to
"Peter.DeRijk" <der...@hgems.uia.ac.be> wrote in message news:<3dca...@news.uia.ac.be>...

> art morel <a...@rain.org> wrote:
> > I would like to be able to grab a script library/package that could be
> > implemented seperately in both tcl procedures and/or an object
> > orientated system such as itcl or all the others. Id like to define
> > the interface then be able to use whoevers package implements the
> > interface with their technology of choice. I haven't thought through
> > this very much but I think if we can cleanly define a interface, have
> > a standard so that many systems(snit,stoop,...) can be used to
> > implement the interface , and the interface User being able to handle
> > it(these drop in replacements), we will get more libraries of cool SW.
>
> Do you mean something like http://rrna.uia.ac.be/interface/. I have currently
> used it in to define the interface of tcldbi (http://rrna.uia.ac.be/dbi/)

Hi Peter,

Thanks for the reply. I have only read the web page descriptions so
far. It looks quite promising. Do you have any simple tutorials of the
interface being used ? The tcldbi is looks quite neat but will take
some study.

Thanks,
art

Donal K. Fellows

unread,
Nov 13, 2002, 6:28:15 AM11/13/02
to

Supposing we say that dictionary paths are lists (and that [dict path] is just
an alias for [list].) What happens then if I want to use a string with spaces
in as a simple key in a single-level dictionary? Having to use a constructor
just to do simple operations is not a good thing, and a virtually identical
argument can be made for any other technique of construction which produces
printable values (non-printable values have other problems.)

IMO, multi-get should be a different command anyway, since it would be returning
a list. (There have been similar discussions on this sort of thing before
relating to the meaning of multiple-index [lindex] results.)

Donal.
--
"Windows is a car with square wheels (architecture) and a huge engine (hype,
etc.), capable of of making the car move despite the square wheels. Linux
is a car with round wheels but a small engine, capable of making the car go
despite the small engine." -- John Latham <j...@cs.man.ac.uk>

Peter.DeRijk

unread,
Nov 14, 2002, 8:39:07 AM11/14/02
to

> Hi Peter,

Here is a simple example (I hope it is not to long for clt, I will be i
putting in the next version)

-------

-------
ne file for simplicity
# It will usually be placed in a file in a doc directory, so it can also be
# used to generate man pages, etc
set stackdock {
<manpage package="interface" title="stack_interface" id="stack_interface" cat="stack">
<namesection>
<name>stack_interface</name>
<desc>description of the stack interface</desc>
</namesection>
<section>
<title>DESCRIPTION</title>
a very simple demonstration interface
</section>
<section>
<title>THE STACK INTERFACE</title>
<commandlist>
<commanddef>
<command><cmd>objectName</cmd> <method>clear</method></command>
<desc>clear the stack</desc>
</commanddef>
<commanddef>
<command><cmd>objectName</cmd> <method>push</method> <m>value</m> ?<m>value</m> ...?</command>
<desc>push value(s) on the stack</desc>
</commanddef>
<commanddef>
<command><cmd>objectName</cmd> <method>pop</method></command>
<desc>get values from the stack</desc>
</commanddef>
</commandlist>
</section>
<keywords>
<keyword>stack_interface</keyword>
</keywords>
</manpage>
}

# interface definition
package require interface
proc ::interfaces::stack-1.0 {option args} {
set interface stack
set version 1.0
switch $option {
interface {
# This is an interface defining object, so it supports the interface interface
# This code will advertise this fact
if {[llength $arg]} {
if {[string equal [lindex $args 0] interface]} {
return 0.8
} else {
error "::interfaces::$interface-$version does not support interface interface"
}
} else {
return [list interface 0.8]
}
}
doc {
# return xml documentation
return $::stackdock
}
test {
# run some tests on an object supposed to support the interface
set len [llength $args]
if {$len < 1} {
error "wrong # args: should be \"interfaces::$interface-$version test object ?options?\""
}
set object [lindex $args 0]
array set opt [lrange $args 1 end]
# the testleak is needed due to a small bug in the interface::test routine
set ::interface::testleak 0
interface::test {interface match} {
$object interface stack
} $version
interface::test {push and pop} {
$object clear
$object push 1
$object pop
} 1
interface::test {push, push and pop} {
$object clear
$object push 1
$object push 2
$object pop
} 2
interface::test {stack empty error} {
$object clear
$object pop
$object pop
} {stack empty} error
# more test should follow
interface::testend
}
}
}

# implementation of "object" implementing the interface
# this is of course just a test case for demonstrating interfaces,
# and not a real object, nor a good or even reasonable implementation
proc stack1 {option args} {
global stack1_data
switch $option {
clear {
set stack1_data {}
}
push {
eval lappend stack1_data $args
}
pop {
if {![llength $stack1_data]} {
error "stack empty"
}
set result [lindex $stack1_data end]
set stack1_data [lrange $stack1_data 0 end-1]
return $result
}
interface {
set interfaces {stack 1.0 nop 0.0}
if {[llength $args]} {
set reqinterface [lindex $args 0]
foreach {interface version} $interfaces {
if {[string equal $reqinterface $interface]} {
return $version
}
}
error "stack1 does not support interface $reqinterface"
} else {
return $interfaces
}
}
}
}

# test if stack1 does indeed comply with the stack-1.0 interface
interface test stack-1.0 stack1
# return documentation
interface doc stack-1.0

Darren New

unread,
Nov 14, 2002, 12:44:27 PM11/14/02
to
"Donal K. Fellows" wrote:
> Supposing we say that dictionary paths are lists (and that [dict path] is just
> an alias for [list].) What happens then if I want to use a string with spaces
> in as a simple key in a single-level dictionary? Having to use a constructor
> just to do simple operations is not a good thing, and a virtually identical
> argument can be made for any other technique of construction which produces
> printable values (non-printable values have other problems.)

Agreed. That's why I wondered if you could get some magic in there that
makes [dict path xyz] not the same as "xyz" and still have everything
work.

Personally, I suspect that the number of cases where the key is
completely arbitrary and thus {[lindex $key 0]!=$key} is going to be
relatively small; generally, on the same order of magnitude as spaces in
array index values. I wouldn't mind having to [list] keys that might
have list-specific characters in them.

> IMO, multi-get should be a different command anyway, since it would be returning
> a list. (There have been similar discussions on this sort of thing before
> relating to the meaning of multiple-index [lindex] results.)

Agreed. I was trying to put such a thing together. My complaint with how
things are now is that if you have a complex tree of values and you want
to change something deep in the tree, you would need to deconstruct the
tree, make the change, and reconstruct it. (Unless I'm reading the TIP
wrong?) It seems wrong that assigning a value to a variable would
(essentially) give you different behavior than just using the value;
that's too much like Perl for my taste.

--
Darren New
San Diego, CA, USA (PST)
Why did humans ever domesticate peeves to start with?

art morel

unread,
Nov 15, 2002, 11:52:38 AM11/15/02
to
"Peter.DeRijk" <der...@hgems.uia.ac.be> wrote in message news:<3dd3...@news.uia.ac.be>...

Wow !!! this is exactly what I was thinking of. Looks great !! Would
you consider this going into the tcllib ? I see the interface test is
not replacing a test package for the implementation object. Since the
interface namespace is a seperate both implementing procedures and
objects can implement it. It is not native inside the OO system so it
will work generically for everything. I am not too familiar with XML
yet. How would you render this documentation ? Maybe you could add to
the demo an implementation in some OO system or ask for others to
provide one for their OO system of choice.

art

Peter.DeRijk

unread,
Nov 15, 2002, 12:34:01 PM11/15/02
to
art morel <a...@rain.org> wrote:
> [long example removed]

> Wow !!! this is exactly what I was thinking of. Looks great !! Would
> you consider this going into the tcllib ? I see the interface test is
> not replacing a test package for the implementation object. Since the
> interface namespace is a seperate both implementing procedures and
> objects can implement it. It is not native inside the OO system so it
> will work generically for everything. I am not too familiar with XML
> yet. How would you render this documentation ? Maybe you could add to
> the demo an implementation in some OO system or ask for others to
> provide one for their OO system of choice.

- Of course I would not mind getting this in tcllib, but I have no idea
how stuff gets in it.
- interface test is indeed not a replacement for a test package for the
implementation object, but is meant to be used in one. An implementation
can support several interfaces, so a typical test package will invoke
interface test for all supported interfaces, and maybe add some testsi
specific to the object.
- The whole idea of the interface package is indeed to be as generic and
implementation agnostic as possbile (cfr. the extremely simplified
example)
- tmml (http://tmml.sourceforge.net/) contains some tools to convert the
XML to man pages or html. (I got the CVS version)

Mark Patton

unread,
Nov 15, 2002, 11:51:39 PM11/15/02
to
"Donal K. Fellows" <donal.k...@man.ac.uk> wrote in message

> I definitely think that some kind of experimental version will be necessary
> before any attempt at integration (though I've hit the need for hash-values in
> the past in my code, and hit a fairly substantial performance wall in the
> process too, so I'd assert that the need for this sort of thing is there.) On
> the other hand, I am very short of time for non-work things at the moment, so an
> actual implementation (probably as an extension when it finally happens) is
> likely to be a while off.

I've implemented most of the TIP and will probably finish it off this
weekend. It's pretty straight forward, but there are some performance
related issues to think about. Once I scrounge up some web space I'll
post a link.

Mark

lvi...@yahoo.com

unread,
Nov 18, 2002, 9:50:17 AM11/18/02
to
Stuff gets into tcllib in at least two ways:

o someone who has written some software signs up to be a http://tcllib.sf.net
developer, talks to the other developers on the tcllib-dev mailing
list (to get points to guidelines, confirm namespace choices, etc.),
and then checks the code , etc. into the cvs

o someone who has written some software evangelizes someone already a tcllib
developer to do the work for them - or at least gets them
enthusiastic enough about the package that the newly recruited
convert does the work for the software creator.


According to Peter.DeRijk <der...@hgems.uia.ac.be>:
:- Of course I would not mind getting this in tcllib, but I have no idea


: how stuff gets in it.

Mark Patton

unread,
Nov 19, 2002, 10:13:46 PM11/19/02
to
mpa...@jhu.edu (Mark Patton) wrote in message
> I've implemented most of the TIP and will probably finish it off this
> weekend. It's pretty straight forward, but there are some performance
> related issues to think about. Once I scrounge up some web space I'll
> post a link.

I finished implementing the TIP. All of the features of the TIP are
implemented and have been used successfully at least once. :)

Code: http://home.earthlink.net/~m-patton/dict-0.01.tar.gz

In a few initial performance tests dictionaries were quite a bit
slower than arrays. The one notable exception was when doing "dict
incr"; avoiding the info exists tests helps quite a bit.

Mark

0 new messages