|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Tue Apr 11, 2006 11:03 pm
Variable types |
I've avoided having "typed" variables for a long time. But now I think it's starting to cause more complexity than simplicity.
For example, consider the following in zMUD:
Code: |
#VAR hp 100
#VAR maxhp 500
#FUNC HpStr {@hp/@maxhp} |
OK, now do a #SHOW @HpStr. What should you get? Should you get 0 since 100 divided by 500 is zero (integer)? Or should you get 0.2 which is 100 divided by 500 as a floating point value. Or should you get the string "100/500"?
Imagine that this is on your status bar. In that case, you probably want it to return the string "100/500" just like in your MUD status line.
Basically, there is no way for zMUD or CMUD to know for sure what you want. And this ends up causing all sorts of problems if you want something that is different than the zMUD default.
In zMUD, you get the STRING result. If you want the integer result, you use %eval. If you want the floating point value, then you need to assign a floating point value to either @hp or @maxhp and then go an %eval. This is quite a pain!
I think it's time to finally add a variable "type" field. It would allow you to set the type of @HpStr to either Integer, Float, or String depending upon how you want the value converted.
CMUD will set the type field automatically to match the default of zMUD. For example:
Code: |
#VAR a 1 // a is now an integer
#VAR a 1.0 // a is a floating point number
#VAR a "1" // a is now a string
#VAR b @a // b is a string with the value of "1"
#VAR b @a+1 // b is an integer with the value of 2
#VAR b (@a+1) // b is an integer with the value of 2
#VAR b {@a+1} // b is a string with the value of "1+1"
#VAR b "@a+1" // b is a string with the value of "@a+1" |
The above examples would represent the results if both @a and @b were set as default "AutoType" variables. But, for example, if you forced the type of @a to be "String", then
#VAR b @a+1
would return a STRING with the value "11" (performed a string concat instead of a numeric addition).
In zMUD, doing floating point math requires you to specify the decimal value (such as 1.0 instead of just 1). In CMUD, you could assign
#VAR a 1
and then set variable A to be Float and that would force floating-point math for calculations involving @a.
In other words, you would still get the "AutoType" (or typeless) features of zMUD, but would be able to override the default type with your own.
Setting the type in the Settings Editor is a trivial change. But we also need some command line syntax for setting the variable type. Unfortunately, the #TYPE command is already taken. Anyone have any suggestions for the syntax? |
|
|
|
edb6377 Magician
Joined: 29 Nov 2005 Posts: 482
|
Posted: Tue Apr 11, 2006 11:16 pm |
I definatly would like to see a change here. I use a plethora of variable types in my scripting. As to a # command #vartype makes sense to me. I think this would vastly improve variable handling on my end. While you are messing with variables i had a note.
#VAR xyzpdq 2 --> Would create a new variable in root (if variable exists it updates it in its current class folder)
@xyzpdq = 2 --> This however creates a new variable in the root folder either way even if one does exist in another class folder.
Kind of annoying really. Just FYI |
|
_________________ Confucious say "Bugs in Programs need Hammer" |
|
|
|
Rainchild Wizard
Joined: 10 Oct 2000 Posts: 1551 Location: Australia
|
Posted: Tue Apr 11, 2006 11:31 pm |
What about a #DIM or #DECLARE (not sure if they are currently used), but that's a pretty common syntax for defining a variable.
Code: |
#DECLARE hp AS integer |
Will there be a way to have a temporary variable? One which you can
Code: |
#DECLARE blah AS temporary string
@blah = "blah"
#SAY @blah |
And at the end of the script execution, @blah goes away?
IMO this still doesn't help your example where you do your @hp/@maxhp since both are probably going to be defined as integers... so we probably need a %cast( @hp AS double ) or something.
Probably you wouldn't need typed variables if you could just %cast( )? |
|
|
|
Belmyrddyn Magician
Joined: 17 Oct 2001 Posts: 371 Location: USA
|
Posted: Tue Apr 11, 2006 11:31 pm |
What about adding an parameter to the current #VAR command? If you want to change the type. The type would persist until that parameter is used again.
|
|
_________________ Belmyrddyn |
|
|
|
edb6377 Magician
Joined: 29 Nov 2005 Posts: 482
|
Posted: Tue Apr 11, 2006 11:50 pm |
Quote: |
#VAR successhits 100
#VAR totalhits 500
#FUNC Accuracy {@successhits/@totalhits}
|
Is an example of a situation where i use this and i would want the .2 number.
In your example i would want 100/500
So this is something that would need to be defined somehow. currently i use
#var accuracy %eval (@successhits/@totalhits} to do this so just some input for your brain
#DECLARE would be ok as well i suppose i would still prefer #VARTYPE personally but i will learn whatever you impliment :) |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Wed Apr 12, 2006 12:52 am |
As Belmyrddyn says just another parameter on an already existing command
#VA [variable] [value] [defaultval] [classname] [type] |
|
_________________ Taz :) |
|
|
|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Wed Apr 12, 2006 12:55 am |
I think I'm leaning towards #VARTYPE too. In languages with things like DECLARE and DIM it is also typically allocating memory, which isn't done in this case. All we are doing is changing the variable type, so VARTYPE seems pretty clear.
Rainchild, as far as casting, I think you missed something in my example. It doesn't matter what the type of @hp or @maxhp are. What matters is the type of the @HpStr function. If @HpStr is set as an Integer type, then the compiler *evaluates* the function as a numeric function, so the / is interpreted as Integer Division regardless of @hp or @maxhp. If @hp is a string, then it is first converted to an integer before performing the division.
I've also decided to add *2* different "string" types. There is a "string (expanded)" type and a "string (literal)" type. In the above example with @HpStr, if the type is set to "String (expanded)" then it would return the string result "100/500" where each variable in HpStr is expanded. However, if the type of @HpStr is set to "String (literal)" then the result would be "@hp/@maxhp".
In other words, setting a variable to "String (literal)" prevents the dreaded variable expansion that zMUD is always doing. It means you don't need to use the %expand(var,1) syntax to expand a variable just once. A "String (literal)" is just a normal string value that is never messed with. I think this addition will really help a lot of people.
edb6377: We had another post in this forum about creating new variables. The #VAR command and the var=value syntax is really for changing the value of a variable, and you *want* this to search in other classes and packages (described in more detail in the other forum topic). What I'm doing in CMUD is adding a new command like #NEWVAR which creates a new variable in the current class. To create a variable in the root class, you would use the #NEWVAR ./varname syntax, also described in the other post.
Rainchild: Re: temporary variables. Yes, there are going to be temporary variables (called "Local" variables) in CMUD, but I'm not sure if it will be in the first beta yet. |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Wed Apr 12, 2006 1:16 am |
Is adding another parameter to #var not possible then?
|
|
_________________ Taz :) |
|
|
|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Wed Apr 12, 2006 1:27 am |
Well, I thought about adding another parameter to #VAR, and will still consider it. But it's already got so many, and setting the variable type would require you to also set the default value and class value (you can only omit optional arguments at the end of a command, and "type" would need to be added to the end of the argument list). This could cause some problems with people accidentally setting the default or class to something else when they really just wanted to change the type. Adding something like #VARTYPE seems like a cleaner solution.
What I might do is add something to the #NEWVAR command since this is brand new anyway. Seems like you'd most often want to set the type at the variable creation time anyway. |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Wed Apr 12, 2006 1:42 am |
Yes, that would be an issue, not the setting of default or class values, they can be sent blank fairly easily but I can imagine many people accidentally setting the wrong default or class when they meant to set the type just solely through forgetting to set blank default or class values. Wow that is a mouthful.
Now then thinking about that and programming you usually decide types at the time of declaration so making it a part of #NEWVAR seems very sensible and then of course for altering already existing variables that is where the #CAST/%cast() would come in much like in programming.
As you have already said #VAR is really for changing already existing variables and definitely will be in CMUD so although you might expect to be able to change the type using #VAR it's no big deal that we may have to adopt a new command/function to do so after all we need to start adopting a new way of thinking about #VAR. |
|
_________________ Taz :) |
|
|
|
wwwfisher Beginner
Joined: 03 Apr 2006 Posts: 12
|
Posted: Wed Apr 12, 2006 2:07 am |
that's sound great!
as we are used to writing #var, #nvar or #vart is more preferable for the ab. of #newvar or #vartype. |
|
|
|
Rainchild Wizard
Joined: 10 Oct 2000 Posts: 1551 Location: Australia
|
Posted: Wed Apr 12, 2006 5:32 am |
If I have a trigger on my prompt and %1 is my hp and %2 is my max hp and I want to work out what percentage of health I'm at I would like to do something like (although I'd use a status bar or guage, but #SAY is for the example):
Code: |
#VAR hp %1
#VAR maxhp %2
#SAY "HP: " + %eval( @hp/@maxhp*100 ) + "%" |
Now, there's going to be a few issues here:
1) we're mixing strings with numbers
2) we're performing integer mathematics so it will perform the divide and get '0' or '1' then multiply so I'll always either be on 0% or 100% health...
As a novice user, I would expect this to return "HP: 57%" and going to be a bit annoyed having to figure out why it's saying "HP: 0%"
Firstly I think division should implicitly cast the inputs to double's so you get the correct math result then cast it back to it's original type at the end of the operation.
Secondly having the %cast( ) would let you do your %cast( @hp/@maxhp*100 AS double ) which will get your 56.6666667 if you did want the precision.
Thirdly I would like to see %cast( ) allow for some formatting, eg I could go %cast( @hp/@maxhp*100 AS double( 2, 2 ) ) which would return 56.67 rather than max precision.
I know that it's not 'technically' how programming languages work, and you could as easily do a @hp*100/@maxhp but IMO this isn't something a novice should have to know or work out. Plus even that will return 56 and not 57 as it should... |
|
|
|
Larkin Wizard
Joined: 25 Mar 2003 Posts: 1113 Location: USA
|
Posted: Wed Apr 12, 2006 1:59 pm |
I know that novices will have some difficulties with variables types at first, but I'd rather they simply learn how from a mentor or by reading a help file than to teach them bad practices.
And, using an "AS" syntax is more VB-style than zMUD-style. It would be more natural to %cast(expression, type), though we already have %int, %float, etc, that do this same basic thing, right? |
|
|
|
Tarn GURU
Joined: 10 Oct 2000 Posts: 873 Location: USA
|
Posted: Wed Apr 12, 2006 2:45 pm Re: Variable types |
Zugg wrote: |
I've avoided having "typed" variables for a long time. But now I think it's starting to cause more complexity than simplicity.
|
I like typing, but I think the details are going to get tricky.
Will this only apply when a result is to be stored in a variable, or do implicit typing rules need to be developed for what happens when you execute
#show @a/@b
based on the types of @a and @b?
If the latter, user functions will probably need to be typed as might their arguments (forcing conversion if possible).
-Tarn |
|
|
|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Wed Apr 12, 2006 5:55 pm |
Rainchild: In your example, using %float is still the solution. As Larkin mentioned, we already have %int, %float, and %string to perform type "casts". Those will continue to be useful for temporary "on-the-fly" type conversions.
I also agree with Larkin that it's better to try and teach people the proper way of programming. It's always better and more efficient to to (@hp*100)/@maxhp (perform the multiplication first, then the division) since this avoids any floating point math. And it's good for novices to learn this, since it applies to any other programming they might do in the future. The problem with floating point is that you end up with all of those extra decimal places (like 56.66666666666...) and then end up having to use the annoying %format function to make stuff look right.
Tarn: In your example of #show @a/@b there are a couple of things going on here:
1) Look at the command and see what arguments it expects. The argument type expected is shown in the Command/Function wizard (press F1)
2) Next, the type of the variables is checked as needed for operations like + which are ambiguous. For an operation like / where only numbers make sense, any strings that can be converted to numbers are automatically converted.
For the command arguments, there are really only 3 major argument types: expression, string, commands. For expressions, they are evaluated as mathematical expressions. For string, any variable references are expanded and there can be a lot of implied concats. For commands, the arguments are compiled as a normal command script.
For the #show command, if you look at the F1 help you will see that it's argument is a "string" type. This means that variables are expanded. So, the code
Code: |
a=5
b=2
#SHOW @a/@b |
would display the string result "5/2". Using the new CMUD syntax you can force an expression by putting parenthesis around it: #SHOW (@a/@b) would give a numeric result of 2 (5 divided by 2 as an integer result). Putting {} around an argument forces normal string expansion mode. Putting quotes around it will treat it as a string and prevent the variable expansion. So #SHOW "@a/@b" would give the string result "@a/@b".
In all of these cases, the actual "type" of @a and @b didn't matter. The only case that is ambiguous is when performing the (@a/@b) numeric operation. The default is to use Integer math. If you set the VARTYPE of either @a or @b to be "Float" then the (@a/@b) result would be 2.5 instead of 2. You could accomplish the same thing using the %float function: (%float(@a)/%float(@b)) if you wanted. But this shows how the "type" of the variables can have an effect.
In this example, changing the type of @a or @b to "string" doesn't accomplish anything. That's because in a mathematical expression, / is always division and division is not defined for strings. So any string that can be converted to a number is automatically converted.
However, consider an alternate example: #SHOW (@a+@b)
Integer math is still the default. But now if you set the VARTYPE of either @a or @b to "String", then the + operator will perform a Concat instead of an Add.
I hope this makes things clearer. Yes, this can be a complex topic, but let's try to focus on keeping it simple. The whole idea is to make CMUD work more naturally than zMUD when it comes to variable types and expansion vs evaluation. |
|
|
|
Tarn GURU
Joined: 10 Oct 2000 Posts: 873 Location: USA
|
Posted: Wed Apr 12, 2006 6:42 pm |
Zugg wrote: |
I hope this makes things clearer. Yes, this can be a complex topic, but let's try to focus on keeping it simple. The whole idea is to make CMUD work more naturally than zMUD when it comes to variable types and expansion vs evaluation. |
I'm not trying to complicate the feature, just to get a complete explanation of it.
Your explanation makes it clear that there will be type coercion (where only a number makes sense, convert to a number) and operators dependent on types (+ means add for numbers, and concatenate for strings).
I get the basic idea now, but some further documentation will be necessary for things like details of type coercion and the circumstances under which an operator like "+" is just another string character and when it's an operator.
-Tarn |
|
|
|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Wed Apr 12, 2006 8:20 pm |
In general, something like + (or () or {} or any other "special" character) is only a string when it is surrounded by double-quotes. That's a good rule of thumb that will keep you from getting into trouble.
However, with that said we probably need to talk about "implied concat" which has always been one of the trickiest things in zMUD, and which CMUD still handles.
"Implied Concat" is the concatenation of strings without using the explicit %concat function and often without even using quotes. This has been a "feature" in zMUD since the beginning and continues to be implemented in CMUD even though it can be tricky sometimes.
Implied Concat happens only when zMUD/CMUD is in string expansion mode. So, refering to the previous post, if the argument for a command is "string" or if you set the VARTYPE of a variable to "string (expansion)" then you are enabling Implied Concat.
Here is an example of Implied Concat:
Code: |
hp=100
maxhp=500
#SHOW {: @hp : @maxhp :} |
This displays:
: 100 : 500 :
and is equivalent to the more formal %concat(": ",@hp," : ",@maxhp," :") explicit function call.
A good way to think about this is that {} is just like " quotes except that it allows the expansion of variables and functions. This means that spaces within {} should be preserved.
Implied Concat also happens when you are using indirect variable expansion using the @{} syntax. For example:
would display: 100hp and is the same as the explicit %concat(@hp,"hp") code. Double quotes are optional. You get the same results with #SHOW @hp"hp"
So, in general, Implied Concat happens within the {} delimeters. So putting a + character within {} causes it to get parsed as a string, and not an operator, just as if it was within " quotes. The + is only an operator when you are parsing an *expression*
As I mentioned in the previous post, it's important to look at the F1 help for a command or function to see if an argument is a "string" or an "expression". You can force expression parsing by putting the expression within () parenthesis. So the + within parenthesis is going to get treated as an operator.
For example, if you look at the F1 help for #MATH you will see that the second argument is an expression. So, the code:
obviously treats the + as an operator even without parenthesis and assigns the number 101 to @a. However, if you put {} around it, then you are changing the mode from expression mode to string mode. So in #MATH a {@hp+1} you are now assigning the *string* "100+1" to the @a variable.
In a way, the choice of delimeter is acting as a "cast" to determine the parsing mode. The () forces expression evaluation mode, the {} forces string expansion mode, and the "" forces string literal mode. If you omit any delimeter, then the parsing mode is determined by the F1 help for the command argument.
Btw, remember that this discussion is about CMUD. Things in zMUD don't work quite this way and are more inconsistent. In zMUD you have the [] for immediate evaluation, and the <> for immediate expansion. Those "modes" are going away in CMUD. They were confusing and hard to parse and they really make compiling difficult. |
|
|
|
Tarn GURU
Joined: 10 Oct 2000 Posts: 873 Location: USA
|
Posted: Wed Apr 12, 2006 8:47 pm |
Zugg wrote: |
SNIP good stuff
|
Thanks.
Quote: |
In general, something like + (or () or {} or any other "special" character) is only a string when it is surrounded by double-quotes. That's a good rule of thumb that will keep you from getting into trouble.
|
Good, I was trying to figure out if things like + were to be special characters that were always operators, or only sometimes (within an expression declared by something like parentheses). I saw your answer, thanks.
Quote: |
So in #MATH a {@hp+1} you are now assigning the *string* "100+1" to the @a variable.
|
Hmm, so then the #MATH command might not always assign a numerical value? Or, if 'a' is of numerical type, does it force the evaluation during the actual assignment?
Quote: |
Btw, remember that this discussion is about CMUD. Things in zMUD don't work quite this way and are more inconsistent.
|
Cleanup is good.
-Tarn |
|
|
|
Sir1l Wanderer
Joined: 01 Oct 2005 Posts: 54
|
Posted: Thu Jul 20, 2006 6:11 pm |
Do these type of variables not work anymore with cmud?
Using 1.03 ATM
Like #TR {%1 MANA %2 HP %3} {%1.mana=%2} |
|
|
|
Guinn Wizard
Joined: 03 Mar 2001 Posts: 1127 Location: London
|
Posted: Thu Jul 20, 2006 6:42 pm |
I don't think that's correct syntax for CMUD or zMUD, though may have worked in zMUD
Assuming they're numbers you're trying to capture, what you should have is
#TR {(%d) MANA (%d) HP (%d)} {%1.mana=%2} |
|
_________________ CMUD Pro, Windows Vista x64
Core2 Q6600, 4GB RAM, GeForce 8800GT
Because you need it for text... ;) |
|
|
|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Thu Jul 20, 2006 10:38 pm |
It's the %1.mana that doesn't work yet in CMUD.
|
|
|
|
|
|
|
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
|
|