Jump to content

Recursion without calling the fucntion inside a fucntion

Wictorian

Can you do recursion without calling a function inside a function?

Link to comment
Share on other sites

Link to post
Share on other sites

Then you’re not recursing 

 

edit: this is a good definition 

 

https://www.urbandictionary.com/define.php?term=recursion

Community Standards || Tech News Posting Guidelines

---======================================================================---

CPU: R5 3600 || GPU: RTX 3070|| Memory: 32GB @ 3200 || Cooler: Scythe Big Shuriken || PSU: 650W EVGA GM || Case: NR200P

Link to comment
Share on other sites

Link to post
Share on other sites

9 minutes ago, Wictorian said:

Can you do recursion without calling a function inside a function?

Strictly speaking it wouldn't be recursion anymore.  If you are talking about trying to turn a function into a non-recursive function...then yes it is possible for a decent amount of problems.  The implementation though would depend on what kind of recursive function you are trying to make non-recursive

 

e.g.

int fib_recursive(int n) {
	if(n <= 0)
    	return -1;
	if(n < 2)
    	return 1;
	return fib(n-1) - fib(n-2); //Of course this is really inefficient
}

//A lot better than the previous one but it isn't as compact anymore (but this is a better solution)
int fib_nonrecursive(int n) {
	if(n < 2)
    	return 1; //Not strictly necessary, but still
        
    int currValue = 1;
    int prevValue = 1;
    n -= 2;
    while(n > 0) {
    	int tmpValue = currValue;
    	currValue = tmpValue + prevValue;
        prevValue = tmpValue;
    	n--;
    }
    
    return currValue;
}

 

3735928559 - Beware of the dead beef

Link to comment
Share on other sites

Link to post
Share on other sites

Spoiler
11 hours ago, wanderingfool2 said:

Strictly speaking it wouldn't be recursion anymore.  If you are talking about trying to turn a function into a non-recursive function...then yes it is possible for a decent amount of problems.  The implementation though would depend on what kind of recursive function you are trying to make non-recursive

 

e.g.






int fib_recursive(int n) {
	if(n <= 0)
    	return -1;
	if(n < 2)
    	return 1;
	return fib(n-1) - fib(n-2); //Of course this is really inefficient
}

//A lot better than the previous one but it isn't as compact anymore (but this is a better solution)
int fib_nonrecursive(int n) {
	if(n < 2)
    	return 1; //Not strictly necessary, but still
        
    int currValue = 1;
    int prevValue = 1;
    n -= 2;
    while(n > 0) {
    	int tmpValue = currValue;
    	currValue = tmpValue + prevValue;
        prevValue = tmpValue;
    	n--;
    }
    
    return currValue;
}

 

 

 

Thanks but this is not what  I meant. I mean literally doing the equilevant of calling the function. I will give and example but

it is not perfect.

 

a = 0 
def func:
#function
	if (a < 10):
    	a+=1
#recurison        
	while (a < 10):
    	a+=1
        
	return(a)

 

Link to comment
Share on other sites

Link to post
Share on other sites

22 minutes ago, Wictorian said:
  Reveal hidden contents

 

 

Thanks but this is not what  I meant. I mean literally doing the equilevant of calling the function. I will give and example but

it is not perfect.

 


a = 0 
def func:
#function
	if (a < 10):
    	a+=1
#recurison        
	while (a < 10):
    	a+=1
        
	return(a)

 

That's not recursion, it's just a loop. And it's exactly what @wanderingfool2 suggested.

Don't ask to ask, just ask... please 🤨

