PDA

View Full Version : A modest proposal...


sparaig
11-04-2006, 06:00 PM
How many people HATE the lack of local variables in MEL? I can understand there are a few issues to implement them due to legacy code and so on, but it is a royal pain not having them.

My suggestion is to implement a key word "local" that means that a variable prepended by "local" implies that it exists globally but can only be accessed by procedures found in the same script file. Maybe anywhere else, "computername_filepath_filename_" has to be prepended to the variable name in order to use it or something, but inside the script files, using "local $name" is enough to reference it properly ...

In other words, within the Maya script editor, "local" works just like the "global" keyword but INSIDE a script file, ONLY procedures inside the file know about it, at least practically speaking:

local int $myLocalInt;

global proc setMyLocalInt(int $myInt)
{
local $myLocalInt;
$myLocalInt = $myInt;
}


global proc int getMyLocalInt()
{
local $myInt;
return $myInt
}



This would make MEL programming a heck of a lot simpler, and might not be all that difficult to implement...

...or maybe it would. /shrug.

Buexe
11-05-2006, 12:42 AM
As far as I understand MEL the variables are always local unless you declare them global. Are you having problems with variables that have the same name? Could you please give a concrete example of what you criticize?
thanks buexe

sparaig
11-05-2006, 03:29 AM
As far as I understand MEL the variables are always local unless you declare them global. Are you having problems with variables that have the same name? Could you please give a concrete example of what you criticize?
thanks buexe


how does one do this within a script file without making $myScriptInt visible to all users by declaring it global? In virtually every other computer language in existence, the language doesn't require you to come up with strange names to prevent accidental use of a specialized variable with a conveniently simple name:


-------------this is a file start------------

int $myScriptInt;

global proc setMyInt(int $myInt)
{
$myScriptInt = $myInt;
}

-------------this is a file end------------

grantimus
11-05-2006, 08:49 AM
you could try this:


{

int $myScriptInt;

global proc setMyInt(int $myInt)
{
$myScriptInt = $myInt;
}

}


I don't know if it will work, I'll mess with it a bit tomorrow.

I understand why this might be a problem, but is it really that much trouble to come up with a naming convention for your global variables? I don't know, maybe you use global variables a lot more than I do.

sunit
11-05-2006, 09:31 AM
not sure what you're trying to do, but if you want to create a variable that's exposed to other procedures in your script, why not instead create a local proc that returns your value.

proc int myScriptInt(){return 1;}

then you can:

global proc myScript()
{
int $myScriptInt = myScriptInt();
}

or use it in a command:

global proc myScript()
{
polyCube -w (myScriptInt());
}

again, i'm not sure what you want to do with this variable, but there're different ways to deal with scoping problems in mel.

-sunit

sparaig
11-05-2006, 09:55 PM
you could try this:


{

int $myScriptInt;

global proc setMyInt(int $myInt)
{
$myScriptInt = $myInt;
}

}


I don't know if it will work, I'll mess with it a bit tomorrow.

I understand why this might be a problem, but is it really that much trouble to come up with a naming convention for your global variables? I don't know, maybe you use global variables a lot more than I do.

Naming conventions are a legacy of bad/primitive language design. Names should reflect the needs of the programmer, not the language writer. I'm an old OOPer myself, where names are everything.

sparaig
11-05-2006, 10:06 PM
not sure what you're trying to do, but if you want to create a variable that's exposed to other procedures in your script, why not instead create a local proc that returns your value.

proc int myScriptInt(){return 1;}

then you can:

global proc myScript()
{
int $myScriptInt = myScriptInt();
}

or use it in a command:

global proc myScript()
{
polyCube -w (myScriptInt());
}

again, i'm not sure what you want to do with this variable, but there're different ways to deal with scoping problems in mel.

-sunit

OK, consider the code I just wrote to allow a notification whenever an object was selected and rotated: I chose a joke name for the global var, but what if wanted to write two different scriptjobs usingthe same format? One for rotations, and one for notifications of some other kind? How many different global vars must I come up with? Why do I have to use ANY for this situation? $scriptJobNum should be local to the script and all I should need to change is the attribute that I want to monitor.



global int $giveuslocalscriptvarsdammitScriptJobNum;

global proc itRotated()
{
string $theSelected[] = `ls -selection`;
print ("by golly " + $theSelected[0] + "rotated!\n");
}

global proc monitorRotation()
{
global int $giveuslocalscriptvarsdammitScriptJobNum;

string $theSelected[] = `ls -selection`;
if($theSelected[0] != "")
{

$cmd = $theSelected[0] + ".rotate";
if ( $giveuslocalscriptvarsdammitScriptJobNum>0)
scriptJob -kill $giveuslocalscriptvarsdammitScriptJobNum -force;
$giveuslocalscriptvarsdammitScriptJobNum = `scriptJob -attributeChange $cmd itRotated -protected`;
}
}

int $jobNum = `scriptJob -e "SelectionChanged" monitorRotation -protected`;

