Calling a Function Before It's Defined

Discussion in 'Ruby' started by Mark Bilk, Apr 9, 2009.

  1. Mark Bilk

    Mark Bilk Guest

    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)
    --
    Posted via http://www.ruby-forum.com/.
     
    Mark Bilk, Apr 9, 2009
    #1
    1. Advertising

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

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
     
    Joel VanderWerf, Apr 9, 2009
    #2
    1. Advertising

  3. Mark Bilk

    matt neuburg Guest

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

    --
    matt neuburg, phd = , http://www.tidbits.com/matt/
    Leopard - http://www.takecontrolbooks.com/leopard-customizing.html
    AppleScript - http://www.amazon.com/gp/product/0596102119
    Read TidBITS! It's free and smart. http://www.tidbits.com
     
    matt neuburg, Apr 9, 2009
    #3
  4. Mark Bilk

    Mark Bilk Guest

    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.



    --
    Posted via http://www.ruby-forum.com/.
     
    Mark Bilk, Apr 9, 2009
    #4
  5. Mark Bilk 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
     
    Sebastian Hungerecker, Apr 9, 2009
    #5
  6. Mark Bilk

    Mark Bilk Guest

    Mark Bilk 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
    -------------------
    --
    Posted via http://www.ruby-forum.com/.
     
    Mark Bilk, Apr 10, 2009
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ryan Ternier
    Replies:
    4
    Views:
    4,042
    Cowboy \(Gregory A. Beamer\) [MVP]
    Jul 29, 2004
  2. Andreas Lagemann
    Replies:
    8
    Views:
    531
    Mike Wahler
    Jan 10, 2005
  3. Oodini
    Replies:
    1
    Views:
    1,837
    Keith Thompson
    Sep 27, 2005
  4. Replies:
    11
    Views:
    594
  5. Alok
    Replies:
    3
    Views:
    286
Loading...

Share This Page