Calling a Function Before It's Defined


#1

I would like to be able to call a function (or a class,
when I get more object-oriented) earlier in the program
file than where I define it. Such a “top-down” layout
seems natural to me. In C I could use a function
prototype for this. If I try it in Ruby, I get an error
(see code below).

Even if I do define everything before I use it, how could
I write a recursive function, or two mutually recursive
functions?

s = “abc”

gives error: undefined method `f’ for main:Object (NoMethodError)

f(s)

def f(x)
print('f: ', x, “\n”)
end

works OK

f(s)


#2

Mark B. wrote:

I would like to be able to call a function (or a class,
when I get more object-oriented) earlier in the program
file than where I define it. Such a “top-down” layout
seems natural to me. In C I could use a function
prototype for this. If I try it in Ruby, I get an error
(see code below).

Two ways:

foo
BEGIN {
def foo; end
}

or

END {
foo
}
def foo; end

Even if I do define everything before I use it, how could
I write a recursive function, or two mutually recursive
functions?

Define the two functions before you call either one. No prob.

def foo(n); p n; bar(n-1); end
def bar(n); foo(n) if n>0; end

p bar(3)


#3

Mark B. removed_email_address@domain.invalid wrote:

f(s)

def f(x)
print('f: ', x, “\n”)
end

works OK

f(s)

The fact that everything is executable code, including “module M”,
“class C”, and “def”, and that code is executed in the order in which it
is encountered, is part of what makes Ruby R… It is used to
accomplish many cool things, like modifying modules that already exist.
So don’t worry, be happy. m.


#4

Joel VanderWerf wrote:

foo
BEGIN {
def foo; end
}

Thanks! Just to make it clear for other beginners
like me, here’s the fixed version of my code:

s = “abc”
f(s)

BEGIN {
def f(x)
print('f: ', x, “\n”)
end
}

Quoting Programming Ruby (the Pickaxe book):

BEGIN and END Blocks
Every Ruby source file can declare blocks of code to be run
as the file is being loaded (the BEGIN blocks) and after
the program has finished executing (the END blocks).

BEGIN {
begin code
}

END {
end code
}

A program may include multiple BEGIN and END blocks. BEGIN
blocks are executed in the order they are encountered.
END blocks are executed in reverse order.


#5

Mark B. wrote:

here’s the fixed version of my code:

s = “abc”
f(s)

BEGIN {
def f(x)
print('f: ', x, “\n”)
end
}

A friend thought of another way,
that avoids even the BEGIN hack:

def mainn
s = “abc”
f(s)
end

def f(x)
print('f: ', x, “\n”)
end

mainn


#6

Mark B. wrote:

I would like to be able to call a function (or a class,
when I get more object-oriented) earlier in the program
file than where I define it. Such a “top-down” layout
seems natural to me. In C I could use a function
prototype for this.

The reason why you have to declare a function in C before you call it
(before
meaning the code position) is fundementally different from why you have
to
define it in ruby before you call it (here before means the runtime).

Examples:
def foo()
bar
end
def bar()
end
foo
Works just fine (because the code in foo that references bar executes
after
bar has been defined (even if it’s position in the code is earlier).

def foo()
1
end
def bar()
foo
end
bar #=> 1
def foo()
2
end
bar #=> 2
You can redefine methods and ruby always executes the version of the
method
that’s currently in existence.

def foo()
def bar()
end
end
bar #error
foo
bar # Now it works

You can define method a within method b. That will have the effect that
after
running method b, method a will be defined (although it wasn’t before).
You can also redefine methods that way:
def foo() 1 end
def bar() def foo() 2 end end
foo #=> 1
bar
foo #=> 2

All this has the effect that you can’t forward declare methods like you
can in
C. If you do this:
def foo() end
foo
def foo() bar end
The call in line 2 will call the empty version of foo because that is
the
version currently in existence.

HTH,
Sebastian