sunit
11-05-2006, 10:36 PM
well, if MEL scripts contained application data, then your request would make sense - as it is, MEL is just an entry into maya's application data. a MEL script doesn't run persistently while you're using maya, it's just a set of functions to access data that exists exclusively in maya, not in your script.

you could, of course, create markers in maya to keep track of the changes you've made. global variables are one way - you can also do things like create nodes with custom attrs that track things like scriptJob ids. or write out a text file.

you can also iterate through the existing scriptjobs until you find yours.

just some ways to interact with maya's data model.
-sunit

grantimus
11-05-2006, 11:10 PM
Naming conventions are a legacy of bad/primitive language design. Names should reflect the needs of the programmer, not the language writer. I'm an old OOPer myself, where names are everything.

You're kidding yourself if you think naming conventions aren't important in object oriented programming. Or any kind of programming for that matter.

I agree that MEL should reflect the needs of the programmer. But the fact is no programming, or scripting, language is perfect. At some point you're going to have to change the way you approach things to fit the language you are using yeah this can be a pain in the @$$ I know.

I'm not saying your arguments have no merit, and I understand the point you're trying to make. But I do think you're making a big deal out of somehting that shouldn't be a big deal. Definatly an inconvient deal though.

sparaig
11-05-2006, 11:11 PM
well, if MEL scripts contained application data, then your request would make sense - as it is, MEL is just an entry into maya's application data. a MEL script doesn't run persistently while you're using maya, it's just a set of functions to access data that exists exclusively in maya, not in your script.


-sunit


Ahhhh.... I understand. Still inconvenient though, especially for the larger scripts like plug-ins and having to rename global vars every time a simple script might be reused is a pain. My original suggestion still makes sense: the MEL interpreter could prepend the $computer_name+$directory+$scriptfile to the "scriptVar" variable and resolve that as needed behind the scenes. That way, you don't have to keep coming up with new global names for things like "$myScriptJobNum" or "$windowCounter" or "$loopCounter" and so on. I mean, I use all sorts of tiny scripts. If I make them large and robust enough, they go into a separate file for constant reuse, but then I have to remember to rename everything by hand. Ick.

sunit
11-05-2006, 11:36 PM
i'm still not sure why you're using lots of global vars. why not, for example, just make a function that finds the specified scriptJob out of the existing ones? that's relatively trivial to do.

you can also do wonders with local procs - it doesn't beat namespaces and classes, but you can mimic some of the functionality by creating entry global procs that call local ones. by declaring (not defining) all of your local procs at the top of your script, you can also extend access to anywhere within your script.

this way, if you're copying functions across scripts, there's no need to rename anything.

i find i don't need that many global vars - off the top of my head, they're useful for a couple of things: 1) setting debug levels, 2) keeping session persistent UI settings, and 3) keeping information for scripts/expressions that deal with large data sets, where you constantly need to access the data across the data set. i have yet to find other reasons...

-sunit

sparaig
11-06-2006, 05:44 AM
You're kidding yourself if you think naming conventions aren't important in object oriented programming. Or any kind of programming for that matter.


I didn't mean naming conventions per se. I meant the requirement to keep track of YOUR global variables vs someone else's when there's no need (in other languages) to make it a global variable in the first place. It needs to be accessable to a few dozen procs in a single script file. Certainly, you can work around it, but the more workarounds you need to do, the less work you end up doing.


I agree that MEL should reflect the needs of the programmer. But the fact is no programming, or scripting, language is perfect. At some point you're going to have to change the way you approach things to fit the language you are using yeah this can be a pain in the @$$ I know.

I'm not saying your arguments have no merit, and I understand the point you're trying to make. But I do think you're making a big deal out of somehting that shouldn't be a big deal. Definatly an inconvient deal though.


It WAS a "modest proposal" afterall, and while I don't like it, this is the first thread I've started that discusses it IIRC, so I'm not sure where you're getting the impression that I'm making a big deal out of it.

And the solution I proposed is simple: just automate a name-convention for "local" variables based on teh computer name, file directory and file name so that the vars exist as globals but any procedure defined in the same file as the local variable only needs to use the short form of the variable name. Doesn't require creating new aspects of MEL design and only requires a single keyword addition: local.

As far as I can tell, it doesn't change anything else about MEL or anyone's programming habits (unless they already have a naming convention of calling their global vars $computername_directorypathname_scriptfilename_variable_name...).

faultymoose
11-06-2006, 06:01 AM
I'm with the OP. While I've not yet run into any issues with conflicting variables, there IS always the slight concern that my scripts might be trying to access the same global variable currently occupied by another script.

I tend to do my absolute best to avoid using global variables all together, but sometimes they're simply a necessity. When that's the case, I throw a "faultymoose" in front of the variable. I'm fairly certain no one else will be using it. An inconvenience, yes. A disaster, no. But it WOULD be nice if there was a convenient solution.

