|
From: EricT <tw...@gm...> - 2025-10-21 01:26:07
|
When you created your array, the index was (2+2) which is 5 chars in
length, and you set the value to 5. When you wanted to retrieve it as an
array(index) and array was actually the null variable, you needed to do
((2+2)) in order to enclose your index in parentheses. You could probably
see it more clearly as,
% set foo((2+2)) 5
5
% array name foo
(2+2)
% puts $foo((2+2))
can't read "foo((2+2)": no such element in array
% set foo((2+2))
5
However, that is 8.6, and the problem appears to be that they stopped at
the first close paren, without doing any balancing. With 9.1 I see the new
error, same as you are getting, although to try it out I had to use a real
array name. Looking at the code, there's a change in 9.x which includes
this and explains the different error messages:
} else if ((*parsePtr->term != ')')){
if (parsePtr->interp != NULL) {
Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj(
"invalid character in array index", -1));
}
The else if is checking the terminating character for the parse. Stepping
it through however, I see that it actually is pointing to the 2nd open
paren following the array name. So, it has scanned the name, saw the first
(, changed to the array logic, but seems to not be pointing at the final
close ) as I would have expected it to and what this code seems to think it
should be as well. This may be a bug. It could explain why they added this
change, but it fails when the first character in the index is an open
paren. You might want to file a ticket on this.
Eric
On Mon, Oct 20, 2025 at 5:34 PM Phillip Brooks <phi...@um...> wrote:
> Thanks for the explanation. Yes, I did try to run both commands
> together. I see what is going on with that statement now. I was unaware
> of the possibility of having an unnamed array previously.
>
> Regarding my Tcl version, I am running vanilla 9.1 of a fairly recent
> vintage, but also tried using 8.5.
>
> Regarding the double parenthesis expression proposal, I'm not sure that I
> follow you. Is there a way to use the single argument set command to
> create an ambiguity between $(( expression )) as an arithmetic expression
> evaluator and some existing code using an unnamed array, or set (or any
> other currently legal syntax)? Since that command doesn't involve the $
> character, I don't see how it gets in the way. If you can think of one,
> can you write a couple of lines of code that illustrate it?
>
> Phil
>
>
>
> On Mon, Oct 20, 2025 at 5:07 PM EricT <tw...@gm...> wrote:
>
>> I believe the reason you got the error was that you actually typed both
>> statements, setting the scalar null variable and then tried the array null
>> variable.
>>
>> However, I believe the problem is that you are running into some parser
>> issues here that the manual doesn't mention. It does, however, say
>>
>> Note that variables may contain character sequences other than those
>> listed above, but in that case other mechanisms must be used to access them
>> (e.g., via the *set *command's single-argument form).
>>
>> And so that is why the above using set does return the value 5. But when
>> trying $ substitution, the rules are more restrictive, and you likely hit
>> one of the edge cases here.
>>
>> Eric
>>
>>
>> On Mon, Oct 20, 2025 at 4:30 PM Phillip Brooks <phi...@um...>
>> wrote:
>>
>>> Let me try making my previous email a little more concise since it
>>> hasn't generated any follow-ups.
>>>
>>> 1) Is there a bust in the TIP 672 example code. I can't run this code
>>> from the TIP:
>>>
>>> set {} foobar ;# scalar variable
>>>
>>> set (index) "array value" ;# array variable
>>>
>>> When I run that, I get:
>>>
>>> can't set "(index)": variable isn't array
>>>
>>>
>>> Please explain.
>>>
>>> 2) The bash shell uses the syntax $(( expression )) for arithmetic.
>>> Does that syntax solve the problem of the unnamed array ambiguity that $(
>>> expression ) introduces? The $(( expression )) syntax, at least in my
>>> small example, seems illegal. I am only testing this out on a simple case
>>> I tried after the above code didn't work:
>>>
>>> % array set {} { 2+2 5 }
>>>
>>> % puts $(2+2)
>>>
>>> 5
>>>
>>>
>>> The above code illustrates the problem with $(2+2) being interpreted as
>>> an index into the unnamed array. If I try doing that with an extra ( in
>>> the expression, it is invalid syntax:
>>>
>>> % array set {} { (2+2) 5 }
>>>
>>> % puts $((2+2))
>>>
>>> invalid character in array index
>>>
>>>
>>> To get at the array element named (2+2), you have to add escape
>>> characters:
>>>
>>>
>>> % puts $(\(2+2\))
>>>
>>> 5
>>>
>>>
>>> It seems to me that if $(( expression )) works generally, it has several
>>> advantages:
>>>
>>> - it is easier to read and type than {=}{ expression }. (While {=}
>>> adds only two characters, { and } are shifted, = is unshifted which makes
>>> for much slower typing.)
>>> - it has precedent in bash
>>> - it doesn't overload the meaning of preexisting valid syntax.
>>>
>>> Are there other issues with $(( expression )) that I don't know of?
>>> Please explain?
>>>
>>> Phil
>>> _______________________________________________
>>> Tcl-Core mailing list
>>> Tcl...@li...
>>> https://lists.sourceforge.net/lists/listinfo/tcl-core
>>>
>> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
>
|