mIRC Home    About    Download    Register    News    Help

Page 1 of 2 1 2 >
Topic Options
#167056 - 19/12/06 07:18 AM Looping as an identifier
SartenX Offline
Pikka bird

Registered: 09/07/06
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

Top
#167069 - 19/12/06 02:35 PM Re: Looping as an identifier [Re: SartenX]
Riamus2 Offline
Planetary brain

Registered: 13/10/04
Posts: 8327
Loc: MA, USA
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)


Edited by Riamus2 (19/12/06 04:23 PM)
_________________________
Invision Support
#Invision on irc.irchighway.net

Top
#167075 - 19/12/06 04:17 PM Re: Looping as an identifier [Re: SartenX]
Mardeg Offline
Babel fish

Registered: 30/10/04
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!)
_________________________
CSS email obfuscator

Top
#167076 - 19/12/06 04:26 PM Re: Looping as an identifier [Re: Mardeg]
Riamus2 Offline
Planetary brain

Registered: 13/10/04
Posts: 8327
Loc: MA, USA
For odd/even, it's as simple as:

$iif($calc(number % 2) == 1,EVEN,ODD)
_________________________
Invision Support
#Invision on irc.irchighway.net

Top
#167079 - 19/12/06 04:34 PM Re: Looping as an identifier [Re: Riamus2]
qwerty Offline
Hoopy frood

Registered: 07/01/03
Posts: 2523
It's simpler than that:
$iif(2 // number,EVEN,ODD)
or
$iif(number & 1,ODD,EVEN)

edit: typo


Edited by qwerty (19/12/06 04:40 PM)
_________________________
/.timerQ 1 0 echo /.timerQ 1 0 $timer(Q).com

Top
#167080 - 19/12/06 04:36 PM Re: Looping as an identifier [Re: Riamus2]
jaytea Offline
Fjord artisan

Registered: 23/02/06
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


Edited by jaytea (19/12/06 04:40 PM)

Top
#167081 - 19/12/06 04:46 PM Re: Looping as an identifier [Re: jaytea]
starbucks_mafia Offline
Hoopy frood

Registered: 09/12/02
Posts: 2962
Loc: Norwich, UK
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.

Top
#167082 - 19/12/06 04:57 PM Re: Looping as an identifier [Re: starbucks_mafia]
jaytea Offline
Fjord artisan

Registered: 23/02/06
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

Top
#167084 - 19/12/06 05:10 PM Re: Looping as an identifier [Re: jaytea]
Sais Offline
Fjord artisan

Registered: 07/10/03
Posts: 313
Loc: UK
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

Top
#167093 - 19/12/06 10:10 PM Re: Looping as an identifier [Re: qwerty]
Riamus2 Offline
Planetary brain

Registered: 13/10/04
Posts: 8327
Loc: MA, USA
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

Top
#167098 - 19/12/06 11:36 PM Re: Looping as an identifier [Re: Riamus2]
jaytea Offline
Fjord artisan

Registered: 23/02/06
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

Top
#167102 - 20/12/06 12:41 AM Re: Looping as an identifier [Re: jaytea]
Riamus2 Offline
Planetary brain

Registered: 13/10/04
Posts: 8327
Loc: MA, USA
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

Top
#167105 - 20/12/06 01:10 AM Re: Looping as an identifier [Re: jaytea]
SartenX Offline
Pikka bird

Registered: 09/07/06
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?

Top
#167107 - 20/12/06 01:37 AM Re: Looping as an identifier [Re: SartenX]
Om3n Offline
Fjord artisan

Registered: 06/07/03
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

Top
#167113 - 20/12/06 02:57 AM Re: Looping as an identifier [Re: SartenX]
Riamus2 Offline
Planetary brain

Registered: 13/10/04
Posts: 8327
Loc: MA, USA
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

Top
#167123 - 20/12/06 05:51 AM Re: Looping as an identifier [Re: Riamus2]
SartenX Offline
Pikka bird

Registered: 09/07/06
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.


Edited by SartenX (20/12/06 06:20 AM)

Top
#167137 - 20/12/06 02:38 PM Re: Looping as an identifier [Re: SartenX]
Riamus2 Offline
Planetary brain

Registered: 13/10/04
Posts: 8327
Loc: MA, USA
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

Top
#167173 - 20/12/06 10:55 PM Re: Looping as an identifier [Re: Riamus2]
Om3n Offline
Fjord artisan

Registered: 06/07/03
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

Top
#167215 - 21/12/06 11:43 AM Re: Looping as an identifier [Re: Riamus2]
Mpdreamz Offline
Hoopy frood

Registered: 27/04/04
Posts: 759
Loc: Arnhem, The Netherlands
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

Top
#167219 - 21/12/06 12:31 PM Re: Looping as an identifier [Re: SartenX]
Mpdreamz Offline
Hoopy frood

Registered: 27/04/04
Posts: 759
Loc: Arnhem, The Netherlands
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

Top
Page 1 of 2 1 2 >