mIRC Home    About    Download    Register    News    Help

Print Thread
Page 1 of 2 1 2
#167056 19/12/06 07:18 AM
Joined: Jul 2006
Posts: 12
S
SartenX Offline OP
Pikka bird
OP Offline
Pikka bird
S
Joined: Jul 2006
Posts: 12
Often when I'm writing a small script to do a specific thing, I need a simple counter to perform an action a given number of times. For example, if I want to echo the sum of all numbers from 1 to 10, I have to do:

Code:
/alias sum { var %sum,%n = $2 | while (%n) { inc %sum %n | dec %n } | return %sum }
//echo -a $sum(1,10)


It would be much nicer and easier to have an identifier, such as $for, that would let me just do:

Code:
//echo -a $for(%x,1,10,1,inc %sum %x) %sum


The reason for having this as an identifier is so that iterative tests can be done in a single command, such as:

Code:
$for(%x,1,$nick($active,0),2,if ($nick($active,%x) == Danny) return Danny is odd!)


would return "Danny is odd!" if Danny were in an odd-numbered position in the active window's nicklist.

The basic form I envision for such an identifier is similar to how for loops in C are often used.

Code:
$for(<variable>,<start>,<end>,<step>,<code>)


I managed to write an alias to provide this functionality, but it suffers from the fact that raw code cannot be passed in without formatting it correctly (either using $+ or $eval(<code>,0)). It also is worthless when trying to write small scripts for others, as in done in many help channels throughout the IRC community. Instead of using a clean for loop, we are stuck using external aliases, resorting to more complex while loops, abusing $regsubex, and running $findfile on large directories. My alias is as follows, and I hope it can be converted to a real built-in identifier.

Code:
alias for {
  set -l [ $1 ] [ $2 ]
  while ($eval($1,2) <= $3) {
    $eval($5,2)
    inc $eval($1,1) $4
  } 
}

This alias must be called by wrapping the parameters:
Code:
//echo -a $for($eval(%x,0),1,10,1,$eval(inc %sum %x ,0)) %sum

Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
Keep in mind that there is a mathematical way to do this.

Adding all digits 1-100:
Code:
//echo -a $calc((100 + 1) * (100 - 1 + 1) / 2)


(ending digit + beginning digit) * (ending digit - beginning digit + 1) / 2 = sum

You use a similar thing for using a step other than 1 (0-100 by 10):
Code:
//echo -a $calc((100 / 10) * (10 * (100 / 10) + 10) / 2)


This is Gauss's formula.

(ending digit / step) * (step * (ending digit / step) + step) / 2 = sum

(ending digit / step) = number of steps

Here's another example (0-20 by 2):
Code:
//echo -a $calc((20 / 2) * (2 * (20 / 2) + 2) / 2)



Note that this works from 0-N. It won't work from 10-N or something else unless you do more work. If you want to do a different starting number than 0, then you'll do the equation twice...

For 10-20 by 2:
Code:
//echo -a $calc(((20 / 2) * (2 * (20 / 2) + 2) / 2) - ((8 / 2) * (2 * (8 / 2) + 2) / 2))



(ending digit / step) * (step * (ending digit / step) + step) / 2 - ((beginning digit - step) / step) * (step * ((beginning digit - step) / step) + step) / 2 = sum

What you're doing is subtracting the sum of all the numbers prior to your starting number from the sum of the total.

You can make a $gauss identifier for this:
Code:
alias gauss {
  return $calc((($2 / $3) * ($3 * ($2 / $3) + $3) / 2) - ((($1 - $3) / $3) * ($3 * (($1 - $3) / $3) + $3) / 2))
}

