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.

Unusual way of defining procedures

Old posts that have not been replied to for several years.
Locked
p
peterre

Post by peterre »

I've been experimenting with a method of defining procedures that I haven't seen used before in eggdrop scripts. It allows neat scripting in some circumstances.

For your interest I've put a script that uses it at

http://www.soft.net.uk/staffs/eggdrop/p ... ert1.0.tcl

or (as a Windows file, viewable with Notepad)

http://www.soft.net.uk/staffs/eggdrop/p ... rt1.0w.tcl

I shall be submitting this to Slennox shortly for his script database, so I'd be grateful if anyone lets me know of any faults they see in the user instructions or code (although I've already tested it pretty carefully).

Peterre


<font size=-1>[ This Message was edited by: peterre on 2001-10-16 05:34 ]</font>

<font size=-1>[ This Message was edited by: peterre on 2001-10-16 05:36 ]</font>
User avatar
stdragon
Owner
Posts: 959
Joined: Sun Sep 23, 2001 8:00 pm
Contact:

Post by stdragon »

It looks interesting, but why do you have that g in your regsubs? Were you going to allow multiple arguments, like arg2 arg3 and you didn't want them to become arg2.0 arg3.0?

It might be better to use X instead of $arg, since people are more used to X from algebra than $arg.

Also, why do you create all those new procs in the foreach loop? Wouldn't it be easier to just keep the entries in an array and eval the code from within one proc?
p
peterre

Post by peterre »

The g in the regsubs is so that the standard function log10 won't get renamed to log10.0 before the expression is passed for evaluation. And yes, I'm sure there are other approaches, e.g. using a single procedure along the lines that you suggest. But then you wouldn't be automatically generating the binds to allow queries like "!f2c 68" Would not queries then have to be like "!conversion f2c 68" where !conversion had a bind to the single procedure that you suggest? That seems less convenient for the user.


<font size=-1>[ This Message was edited by: peterre on 2001-10-17 06:57 ]</font>
User avatar
stdragon
Owner
Posts: 959
Joined: Sun Sep 23, 2001 8:00 pm
Contact:

Post by stdragon »

Code: Select all


set con(f2c) {blah blah blah}
set con(c2f) {blah blah blah}

foreach cmd [array names con] {
  bind pub - !$cmd [list pub_handler $cmd]
  bind msg - !$cmd [list msg_handler $cmd]
  bind dcc - $cmd [list dcc_handler $cmd]
}

proc pub_handler {cmd nick uhost hand chan text} {
 global con

  # con($cmd) is the entry for this thing
}

proc msg_handler {cmd nick uhost hand text} {
 global con

  # con($cmd) is the entry for this thing
}
...
p
peterre

Post by peterre »

That's neat. Thanks. It looks as though it will work fine. I'll rewrite that part of the script your way, then if it turns out well, and you're agreeable, I'll submit it with the two of us as joint authors. Of course I'll confer with you before I put out anything in our joint names.

<font size=-1>[ This Message was edited by: peterre on 2001-10-17 09:30 ]</font>
p
peterre

Post by peterre »

I tried your method, and it works fine. But having done that, I'm inclined to think that the original method is slighter better. Here's how I implemented your method. My original proc con_form remains as before.

foreach cmd [array names con] {
bind dcc - $cmd [list con_dcc_form $cmd]
bind msg - !$cmd [list con_msg_form $cmd]
bind pub - !$cmd [list con_pub_form $cmd]
}

proc con_dcc_form {cmd hand idx arg} {
global con
con_form D 0 $idx $arg $cmd [lindex $con($cmd) 0] [lindex $con($cmd) 1] [lindex $con($cmd) 2] [lindex $con($cmd) 3] [lindex $con($cmd) 4]
}

proc con_msg_form {cmd nick uhost hand arg} {
global con
con_form M 0 $nick $arg $cmd [lindex $con($cmd) 0] [lindex $con($cmd) 1] [lindex $con($cmd) 2] [lindex $con($cmd) 3] [lindex $con($cmd) 4]
}

proc con_pub_form {cmd nick uhost hand chan arg} {
global con
con_form $con(reply) $chan $nick $arg $cmd [lindex $con($cmd) 0] [lindex $con($cmd) 1] [lindex $con($cmd) 2] [lindex $con($cmd) 3] [lindex $con($cmd) 4]
}

This is longer than the original, and involves the user in some extra braces when entering new formulae. Only small points, but leading me to the conclusion that the original method is slightly better. But I'm willing to be persuaded otherwise.

This forum seems a good place for interesting discussions like this.
User avatar
stdragon
Owner
Posts: 959
Joined: Sun Sep 23, 2001 8:00 pm
Contact:

Post by stdragon »

You don't even need those 3 con_* procedures.

Code: Select all

foreach cmd [array names con] {
  bind dcc - $cmd [list con_form $cmd d]
  bind msg - !$cmd [list con_form $cmd m]
  bind pub - !$cmd [list con_form $cmd p]
}

proc con_form {cmd method args} {
  if {$method == "p"} {set dest [lindex $args 4]} <-- channel
  if {$method == "m"} {set dest [lindex $args 0]} <-- nick
  if {$method == "d"} {set dest [lindex $args 1]} <-- idx
  set arg [lindex $args end]
  ...
}
To enter the algorithms, if you don't like braces, then create a proc to do it:

Code: Select all

proc newalg {args} {
  global con
  set cmd [lindex $args 0]
  set text [join [lrange $args 1 end]]
  regsub -all x $text { ($arg) }
  # For extra points, regsub x**y and x^y to pow(x,y)
  set con($cmd) $text
}

newalg square x * x
newalg cuberoot pow(x, 1/3)
...
Now you can add a simple bind to create new algorithm without editing the tcl file.
p
peterre

Post by peterre »

Regarding the regsubbing of x^y to pow(x,y), I already have a version that does that with simple expressions that can include many types of nesting, but it can be defeated by some complex nested expressions. Regular grammars cannot count brackets, so the algorithm must be iterative (or recursive). I found that it got a bit tricky so I decided to defer devising a general x^y => pow(x,y) mapper for a later version. I shall enjoy working out a suitable algorithm.

Regarding the code that you give, you have not taken into account the role of con(reply). But that can be taken care of by (for example):

proc con_form {cmd source args} {
global con
if {$source == "d"} {set method D;set chan 0;set ident [lindex $args 1]}
if {$source == "m"} {set method M;set chan 0;set ident [lindex $args 0]}
if {$source == "p"} {set method $con(reply);set chan [lindex $args 3];set ident [lindex $args 0]}
.....
.....

A solution based on this gives a smaller script than my original, although I don't think it's any more readable because of the need for several lindex commands, e.g. as above, and also to recover the other values from within the array, which make the reader have to count along the values in the array to see which value is being obtained. The values follow through in a more readable fashion in my original code.

Putting in the algorithm for the braces puts the size of the code back up again - not that size of code is a good criterion - readability and maintainability are the more important criteria.

All in all, your solution is good, and I'm grateful to you for showing me the technique of using bind .... [list ....]. I'd never thought of that before.

As to which is the better, or more elegant, solution, they each have their advantages.

<font size=-1>[ This Message was edited by: peterre on 2001-10-19 03:40 ]</font>
Locked