sparaig
11-07-2006, 02:00 AM
I'm with the OP. While I've not yet run into any issues with conflicting variables, there IS always the slight concern that my scripts might be trying to access the same global variable currently occupied by another script.

I tend to do my absolute best to avoid using global variables all together, but sometimes they're simply a necessity. When that's the case, I throw a "faultymoose" in front of the variable. I'm fairly certain no one else will be using it. An inconvenience, yes. A disaster, no. But it WOULD be nice if there was a convenient solution.

I think where it would REALLY come in handy is MEL-based plugins and Maya's own internal scripts. If you look at those, they are quite a bit more complicated than they need to be because globals are avoided whenever possible. If a script-local variable was available, you could have script-wide storage of important information without worrying about whether or not names were duplicated. That would make high-end MEL programming a lot more like regular programming, so the algorithms found in text books could be converted without major design-changes.

Buexe
11-07-2006, 09:09 AM
I have written megabytes of MEL scripts and use global variables on a regular basis. Different production companies use those tools and I have never had a double-name problem. BTW the same argument could be used for optionVars, there is also the chance of some other script overwriting those.
And what are MEL-based plug-ins?

sparaig
11-08-2006, 01:32 AM
I have written megabytes of MEL scripts and use global variables on a regular basis. Different production companies use those tools and I have never had a double-name problem. BTW the same argument could be used for optionVars, there is also the chance of some other script overwriting those.
And what are MEL-based plug-ins?


scripts that are loaded at the start of Maya execution by putting the name of the script in the usersetup.mel file.

And I'm talking about multiple scripts written by the same individual. The template I provided for monitoring attributes via a scriptJob could use the same local script var so you wouldn't have to come up with unique names for common uses, like $scriptJobNum.

This is basic computer language design.

Robert Bateman
11-08-2006, 02:08 AM
there's no need for global vars in mel whatsoever. You can store temporary variables in a random node you create within a DG (which has the advantage of being persistable in files if needed, and changes can be undone to that data which does make things a little bit more useful when developing more comples tools). Alternatively you can use optionVar to persist user preferences (for GUI's or command options). Passing args to funcs does actually work, and it does tend to leave your code free from globals (which makes it more re-usable in the long run).

It's worth remembering that mel is only really a journalling service for Maya's undo mechanism. As such language features such as structs don't exist, so any form of data storage in mel is not really a good idea.

If you really need to, you can store global vars on a per-file basis within a scriptNode, however they will persist after the node has executed - so that still kinda sucks.

Most of the time the reason people feel the need for some global or other, is simply to get a variable from a GUI object (ie, the global is the mel widget name). Typically that's not actually needed if you use the hash type command callbacks (ie, -cc "myCallback(#1)"), or take a bit more care constructing your callback strings to recieve the name of gui items within the string.

Naming conventions are a legacy of bad/primitive language design. Names should reflect the needs of the programmer, not the language writer. I'm an old OOPer myself, where names are everything.

I'd agree 100% if we were talking about C++ of C# since they have the ability to scope variable names within classes & namespaces. In mel, you really do need to prefix that var with something to identify it as yours, ie your name initials etc.

The template I provided for monitoring attributes via a scriptJob could use the same local script var so you wouldn't have to come up with unique names for common uses, like $scriptJobNum.

however, using scriptjobs to monitor attribute changes is exceptionally slow, and really is a *very* bad idea....

sparaig
11-08-2006, 04:35 AM
however, using scriptjobs to monitor attribute changes is exceptionally slow, and really is a *very* bad idea....

I wouldn't doubt it. It seemed the only way automate what the guy wanted, however.

HapG
11-10-2006, 05:54 PM
In other words, within the Maya script editor, "local" works just like the "global" keyword but INSIDE a script file, ONLY procedures inside the file know about it, at least practically speaking:

I think your original issue is that any variable declared in maya's SCRIPT EDITOR will be persistent (global) for that maya session. Variables decared in a procedure are not global or persistent unless they are declared as global.

I occasionally get invalid re-declaration errors using the script editor, but a restart of maya will solve that.

sparaig
11-11-2006, 10:13 PM
I think your original issue is that any variable declared in maya's SCRIPT EDITOR will be persistent (global) for that maya session. Variables decared in a procedure are not global or persistent unless they are declared as global.

I occasionally get invalid re-declaration errors using the script editor, but a restart of maya will solve that.

Sorta. What I would like to see is a way of allowing persitance of variables declared at the outer block level of a script file. The "local" keyword would allow access from procedures declared in that file (as long as they used the local keyword to declare a variable inside the procedure) but you wouldn't have any possible name-stomping issues from other variables declared global or declared local in other script files.

in other words this use of the variable name:

in file1:

local string $tempString;
global proc procedure1()
{
local string $tempString
//...
}


isn't the same as this:

in file2:

local string $tempString;
global proc procedure2()
{
local string $tempString
//...
}


even though both are persistant. It just makes for cleaner and simpler code design, IMHO.

CGTalk Moderation
11-11-2006, 10:13 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.