USE: $gauss(beginning number,ending number,step)
EXAMPLE: $gauss(10,100,10)
NOTE: You should make sure that there is an even number of steps (1-4 step 2 wouldn't work well, but 0-4 step 2 would)

Last edited by Riamus2; 19/12/06 04:23 PM.

Invision Support
#Invision on irc.irchighway.net
Joined: Oct 2004
Posts: 73
M
Babel fish
Offline
Babel fish
M
Joined: Oct 2004
Posts: 73
There are a good many threads covering the issue of implementing for loops if you search for them.
Obligatory workaround for specified example:
Code:
//echo -a $iif($fline($active,Danny,1,1) & 1,Danny is odd!)

Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
For odd/even, it's as simple as:

$iif($calc(number % 2) == 1,EVEN,ODD)


Invision Support
#Invision on irc.irchighway.net
Joined: Jan 2003
Posts: 2,523
Q
Hoopy frood
Offline
Hoopy frood
Q
Joined: Jan 2003
Posts: 2,523
It's simpler than that:
$iif(2 // number,EVEN,ODD)
or
$iif(number & 1,ODD,EVEN)

edit: typo

Last edited by qwerty; 19/12/06 04:40 PM.

/.timerQ 1 0 echo /.timerQ 1 0 $timer(Q).com
Joined: Feb 2006
Posts: 546
J
Fjord artisan
Offline
Fjord artisan
J
Joined: Feb 2006
Posts: 546
can be even simpler :P

Code:
$iif(2 // number,EVEN,ODD)
$iif(number & 1,ODD,EVEN)


edit: lol qwerty, great minds... ;O

anyway, if this for loop functionality was added it definitely shouldn't be in the form of an identifier. think of trying to use $findfile() to perform a series of commands, it's a pain, you'd have to use workarounds like another alias.. or /scon or /scid and then youd have to worry about escaping everything.. it all becomes messy

if it's ever added, the way that would be most suitable, imo, would be:

Code:
for (%i = 1, %i < 10, inc %i) {
  commands
}


as an example. inc %i could become %i ++ depending on how it would be implemented. of course this resembles a while loop, but can be used in cases where the condition need not be re-evaluated each iteration

but as an identifier? no thanks ;S

Last edited by jaytea; 19/12/06 04:40 PM.
Joined: Dec 2002
Posts: 2,962
S
Hoopy frood
Offline
Hoopy frood
S
Joined: Dec 2002
Posts: 2,962
The identifier method has a good deal of possibility also, basically it (potentially) becomes an efficient iterating method like $*. As long as it was able to be nested within other identifiers it could be very useful. Note that there's nothing preventing for from being both a statement and an identifier.

I wouldn't want to see the %var++/-- operators added though. While they serve a useful purpose in some languages where pre/post-increment/decrement are meaningful because variables may be set in-line, it doesn't make any sense in mIRC scripting where they'd have to be a separate command anyway. That is unless things like %++blah would start being valid expressions in commands, which I'd hate to see.


Spelling mistakes, grammatical errors, and stupid comments are intentional.
Joined: Feb 2006
Posts: 546
J
Fjord artisan
Offline
Fjord artisan
J
Joined: Feb 2006
Posts: 546
Originally Posted By: starbucks_mafia
The identifier method has a good deal of possibility also, basically it (potentially) becomes an efficient iterating method like $*. As long as it was able to be nested within other identifiers it could be very useful. Note that there's nothing preventing for from being both a statement and an identifier.


oh yes, if it can be used inline to overcome the problems $* currently has, that would be really nice to see laugh i was thinking of it as related to $findfile() with its command parameter, but functionality like $* would make much more sense

Joined: Oct 2003
Posts: 313
S
Fjord artisan
Offline
Fjord artisan
S
Joined: Oct 2003
Posts: 313
I think I'd rather see a 'foreach' style construct for iterating over elements of a list.

e.g.
Code:
foreach(%i,$chan(N)) { echo -a %i }


not sure how you'd format that nicely for parsing that, though.

You could also add something like Perl has - the '..' "operator" - so you can construct normal for loops like:

Code:
foreach $i (1..10) { print $i }






Sais
Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
Originally Posted By: qwerty
It's simpler than that:
$iif(2 // number,EVEN,ODD)
or
$iif(number & 1,ODD,EVEN)


Hm. I think I've seen someone mention // here before. I know what % is doing, but what is // as a mathematical term/operation? And what's &?


Invision Support
#Invision on irc.irchighway.net
Joined: Feb 2006
Posts: 546
J
Fjord artisan
Offline
Fjord artisan
J
Joined: Feb 2006
Posts: 546
// isn't a mathematical operator, it's just a conditional operator on mirc meaning "is a factor of", so if (2 // N) checks if N is a multiple of 2

& represents a bitwise comparison, if (N & M), where M is some power of 2, is true if the bit with value M is turned on in N. so if (N & 1) is true if bit with value 1 (the first bit) of N is on, i.e. if its odd



"The only excuse for making a useless script is that one admires it intensely" - Oscar Wilde
Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
Heh, well factors are mathematical even if you don't use // in a mathematical formula. I was really just looking for the mathematical wording used for the character, which you provided. Thanks.


Invision Support
#Invision on irc.irchighway.net
Joined: Jul 2006
Posts: 12
S
SartenX Offline OP
Pikka bird
OP Offline
Pikka bird
S
Joined: Jul 2006
Posts: 12
I don't remember which language it is, but there is one where // is the modulus operator...

I realize that all my examples could be worked around (especially the Gauss solution), but that's not the point. If you want to do a loop with a simple command, especially when done from the command line, you currently have to use a lot of worthless garbage.

I don't think including for loops makes ++ and -- necessary (I agree they'd suck)... I prefer to have the incrementing built into the loop, like in BASIC.

My biggest reason for having it as an identifier is so it could be used to make simple iterative tests easier. Like finding the first time another identifier matches a given criteria. Unlike $*, it should not execute the statement that contains it multiple times. It should only execute the command that's passed to it multiple times.

I like foreach structures... but how would mIRC determine what's an element in a list?

Joined: Jul 2003
Posts: 655
Fjord artisan
Offline
Fjord artisan
Joined: Jul 2003
Posts: 655
Originally Posted By: SartenX
I like foreach structures... but how would mIRC determine what's an element in a list?

Im guessing this would involve tokens, or lines in a buffer/file/socket/etc.


"Allen is having a small problem and needs help adjusting his attitude" - Flutterby
Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
I did see a good $for identifier a long time ago (years) in this forum. You might search for $for and set it to 5 years and see what you find. As for having one included, it wouldn't be a bad thing, but I wonder if it would be considering it's been requested off and on for years without being added. That doesn't mean it won't be someday, of course.


Invision Support
#Invision on irc.irchighway.net
Joined: Jul 2006
Posts: 12
S
SartenX Offline OP
Pikka bird
OP Offline
Pikka bird
S
Joined: Jul 2006
Posts: 12
tokens would work... though it'd have to be something like $fortok(<variable>,<start>,<end>,<C>,<command>)

I searched... I didn't find anything...

EDIT: I searched again, and found old posts dealing with it. Mostly, there were objections relating to being able to do it with a while loop. One objection mentioned that a "$loop(<number>,<command>)" identifier wouldn't be useful because they almost always want to use multiple commands in the loop.

I wrote the scripts at http://paste.sarten-x.com/pastebin.pl?number=85 for fun, and all the ones that use $regsubex($str... could all be simplified greatly using a $for.

OTHER EDIT: It should be said that those scripts were written with the intent of using a single command to do the task. They also were written mostly after 3:00 AM.

Last edited by SartenX; 20/12/06 06:20 AM.
Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
Hm... I could have sworn there was an actual FOR script written somewhere... but it's been at least a couple of years, so I don't remember anything else about it.

Anyhow, I agree with what people said regarding the use of WHILE. The only real difference between FOR and WHILE is that the increment is included in the FOR line, but not in the WHILE line. Sure, you could make an identifier for FOR rather than an actual looping command like FOR is usually seen (C++ for example) or like WHILE is here... but that just is more trouble, imo, than using it the way WHILE is used. And in that way, it isn't really helping anything.

But that's just me... I have never had an issue with using WHILE instead of FOR.


Invision Support
#Invision on irc.irchighway.net
Joined: Jul 2003
Posts: 655
Fjord artisan
Offline
Fjord artisan
Joined: Jul 2003
Posts: 655
Dont worry, your not loosing your mind! There was a for script written at one point, iirc it was incomplete though (problems looping through lines in files i think? cant remember exactly), but i couldn't find it with search either. I know i replied to it so i even search through my own posts.


"Allen is having a small problem and needs help adjusting his attitude" - Flutterby
Joined: Apr 2004
Posts: 759
M
Hoopy frood
Offline
Hoopy frood
M
Joined: Apr 2004
Posts: 759
Theres a dozen FOR scripts but they all lack multi line support. Its been argued by Khaled in the past that a while pretty much covers all your looping needs which is true in a way but a while can be quite annoying.
Code:
var %x = 0 , %y = 10
while (%x <= %y) { 
  ..
  inc %x
}

is a lot more annoying to type out then
Code:
for (%x=0,%y=10;%x <= %y;inc %x) { 
   ..
}


It just looks ALOT better the pure aesthetic reasons are enough for me to want it BAD.

I guess a foreach could work in mIRC. %0 specifies the N parameter
Code:
foreach($nick(#,%0)) { 
  ..
}


Where mIRC loops from 1 till $nick(#,0) rather then as long as it doesn't return NULL keeping hash tables in mind. The requirements for a foreachable identifier are simple there's an N parameter if N = 0 return the total amount of items. Which is basically how all mirc identifiers work.

Yes a while can do it all but other loop methods can cater to our scripting needs much more efficiently.


$maybe
Joined: Apr 2004
Posts: 759
M
Hoopy frood
Offline
Hoopy frood
M
Joined: Apr 2004
Posts: 759
Originally Posted By: SartenX
tokens would work... though it'd have to be something like $fortok(<variable>,<start>,<end>,<C>,<command>)

To include an end like that could be done with the foreach mentioned in my post above:
Code:
foreach($gettok(%var,%0,32),%i) { 
  if (%i == 5) break;
  ..
}


$maybe
Page 1 of 2 1 2

Link Copied to Clipboard