setting an array, just use set arrayname($nick) "something"*** n is set to "jim"
<speechles> .set n "jim"
<sp33chy> Ok, set.
*** nick_jim is set to "beam"
<speechles> .set nick_$n "beam"
<sp33chy> Ok, set.
*** show the contents of new variable nick_jim
<speechles> .tcl set nick_jim
<sp33chy> Tcl: beam
Thanks for replying.speechles wrote:*** n is set to "jim"
<speechles> .set n "jim"
<sp33chy> Ok, set.
*** nick_jim is set to "beam"
<speechles> .set nick_$n "beam"
<sp33chy> Ok, set.
*** show the contents of new variable nick_jim
<speechles> .tcl set nick_jim
<sp33chy> Tcl: beam
Code: Select all
bind pub - !test atest_proc
proc atest_proc {nick uhost handle chan text} {
set nick_$nick "beam"
putserv "privmsg $chan : nick_$nick is set to $nick_$nick "
}
Next, just to be sure of typos, etc. , I tried this:Tcl error [atest_proc]: can't read "nick_": no such variable
Code: Select all
proc atest_proc {nick uhost handle chan text} {
set n "jim"
set nick_$n "beam"
putserv "privmsg $chan : var named nick_$n is set to $nick_$n "
}
Isn't that strange?... that it works from the command line, but not in a procedure?Tcl error [atest_proc]: can't read "nick_": no such variable
Wouldn't that just set an element within the array though?setting an array, just use set arrayname($nick) "something"
arfer wrote:You can create a variable with name equal to the value of another variable.
Say for example I set the value of the variable named testnick ($testnick) to arfer, then use it to create a variable named arfer (with value "my nick").
[23:23] <arfer> .tcl set testnick arfer
[23:23] <osmosis> Tcl: arfer
[23:24] <arfer> .tcl set $testnick "my nick"
[23:24] <osmosis> Tcl: my nick
[23:24] <arfer> .tcl set arfer
[23:24] <osmosis> Tcl: my nick
A new variable was created called arfer, with a value "my nick" as evidenced by the final set command above.
Code: Select all
proc atest_proc {nick uhost handle chan text} {
set $nick "beam"
putserv "privmsg $chan :a variable named $nick has been created with value [subst $$nick]"
}
Code: Select all
set ar($nick) "beam"
Code: Select all
set name [array names ar -regexp (?i)ARF]
Code: Select all
bind pub - !test atest_proc
####### Use global command to link the localspace variable to the globalspace one...
proc atest_proc {nick uhost handle chan text} {
global "nick_$nick"
set nick_$nick "beam"
putserv "privmsg $chan :nick_$nick is set to [set nick_$nick]"
}
####### Use full namespace path
proc atest_proc {nick uhost handle chan text} {
set ::nick_$nick "beam"
putserv "privmsg $chan :nick_$nick is set to [set ::nick_$nick]"
}
####### Use the upvar command to link the globalspace variable to "thenick"
proc atest_proc {nick uhost handle chan text} {
upvar #0 nick_$nick thenick
set thenick "beam"
putserv "privmsg $chan :nick_$nick is set to $thenick"
}
####### Use full namespace path along with arrays
proc atest_proc {nick uhost handle chan text} {
set ::nick_($nick) "beam"
puserv "privmsg $chan :nick_($nick) is set to $nick_($nick)"
}
Ah! so it WAS the last line that I suspected. Didn't realize the proc was running that far.arfer wrote:It is the putserv statement that is causing the error, there is nothing wrong with the statement
set nick_$nick "beam"
It even looked odd to me. But I was just trying to make minimal changes and trying to watch results, at this point.Apart from it being rather horrendous code
I'm getting the feeling that I might be going about trying to accomplish the chore with the wrong ideas right from the start.Specifically, it is $nick_$nick that cannot be read. It is not even possible to enclose the name in braces ${nick_$nick} since this prevents the second $ from causing variable substitution.
I'm not sure if there is a solution to your specific method. I would urge you to reconsider what you are doing and why you are doing it. It is rather like having a variable name containing spaces, in that it generally leads to unnecessary difficulties somewhere down the line.
This is new to me - the subst command. I've just been to the TCL online manual and looked it up, and I really don't 'get it' yet.That code above ought to work but it's very messy. I am beginning to regret answering the original question because this is not something I would do.Code: Select all
proc atest_proc {nick uhost handle chan text} { set $nick "beam" putserv "privmsg $chan :a variable named $nick has been created with value [subst $$nick]" }
arfer wrote:Just to continue with the thread, the 'normal' way of creating a variable dynamically that is dependent on the value of another variable is to use arrays
So within the proc above
Much safer. The array named 'ar' now contains an element who's name is equal to the value of the variable named nick (ie. $nick), and this array element has a value "beam". It can be referrenced within the proc using $ar($nick).Code: Select all
set ar($nick) "beam"
Arrays also lend themselves to some very useful additional Tcl functions.
For example, if I knew an array element name contained the sequence of characters ARF but didn't know the exact nick it represented (element name) was arfer or the case was lower, I could find it using something like
Declare the array as global within the proc if you wish to use it elsewhere.Code: Select all
set name [array names ar -regexp (?i)ARF]
Why?nml375 wrote:Just to clarify one thing, that has not been covered in the previous posts...
You are currently dealing with variables in local namespaces (within the procs). These do not persist inbetween invocations of the proc. What you need to do, ....
Thanks for the explanation. It still makes me do a double take though.arfer wrote:Subst is a command that is used to force variable, command or backslash substitution where it might otherwise fail to occur.
Take the following example :-
[00:15] <arfer> .tcl set a one
[00:15] <Baal> Tcl: one
[00:16] <arfer> .tcl set $a two
[00:16] <Baal> Tcl: two
[00:17] <arfer> .tcl set c $$a
[00:17] <Baal> Tcl: $one
[00:17] <arfer> .tcl set c [subst $$a]
[00:17] <Baal> Tcl: two
$$a resulted in an unexpected return value. Seemingly the innermost $ did not invoke substitution. This was forced by using subst command, yielding the expected result.
Code: Select all
# *** configuration *** #
set vPlaybackMemory 5
set vPlaybackChannel #eggTCL
# *** code *** #
bind PUB o !playback pPlaybackOutput
bind PUBM - * pPlaybackStore
if {[info exists vPlaybackData]} {unset vPlaybackData}
proc pPlaybackOutput {nick uhost hand channel txt} {
global vPlaybackData vPlaybackMemory
for {set x 1} {$x <= $vPlaybackMemory} {incr x} {
if {[info exists vPlaybackData($x)]} {puthelp "NOTICE $nick :$vPlaybackData($x)"}
}
return 0
}
proc pPlaybackPromote {nick channel} {
if {[isop $nick $channel]} {
return "<@$nick\>"
} elseif {[isvoice $nick $channel]} {
return "<+$nick\>"
} else {return "<$nick\>"}
}
proc pPlaybackStore {nick uhost handle channel txt} {
global vPlaybackChannel vPlaybackData vPlaybackMemory
if {[string equal -nocase $channel $vPlaybackChannel]} {
if {![string match "!playback*" $txt]} {
if {![isbotnick $nick]} {
for {set x 1} {$x < $vPlaybackMemory} {incr x} {
if {[info exists vPlaybackData([expr {$x + 1}])]} {set vPlaybackData($x) $vPlaybackData([expr {$x + 1}])}
}
set vPlaybackData($vPlaybackMemory) "[pPlaybackPromote $nick $channel] $txt"
}
}
}
return 0
}