This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

cannot unset an element in an array under certain conditions

Help for those learning Tcl or writing their own scripts.
Post Reply
w
willyw
Revered One
Posts: 1209
Joined: Thu Jan 15, 2009 12:55 am

cannot unset an element in an array under certain conditions

Post by willyw »

Hello,

I've taken some ideas, and bits and pieces of script that I've found around, and made myself a script to hold some info, when a user parts the channel.

Like this:

Code: Select all

set array_name([string tolower $nick],$chan) "$nick $uhost $chan [unixtime]"
Seems to work fine.

When the user returns to the channel, script has bot say something like, "Welcome back nick, it has been xx minutes(seconds, whatever) since you were last here".

Code: Select all

foreach item [array names array_name] {
(here, compare hostmask stored in array, to current $host ... if it matches,  then announce, etc.)
This too, seems to work fine.

At this point, I want the script to unset the saved info. To get rid of it.

Code: Select all


array unset array_name $item

This works fine too, until somebody has a nick with square brackets in it.
Usually, $item would be something like: somenick,#chan and it works.
However, if the user had a nick with brackets in it:
[s]omenick,#chan - then it doesn't work.


I've played around with [split $item] and [join [split $item]] in the script.
No luck.

Next, I tried doing it "by hand", in partyline with .tcl array unset. I can't get it to unset with:
.tcl unset array unset [s]omenick,#chan and it errors with unknown command of course.

Next I tried, .tcl array unset {[s]omenick,#chan} and it didn't error... but it didn't unset it either.
So far, the only way I've been able to do it from the partyline command line is: .tcl array unset {\[s\]omenick,#chan}
Using the backslash to escape the brackets does work.

I thought that if I could manipulate my varname and element such that the element was enclosed in curly braces, I'd be ok.
( http://www.peterre.info/characters.html )
Apparently, I'm overlooking something.

I hope I've made no confusing typos in this post... I've looked at the script so much and tried so many things now, that it is almost all a blur.
It is really bugging me now. :)

If someone could explain to me how to do it, and what my mistake is, I would like that very much.

Thanks
User avatar
speechles
Revered One
Posts: 1398
Joined: Sat Aug 26, 2006 10:19 pm
Location: emerald triangle, california (coastal redwoods)

Post by speechles »

Code: Select all

unset array_name($item)
This will safely unset one element of your array. ;)
w
willyw
Revered One
Posts: 1209
Joined: Thu Jan 15, 2009 12:55 am

Post by willyw »

speechles wrote:

Code: Select all

unset array_name($item)
This will safely unset one element of your array. ;)
Thanks for the reply.


With a quick test from the command line in partyline - yes, it seems to work.
But... only if I use the variable.
If I use the exact same info as is contained in the variable, ... just type it in... then the command fails, as it is trying to evaluate whatever it sees inside the square brackets.

What's the difference? this is baffling. The info is exactly the same.....
doesn't $item appear to TCL as the same info as when I type it in, using no variable?


Also, was I doing something wrong, with using array unset ? It looked like it was the right way to do it, to me. I just wonder how I got so far astray.

I'm headed out to edit my script, and do some testing for real now.
I'll comment on how it worked out, later.

Many thanks.
User avatar
speechles
Revered One
Posts: 1398
Joined: Sat Aug 26, 2006 10:19 pm
Location: emerald triangle, california (coastal redwoods)

Post by speechles »

<speechles> .tcl set my_array(\x5bhello\x5d) "testing testing 1 2 3"
<bot> Tcl: testing testing 1 2 3
<speechles> .tcl set b $my_array(\x5bhello\x5d)
<bot> Tcl: testing testing 1 2 3
<speechles> .tcl set a [array names my_array]
<bot> Tcl: {[hello]}
<speechles> .tcl set my_array(\[hello\]) "\[ is the same as \x5b, but \x5b being evaluation safe ;)"
<bot> Tcl: [ is the same as [, but [ being evaluation safe ;)
<speechles> .tcl set a [array names my_array]
<bot> Tcl: {[hello]}
<speechles> .tcl set b $my_array(\x5bhello\x5d)
<bot> Tcl: [ is the same as [, but [ being evaluation safe ;)
This is proof that the parenthesis of the array element are evaluated in the presence of brackets []. The trick is shown above, use the power of evaluation to defeat it. Use the x-encoding value (hex) of the bracket you wish and it effectively becomes an escaped bracket of the exact type you've used, right or left. This same method works for all characters.
willyw wrote:doesn't $item appear to TCL as the same info as when I type it in, using no variable?
The short answer is "NO". Tcl expects a variable to be post processed (known as already evaluated). Whereas your partyline/command-line approach is expected to be pre-processed. Your expected to issue commands, whereas issuing commands from within variables is somewhat rare (..and why [subt]/[eval] with tcl-filters exist). This is why you must use escapes (\), x-encoding(hex), u-encoding(unicode), etc .. to prevent these special characters from influencing Tcl. The long answer is a quiet "...yes", but to explain why would cause a hole in the fabric of time/space and cause a giant rift which might cause the Earth to vanish as if it never existed. So is easier to just say "NO"... :D

http://www.peterre.info/characters.html
This explains how this further affects substitution and evaluation order. So reading it is advised as well. ;)
w
willyw
Revered One
Posts: 1209
Joined: Thu Jan 15, 2009 12:55 am

Post by willyw »

It appears that the solution you proposed above, works. :)
Thank you.

Wow... I didn't realize I'd touched on something so deep.

Thanks for trying to explain.... I'm not sure I got it all, but that's not your fault.
http://www.peterre.info/characters.html
This explains how this further affects substitution and evaluation order. So reading it is advised as well. ;)
That's the one I mentioned earlier. It too has some things in it, that even though I've read over it, I don't fully grasp. It is bookmarked here though. :)

What was wrong with my trying to use array unset though?
It sure looked like a workable command, when I looked it up. Is this just a quirk... that it won't work in this case?
t
thommey
Halfop
Posts: 76
Joined: Tue Apr 01, 2008 2:59 pm

Post by thommey »

array unset arrayName ?pattern?
Unsets all of the elements in the array that match pattern (using the matching rules of string match).
-- snip --
(emphasize mine). from http://www.tcl.tk/man/tcl8.5/TclCmd/array.htm#M15.
string match ?-nocase? pattern string
-- snip --
[chars] Matches any character in the set given by chars.
-- snip --
from http://www.tcl.tk/man/tcl8.5/TclCmd/string.htm#M40.

And that's why set item {[s]}; array unset myarray $item will unset $myarray(s) only, and is different from unset array($item) which unsets the array element with the literal name "[s]".
Post Reply