Notifications
Clear all

[Closed] Lambdas in Maxscript – First Attempt

Yes this Job solution goes more in the right direction.
I just don’t like the fact that i need to specify the action somewhere else and not directly where i assign it to a parameter (here when calling doAJob).
And for every Action a different job structure seems also not necessary

i just want to say that i don’t see what the MaxScript can get as an advantage with a “lambda” expression support…

1 Reply
(@enterfield)
Joined: 11 months ago

Posts: 0

Well my last solution (Generate5RandomNumbers) shows that I can define a function inside the paramters of
a function call, so maybe lambda expressions arent’t really what is missing, but the feature it needs is closure. The ability to access the outer local variables inside a inner function.

This feature would make maxscript a lot better for writing cleaner code.
I can write functions that are absolut independent of its outside world and let another function do the coordination of the data flow through those independet units.

and what is “lambda” expression doing you think?

struct incrementor 
(
	value = 0,
	inc = 1,
	fn doit = (value += inc) 			
)

fn lambdaInc incrementor inc_value: count:1 = 
(
	if inc_value != unsupplied do incrementor.inc = inc_value
	for k=1 to count do incrementor.doit() 
	incrementor.value
)	

lambdaInc (incrementor value:2.5) inc_value:0.1 count:4 


Found this solution now to be quiet close to what I want to do. Even the syntax is similar.

Only downside there is no closure so i can only excess global variables. But if i set them to undefined at the end maybe it’s not to bad. I don’t know… always hearing global variables are bad.

		
	fn Generate5RandomNumbers onEachNumber: =
	(
		for i = 1 to 5 do
		(
			rnd = random 0 100
			onEachNumber rnd
		)
	)
	
	fn main =
	(
		global numbers = #()
		
		Generate5RandomNumbers \
			onEachNumber:(fn _ rndNumber = (
				append numbers rndNumber
				print ("Generated: " + rndNumber as string)
			))	
				
		
		print ("5 numbers:")
		print numbers
		print ("----
")
				
		global numbers = undefined		
	)

main()

Denis thanks for all those ideas!

But they still have something in common. Function ‘a’ and function ‘b’ are quiet close coupled.
You can even see that in the names you gave them. “incrementor” and “lambdaInc” .
“job” “doAJob” .
What i am looking for is, that you can do ‘anything’ with the output that a function ‘a’ is producing and defining what happens after that at the same spot where I call function a.
So the flow of reading the code helps to understand the data flow.
( Generating5RandomNumbers
onEachNumber : take the generated number and do ‘lambda expression’)

The idea is to be able to code in a more data flow oriented programming style with maxscript.
Not just do one function that has another function as input to alternate its behavior,
( What is rarely really needed – in most cases these are only needed for filter functions )
but instead use this for close to every function in the script.

Here are two ways to avoid Globals, but I don’t know if they fit your needs.
I really don’t understand very well nor lambda functions, nor what you are looking for.

  • The first one is preceding any function with a variable to hold the result.
  • The second one is giving a returned value for the result.

	fn λ_Generate5RandomNumbers RESULT onEachNumber: =
	(
		for i = 1 to 5 do
		(
			rnd1 = random 0 100
			rnd2 = random 0 100
			onEachNumber RESULT rnd1 rnd2
		)
	)
	
	fn main =
	(
		numberRESULT = #()
		
		λ_Generate5RandomNumbers numberRESULT\
			onEachNumber:(fn λ numberRESULT rndNumber1 rndNumber2 = (
				rndNumber = rndNumber1 * rndNumber2
				append numberRESULT rndNumber
				print ("Generated1: " + rndNumber1 as string)
				print ("Generated2: " + rndNumber2 as string)
				print ("Generated Product: " + rndNumber as string)
			))	
				
		
		print ("5 numbers:")
		print numberRESULT
		print ("----
")
	)
	
	fn λ_Generate5RandomNumbers2 onEachNumber: =
	(
		RESULT = #()
		for i = 1 to 5 do
		(
			rnd1 = random 0 100
			rnd2 = random 0 100
			append RESULT (onEachNumber rnd1 rnd2)
		)
		RESULT
	)

	fn main2 =
	(
		numberRESULT = λ_Generate5RandomNumbers2 \
			onEachNumber:(fn λ rndNumber1 rndNumber2 = (
				rndNumber = rndNumber1 * rndNumber2
				print ("Generated1: " + rndNumber1 as string)
				print ("Generated2: " + rndNumber2 as string)
				print ("Generated Product: " + rndNumber as string)
				rndNumber
			))	
				
		
		print ("5 numbers:")
		print numberRESULT
		print ("----
")
	)

	main()
	print "*****"
	main2()
	

Another example:

	
	
	fn λ_Generate2RandomNumbersAndDoSomething doSomething: =
	(
		rnd1 = random 0 100
		rnd2 = random 0 100
		doSomething rnd1 rnd2
	)

	fn main =
	(
		point2Value = λ_Generate2RandomNumbersAndDoSomething \
			doSomething:(fn λ_Point2 rndNumber1 rndNumber2 = (
				[rndNumber1, rndNumber2]
			))	
		format "Point2= %
" point2Value
			
		numberSum = λ_Generate2RandomNumbersAndDoSomething \
			doSomething:(fn λ_Sum rndNumber1 rndNumber2 = (
				rndNumber1 + rndNumber2
			))	
		format "Sum= %
" numberSum
		
	)

	main()
	

And a ‘subLamda’ expression:

	
	
	fn GenerateIntegerArray =
	(
		dim = random 3 10
		theArray = for i = 1 to dim collect (random 0 100)
	)
	
	fn workWithArray theArray action: =
	(
		action theArray
	)

	fn main =
	(
		theArray = GenerateIntegerArray()
		
		printSortedArray = workWithArray \
						(theArray = workWithArray theArray \
							action:(fn λ_Sort theArray = (
								sort theArray
								)
							)
						) \
						action:(fn λ_Print theArray = (
							format "Sorted Array= %
" theArray
							)
						)
	)

	for i = 1 to 5 do main()
	

Summary: I don’t know if it’s useful for anything, but it’s funny.
¡¡Merry Christmas and Happy New Year!!

Page 2 / 4