Please help me understand this simple recursion. I'm very new to programming, so I'm wondering how exactly this happens step by step.
I'm trying to learn recursion, but I'm stuck with the addition of "+"
function foo($bar) {
if ($bar == 1) return 1;
elseif ($bar == 0) return 0;
else return foo($bar - 1) + foo($bar - 2);
}
When trying to understand recursion I find it helps a lot to write down each individual case for a specific parameter and then build your understanding from there.
So let's take the example of foo(3)
foo(3) -> we don't hit either base case, so our function now wants to return
foo(2) + foo(1)
First we need to get foo(2)
foo(2) -> Again no base case, so we return
foo(1) + foo(0)
foo(1) = 1 and foo(0) = 0 (these are our base cases) so we see that
foo(2) = 1 + 0
Now our look at foo(3) is resolved to
foo(3) -> (1 + 0) + foo(1)
foo(1) = 1, so we can finally see that
foo(3) -> (1 + 0) + 1 = 2
You have to remember that recursion is basically building a "tree" of function calls - it's going to go as far down the tree as possible, and then come up one level and see what else it has to do to continue. I'm not sure how clear this is but hopefully it helps.
it's simple really (once you wrap your head around it). In the last line you are calling the function foo twice and adding their return values together.
here is a sample trace
call 1:
foo(3)
return foo(2) + foo(1)
call 2:
foo(2)
return foo(1) + foo(0)
call 3:
foo(1)
return 1
unrolls to call 2:
return 1 + foo(0)
call 4:
foo(0)
return 0
unrolls to call 2 again:
return 1 + 0
unrolls to call 1:
return 1 + foo(1)
call 5:
foo(1)
return 1
unrolls to call 1 again:
return 1 + 1
The first invocation of foo() ends up calling two additional invocation of foo(). Each of those two in turn calls two of their own, and so on.
First Iteration
foo()
Second Iteration
foo() foo()
Third Iteration
foo() foo() foo() foo()
etc.
So, if foo() does not hit one of the termination conditions, it always calls itself twice more.
It may be instructive to add a variable indicating the call depth and having foo() print out its arguments including the call depth argument.
Related
I have a function
function foo(a)
if a > 5
a = 5
end
some_more_code
end
If the if-statement is true I would like to end the function but I don't want to return anything - to change the value of a is all I need.
How do I do that?
You can write (note that I have also changed the syntax of function definition to make it more standard for Julia style):
function foo(a)
if a > 5
a = 5
return
end
# some_more_code
end
Just use the return keyword without any expression following it. To be precise in such cases Julia returns nothing value of type Nothing from a function (which is not printed in REPL and serves to signal that you did not want to return anything from a function).
Note though that the value of a will be only changed locally (within the scope of the function), so that outside of the function it will be unchanged:
julia> function foo(a)
if a > 5
a = 5
return
end
# some_more_code
end
foo (generic function with 1 method)
julia> x = 10
julia> foo(x)
julia> x
10
In order to make the change visible outside of the function you have to make a to be some kind of container. A typical container for such cases is Ref:
julia> function foo2(a)
if a[] > 5
a[] = 5
return
end
# some_more_code
end
foo2 (generic function with 1 method)
julia> x = Ref(10)
Base.RefValue{Int64}(10)
julia> foo2(x)
julia> x[]
5
Is there a way to check if a function has keywords arguments in Julia? I am looking for something like has_kwargs(fun::Function) that would return true if fun has a method with keyword arguments.
The high level idea is to build a function:
function master_fun(foo::Any, fun::Function, ar::Tuple, kw::Tuple)
if has_kwargs(fun)
fun(ar... ; kw...)
else
fun(ar...)
end
end
Basically, #Michael K. Borregaard's suggestion to use try-catch is correct and officially works.
Looking into the unofficial implementation details, I came up with the followng:
haskw(f,tup) = isdefined(typeof(f).name.mt,:kwsorter) &&
length(methods(typeof(f).name.mt.kwsorter,(Vector{Any},typeof(f),tup...)))>0
This function first looks if there is any keyword processing on any method of the generic function, and if so, looks at the specific tuple of types.
For example:
julia> f(x::Int) = 1
f (generic function with 1 method)
julia> f(x::String ; y="value") = 2
f (generic function with 2 methods)
julia> haskw(f,(Int,))
false
julia> haskw(f,(String,))
true
This should be tested for the specific application, as it probably doesn't work when non-leaf types are involved. As Michael commented, in the question's context the statement would be:
if haskw(fun, typeof.(ar))
...
I don't think you can guarantee that a given function has keyword arguments. Check
f(;x = 3) = println(x)
f(x) = println(2x)
f(3)
#6
f(x = 3)
#3
f(3, x = 3)
#ERROR: MethodError: no method matching f(::Int64; x=3)
#Closest candidates are:
# f(::Any) at REPL[2]:1 got unsupported keyword argument "x"
# f(; x) at REPL[1]:1
So, does the f function have keywords? You can only check for a given method. Note that, in your example above, you'd normally just do
function master_fun(foo, fun::Function, ar::Tuple, kw....)
fun(ar... ; kw...)
end
which should work, and if keywords are passed to a function that does not take them you'd just leave the error reporting to fun. If that is not acceptable you could try to wrap the fun(ar...; kw...) in a try-catch block.
I want to print out the elements in the list in reverse order recursively.
def f3(alist):
if alist == []:
print()
else:
print(alist[-1])
f3(alist[:-1])
I know it is working well, but I don't know the difference between
return f3(alist[:-1])
and
f3(alist[:-1])
Actually both are working well.
My inputs are like these.
f3([1,2,3])
f3([])
f3([3,2,1])
There is a difference between the two although it isn't noticeable in this program. Look at the following example where all I am doing is passing a value as an argument and incrementing it thereby making it return the value once it hits 10 or greater:
from sys import exit
a = 0
def func(a):
a += 1
if a >= 10:
return a
exit(1)
else:
# Modifications are made to the following line
return func(a)
g = func(3)
print(g)
Here the output is 10
Now if I re-write the code the second way without the "return" keyword like this :
from sys import exit
a = 0
def func(a):
a += 1
if a >= 10:
return a
exit(1)
else:
# Modifications are made to the following line
func(a)
g = func(3)
print(g)
The output is "None".
This is because we are not returning any value to handle.
In short, return is like internal communication within the function that can be possibly handled versus just running the function again.
What's the term for when a recursive algorithm doesn't always reach all functions on each level? Consider this code:
function f(value):
if val < -10 return g(value + 1)
if var > 10 return h(value - 1)
else return 0
function g(value):
if value % 2 == 0 return f(value / 2)
else return h(value)
function h(value):
if value % 2 == 1 return g(value - 1)
else return h(value - 1)
Each recursive call may call a different function such as when we start with 15:
f(15)
h(14)
h(13)
g(12)
f(6)
return 0
I've never heard of a specific term for what you describe, it's simply referred to as recursion.
The fact that it executes potentially different pathways for certain levels of recursion doesn't really make it special, any more than the same feature in a loop:
for i = 1 to 10:
if i is even:
print i, " is even"
else:
print i, " is odd"
That's still called a loop (not something like "alternating loop" or "iteration dependent behavioural loop"). It's similar to your recursion example.
In fact, recursion always has different behaviour at at least one level (the last one) since, without that, it would recur forever and you would most likely overflow the stack.
I need to write a recursive function that returns the remainder of two numbers. Here's what I wrote:
def remainder(a,b):
if a==b:
return 0
else:
k=a-b
return a-b + remainder(b,a-k)
If we test remainder(5,3) the function will return 2 and it's correct but if we test remainder(15,3),
we'll get 12 and its false. I just don't know how to debug it.
You are missing a case: (when a < b)
def remainder(a,b):
if a<b: #trivial: remainder = a - b*0 = a
return a
else: #reduce the problem to a simple one
return remainder(a-b, b)
Test:
print remainder(15,3)
Output:
0
Here if you are lazy and don't want to write more than 2 lines:
def remainder(a,b):
return a if a < b else remainder(a-b, b)
It should be something like this :
def remainder(a,b):
if a<b:
return a
else:
return remainder(a-b,b)
You can do:
def remainder(a, b):
if a < b:
return a
return remainder(a - b, b)
Examples:
>>> remainder(15, 3)
0
>>> remainder(14, 3)
2
>>> remainder(13, 3)
1
If a < b then it means we're done: we know the result of the computation and we can return a. Otherwise we need to subtract b from a and we call remainder again recursively. This can then repeatedly continue until a is smaller than b. Once that happens the recursion stops (i.e., it won't call remainder again) but we're able to return the result.