*) separation of -upvar <varname> into -upvar <bool> and -varname <varname>
This one was suggested by kbk. A few days later I asked him on tkchat about
his motivation. In a nutshell, it was that Kevin didn't like the idea
of the empty string meaning "I don't care for outer name" and that the
empty string would not have been a usable <varname> to hold the outer
variable's name, then. Given that :: and () are already "characters non
grata" for formal argument names and that therefore argument names are
already not "any string"s, then the idea of using the empty string for
the outer name doesn't seem all that precious to me to make upvar use
so much more verbose.
It may be inopportune to criticize kbk's ideas (with all his other contri-
butions being as awesome as they are), but here that's exactly what I
feel like doing.
*) -required <bool> (with this option's default depending on namedness of
options).
Apart from that I principally dislike having formal arguments being
initially unset, I even more dislike, that for named arguments this
would even be the default behaviour unless "-required 1" is explicitly
spelled out.
I do understand the usecase of some "out-of-band" state for unspecified
optional arguments (e.g. lsort -command) and suggested an approach with
"-list" to address this not-quite-that-common usecase.
But even if unsetting optional arguments (that aren't passed a value) is so
much preferred, the requiredness behaviour should at least be same for all
types of parameters, and it should be named for what it means: something
along -defaultunset <bool>. It's about what happens to unspecified params,
not about actual requiredness, because for the latter the -default option
also plays a role.
On Mon, Apr 24, 2017 at 12:58 AM, Mathieu Lafon <mla...@gmail.com> wrote:
>
> TIP #457 and its implementation have just been updated.
> [...]
> As usual, feedback and comments are welcomed.
Thanks for committing all the doc changes.
With this, the nifty fossil-diff to trunk at
http://core.tcl.tk/tcl/vdiff?from=0ca94b41a13ea375&to=e722c70aad11a12a&sbs=1
gives a very good view of the volume of additions to code, tests, and docs.
Which leads me to the following observation: this is a big piece
(meaning some code maintenance work) with rich semantics and syntax
(meaning a large extra doc section).
In other words, this departs from the usual "Tcl is a simple language"
rather drastically, by increasing the cognitive entry cost to proc.n.
In addition, this move is done in support of a specific style that's
fashionable in other languages but not really a game-changer in Tcl.
Also, unless I've missed part of the discussion, it is not completely
neutral in terms of perf, as much work on the BC optimizer is still
due before named args can be morphed into positional at compile time.
For this reason, my current position is to vote NO regarding the TIP
itself (meaning core inclusion); but all this work should not be lost
and could very well live in an extension (with the only difference
that input arglist parsing should be explicitly requested by calling a
helper function).
I said: "not all that common", not: "doesn't exist".
The examples you gave (-dir, -mode) both look pretty much like as if the
empty string would be a fine default not getting in the way of useful values.
Even for lsort, an empty -command could have been singled out as a default
that would be equivalent to not specifying a -command option. I wouldn't call
foreach i {a b c d e f g} {
proc $i x {puts [info level 0]; string compare {*}[info level 0] }
}; lsort -command {} {g f e d c b a}
a worthy usecase for an empty command.
The only real undefaultable case presented so far in the whole discussion
is [set]'s second argument.
PS: if you shared two or three of your *really undefaultable* optional
params, that you come across occasionally, it might even make me shut up
about their marginality.
The hazards of sleeping ;)
> Will someone reading “{foo -upvar bar}” automatically assume that
> means “the upper variable name is in bar and the value is in foo”
> or “the upper variable name is in foo...” (since every other
> variable the named variable contains exactly what was on the
> command line) “... and the value is in bar” (since that’s after
> the upvar).
I agree, that the option name "-upvar" doesn't really make this clear,...
> {foo -upvar 1 -varname bar} is unambiguous.
... but I think that the extra option fails to make it any clearer.
Maybe, the even more natural thing would be: {varname -upvarto var} afterall.
And yes, it would indeed force the user to define two varnames (or just add
a & or * to the formal arg name). That would also avoid the {} special case ;)
A separate -varname option only makes sense if it would capture the exact
part of the call-time arguments that affected this argument. But then its
assigned value would need to be always a list, to allow for option and value
or flag or empty(if defaulted). Iirc, that was one issue raised a while ago:
passing on all the options from a wrapper to the original command.
Brian's approach (allowing to query the link target lateron without extra
verbosity in the argspec -- not the ${&/-\$} incompatible line noise) also
looks fine to me.
> I’m not sure I understand that. The varname contains the outer variable
> name for error reporting and similar stuff.
Slightly different thing. In that suggestion, the variable named to "-varname"
would not be specific to those argspecs with -upvar.
e.g.:
proc foo {
{arg1 -upvar 1 -varname arg1v}
{arg2 -name x -switch y -varname arg2v}
{arg3 -default "def" -varname arg3v}
} { list $arg1 $arg1v -- $arg2 $arg2v -- $arg3 $arg3v }
arg1 requires an argument, so $argv1 will always be [list <outername>]
$arg2v might be equal to {} or "-y" or [list -x $arg2], depending on
how it was called.
$arg3v is either empty (if defaulted) or a singleton list of $arg3
[concat $arg1v $arg2v $arg3v] would be pretty close to
[lrange [info level 0] 1 end] except that duplicate call options
and "--" would be weeded out. foo -x v1 -y -x bar ---> $arg3v eq "-x bar"
If this proc foo was to be wrapped by a proc bar with same arg-spec,
then proc bar could safely tailcall foo {*}$arg1v {*}$arg2v -- {*}$arg3v
from its body. Not saying this is comfortable. But the ability to do it
was once asked for, quite a while ago.
> proc fiddle {{foo -upvar 1 -varname -foo}} {
> if {![string length $foo]} {
> error “Expected non-empty foo in ${-foo}”
> }
> }
The extra list level might even be beneficial here, for vars where
it is even visible.
> > Brian's approach (allowing to query the link target lateron without extra verbosity in the argspec -- not the ${&/-\$} incompatible line noise) also looks fine to me.
> What incompatible line noise? Variable names can contain arbitrary metacharacters already.
That's exactly why it's incompatible.
How I understood the ${&foo} thing, it was suggested such, that in your
proc fiddle you'd omit the -varname -foo from the argspec, but still
have ${&foo} contain (magically) the outer name for foo. This I don't
like. Instead something like [info linktarget foo] would be fine, but
that needs a way to also deal with other linked vars - probably out of
scope for this TIP.
On 4/26/17, 9:00 AM, "Andreas Leitgeb" <a...@logic.at> wrote:
Nutshell: case -upvar still pending, case -required dropped. :-}
Originally I was inclined to support the simpler upvar syntax, but after sleeping on it... it does seem a bit potentially confusing. Will someone reading “{foo -upvar bar}” automatically assume that means “the upper variable name is in bar and the value is in foo” or “the upper variable name is in foo...” (since every other variable the named variable contains exactly what was on the command line) “... and the value is in bar” (since that’s after the upvar). {foo -upvar 1 -varname bar} is unambiguous.
> The variable name is not directly accessible but should be easy to get by searching in upper call frames.
I miss some point here?
The variable name is suplied to the proc directly as argument, so here it an example on instruction level:
```
(0) push1 0 # "upvar"
(2) push1 1 # "lev"
(4) loadStk
(5) push1 2 # "x"
(7) loadStk
(8) push1 2 # "x"
(10) invokeStk1 4
```
That would be equivalent to {upvar $lev $x x} in first compiled body of `proc some { {x -upvar 1} ...}`.
Actually I guess, that implementing of the new INST for upvar would be more favored.
Something like:
```
push1 0 # "lev"
push1 1 # "x"
upvarStk 2
```
Or if var and value should be differently (e. g. via option `-variable`):
```
push1 0 # "lev"
push1 1 # "x"
push1 2 # "y"
upvarStk 3
```
But I don't see it as beneficial, because if someone need it, then he can just use `upvar $x y` instead.
Regards,
sebres