Code Comments
Programming Forum and web based access to our favorite programming groups.I've encountered a following problem - I'm passing into procedure
optional parameter, which can have quite complex internal Tcl_Obj
representation (custom object type from my C extension).
This object is optional. Be it some simple Tcl object such as string,
list etc, I would use following code:
proc do_something {{object {}}} {
if {[string length $object]} {
# do something with object
} else {
# do something without object
}
}
Problem is that [string length] does conversion of object into string
representation. Its typePtr->name now is "string". And when I want to do
something with it, internal representation is constructed again from
string one, which can be quite time-consuming.
If it was Perl, I would use if (defined($object)) which would just check
if something is there, without even accessing its internals.
How to do the same thing in Tcl? Is there any standard Tcl command,
which allows to check whether function argument just contain something?
I'm afraid that using default value other than empty string wouldn't
help, because comparation would result in conversion of object into type
of second operand.
In this particular case using of special keyword args might help
proc do_something {args} {
if {[llength $args]} {
#do something with [lindex $args 0]
} else {
# do sometihnf without object
}
}
But more universal way is desirable.
--
"You, sir, are nothing but a pathetically lame salesdroid!
I fart in your general direction!"
-- Randseed on #Linux
Post Follow-up to this messageThe only way I can think of off the top of my head is:
proc do_something {args} {
switch -exact [llength $args] {
0 {
# it wasn't provided
set object {}
} 1 {
set object [lindex $args 0]
} default {
error "usage: do_something ?object?"
}
}
# ...
}
Hope that helps,
Rob Seeger
Victor Wagner wrote:
> I've encountered a following problem - I'm passing into procedure
> optional parameter, which can have quite complex internal Tcl_Obj
> representation (custom object type from my C extension).
>
> This object is optional. Be it some simple Tcl object such as string,
> list etc, I would use following code:
>
> proc do_something {{object {}}} {
> if {[string length $object]} {
> # do something with object
> } else {
> # do something without object
> }
> }
>
> Problem is that [string length] does conversion of object into string
> representation. Its typePtr->name now is "string". And when I want to do
> something with it, internal representation is constructed again from
> string one, which can be quite time-consuming.
>
> If it was Perl, I would use if (defined($object)) which would just check
> if something is there, without even accessing its internals.
>
> How to do the same thing in Tcl? Is there any standard Tcl command,
> which allows to check whether function argument just contain something?
>
> I'm afraid that using default value other than empty string wouldn't
> help, because comparation would result in conversion of object into type
> of second operand.
>
> In this particular case using of special keyword args might help
>
> proc do_something {args} {
> if {[llength $args]} {
> #do something with [lindex $args 0]
> } else {
> # do sometihnf without object
> }
> }
>
> But more universal way is desirable.
>
>
Post Follow-up to this messageOn Fri, 20 Aug 2004 20:16:26 GMT, Robert Seeger <robert@rkseeger.net>
wrote:
>The only way I can think of off the top of my head is:
>
>proc do_something {args} {
> switch -exact [llength $args] {
> 0 {
> # it wasn't provided
> set object {}
> } 1 {
> set object [lindex $args 0]
> } default {
> error "usage: do_something ?object?"
> }
> }
> # ...
>}
Or sort of combine your present solution with 'args', like
proc do_something {param1 param2 args} {
switch -exact [llength $args] {
0 {
# it wasn't provided
set object {}
} 1 {
set object [lindex $args 0]
} default {
error "usage: do_something param1 param2 ?object?"
}
}
# ...
}
HTH
Helmut Giese
Post Follow-up to this messagevitus@45.free.net (Victor Wagner) writes:
> Problem is that [string length] does conversion of object into string
> representation. Its typePtr->name now is "string". And when I want to do
> something with it, internal representation is constructed again from
> string one, which can be quite time-consuming.
"shimmering"
> How to do the same thing in Tcl? Is there any standard Tcl command,
> which allows to check whether function argument just contain something?
No. If it was given, then it contains something -- the zero-length
string.
There are two ways to do optional function parameters: with the
args list (which probably better suits you) or pairs of {arg default}.
To test if a parameter was given in $args, use [llength $args].
To test if a parameter was omitted, and given a default, then
you have to test for a recognizable default. To avoid shimmering,
you should specify a default value with the same internal representation
as the argument it replaces, and a test that does not force a
different internal representation.
I guess there is a third way:
Instead of passing the value to the function, pass a variable name
(pass by reference). Then you can use upvar to get a local variable
reference, and then use [info exists] to see if the parameter exists
or not.
Donald Arseneau asnd@triumf.ca
Post Follow-up to this messageVictor Wagner wrote:
> I've encountered a following problem - I'm passing into procedure
> optional parameter, which can have quite complex internal Tcl_Obj
> representation (custom object type from my C extension).
>
> This object is optional. Be it some simple Tcl object such as string,
> list etc, I would use following code:
>
> proc do_something {{object {}}} {
> if {[string length $object]} {
> # do something with object
> } else {
> # do something without object
> }
> }
>
> Problem is that [string length] does conversion of object into string
> representation. Its typePtr->name now is "string". And when I want to do
> something with it, internal representation is constructed again from
> string one, which can be quite time-consuming.
>
[snip]
I don't want to derail the discussion, but I'm curious why the construction
of a string from the internal representation should invalidate the internal
representation. It is sometimes the case that string->internal conversion
will want to invalidate the string representation (i.e. if different
strings could yield the same internal representation and you want to insure
that a canonical string representation is reconstructed). Perhaps the "C"
extension could be mended to not invalidate the internal rep when the
string rep is updated.
Andrew
Post Follow-up to this messageDonald Arseneau wrote:
> There are two ways to do optional function parameters: with the
> args list (which probably better suits you) or pairs of {arg default}.
> To test if a parameter was given in $args, use [llength $args].
> To test if a parameter was omitted, and given a default, then
> you have to test for a recognizable default. To avoid shimmering,
> you should specify a default value with the same internal representation
> as the argument it replaces, and a test that does not force a
> different internal representation.
>
> I guess there is a third way:
>
> Instead of passing the value to the function, pass a variable name
> (pass by reference). Then you can use upvar to get a local variable
> reference, and then use [info exists] to see if the parameter exists
> or not.
>
> Donald Arseneau asnd@triumf.ca
There's a fourth way:
proc do_something {{object {}}} {
________if {[llength [info level 0]] > 1} {
________________# do something with object
________} else {
________________# do something without object
________}
}
This will allow you to really determine if an argument was specified, even
if it is exactly the same as the default value for the optional argument.
Schelte.
--
set Reply-To [string map {nospam schelte} $header(From)]
Post Follow-up to this messageSchelte Bron <nospam@wanadoo.nl> writes:
> ________if {[llength [info level 0]] > 1} {
Niiiice.
Donald Arseneau asnd@triumf.ca
Post Follow-up to this messageHehe, I was thinking the exact same thing. When I saw it, my first thought was "omg, thats slick, why didn't I think of that". I've always used args in situations like that and hated it because it I either have to keep a usage error notice up to date, or the user will have no clue what the args are unless they look at the source. Rob Seeger Donald Arseneau wrote: > Schelte Bron <nospam@wanadoo.nl> writes: > > > > > Niiiice. > > Donald Arseneau asnd@triumf.ca
Post Follow-up to this message
> There's a fourth way:
>
> proc do_something {{object {}}} {
> if {[llength [info level 0]] > 1} {
> # do something with object
> } else {
> # do something without object
> }
> }
>
> This will allow you to really determine if an argument was specified, even
> if it is exactly the same as the default value for the optional argument.
>
> Schelte.
My try at this:
proc defaultvalues? {} {
expr {[llength [info args [lindex [info level 1] 0]]] -
([llength [info level 1]]-1)}
}
Trying it out:
% proc test {a {b 1} {c 2}} {puts [defaultvalues?]}
% test 1
2
% test 1 2
1
% test 1 2 3
0
Michael
Post Follow-up to this messageAndrew Mangogna wrote: >Victor Wagner wrote: > >I don't want to derail the discussion, but I'm curious why the construction >of a string from the internal representation should invalidate the internal >representation. The problem is that many of the [string] subcommands don't actually operate on the string representation! Instead, they convert the UTF8-encoded string rep to a UCS-2-based internal representation. See generic/tclStringObj.c for all the details, but the basic idea is that some operations ([string length], [string range], a few others) are easier to implement and/or faster with a fixed-length encoding than they are with a variable-length one. --Joe English
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.