MXS: struct definition, local variables, declaration order etc...


#1

Currently i try to enforce some stricter coding style ( class like encapsulating in structs , usage of public/private etc…). But now i come to a simple curiosity

let’s asume the following, hypothetical struct definition:

struct Test
(
	varA=5,
	function print1=( print varA ),
        varA=10,
	function print2=( print varA )
)

so now when i create an instance of struct Test and call the functions, i get this output

t=Test()  -- create an instance
t.varA   -- puts out: 10 , as expected

t.print1()     --  prints: 5 ???

t.print2()     -- this prints the expected value:  10 

Why the hell does print1() not print the currently set value ? Is this really depening on the order of variable definition ? To my understanding, print1() should do as its function body tells it to do, print the current value of variable varA, which it apparently does not

any hints or insights ?

PS:
this is maybe the relevant part in the help docs, but honestly, i can’t see this to be a reason for the above behavior…

Local functions defined in structures are not stored in every instance of the structure. The local function is stored once in the structure definition and references to them in the instances refer to their definitions in the structure definition.


#2

BTW:
the following code works as expected

struct Test
(
	varA=5,
	function f1=( print varA ),
	function f2=( a=10 )
)

after calling f2(), f1() prints the correct value of varA ( 10 )

i think it has something to with the fact that in the first posted struct example, the line “varA=10,” is an assignment and no declaration like varA=5, in the first line. Maybe it’s even not allowed to make assignments to existing variables in this part of a struct definition, but in that case the maxscript parser should spit out a syntax error IMHO

Nevertheless: why this assignment is working for print2() but not for print1() still is a curiosity for me.

I would really be happy if someone ( maybe Bobo ) could explain the whole thing, as i find it quite puzzling :wink:


#3

I think the real problem here is that maxscript doesn’t smack you upside the head for declaring the same member twice, and let’s you successfully compile a cluster**** of a struct.

Notice the output you get when creating an instance of the struct:

t = test()
--Output: (Test 5 varA:10)

Notice that it creates the struct with two data members, meaning the first varA was not overwritten, only its name was stripped!
When print1 was evaluated, varA still pointed to the first declaration, so the function will still point to the now anonymous(?) data member.
When print2 is evaluated, varA already points to the new delcaration.

Another confirmation of this is that if you create an instance with specific parameters, the value of the anonymous member changes:


t = test 2 3
--Output: (Test 2 varA:3)


#4

Thanks for confirming that i’m not insane :wink:

I noticed the same, but only in Max versions prior Max 2010, which version did you test ?
In Max 2010+ i do not get the nameless leftover output, but that one instead

t=test()
(test varA:10)

Seems the maxscript changes with Max 2010 simply hide that awful internal, but still produces the same junk internally


#5

You’re right, I checked in 2009.

I guess you can’t ‘fix’ 300 bugs every release without sweeping some dirt under the carpet :wink:


#6

Okay - and this is exact the thing that has bitten me in the current project and why i startet to investigate the above problem. if i precede “varA” in Print1() with “this” (“this.varA” ) , it works correctly and spits out “10”

so indeed: the method above just “clusterf*s” the whole struct…


#7

Out of curiosity, what is the output from

t = test 2 3

in 2010+?


#8
(test varA:3)

print1() outputs 2
print2() outputs 3


#9

Brilliant, so it’s all the same except the ‘as string’ representation of the struct. :shrug:


#10

Just a small update:

Larry Minton ( Autodesk) confirmed this being a problem and agrees that this kind of double declarations using the same membername inside of a struct should throw a compile time error.

Technically it has something to do with the way members are stored in a struct:
they are stored in a hashtable which loses track of the first definition after the same name gets declared a second time (or something in that way :wink: )

Anyways, let’s hope this will get a fix (compiler error),
in the meantime i have to wade through all my code and search for the baddies


#11

Interesting, although declaring duplicated variables should always be a no no !!


#12

Yeah ,essentialy the solution to this will/should be the maxscript parser/compiler throwing an error, according to Larry
Initially, considering the lax typechecking of Maxscript, i would assume a redeclaration/redefinition in that example above, but i’m fine with maxscript throwing an error too:-)


#13

i prefer to get a warning message only with optional popup.
for me it doesn’t look like an error. it’s kinda a feature that i don’t know how to use yet :slight_smile:


#14

Just a word of warning to all maxscripters:

In Max 2014, multiple struct member variable declaration of the same name will throw a compile error. This is true for standard variables. The behaviour for MXS function variables inside structs has not changed, to still allow the pseudo forward declaration many scripters got used too…

So the following will throw an compile time error in Max 2014 (worked in previous Max versions):

struct TestA
(
	member1,
	anotherMember,
	member1=10      -- now causes an compile error to be thrown
)

while the following will still work ( thanks god )

struct TestB
(
	-- pseudo forward declaration for F1()
	function F1=(),
	member1,
	
	function DependsOnF1=
	(
		-- we can only use F1() here because of our "forward declaration" above
		F1()	
	),	

	--essentially a second time we declare F1(), but that's still allowed
	function F1=      
	(
		print member1	
	)
)

#15

Josef… you mention using “this” (like this.varA) . How far back is this compatible. I used this when I first starting MAXScript in a struct for a while (as it’s how I’m used to programming in other languages) but got a bunch of emails from people who had MAXScript exceptions when I used that. I had to update the code to never use this.property (though for whatever versions of Max I was testing it always worked).

How commonly does anyone here use this ?


#16

i use this a lot. it was added to structure system about 10 years ago. max 8???


#17

I think you’re wrong. Doesn’t work on max 2009. It’s either 2010 or 2011. Perhaps you mean this in the context of a controller, which was max8 I think.


#18

really? max 2010 has it.


#19

I am pretty sure that when I started writing MAXScript, I was using either 3ds Max 2010 or 2011. All was fine in a certain script until I changed to using this.whatever in a game exporter I work on, and a bunch of users sent complaints … so I had assumed at the time that this was only recently added. So I’ve avoided it since.


#20

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.