Help with structs in Max

Hey all,
I am still trying to wrap my head around structs in Max, but am having trouble. In Python you can use a dictionary to store multiple arrays. My thinking was that structs do something similar, but it seems they behave more like classes. I suppose my question here is two fold.
First I want a mechanism by which I can store multiple arrays at a top level so that one function can gather a bunch of data and another function can retrieve that data to be used for some purpose.
Second, I would like a better understanding of what structs are and how to use them. I found the Max documentation to be lacking in examples that pertain to the type of thing I want to do, and I am not much of a programmer by nature.

In the following code, I am using the script Randall Hess wrote for my benefit as a launching point. With this code I can find the name and transform of all my biped objects. The idea would be to store the name and transform of each object so I can use that information in fn load_bone_data. It would seem that I am collecting the information I need into the struct bone_info, but that data is no longer available when I call load_bone_data and I get a return of undefined. Pardon my noobishness, but I really want to understand these core Maxscript concepts.

struct bone_info (bone_name, parent_name, bone_xform)

-- recursive function to get biped children objects
fn get_bip_children bip_obj bone_data =
(	
	
	-- make sure the current biped object has children
	if (bip_obj.children != undefined) do (
		
		-- loop through all of the current bone's children
		for child in bip_obj.children do (
			
			-- ignore these biped objects
			match_footsteps = matchpattern child.name pattern:"*footsteps"
			match_nubs = matchpattern child.name pattern:"*nub"
			
			-- do not add certain objects as bones, this is a preference
			if (not match_footsteps) and (not match_nubs) do (			
			
				-- create an object for the current child bone
				tm = child.transform
				childTransform = translate(tm.rotation as matrix3)tm.pos
				
				new_bone = bone_info child.name bip_obj.name childTransform			
				
				-- update the bone_data array with the current child
				append bone_data new_bone
				
				-- see if the current child has and children
				if (child.children != undefined) do (
					get_bip_children child bone_data
				)
			)
			
		)	
	)
	
	return bone_data
)



fn create_skeleton bip prefix =
(
	-- get the biped root node
	bip_root = bip.controller.rootnode
	
	local bone_data = #()

	-- create an object for the root bone.  Add to struct
	tm = bip_root.transform
	rootTransform = translate(tm.rotation as matrix3)tm.pos
	root_bone = bone_info bip_root.name rootTransform
	append bone_data root_bone	
	
	-- get bone data (names and hierarchy) from the biped
	bone_data = get_bip_children bip_root bone_data
	
	
	#(bone_data)
)



fn main_function=
(
	if (selection.count == 1) and (classof selection[1] == Biped_Object) then (
		-- create the skeleton with a new prefix
		bindBones = create_skeleton selection[1] "Bone"

	) else (
		messageBox "Select a single biped node" title:"Create Skeleton"
	)
)


fn load_bone_info = 
(
	boneInfo = bone_info()
	a = boneInfo.bone_name
	print a
)


main_function()

load_bone_info()


In your load_bone_info() function you have the following statement:

boneInfo = bone_info()

After that you’re trying to query one of the properties of boneInfo, expecting to get back data that you have put in the struct previously. The problem is that what you are doing is creating an instance of bone_info named boneInfo. That instance, since it is newly constructed from the struct definition, has no data in it.

Also, in create_skeleton() you are creating an array called bone_data, appending information to it, and then changing the value of that array based on the return value from get_bip_children(), which takes the bone_data array as an input parameter. It’s hard to follow what you want there since you are using an array as input into a function but then clobbering that same array with the return from the function.

But, given that main_function has a variable called bindBones, which I think is supposed to contain an array that has an array of bone_info structs (why the nested arrays?) all you need to do is pass bindBones back from main_function and send that in to load_info to query it for information. Like so:

( 
	struct bone_info (bone_name, parent_name, bone_xform)
	
	-- recursive function to get biped children objects
	fn get_bip_children bip_obj bone_data =
	(	
		
		-- make sure the current biped object has children
		if (bip_obj.children != undefined) do (
			
			-- loop through all of the current bone's children
			for child in bip_obj.children do (
				
				-- ignore these biped objects
				match_footsteps = matchpattern child.name pattern:"*footsteps"
				match_nubs = matchpattern child.name pattern:"*nub"
				
				-- do not add certain objects as bones, this is a preference
				if (not match_footsteps) and (not match_nubs) do (			
				
					-- create an object for the current child bone
					tm = child.transform
					childTransform = translate(tm.rotation as matrix3)tm.pos
					
					new_bone = bone_info child.name bip_obj.name childTransform			
					
					-- update the bone_data array with the current child
					append bone_data new_bone
					
					-- see if the current child has and children
					if (child.children != undefined) do (
						get_bip_children child bone_data
					)
				)
				
			)	
		)
		
		return bone_data
	)
	
	
	
	fn create_skeleton bip prefix =
	(
		-- get the biped root node
		bip_root = bip.controller.rootnode
		
		local bone_data = #()
	
		-- create an object for the root bone.  Add to struct
		tm = bip_root.transform
		rootTransform = translate(tm.rotation as matrix3)tm.pos
		root_bone = bone_info bip_root.name rootTransform
		append bone_data root_bone	
		
		-- get bone data (names and hierarchy) from the biped
		bone_data = get_bip_children bip_root bone_data
		
		
		#(bone_data)
	)
	
	
	
	fn main_function =
	(
		local bindBones = #()
		
		if (selection.count == 1) and (classof selection[1] == Biped_Object) then (
			-- create the skeleton with a new prefix
			bindBones = create_skeleton selection[1] "Bone"
	
		) else (
			messageBox "Select a single biped node" title:"Create Skeleton"
		)
		
		return bindBones
	)
	
	
	fn load_bone_info bindBones = 
	(
		for bb in bindBones do (
			print (bb.bone_name as string)
		)
	)
	
	
	local bindBones = main_function()
		
	load_bone_info bindBones
)

As a further follow up. Consider the following regarding structs in MaxScript:

If the struct only contains functions you may access the struct definition directly, without having to create an instance of it.

If the struct contains member data (variables, arrays, other structs, etc…) then you have to create an instance from the struct definition before you can store values in those properties.