Notifications
Clear all

[Closed] Trying to 'overload' function within struct

I am trying to use MAXScript structs as a poor man’s substitute for object oriented programming, but I fail to find a good way to overload functions. Basically, I want to define a struct and then create several instances of it, each one having a different implementation of the same function.

Here’s a toy example which does not work but hopefully shows what I am trying to do:

struct myStruct (
    val,
    tmp,
    printMyVal = fn tmp = ( format "my value is %
" val)
)
q = myStruct()
q.printMyVal()

The last line produces and error: “Struct member access requires instance: val” and I don’t understand why the function inside the struct cannot see the struct members?

If I replace the last line of the struct in the example above with this

printMyVal = fn tmp = ( format "my value is %
" myStruct.val)

the error I get is “Unknown property: “val” in #Struct:myStruct” – even though there IS a property ‘val’ in that struct, as you can check by using

hasProperty myStruct "val"

.

Any ideas?

Thanks!
– MartinB

34 Replies
struct myStruct (
    val,
    fn printMyVal = ( format "my value is %
" val),
    fn dosomethingelse = (print "jo"),

    fn executemyfn = dosomethingelse()
)
q = myStruct()
q.executemyfn()

I’m not sure if this is what you’re trying to achive…

Well, I want the function to be able to access the struct variable (val in the example).
While in your example ‘printMyVal’ can do this, I cannot change printMyVal later on.

Having defined the struct with a function that can access a struct member, I also would like to redefine the function of a specific instance of the struct later on (and the new function also needs access to the struct members). Therefore I was storing the function in a struct member variable in my original example, so I could reassign the variable to a new function.

Eventually I want to create a basic struct that has all the variables and functions I need. I create an instance of that struct as normal. But then later I want to ‘derive’ from that struct to create a new instance that has a redefined function with the same name.

Here’s some toy code to better explain what I am after:

struct myStruct (
    val,
    fn printMyVal = ( format "my value is %
" val)
)
q = myStruct()
q.val = 123
q.printMyVal()
-- the above works just fine, no problem...

-- ... but this below does not:
a = myStruct()
a.val = Sphere()
a.printMyVal = fn tmp = ( format "my radius is %
" val.radius )

I seem to be missing something about the variable scope when defining functions in a struct but fail to see what…

Maybe this helps you:

clearlistener()

struct myStruct
(
    val,
	printMyVal,
	
	fn setoriginalfunction = 
	(
		printMyVal = (fn tmp = (format "Original Function:%
" a.val))
	),
	
	initialized = setoriginalfunction()
)

a = myStruct()
a.val = 50

a.printMyVal()

a.printMyVal = (fn tmp = (format "replaced Function:%
" a.val))
a.printMyVal()
	
a.printMyVal = (fn tmp = (format "Replaced Function 2nd time:%" a.val))
a.printMyVal()

This is how you can replace functions inside structs.

edit: i just realized a problem in the contructor to create the original function. It’s not possible to assign a.val if you run it for the first time. So my way would be like this:

clearlistener()

struct myStruct
(
	val,
	printMyVal
)

a = myStruct()
a.val = 50
a.printMyVal = (fn tmp = (format "Original Function:%
" a.val))

a.printMyVal()

a.printMyVal = (fn tmp = (format "replaced Function:%
" a.val))
a.printMyVal()
	
a.printMyVal = (fn tmp = (format "Replaced Function 2nd time:%" a.val))
a.printMyVal()

edit2: Okay, i think now i understand the problem behind this…
I don’t know if there is way for proper self referencing, maybe the masters here can help out. I would be interested in this, too.

edit3: maybe this points to the right direction: http://forums.cgsociety.org/showthread.php?t=272425

I may mis-understand something but the following is an example of a “baseclass” like struct and a “subclass” like struct where the subclass-struct extends the base class’s functionality ( in this case the base class prints the node’s name, the subclass calls the base class’s delegate and prints the radius ( if the property exists )
This way you can generate various subclass structs for specific purposes

struct DelegateBase
(
	public
	DelegateFunc = undefined,
	exampleMember = "This is some string in the base class",

	private	
	function InternalDelegate = (),-- forward declaration
		
	on create do
	(
		DelegateFunc = InternalDelegate
	),

	
	function InternalDelegate val=
	(
		if( isValidNode val ) do 
			format "Node Name: %
" val.name
	)	
)

struct DelegateSub
(
	private 
	base = DelegateBase(),
	
	public 	
	function DelegateFunc val =
	(
		base.DelegateFunc( val )
		if( hasproperty val #radius ) do 
			format "Radius: %
" val.radius
		
		-- you have access to base struct member too
		format "%
" base.exampleMember
	)
)

To Test:
mySubInstance = DelegateSub()
mySubInstance.delegateFunc( Sphere() )
— output is:
— Node Name: Sphere001
— Radius: 25.0
— This is some string in the base class

On the other hand you could simply skip all the inheritance stuff and only have the base delegate struct ( DelegateBase ) and create instances from it. Than you can reassign the instance’s “DelegateFunc()” to any other function you like

For example ( using the above DelegateBase struct definition only )

-- declare/define some function i want to assign to the instance function delegate 
[B]function DumpVtxCount val= 
(
	format "# of Vertices: %
" ( try  (getNumVerts val.mesh ) catch( -1 ) )
)
[/B]
-- create a instance of my delegate struct
[B]myInstance = DelegateBase()[/B]

--assign above's function as delegate
[B]myInstance.delegateFunc = DumpVtxCount[/B]

-- call the delegate
[B]myInstance.delegateFunc( Sphere() )[/B]

-- output : # of Vertices: 114
-- other instances still have the original base struct's  delegateFunction
[B]myInstance2 = DelegateBase()
myInstance2.delegateFunc( Sphere() )[/B]

--output: Node Name: Sphere002

1 Reply
(@martinb)
Joined: 11 months ago

Posts: 0

I need to spend a little more time with the code but this looks pretty close to what I have in mind! The only thing missing is the use of an additional internal variable, defined in struct DelegateBase, by the two delegateFunc() functions.

wait a little. all solutions look too complicated. am i missing something? do we need some sort ‘virtual’ function in a struct?

This seems to work:

(
	struct myStruct
	(
		PrintMyVal,
		on create do PrintMyVal = (fn PrintMyVal = print "Master Function")
	)
	
	a = myStruct()
	
	b = myStruct()
	b.PrintMyVal = (fn PrintMyVal val = print val)
	
	c = myStruct()
	c.PrintMyVal = (fn PrintMyVal val:0 t:1 = format "val:%	t:%
" val t)
	
	a.PrintMyVal()
	b.PrintMyVal 55
	c.PrintMyVal val:200 t:30
)
2 Replies
(@martinb)
Joined: 11 months ago

Posts: 0

Almost – if you now can add another variable to your struct AND access that variable from within the different PrintMyVal functions then you have solved my problem…

(@polytools3d)
Joined: 11 months ago

Posts: 0

One way could be like this:

(
	struct myStruct
	(
		myVar = 0,
		PrintMyVal,
		on create do PrintMyVal = (fn PrintMyVal = print "Source")
	)
	
	a = myStruct()
	
	b = myStruct()
	b.PrintMyVal = (fn PrintMyVal val: ref:b = print (ref.myVar * val))
		
	c = myStruct()
	c.PrintMyVal = (fn PrintMyVal val: ref:c = print (ref.myVar * val))
	
	d = myStruct()
	d.PrintMyVal = (fn PrintMyVal val: ref:d = print (ref.myVar * val))
	
	a.PrintMyVal()
	
	b.myVar = 3
	b.PrintMyVal val:2
		
	c.myVar = 5
	c.PrintMyVal val:4
		
	d.myVar = 7
	d.PrintMyVal val:6
)

well… the task is surprisingly interesting. let’s issue a challenge.

there is a structure which has three variables for sure – A,B,C, and one variable used to specify an action – F. the structure has to be designed to execute an action defined by user using A and B and make a result in C.

the pseudo code is:

struct VirtualStruct
(
    A, B, -- input
    C, -- output
    F, -- action function
    ... -- everything you need to make it works
) 

fn userAction = (...)
s = VirtualStruct A:1 B:2
s.F = userAction
... -- do something with s
s.C == F(A, B)

To make the puzzle complete, you should add

“F, – action function that does something with A and B”

and

“s.F = userAction – some custom function that does something with A and B”

Being able to access the member variables of the struct from a modified function is the main challenge – without passing the struct as an argument, that is. If you simply pass the struct instance to the function (‘s.F arg1 s’ in your pseudo code) then it’s easy, but also highly redundant.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

it’s not a puzzle for me. i know a solution. when i show it all will say: “Sure, it’s so simple”

no… you pass the reference to the structure with your custom function. it’s too simple. and the custom function has to know that some specific variable exists.

1 Reply
(@polytools3d)
Joined: 11 months ago

Posts: 0

I thought it was too complex so here is a simpler version:

(
	struct myStruct
	(
		myVar = 0,
		PrintMyVal,
		on create do PrintMyVal = (fn PrintMyVal = print "Source")
	)
	
	a = myStruct()
	
	b = myStruct()
	b.PrintMyVal = (fn PrintMyVal val: = print (b.myVar * val))
		
	c = myStruct()
	c.PrintMyVal = (fn PrintMyVal val: = print (c.myVar * val))
	
	d = myStruct()
	d.PrintMyVal = (fn PrintMyVal val: = print (d.myVar * val))
	
	a.PrintMyVal()
	
	b.myVar = 3
	b.PrintMyVal val:2
		
	c.myVar = 5
	c.PrintMyVal val:4
		
	d.myVar = 7
	d.PrintMyVal val:6
)
Page 1 / 2