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.

Variable setting problems

Help for those learning Tcl or writing their own scripts.
Post Reply
C
ChooChoo
Voice
Posts: 6
Joined: Thu Oct 22, 2009 12:03 pm

Variable setting problems

Post by ChooChoo »

Hi,

Code: Select all

             for {set i 0} {$i<3} {incr i} {
               for {set j 0} {$j<$countzeilen$i} {incr j} {
                 set zeile$i$j [string trim $zeile$i$j ":"]
               }
             }
the problem is a puttogether variable "$countzeile$i" is not allowed, how can i fix it with the right syntax?

also, same problem with the puttogether [string trim...]

thanks in advance.
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

I see what you mean regarding :-

Code: Select all

for {set j 0} {$j<$countzeilen$i} {incr j} {
It yields a strange looking error in my editor while being parsed :-

parse error: missing operator at _@_ in expression "$J<$countzeilen_@_$i

You could try throwing in a command that causes the variable values to be concatenated before being used in the logical test, such as :-

Code: Select all

for {set j 0} {$j<[join $countzeilen$i]} {incr j} {
Or, create a temporary variable :-

Code: Select all

set temp $countzeilen$i
for {set j 0} {$j<$temp} {incr j} {
As for :-

Code: Select all

set zeile$i$j [string trim $zeile$i$j ":"]
I see nothing syntactically wrong with this statement, as long as the variable named zeile already exists.

This is not to say whether or not the code actually does what you expect. I can't really comment on that since i don't know what you expect.
I must have had nothing to do
C
ChooChoo
Voice
Posts: 6
Joined: Thu Oct 22, 2009 12:03 pm

Post by ChooChoo »

thx for the reply.

there are 3 vars countzeilen0 , countzeilen1, countzeilen2 each containing a number.

if i < countzeilen0
if i < countzeilen1
.....


the tempstuff is not working :

set temp $countzeilen$i
for {set j 0} {$j<$temp} {incr j} {

Tcl error [tsharing]: can't read "countzeilen": no such variable

because he ignores the $i
he does "set temp countzeilen"
and not "set temp countzeilen0"


and version #2

for {set j 0} {$j<[join $countzeilen$i]} {incr j} {

does the same
Tcl error [tsharing]: can't read "countzeilen": no such variable


edit :
about the trim

there are 3 * x vars (x = countzeilen)
zeile00 = "string with : : :"
zeile10 = "string with : : :"
zeile20 = "string with : : :"

till

zeile0x where x = countzeilen0 "containting a string with some :"
zeile1x where x = countzeilen1 "containting a string with some :"
zeile2x where x = countzeilen2 "containting a string with some :"
User avatar
speechles
Revered One
Posts: 1398
Joined: Sat Aug 26, 2006 10:19 pm
Location: emerald triangle, california (coastal redwoods)

Re: Variable setting problems

Post by speechles »

ChooChoo wrote:Hi,

Code: Select all

for {set i 0} {$i<3} {incr i} {
   for {set j 0} {$j<$countzeilen$i} {incr j} {
      set zeile$i$j [string trim $zeile$i$j ":"]
   }
}
the problem is a puttogether variable "$countzeile$i" is not allowed, how can i fix it with the right syntax?

also, same problem with the puttogether [string trim...]

thanks in advance.
Why not use an array? It's much simpler.

Code: Select all

for {set i 0} {$i<3} {incr i} {
   for {set j 0} {$j<$countzeilen($i)} {incr j} {
      set zeile($i,$j) [string trim $zeile($i,$j) ":"]
   }
}
Notice how much more readable it looks this way? ;)
As arfer said, have no idea what the intention of this is, but using arrays will make it easier on your head.
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

It does not ignore the $i. When trying to concatenate the value of the variable countzeilen with the value of the variable i, it is saying that the variable countzeilen does not exist, which is true.

Though I can now see what you are getting at. You wish to use the for loop to form the three variable names countzeilen0 countzeilen1 and countzeilen2 and then access their values.

Potentially I think that coding in this manner can get very messy, my suggestion would be to start thinking of using arrays.

If you have the array variable countzeilen with say elements countzeilen(0), countzeilen(1) and countzeilen(2) etc then their name/value pairs can be accessed using :-

Code: Select all

foreach {name value} [array get countzeilen] {
    # code here using $name and/or $value
}
Or you could set the value of an array element using another variable value as the element name :-

Code: Select all

set countzeilen($i) "whatever"
Although Tcl arrays can only be one dimentional, you can quite easily emulate multidimensional arrays using something like the following :-

Code: Select all

set countzeilen(${i},$j) "whatever"
Providing the variable i exists in the first example, or both i and j in the second then the code if fine.

I would urge you to reconsider your logic.

Otherwise, building a variable name from other strings and/or variable values, then accessing or setting the built variable value may well require the use of $$. Like I said, messy. Though sometimes possible, with care. I would not use the logic you were originally intending to use.

If you explain more completely what you are trying to do, I will try to help further.
I must have had nothing to do
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

Sorry Speechless we seem to have been posting simulaneously.

Out of interest, I don't suppose you could shed any light on this (from the original error) :-

parse error: missing operator at _@_ in expression "$J<$countzeilen_@_$i

The _@_ bit in particular. What's that all about?
I must have had nothing to do
User avatar
speechles
Revered One
Posts: 1398
Joined: Sat Aug 26, 2006 10:19 pm
Location: emerald triangle, california (coastal redwoods)

Post by speechles »

arfer wrote:Sorry Speechless we seem to have been posting simulaneously.

Out of interest, I don't suppose you could shed any light on this (from the original error) :-

parse error: missing operator at _@_ in expression "$J<$countzeilen_@_$i

The _@_ bit in particular. What's that all about?

Code: Select all

for {set j 0} {$j<$countzeilen$i} {incr j} { 
This is assumption, but probably a correct assumption. The problem is the middle part of the for loop ({$j<$countzeilen$i}) is treated as if it were an [expr] command. Same as using an if statement as it is also treated as an expr. As such, since you mash two variables together, the expr command is confused about this. It thinks there should be an operator (+ - etc) placed between the variables and uses the _@_ to signify the spot where it thinks this should be. This is why that method of scripting is difficult (and as you mentioned messy), because embedding variables of this type into an expr always results in the same error regarding missing operators (searching the forums for _@_ you will see scripts that use this method fail when commands which base their logic on expressions are used. The best way to acheive this is use the tools tcl gives you and base your expressions around arrays. ;)

Upon reading up on this, appears my thinking was indeed correct.
found on google wrote:In Tcl syntax yes, but expr has its own little language, where some
things are different:

% set a 1; set b 2
2
% expr $a$b+3
15
% expr {$a$b+3}
missing operator at _@_
in expression "$a_@_$b+3"
It appears when using these commands, they enclose the expr within braces (to prevent exploits of course) and this causes this scenario.
On the other hand, you can use "" to force string concatenation in the
middle of an expression:

% expr {"$a$b"+3}
15
But appears you can avoid this by enclosing your mashed together variables within double quotes.. ;)
C
ChooChoo
Voice
Posts: 6
Joined: Thu Oct 22, 2009 12:03 pm

Post by ChooChoo »

thanks, the array stuff worked, didnt thought about that :)

another thing, is it possible to do a endless loop till a channel trigger breaks it?

my example breakes my eggdrop (he times out)

Code: Select all

set chan "#channel"
set blub "!blub"

bind pub - $blub blub

set running 0
set break ""

proc blub {nick uhost hand chan args} {
  global running
  global break
  set parameter [lindex [split $args] 0]
  set parameter [string trimleft $parameter "\{"]
  set parameter [string trimright $parameter "\}"]

  if {$parameter ==""} {
    putserv "PRIVMSG $chan no Parameter found."
  } elseif {$parameter =="start" && running ==0} {
      set running 1  
      while {break != "stop"} {
        do something
        after 30000
      }
    } elseif {$parameter =="stop"} {
        global break
        set break "stop"
        set running 0
      } else {
          putserv "PRIVMSG $chan wrong parameter"
        }
}
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

proc blub {nick uhost hand chan args} {
  global running
  global break
  set parameter [lindex [split $args] 0]
  set parameter [string trimleft $parameter "\{"]
  set parameter [string trimright $parameter "\}"] 
The above is done incorrectly. In fact every single piece of code above is wrong with the exception of the two global statements.

The problem is your using the 'special' argument (args) in your procedure header. This is special because it allows that argument to swallow any which may follow it as well as the one in it's place. The result in this case is a list, not a string. If you don't need or understand the function of args, use anything else, arg, text, etc.

Code: Select all

set parameter [lindex [split $args] 0]
Here you split args, but in this case args is already a list. This will of course cause visible bracings to appear in your output as evidenced by the following two lines:

Code: Select all

set parameter [string trimleft $parameter "\{"]
set parameter [string trimright $parameter "\}"] 
Here you make the mistake of using left and right, when [string trim] would've done both at the same time. But the larger mistake is using this at all, as it's a messy hack. If you had chosen something other than 'args' for your procedure header these two lines are not needed and the line above these two would work as intended without them.

Now on to your question itself. What your asking is can eggdrop do two things at once? The short answer is no. The longer answer is yes, but unfortunately this requires background processes run outside the tcl event engine, and we know these as modules. These run independently of the eggdrop and can interact with it. The module can run and return events to the eggdrop until the eggdrop tells it to stop. So in short, to do what you want, you would need to learn c/c++ and compile your code as a module.

Note: You can give a pseudo loop like behavior with the use of [timer] or [utimer] and re-invoking them before the procedure they invoke ends. But this requires care and diligence at making sure before you re-invoke them they aren't already running. A rehash/restart can cause several instances to occur, each invoking the procedure to re-invoke themselves. Over time and several rehash/restarts these will cause serious drain on the cpu running your bot. But with careful strategy this could be how you can solve the problem. The second golden rule of tcl can help you regarding timer and utimer. Read about it here.
C
ChooChoo
Voice
Posts: 6
Joined: Thu Oct 22, 2009 12:03 pm

Post by ChooChoo »

thanks for the headsup.

ill just use another messy hack and use another bot to trigger the function ever 30 seconds ;)

thread can be closed.
Post Reply