# defined? for recursive function call v/s defined? for function call stack

Discussion in 'Ruby' started by Alok, Apr 12, 2006.

1. ### AlokGuest

I have some confusion about recursive function calls and definition of
variables in those functions. Consider these two code snippets for the
variable "b".
<PRE>
# def_stack.rb
def call1()
print "call1()\n"
b = "something"
if defined? b
print "defined? b is defined " + (defined? b).to_s + " with value " +
b.to_s + "\n"
else
print "defined? b is not defined " + (defined? b).to_s + " with value
" + b.to_s + "\n"
end
call2()
end

def call2()
print "\n\ncall2()\n"
if defined? b
print "defined? b is defined " + (defined? b).to_s + " with value " +
b.to_s + "\n"
else
print "defined? b is not defined " + (defined? b).to_s + ".\n"
end
end

call1()
</PRE>
outputs >>>
call1()
defined? b is defined local-variable with value something

call2()
defined? b is not defined .

Whereas for a recursive function
<PRE>
# def_recurse.rb
def call1( a )
print "\n\ncall1( " + a.to_s + " )\n"
if a == 1
b = "something"
recurse = true
else
recurse = false
end

if defined? b
print "defined? b is defined " + (defined? b).to_s + " with value " +
b.to_s + "\n"
else
print "defined? b is not defined " + (defined? b).to_s + ".\n"
end

call1( a + 1 ) if recurse
end
call1( 1 )
</PRE>
outputs >>>

call1( 1 )
defined? b is defined local-variable with value something

call1( 2 )
defined? b is defined local-variable with value

Why is the difference a difference for the definition of variable b in
the two functions. In particular, why is it that for a recursive
function the variable b appears defined in second call even though it
was never defined there.

I guess that a symbol table check routine looks for a variable
definition using the variable name & function name alone (for this
e.g.) and not using variable name & function name & function instance.
If this is the case, then it would explain why the the variable appears
undefined for the function call stack example.

Would much appreciate responses which can clarify what the ruby
interpreter does here.
--
cheers,
Alok

Alok, Apr 12, 2006

2. ### OliverMarchandGuest

You are stumbling across a subtle heuristic in the ruby interpreter.
You find an explanation in the PixeAxe book. The reason for b always
being defined is that the interpreter needs to see the variable to
define it, not actually assign it. Here is how you can do what you
want:

def recfct(a,b=nil)
b=1 if a>5
print "#{a}: b is #{b}\n"
return if a>10
recfct(a+1)
end

recfct(1)

yields:

1: b is
2: b is
3: b is
4: b is
5: b is
6: b is 1
7: b is 1
8: b is 1
9: b is 1
10: b is 1
11: b is 1

cheers,
Oliver

OliverMarchand, Apr 12, 2006

3. ### OliverMarchandGuest

(see the OP below what I am referring to)

I guess you are saying that one could save interpreting the "zillion
lines of code", while "somecondition" is not fulfilled. On one side:
this is not good programming style and in general the number of
executed lines in a code should by far exceed the number of lines in a
code - thus the interpretation time in general should be neglectable.
On the other hand, when assuming that short blocks are the most common
case it is questionable whether a dynamic interpretation would really
be the faster choice.

On a side note: In a programming contest among my colleagues for
solving short little problems and measuring the speed, we found
enlightning results. Typical excercises were evaluation of an
expression given as a string, creating a dictionary, finding string
sub-sequences, statistical tasks, numerical calculations, etc. mostly
related to scientific computing.

(a) in a first round Perl often the fastest! Python and ruby often
close.
(b) Java always very slow and long codes
(c) C++ extremely complicated and long codes - often needs tuning to
beat (a) languages
(d) Fortran people never bothered taking part

cheers,
Oliver

2006/4/12, Alok <>:
OliverMarchand wrote:
> The reason for b always
> being defined is that the interpreter needs to see the variable to
> define it, not actually assign it.

Ok, I get it. The intepreter would have created the variable "b" for
the recursive function even though it has not executed the assignment
line. This makes sense. Thank you for responding.

This now makes me wonder about interpreted language runtime efficiency
for the "if - then - else" case below.

if somecondition then
# a zillion lines of code here to be interpreted.
else
print "hello world"
end

Guess this could(?) be resolved during initial compilation - something
like the Java byte code? And is this also possible for a dynamic
programming language like Ruby?

OliverMarchand, Apr 13, 2006
4. ### AlokGuest

OliverMarchand wrote:
> I guess you are saying that one could save interpreting the "zillion
> lines of code", while "somecondition" is not fulfilled. On one side:
> this is not good programming style and in general the number of
> executed lines in a code should by far exceed the number of lines in a
> code - thus the interpretation time in general should be neglectable.
> On the other hand, when assuming that short blocks are the most common
> case it is questionable whether a dynamic interpretation would really
> be the faster choice.

In short, what you are implying is that in actual programming problems
we would hardly come across scenarios for the following construct
below. And hence interpreters are an acceptable solution to code
execution.
if somecondition
# zillion lines of code here ...
else
print "hello world"
end

Also, I am not clear about your response on dynamic interpretation (is
this the same as, or implemented using, interim compilation to byte
code like in Java?) Are you implying in your response that for short
blocks dynamic interpretation is not a faster choice in terms of code
execution speed?

Thanks for replying. I intended to respond to the Group but ended up
sending you a private message instead.
best regards,
Alok.

Alok, Apr 13, 2006