Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD General Discussion
Dwoggurd
Wanderer


Joined: 29 Jan 2008
Posts: 63

PostPosted: Sun Mar 09, 2008 10:11 pm   

%expand and local variables
 
It looks like %expand isn't working when its argument is a local variable

#SAY %expand(@str) expands str variable

but

#SAY %expand($str) simply prints "$str"
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Mon Mar 10, 2008 12:16 am   
 
I can confirm that behaviour, but it's possibly not a bug - %expand might've been intended for use with real variables only. If you post the script you're trying to use it in, we can suggest alternatives.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
Dwoggurd
Wanderer


Joined: 29 Jan 2008
Posts: 63

PostPosted: Mon Mar 10, 2008 5:55 am   
 
I write a function that expands its parameter and returns the result (with some modifications)
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Mon Mar 10, 2008 5:10 pm   
 
%expand is really left over from zMUD compatibility and shouldn't be needed in CMUD. Just use

#SAY $str

and that will work fine. In any case, %expand does not support local variables, sorry. If you are doing something fancy, you might want to use %eval instead.
Reply with quote
Dwoggurd
Wanderer


Joined: 29 Jan 2008
Posts: 63

PostPosted: Mon Mar 10, 2008 6:25 pm   
 
I write a function that generates a string-command, later I may send it to the server.
#SAY won't help me.
I tried %eval, but I'm not sure how exactly it works. For example, it removes spaces between words (because it concatinates words?) which is an inconvenience.
Basically, I have a string that may have aliases and I want to produce a command ready to be sent. I expand aliases within the string with %alias and I need to expand variables too. Currently the only hack way I found: I copy the function argument into a global variable, then %expand it, so all variable/function references are exapanded within the string.
If it is not supposed to be done in CMUD, any suggestion how I can achieve my goal?
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Mon Mar 10, 2008 6:40 pm   
 
If you are trying to execute a command stored in a string, then you should use #EXEC. If you show us more details on the script you are using, then one of the other Gurus might be able to help more.
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Mon Mar 10, 2008 6:53 pm   
 
Just to clarify, "more details" means "the code you're using" as well as what you want to type to use it, what its purpose is, and what you intend it to do when you run it.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
Dwoggurd
Wanderer


Joined: 29 Jan 2008
Posts: 63

PostPosted: Mon Mar 10, 2008 8:13 pm   
 
No script, sorry, it's complicated. In my specific case I've found a workaround with global variables.

But, in general, I need something that expands aliases and variables. I don't need to evaluate it and I don't need to execute it. I need just expansion.
I pass a string containing some command (as if I would type in the input window). It can be a real server command or an alias name with parameters.
As a result, I need to get a string containing a command exactly as it would be sent to the server (with aliases and variables expanded).

I don't want to %exec it because I may modifiy it if needed. I do some regex-replace on the resulting command.
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Mon Mar 10, 2008 8:20 pm   
 
Have you seen some of the scripts in the Finished Scripts section? We're no strangers to complexity :P

Really, there's very little we can do to help you without seeing your code. It's probably something systemic in the way you're tackling the problem rather than changing a couple of lines. Without knowing what you're trying to do specifically - that is, whatever it is on your MUD you're trying to script, not "expand a string" - and how you're going about doing it, there's not much we can do.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
JQuilici
Adept


Joined: 21 Sep 2005
Posts: 250
Location: Austin, TX

PostPosted: Mon Mar 10, 2008 9:26 pm   
 
Also, please note that, unlike #EXEC, the %exec function does NOT send stuff to your MUD. Instead, it evaluates the argument as a command, and RETURNS the commands that would have been sent (as a string list). E.g.
Code:
#show %exec(%concat("#10",%char(32),"sneeze"))
will print a stringlist with 10 'sneeze's in it, but nothing is sent to the MUD.
_________________
Come visit Mozart Mud...and tell an imm that Aerith sent you!
Reply with quote
Arminas
Wizard


Joined: 11 Jul 2002
Posts: 1265
Location: USA

PostPosted: Mon Mar 10, 2008 9:34 pm   
 
If you don't like %exec then you might like %alias better.

Finally you probably should be using functions for what you are doing in the first place.
Cmud recently gained the ability to use real functions with return statements.
The odds are that if you are constructing a string to be used elsewhere that you would be better off using a function.
_________________
Arminas, The Invisible horseman
Windows 7 Pro 32 bit
AMD 64 X2 2.51 Dual Core, 2 GB of Ram
Reply with quote
Dwoggurd
Wanderer


Joined: 29 Jan 2008
Posts: 63

PostPosted: Mon Mar 10, 2008 10:17 pm   
 
