If Then challenges working toward Code Block recursion

I am trying to make a simple recursive model. For example, I will call a function and it will recurse until a set of conditions are met.

After reading some advice in the primer, it seems like script in a code block or python are both good options, and so I’m starting with code blocks.

I am having trouble implementing if/then inside the a simple block. I found this example in forums but it is throwing errors:

  • in code blocks you can use if and else as well, if (condition) { // do this thing } else{ //do that thing } you may need to put this inside an imperative block like result = [imperative]{ a = 0; if(100<200){ a = 10; } return = a; } (not tested)!

I’ve tried a bunch of variations, I don’t really understand what the “imperative” command means or how it works inside another function and can’t seem to find any documentation.


(I was not able to upload my dynamo file - the forum reports that I am a new user)

If there is a good example for recursion in a code block, I would love to see it.

Please note this page has a typo… missing the “=” from this function example near top of page:
https://primer.dynamobim.org/07_Code-Block/7-4_functions.html

Thanks!
Bruce

Welcome to the Dynamo community @bruce.crock

[Imperative] (note that the word begins with an Upper case ‘I’)

A recursive function is one where a function calls itself within it’s definition. This isn’t possible in Design Script. But, it doesn’t seem like you’re looking for that functionality.

Actually = (following return) is optional in the more recent versions of Dynamo

Below is an example of an Imperative function …

def OddEven(min,max)
{
	result = [Imperative]
	{
		a = [];
		c = 0;
		for (i in min..max)
		{
			if (i % 2 == 0)
			{
				a[c] = i + " is Even";
				c = c + 1;
			}
			else
			{
				a[c] = i + " is Odd";
				c = c + 1;
			}
		}
		return a;
	}
	return result;
};
1 Like

Thanks so much for your help. Capital “I” in “Imperative” solved my first error.

Here is the page where I read that DesignScript can support recursion: Scripting Strategies | The Dynamo Primer

I’m going to keep trying now that I’m unblocked from step 1 :wink:

I appreciate the example of the imperative inside a function, I can use that as a template.

As you guessed, I’m using an older version which must require the “=”. I will update soon.
Thanks again,
Bruce

1 Like

I stand corrected. Below is a quick example of a Recursive function

def factorial(n)
{
    return [Imperative]
    {
	    if (n <= 1)
	        {
	        	return 1;
	        }
	    else
	        {
	        	return n * factorial(n-1);
	        }
	}
};
2 Likes

can you only define a recursive function in imperative mode? I read through the DS specification and the language guide, and it doesn’t seem to address this. I’m trying to get better at using DesignScript and i’m writing this same factorial function

def fact (n)
{
     return (n==0) ? 1: n*fact(n-1);
}

but the application times out when i run it.

An If statement can only be used inside an Imperative block. You can still use the DS shorthand version but for some reason it doesn’t return the same error when outside an Imperative block.

maybe this is better as it’s own topic. I’m not sure how to process your response because i’m not trying to use an If statement. I’m using the inline conditional statement to try and make a recursive call in the associative mode, but the dynamo doesn’t finish running. I’m not seeing what might be wrong in the statement to cause it to loop infinitely.

as illustrated above, you can make a recursive call in the imperative mode (and i was able to replicate this), but that’s a little odd to me that recursion like this wouldn’t also be supported in the associative mode. the associative mode seems to hold more to functional paradigms, and i guess i just think of recursion as an approach used in the functional style.

2 Likes

The conditional statement you’re using is just DesignScript shorthand for an If statement.

test ? returnTrue : returnFalse;

If test is true, return returnTrue, else return returnFalse. Either way, it’s probably safe to assume that any (branching) conditional statement has to be within an Imperative block.

That seems to be the case

Interesting observation, makes sense. (To provide some background, in functional programming, tail call recursion is generally used as an alternative to loops)
Maybe @Aparajit_Pratap or @Michael_Kirschner2 can throw some light on this.

@Nick_Boyts I’m afraid, an inline conditional like test ? returnTrue : returnFalse; for associative language is not entirely the same as an if-else statement. An inline conditional can be used in both Associative and Imperative code, however, in associative code, the conditional statement can replicate over its inputs, while in imperative code, the inline conditional is essentially equivalent to an if-else statement. In the following graph, you can see the difference. In the case of the associative block below, it replicates over test, while in the case of the imperative code block, test is treated as an array. Since anything other than 0 or false evaluates to true, the array evaluates to true and the imperative code executes just once (doesn’t replicate).

2 Likes

Ah. Thank you for clarifying, @Aparajit_Pratap. Am I correct in thinking that the associative inline statement still won’t work over an array when inside a function though?

Going by this, defining a recursive function in an inline conditional is possible, in Imperative mode. Thanks for the clarification.

fct1_2021-10-26_12-36-24

def fact (n)
{
     return [Imperative]
     {
     	return (n<=1) ? 1 : n*fact(n-1);
     }
};
3 Likes

It could work like this …

def funct(test:var[]..[],tr:var[]..[],fl:var[]..[])
{
	return test<1> ? tr : fl;
};
1 Like

Of course. Just define the input types. :man_facepalming:
Thanks, Vikram.

@Nick_Boyts if you’re using the inline expression inside a function, you need to apply the replication guides on the function parameters, not in the expression, like so:

1 Like

@Vikram_Subbaiah I need to come up with a good explanation of whether recursion will or will not work in the associative context and why or why not. I don’t have a good answer at the moment but will try to respond soon.

1 Like

Yeah, don’t know why I didn’t do that at the time. I think I was still wrapping my head around why it was working in one case but not in another. Thank you for explaining everything. It’s been a good learning experience.

1 Like

maybe i was thinking about imperative mode as too strong of a difference, like you can -only- write imperative block. I need to come back to this. Thanks for the insight!

1 Like