 |
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Sat Mar 21, 2009 10:15 pm
[3.05] Setting Local Variables conflicts when params |
If you define local variables as parameters and then call the function without parameters you cannot set the those local variables to anything inside the alias.
Instructions:
| Code: |
1) Start Cmud, press escape to get to a blank session.
2) Type 'test'
You'll see:
First Arg:
Second Arg:
Third Arg:
Which is ignoring the assignment made in the alias:
$one = 1
$two = 2
$three = 3
#say First Arg: $one
#say Second Arg: $two
#say Third Arg: $three
|
XML Code:
| Code: |
<?xml version="1.0" encoding="ISO-8859-1" ?>
<cmud>
<class name="test5" copy="yes">
<alias name="test" copy="yes">
<value>$one = 1
$two = 2
$three = 3
#say First Arg: $one
#say Second Arg: $two
#say Third Arg: $three
</value>
<arglist>$one, $two, $three</arglist>
</alias>
</class>
</cmud>
|
|
|
|
|
 |
Arde Enchanter
Joined: 09 Sep 2007 Posts: 605
|
Posted: Sat Mar 21, 2009 10:39 pm |
Confirmed.
Add "#PRINT %numparam" to the beginning of your alias and run
test
test 1
to see some interesting results |
|
_________________ My personal bug|wish list:
-Wrong Priority when copy-paste setting
-1 prompt trigger for Mapper, Session and General Options, not 3 different!
-#SECTION can terminate threads
-Buttons can't start threads |
|
|
 |
Zugg MASTER

Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Mon Mar 23, 2009 4:59 pm |
Actually, it works fine if you call your alias with the proper number of arguments, like "test 4 5 6". The problem is that until you pass the arguments, the local variables for the arguments aren't defined yet (they have a %null value) which means they aren't even on the stack and cannot be assigned to. This isn't going to be easy to fix any time soon, so you'll need to live with it for now.
|
|
|
|
 |
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Mon Mar 23, 2009 5:43 pm |
Zugg:
They are defined and assigned right at the beginning of the alias with:
$one = 1
$two = 2
$three = 3
If I remove the three variables from the 'Argument List' the definitions in the code are valid. Why should adding them to the 'Argument List' suddenly invalidate my otherwise working definitions/assignment in the code? |
|
|
|
 |
Zugg MASTER

Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Mon Mar 23, 2009 11:40 pm |
What I am saying is that when you add them to the Argument List, but then call "test" with no arguments, the arguments are not defined. There *names* are defined, but the stack location of an argument is different from a normal local variable. You *are* actually setting local variables with the same names as the arguments, but when you try to access the arguments, you are accessing the local variables in the argument stack and not the regular local variables. And the local variables in the argument stack are still nil because no arguments were passed to the alias.
I'm not saying that it isn't a bug. It is. But it's very obscure. Technically, CMUD shouldn't even let you assign a value to an argument. Arguments are supposed to be static. So the fact that it's not working doesn't really both me much. The fact that it *does* work when using "test 1 2 3" is actually more of the problem. |
|
|
|
 |
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Tue Mar 24, 2009 12:25 am |
Shoot, I've been assigning values to arguments all over the place. I had no idea they weren't supposed to be changed. They share the same syntax with local variables so I assumed they could be used interchangeably.
How about when I set the value of local variables inside a trigger with ($localvar:) syntax? Are those suppose to be static as well?
I think this is a case of, if it can be done, it will be done. Perhaps the better solution would be to disallow assignment to arguments, if that is possible. |
|
|
|
 |