It looks like %exec doen't work correctly with local variables too.
I stumble in some wierdness and I'm not sure what are conditions for it, probably some mess with nested %exec and local variables.

Here is a short example:

#ALIAS test {ok}
#Function testfunc { #RETURN %exec(test) }

#ALIAS wtf
{
$s = "@testfunc()"
#SAY {"1:" %exec($s)}
#var globalS $s
#SAY {"2:" %exec(@globalS)}
}

I get output:
ok
1:
2: ok
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Tue Mar 11, 2008 1:04 am   
 
Whatever you are actually trying to do, you are making for too hard. An old saying is, "There are 6 ways to skin a cat." With CMud there are usually at least 12 ways to code something, and probably 3 of them are only known by a few really old scripters. Those 3 ways are generally next to useless, but we know them for the 1 time they will be useful. You are trying to use such a method at the wrong time.

One should rarely if ever need to use #EXEC, and even more rarely should one need to use %exec. They are pretty much only needed when one wants to work around a limitation in the parsing of a script. Those limitations are in place to protect most users from themselves, and very rarely need to be bypassed.

I would have to quote Fang:
Quote:
Really, there's very little we can do to help you without seeing your code. It's probably something systemic in the way you're tackling the problem rather than changing a couple of lines. Without knowing what you're trying to do specifically - that is, whatever it is on your MUD you're trying to script, not "expand a string" - and how you're going about doing it, there's not much we can do.
If you feel that your script contains something highly proprietary that you do not wish to publish, then I would suggest you contact one of the people that has replied so far with PM to see if they will work with you one on one. Both Arminas an JQuilici are long time respected contributors to this community; Fang and I are moderators in these forums. If you can't trust at least one of us then we have been doing something wrong.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Tech
GURU


Joined: 18 Oct 2000
Posts: 2733
Location: Atlanta, USA

PostPosted: Tue Mar 11, 2008 1:37 am   
 
What were you expecting? The code seems to be working fine.

The first command actually executes the code (i.e. sends it as a command to the mud). You have say of the output but because there is none, nothing occurs when you do "1:".

When you print "2:" you actually seeing an artifact of the fact that functions were implemented as variables in zMUD and some of that is maintained for compatibility. The global variable evaluates the function call that you assign. Since it just evaluates to text thats essentially what the variable gets set to 'ok'. Note that it's displayed with the #SAY command (note it's in blue) versus being executed (i.e. sent to the mud) as in case "1:' which is why "1:" shows up as yellow.
_________________
Asati di tempari!
Reply with quote
Dwoggurd
Wanderer


Joined: 29 Jan 2008
Posts: 63

PostPosted: Tue Mar 11, 2008 2:53 am   
 
Tech wrote:
What were you expecting? The code seems to be working fine.

The first command actually executes the code (i.e. sends it as a command to the mud). You have say of the output but because there is none, nothing occurs when you do "1:".

When you print "2:" you actually seeing an artifact of the fact that functions were implemented as variables in zMUD and some of that is maintained for compatibility. The global variable evaluates the function call that you assign. Since it just evaluates to text thats essentially what the variable gets set to 'ok'. Note that it's displayed with the #SAY command (note it's in blue) versus being executed (i.e. sent to the mud) as in case "1:' which is why "1:" shows up as yellow.


I expect both SAYs work similarly.
The only difference between them is local vs. global variables.

I don't post my script because I don't want to go through the pain of cutting what is relevant and what is not in my set of macroses.
And I stated my goal clearly, I wish to write a function that fully expands its argument and returns the result as a string. I don't want to send it right away, execute it or put as #SAY argument. I just need a string with all variables and simple aliases expanded, because I want to do some post-processing later. Until now I played with %expand, %alias and temporary global variables. Keep in mind, that in my case I'm talking about primitive aliases that are just shortcuts but may call nested primitive aliases, so right now I use recursive %alias/%expand calls.
Whoever has a good idea how to do that, feel free to give a hint or post a script.

Vijilante wrote:

One should rarely if ever need to use #EXEC, and even more rarely should one need to use %exec.


I didn't even use %exec until now, it wasn't my idea. In my original post I discuss %expand behavior.
However, %exec's behavior is somewhat wierd too, I'm not sure if it is a feature or a bug.
In normal programming languages you may expect it work the same way with global and local variables. (Thus produce the same "output").
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Tue Mar 11, 2008 10:17 am   
 
Quote:
In normal programming languages you may expect it work the same way with global and local variables. (Thus produce the same "output").
I will use a simple example in C to show this is not the case, and why local variables shouldn't actually be expected to work with %exec and #EXEC. If you read Zugg's first post again you will see he says %expand wasn't removed from zScript for zMud compatibility, and that %eval will handle the local variable for you.