sudo chmod -R 000 /*

Link to comment
Share on other sites

Link to post
Share on other sites

15 minutes ago, Sauron said:

That's not recursion, it's just a loop. And it's exactly what @wanderingfool2 suggested.

Yes I said it is not perfect. I thought it was closer because the function adds 1 to a if it is lesser than a and the loop is like calling the function, not just adding 1 to a.

Link to comment
Share on other sites

Link to post
Share on other sites

34 minutes ago, Wictorian said:

Yes I said it is not perfect. I thought it was closer because the function adds 1 to a if it is lesser than a and the loop is like calling the function, not just adding 1 to a.

The difference is in how it's handled by the interpreter or compiler. Function calls are pushed on the stack, loops aren't - although for something as simple as adding 1 to a variable 10 times you might find that the compiler just substitutes it with "a = 10".

 

Performance-wise they're pretty much identical if you use tail recursion (which makes it so only one function call is on the stack at any given time), you should use the one that is simpler for the problem you're trying to solve.

Don't ask to ask, just ask... please 🤨

sudo chmod -R 000 /*

Link to comment
Share on other sites

Link to post
Share on other sites

7 minutes ago, Sauron said:

The difference is in how it's handled by the interpreter or compiler. Function calls are pushed on the stack, loops aren't - although for something as simple as adding 1 to a variable 10 times you might find that the compiler just substitutes it with "a = 10".

 

Performance-wise they're pretty much identical if you use tail recursion (which makes it so only one function call is on the stack at any given time), you should use the one that is simpler for the problem you're trying to solve.

Yeah my concern isn't performance, as you might know you can't call a function inside a function in some languages (autohotkey) so I was curious if it could be done at all.

Link to comment
Share on other sites

Link to post
Share on other sites

47 minutes ago, Wictorian said:

Yeah my concern isn't performance, as you might know you can't call a function inside a function in some languages (autohotkey) so I was curious if it could be done at all.

Yes, anything that can be done with recursion can be done with a loop and vice versa.

Don't ask to ask, just ask... please 🤨

sudo chmod -R 000 /*

Link to comment
Share on other sites

Link to post
Share on other sites

19 hours ago, Wictorian said:

Can you do recursion without calling a function inside a function?

Yeah, use the spaghetti gotos in assembly. Saved stack pointer and all the local variables to stack, decrement stack pointer, then do a jump. You are reinventing the wheels and implementing what would be a function and function call in higher language pretty much. 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

6 hours ago, Wictorian said:

Yeah my concern isn't performance, as you might know you can't call a function inside a function in some languages (autohotkey) so I was curious if it could be done at all.

Autohotkey supports recursion.  Actually all languages that I can think of support recursion in some form.  The biggest problem with recursion though that that people have a tendency to not think about the stack size.  An example of where one might think autohotkey is broken is an example below (where it crashes).

 

IWillEventuallyCrash() {
    sleep 1
    IWillEventuallyCrash()
}

This crashes because you will eventually reach a stack overflow (since each function call adds to the stack without returning the stack eventually gets filled up).  [Even the fib function I wrote would overflow at a certain number).

 

If anyone happens to know of any languages that don't support recursion, it'd be interesting to know (I'm curious now)  I'd imagine it's the really old languages that wouldn't support it

3735928559 - Beware of the dead beef

Link to comment
Share on other sites

Link to post
Share on other sites

23 minutes ago, wanderingfool2 said:

If anyone happens to know of any languages that don't support recursion, it'd be interesting to know (I'm curious now)  I'd imagine it's the really old languages that wouldn't support it

I guess in theory a language with a single-function stack would not allow recursion (or any function calls at all beyond the main function). You could also artificially check that no function calls itself at any point I suppose.

Don't ask to ask, just ask... please 🤨

sudo chmod -R 000 /*

Link to comment
Share on other sites

Link to post
Share on other sites

9 hours ago, Sauron said:

tail recursion (which makes it so only one function call is on the stack at any given time

Can you elaborate? Am I right in assuming that the compiler can recognize a tail recursive function and instead of pushing a new frame to the stack it will reuse the previous one because it's no longer in use?

ಠ_ಠ

Link to comment
Share on other sites

Link to post
Share on other sites

3 minutes ago, shadow_ray said:

Can you elaborate? Am I right in assuming that the compiler can recognize a tail recursive function and instead of pushing a new frame to the stack it will reuse the previous one because it's no longer in use?

It will definitely pop the previous function call off of the stack before loading the new one, whether it reuses the same exact stack frame or not probably depends on the specific language and implementation (but I do believe that in most cases it does). Of course this requires a compiler that implements this feature.

Don't ask to ask, just ask... please 🤨

sudo chmod -R 000 /*

Link to comment
Share on other sites

Link to post
Share on other sites

16 hours ago, wanderingfool2 said:

Autohotkey supports recursion.  Actually all languages that I can think of support recursion in some form.  The biggest problem with recursion though that that people have a tendency to not think about the stack size.  An example of where one might think autohotkey is broken is an example below (where it crashes).

 


IWillEventuallyCrash() {
    sleep 1
    IWillEventuallyCrash()
}

This crashes because you will eventually reach a stack overflow (since each function call adds to the stack without returning the stack eventually gets filled up).  [Even the fib function I wrote would overflow at a certain number).

 

If anyone happens to know of any languages that don't support recursion, it'd be interesting to know (I'm curious now)  I'd imagine it's the really old languages that wouldn't support it

What I meant by autohotkey doesn't support recursion is it doesn't support calling any function inside a function...

Link to comment
Share on other sites

Link to post
Share on other sites

15 minutes ago, Wictorian said:

What I meant by autohotkey doesn't support recursion is it doesn't support calling any function inside a function...

It definitely does. I have multiple scripts where I call functions inside other functions.

Hand, n. A singular instrument worn at the end of the human arm and commonly thrust into somebody’s pocket.

Link to comment
Share on other sites

Link to post
Share on other sites

13 hours ago, WereCatf said:

It definitely does. I have multiple scripts where I call functions inside other functions.

Well I would be more than happy if you told me how I can do it. Because it gave warning that I can't call a function inside a function.

Link to comment
Share on other sites

Link to post
Share on other sites

2 hours ago, Wictorian said:

Well I would be more than happy if you told me how I can do it.

Well, here's an extremely simple script that calls a function inside another function:

~Space::firstFunction()

thirdFunction(x)
{
	return x + 1
}

secondFunction(y)
{
	MsgBox % "thirdFunction returned: " . thirdFunction(y)
}

firstFunction()
{
	secondFunction(3)
	ExitApp
}

 

2 hours ago, Wictorian said:

Because it gave warning that I can't call a function inside a function.

Either you have some old or odd version of Autohotkey installed or you're simply doing something wrong yourself.

Hand, n. A singular instrument worn at the end of the human arm and commonly thrust into somebody’s pocket.

Link to comment
Share on other sites

Link to post
Share on other sites

Spoiler
8 hours ago, WereCatf said:

Well, here's an extremely simple script that calls a function inside another function:



~Space::firstFunction()

thirdFunction(x)
{
	return x + 1
}

secondFunction(y)
{
	MsgBox % "thirdFunction returned: " . thirdFunction(y)
}

firstFunction()
{
	secondFunction(3)
	ExitApp
}

 

Either you have some old or odd version of Autohotkey installed or you're simply doing something wrong yourself.

 

 It gives the attached error. I am posting the code just in case and if you would bother taking a look but I don't know if it is about it, I did something similar to you anyways. Also there may be errors / bugs but I don't know if they are related with the issue..

Spoiler

Break(){
a = 0
While a < 12{
a = a + 1
send {space}
Sleep 500

} 
}
Move(dir){
if (dir = right)
    send {d}
    send {d}
    send {d}
else {
    send {a}
    send {a}
    send {a}
}
}
calcDir(x, sDir){
if sDir = "left"
    v = 0
else {
v = 1
} 
if (Mod(col,2) = v)
    dir = "left"
else{
dir = "right" 
return dir
}
BreakLine(col,sDir){
ESC::
    k=!k 
dir = calcDir(col, sDir) 
i = 0
While i < 97{ 
i = i + 1
Move(dir)
if k
    Break()
}
}
BreakWorld(){
InputBox, H, Enter World Height, sEnter world height., , 640, 480
if ErrorLevel
    MsgBox, CANCEL was pressed.
else
    MsgBox, You entered "%H%"
InputBox, sDir, Enter World Height, Enter starting direction., , 640, 480
if ErrorLevel
    MsgBox, CANCEL was pressed.
else
    MsgBox, You entered "%sDir%"
x = 0
While (x < 97){
BreakLine(x,sDir)
Break()
if (calcDir(x,sDir) = "left")
    MouseMove, 1052, 546
else {
MouseMove, 219, 552
}
y = 0
While a < 12{
y = a + 1
MouseClick, left
Sleep 500
Move(calcDir(x,sDir))
x = x + 1
}
}
BreakWorld()

 

 

func.PNG

Link to comment
Share on other sites

Link to post
Share on other sites

23 minutes ago, Wictorian said:
  Reveal hidden contents

 

 It gives the attached error.

func.PNG

Read the error better: it says you can't put a function inside a function, NOT that you can't call a function from another function. You are defining a hotkey for ESC inside a function, but that's not how hotkeys work.

Hand, n. A singular instrument worn at the end of the human arm and commonly thrust into somebody’s pocket.

Link to comment
Share on other sites

Link to post
Share on other sites

9 minutes ago, WereCatf said:

Read the error better: it says you can't put a function inside a function, NOT that you can't call a function from another function. You are defining a hotkey for ESC inside a function, but that's not how hotkeys work.

Do you know how I can stop the program when I want without doing that?

Link to comment
Share on other sites

Link to post
Share on other sites

Just now, Wictorian said:

Do you know how I can stop the program when I want without doing that?

You could e.g. just simply define the hotkey for ESC outside any functions with:

ESC::ExitApp

Or you check inside your loop whether a key is pressed:

ESC::loopFunction()

loopFunction()
{
	MsgBox % "Begin loop!"
	while(1){
		if(GetKeyState("ESC", "P"))
			break
	}
	MsgBox % "ESC pressed, exiting!"
	ExitApp
}

Or instead of a hard loop, you use timer-events or plenty of other ways.

Hand, n. A singular instrument worn at the end of the human arm and commonly thrust into somebody’s pocket.

Link to comment
Share on other sites

Link to post
Share on other sites

11 hours ago, Wictorian said:

It gives the attached error. I am posting the code just in case and if you would bother taking a look but I don't know if it is about it, I did something similar to you anyways. Also there may be errors / bugs but I don't know if they are related with the issue..

Is that how the code looks?  (Without indentations).

 

I'll step you through my thought processes on figuring out your error

The error is saying you can't define a function (not calling) inside a function (AHK compiles and isn't JIT *Edit oops my bad, I guess AHK is JIT...I was thinking of something else*).  That means you have as an example (function a() { function b() }.  That leads me to believe you are missing a bracket.

I looked at the line it says was the problem, and looked right before it (and sure enough, it looks like you are missing a bracket).

 

One of the things to note is it's good coding practices to have proper indentations, as it allows you to spot issues a lot easier.  I've indented to what I think your code is suppose to look like (I've left in the missing brackets as an example how it makes it easier to spot issues, since the indentations don't match what the code is written as).

 

After the indentations, note that there is a missing } and also a missing { } (maybe, not entirely sure)

Spoiler


Break(){
	a = 0
	While a < 12{
		a = a + 1
		send {space}
		Sleep 500
	} 
}

Move(dir){
	if (dir = right) ******UHM missing a { ?
		send {d}
		send {d}
		send {d}
	**Spotted the missing { because there was a missing } on this line
	else {
		send {a}
		send {a}
		send {a}
	}
}

calcDir(x, sDir){
	if sDir = "left"
		v = 0
	else {
		v = 1
	} 
	if (Mod(col,2) = v)
		dir = "left"
	else{
		dir = "right" 
		return dir
	}

***A quick glance shows that you are missing a } here

BreakLine(col,sDir){
	ESC::
	k=!k 
	dir = calcDir(col, sDir) 
	i = 0
	While i < 97{ 
		i = i + 1
		Move(dir)
		if k
			Break()
	}
}

BreakWorld(){
	InputBox, H, Enter World Height, sEnter world height., , 640, 480
	if ErrorLevel
		MsgBox, CANCEL was pressed.
	else
		MsgBox, You entered "%H%"
	InputBox, sDir, Enter World Height, Enter starting direction., , 640, 480
	if ErrorLevel
		MsgBox, CANCEL was pressed.
	else
		MsgBox, You entered "%sDir%"
	x = 0
	While (x < 97){
		BreakLine(x,sDir)
		Break()
		if (calcDir(x,sDir) = "left")
		MouseMove, 1052, 546
		else {
		MouseMove, 219, 552
		}
	y = 0
	While a < 12{
		y = a + 1
		MouseClick, left
		Sleep 500
		Move(calcDir(x,sDir))
		x = x + 1
	}
}


BreakWorld()

 

 

Another helpful thing to do, try googling error messages.  Googling "ahk functions cannot contain functions" for me returned the answer in the first result (reading through a post of someone who had the problem and someone answering)

3735928559 - Beware of the dead beef

Link to comment
Share on other sites

Link to post
Share on other sites

On 5/7/2021 at 12:09 PM, WereCatf said:

You could e.g. just simply define the hotkey for ESC outside any functions with:


ESC::ExitApp

Or you check inside your loop whether a key is pressed:


ESC::loopFunction()

loopFunction()
{
	MsgBox % "Begin loop!"
	while(1){
		if(GetKeyState("ESC", "P"))
			break
	}
	MsgBox % "ESC pressed, exiting!"
	ExitApp
}

Or instead of a hard loop, you use timer-events or plenty of other ways.

well I removed ESC and it still says funtions cannot contain functions

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×