Calling a Function Before It's Defined

M

Mark Bilk

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)
 
J

Joel VanderWerf

Mark said:
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)
 
M

matt neuburg

Mark Bilk said:
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).

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)

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 Ruby. It is used to
accomplish many cool things, like modifying modules that already exist.
So don't worry, be happy. m.
 
M

Mark Bilk

Joel said:
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.
 
S

Sebastian Hungerecker

Mark said:
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
 
M

Mark Bilk

Mark said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top