Zugg MASTER

Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Tue Mar 24, 2009 5:00 pm |
I doubt I will actually disallow assignment to arguments since implementing that correctly is probably just as hard as just fixing the assignment problem.
When I talk about not assigning values to arguments, I'm speaking in a more general "best programming practices" kind of way. In general, arguments are a way to pass information *into* a method or function. Some languages allow you to "pass by reference" where modifying an argument passes data back *out* of a method or function, modifying the calling variables. Look at the following example:
| Code: |
#ALIAS myFunc($a) {$a = 456}
#VAR myVar 123
myFunc @myVar |
Now, if the argument $a is passed by "value", which is the default in most languages, then modifying $a in the myFunc function doesn't have any external effect. However, if the language passes $a by "reference" and you call myFunc with a variable (like @myVar), then assigning 456 to $a would actually modify the contents of the @myVar passed variable.
How, CMUD doesn't do any passing by reference, so this isn't a problem. But some languages do. And it's just bad programming practice to use arguments as local variables since assigning to them might have external consequences in some languages. If you know what you are doing, there are many cases where it makes good sense to modify an argument, but you should only do it when you understand exactly what's going on, and not just because it's "easier" to re-use an argument as a local variable.
In general, local variables are "cheap". There isn't any performance reason to re-use an argument instead of just making another local variable instead. It's like properly naming your variables. It's easy to be lazy and give your variables short names that are hard to remember ($a, $b, $c, etc). But it doesn't "cost" anything to give them meaningful longer names.
As a final example, let's say you have a function that takes the current amount of exp gained from killing a mob and then adds it to a counter. Here is some sample made-up code:
| Code: |
#FUNCTION addExp($expGained) {
#IF (@BonusMode) { $expGained = $expGained* 10 }
totalExp = @totalExp + $expGained
} |
OK, a trivial example. The idea is that for some reason there is a "bonus mode" where your gained exp counts 10-times more than otherwise. Like I said, it's just a made-up example. And you might think it's a perfectly valid way to handle it. But from a very technical programming style point of view, at the end of this function, $expGainedno longer represents the actual experience gained. The original value passed to the function has been lost because it has been overwritten. But it's only overwritten when @BonusMode is true. So sometimes $expGained still represents the amount of exp gained, and sometimes it's 10-times that value. If this script was more complicated, it might not be obvious what $expGained really was at the end of the function.
A better way to write this from a "style" point of view would be:
| Code: |
#FUNCTION addExp($expGained) {
#LOCAL $expInc
#IF (@BonusMode) { $expInc = $expGained* 10 } { $expInc = $expGained}
totalExp = @totalExp + $expInc
} |
Now it's really more obvious what is going on, and it's obvious (from the #LOCAL statement) that $expInc is a completely local value with no connection to anything external to the function. If you still needed the value of $expGained at the end of the function, you'd still be able to use it since it isn't overwritten.
Yes, the downside is that the script is slightly slower since it always assigns a value to $expInc. In reality, this is pretty fast code since it's manipulating arguments and local variables on the runtime stack. So it's a tradeoff between raw performance and more supportable code.
Seems trivial in this example, but in larger scripts it can become a bigger issue and make it harder to support.
Finally, I'm not really saying to worry about this much in CMUD. CMUD scripts are rarely complicated enough to make this an issue. But if you are learning to program in CMUD with the intent of programming in other languages someday for a real job, it's good to think about these things and learn good programming practices from the beginning. |
|
|
|
 |
ReedN Wizard
Joined: 04 Jan 2006 Posts: 1279 Location: Portland, Oregon
|
Posted: Tue Mar 24, 2009 6:08 pm |
I think I normally overwrite their values when I need to do something like:
#FUNCTION printName($name) {
$name = %proper($name)
#print <color bla>$name</color>
}
Usually in cases when the incoming data may need to be tweaked to be correct. But I understand your points.
Are local variables defined in the regex pattern, ie ($localvar:\d+) considered arguments or just plain local variables? |
|
|
|
 |
Zugg MASTER

Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Wed Mar 25, 2009 4:37 pm |
The variables defined in a trigger pattern are considered arguments, so they will probably have the same problem.
|
|
|
|
 |
|
|
|
|
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
|
|