Now the explanation for %exec and #EXEC
Code:

int global = 1;

void exec (char *text, int size) {
 int i = 0;
 while (i<size) {text[i++]+=local;} //line fails can't access local
}

void exec2 (char *text, int size) {
 int i = 0;
 while (i<size) {text[i++]+=global;} //line works with global variable
}

void main (void) {
 int local = 1;
 char testfunc[5]="ok";
 exec(testfunc,strlen(testfunc));
 //this can't work because local will not be defined there %exec and #EXEC without
 //expansion control tricks involving %concat and "" placements.
}
There you have it.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Arminas
Wizard


Joined: 11 Jul 2002
Posts: 1265
Location: USA

PostPosted: Tue Mar 11, 2008 2:19 pm   
 
Ok, let me explain my cause for suggesting functions.

$localvar = %concat("blah", %rightback("big bunch of bolarky",3),%if(%1==3,"this","that"),%2)

Now you want to do with all of this stuff...

#send/loop/whatever %expand($localvar) //That isn't working.

If instead of setting that local variable to this you simply used a function

#function rlocalvar {#return %concat("blah", %rightback("big bunch of bolarky",3),%if(%1==3,"this","that"),%2)}

then do.

#send/loop/whatever @rlocalvar(%1,%2)

For that matter if you go in and tic the use default option on a regular variable it is supposed to be as fast as a local variable anyway.

Mind that I have not run any of this through a syntax checker. I'm typing from the top of my head but. I build strings all of the time and have used everything that has been suggested in this entire thread. Yes I have been annoyed a time or two by local variables not working with some of the functions like expand. But like Vijilante said there are lots of ways to work around those annoyances.

The problem being that there are also a lot of things that can be done to cause you to think you need it to work a certain way. We need a specific example of what you are trying to do so that we can show you another way to do it.
_________________
Arminas, The Invisible horseman
Windows 7 Pro 32 bit
AMD 64 X2 2.51 Dual Core, 2 GB of Ram
Reply with quote
Dwoggurd
Wanderer


Joined: 29 Jan 2008
Posts: 63

PostPosted: Tue Mar 11, 2008 5:58 pm   
 
Dynamic function creatin is interesting, though how fast it is?
Also, I don't set a local variable, I just have a source string as an argument of my function. One more question: a named argument acts the same way as a local variable? And what will happen if I construct a dynamic function from a named argument (if anything).
Reply with quote
Arminas
Wizard


Joined: 11 Jul 2002
Posts: 1265
Location: USA

PostPosted: Tue Mar 11, 2008 6:45 pm   
 
I'm not talking about dynamically creating a function... I'm talking about using functions to transform your string.
You would have the function created and waiting to be used in your script.

As far as named arguments acting like local variables. %1 should be the same as first named argument %2 should be the same as second named argument etc. And those SHOULD still work with expand. Though you should not NEED to use it.
_________________
Arminas, The Invisible horseman
Windows 7 Pro 32 bit
AMD 64 X2 2.51 Dual Core, 2 GB of Ram
Reply with quote
Larkin
Wizard


Joined: 25 Mar 2003
Posts: 1113
Location: USA

PostPosted: Tue Mar 11, 2008 6:45 pm   
 
A named argument is a local variable, for all intents and purposes.

I think Arminas was suggesting that you could create a single function for processing the arguments and re-use it in your alias to do whatever it is you're doing. I don't know that you'd want to create a new function each time you use the alias.

Another route would be to use Lua, Python, or some other script language for your complex processing. You could make a CMUD function that utilizes Lua and that might help you circumnavigate some of the limitations you're up against, maybe?

Again, we still don't know exactly what you're doing or why, so it's a little hard to give accurate and specific suggestions.
Reply with quote
Dwoggurd
Wanderer


Joined: 29 Jan 2008
Posts: 63

PostPosted: Tue Mar 11, 2008 8:51 pm   
 
Ok, I've tried to make a simple example to demostrate what problems I have:

Below in black bold what I type in the input window
in blue #SAYs
in green (instead of default yellow) what has been sent to the server

Let's assume I have some simple aliases which I can use as standalone, so I don't want to change them.
#VAR Name Zugg
#VAR text Hello
#ALIAS alias1 {tell %1 @text}

Now I want to have another alias that can take alias1 as a parameter. I would like to use it as a standalone too.
I can do it using %exec:

#ALIAS alias2 {do %exec(%-1 " " @Name)} - this alias is working fine, but I can't use it in my final alias "test" below because it executes it's parameter and I get wierd "output".

alias2 alias1
do tell Zugg Hello

Or I can try to "expand" (in wide sense, expand aliases and variables) it's parameter so it will be sent to the server when I use this alias as a standalone:

#ALIAS alias3 {do %alias(%-1, @Name)} - this variant isn't working because @Name variable isn't expanded and I don't know how to expand it. This is one of my problems Very Happy

alias3 alias1
do tell Zugg @text - I want to modify it so my variables are expanded too.

Now my final alias "test":
#ALIAS test {
#SAY {-------------------}
$s = %exec(%-1)
#IF (%match($s, "Zugg") > 0) { #SEND {$s} } { #SEND {$s Zugg}}
}
I used %exec here too, but it doesn't work as I want. So here I would prefer another full expansion until all aliases and variables are expanded.

test
-------------------
Zugg

test alias1 Zugg
-------------------
tell Zugg Hello

test alias2 alias1
-------------------
do tell Zugg Hello - I send two lines to the server and it is not what I wanted.
Zugg

test alias3 alias1
-------------------
do tell Zugg @text - the variable isn't expanded and the server will not understand it.

So that's why I need some sort of expansion. I can't get it working using exec (because it executes too early for me?) as I get several lines of output.
Or I need some different approach to the problem.
In short, I want my alias1 and alias2(3) work as standalone aliases. And I want to able to use them as paramteres for my "test" alias.
Reply with quote
Arminas
Wizard


Joined: 11 Jul 2002
Posts: 1265
Location: USA

PostPosted: Wed Mar 12, 2008 2:46 am   
 
I STILL think there is a better way to do this, Like say using functions instead of aliases.., but.
This does what you are talking about. Note the use of %quote...
Code:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<cmud>
  <func name="expandA">
    <value>#return %quote(%alias(%1,%2))</value>
  </func>
  <var name="text">Hello</var>
  <var name="Name">Zugg</var>
  <alias name="test">
    <value>#SAY {-------------------}
$s = @expandA(%1,%2)
#IF (%match($s, "Zugg") > 0) { #SEND {$s}} { #SEND {$s Zugg}}</value>
  </alias>
  <alias name="alias3">
    <value>#send {do @expandA(%1,@name)}</value>
  </alias>
  <alias name="alias1">
    <value>tell %1 @text</value>
  </alias>
</cmud>
_________________
Arminas, The Invisible horseman
Windows 7 Pro 32 bit
AMD 64 X2 2.51 Dual Core, 2 GB of Ram
Reply with quote
Arminas
Wizard


Joined: 11 Jul 2002
Posts: 1265
Location: USA

PostPosted: Wed Mar 12, 2008 3:31 am   
 
Note that I did replace a couple of %-1 with %1 or %1, %2.

I think between what I showed you and some inventive uses of %quote you can do what you want the way that you want to.
Even if I think it is weird to even try. Razz
_________________
Arminas, The Invisible horseman
Windows 7 Pro 32 bit
AMD 64 X2 2.51 Dual Core, 2 GB of Ram
Reply with quote
Dwoggurd
Wanderer


Joined: 29 Jan 2008
Posts: 63

PostPosted: Wed Mar 12, 2008 4:37 am   
 
Hmm, I tried your script but I don't understand how it should work.

test alias3 alias1
produces:
-------------------
~#send {do tell Zugg Hello}

%-1 was used for a purpose, I don't know how many arguments will be passed to my aliases. I can also pass not aliases, but "literal" commands. So in my actual alias I analyze the argument word by word, leave literals unchanged and expand aliases with %alias.
Reply with quote
Arminas
Wizard


Joined: 11 Jul 2002
Posts: 1265
Location: USA

PostPosted: Wed Mar 12, 2008 1:18 pm   
 
Ok well, have I mentioned that you are going about this a really odd way? Yes... I think I have. Have you considered oninput triggers?

Also note that I mentioned tinkering would be in order.

Code:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<cmud>
  <alias name="alias1">
    <value>tell %1 @text</value>
  </alias>
  <alias name="alias3">
    <value>do @expandA(%1,@name)</value>
  </alias>
  <alias name="test">
    <value>#SAY {-------------------}
$s = @expandA(%1,%-2)
#IF (%match($s, "Zugg") > 0) { #SEND {$s}} { #SEND {$s Zugg}}</value>
  </alias>
  <var name="Name">Zugg</var>
  <var name="text">Hello</var>
  <func name="expandA">
    <value>#return %subchar(%quote(%alias(%1,%2)),~~)</value>
  </func>
</cmud>


Is closer than it was. This IS looking more like you should start trying #oninput triggers with the #noinput option.
Zugg has also stated that he is going to change the way %-1 is expanded. This will make doing odd things like this easier.
_________________
Arminas, The Invisible horseman
Windows 7 Pro 32 bit
AMD 64 X2 2.51 Dual Core, 2 GB of Ram
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD General Discussion All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net