Professional Web Applications Themes

Closures and Letrec - Ruby

Is there a way to create recursive anonymous closures in ruby? For instance if I write even = proc {|x| x == 0 ? true : odd(x-1)} odd = proc {|x| x == 1 ? true : even(x-1)} In this case even definitely doesn't know about odd, and actually doesn't even know about even. Odd is aware of even though. At least that's how I have interpreted how ruby works. We get recursion with full methods, just not with anonymous procs. Is there any intention for support for this with anonymous procs? Perhaps though a different syntax? procrec or something? ...

  1. #1

    Default Closures and Letrec

    Is there a way to create recursive anonymous closures in ruby? For instance
    if I write
    even = proc {|x| x == 0 ? true : odd(x-1)}
    odd = proc {|x| x == 1 ? true : even(x-1)}

    In this case even definitely doesn't know about odd, and actually doesn't even
    know about even. Odd is aware of even though. At least that's how I have
    interpreted how ruby works. We get recursion with full methods, just not with
    anonymous procs. Is there any intention for support for this with anonymous
    procs? Perhaps though a different syntax? procrec or something?

    Charlie
    Charles Guest

  2. #2

    Default Re: Closures and Letrec

    Charles Comstock wrote: 

    Actually, even does know about even because Ruby sees an assignment to
    even. To let even know about odd, do this ...

    odd = nil
    even = proc {|x| x == 0 ? true : odd.call(x-1) }
    odd = proc {|x| x == 0 ? false : even.call(x-1)}

    By assigning to odd, ruby now knows that "odd" is a variable, not a
    method name. (Notice I changed the definition of odd to avoid infinite
    recursion for the false case.)

    --
    -- Jim Weirich net http://onestepback.org
    -----------------------------------------------------------------
    "Beware of bugs in the above code; I have only proved it correct,
    not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)


    Jim Guest

  3. #3

    Default Re: Closures and Letrec

    In article <cec.wustl.edu>,
    Charles Comstock <wustl.edu> wrote:
    : Is there a way to create recursive anonymous closures in ruby? For instance
    : if I write
    : even = proc {|x| x == 0 ? true : odd(x-1)}
    : odd = proc {|x| x == 1 ? true : even(x-1)}
    :
    : In this case even definitely doesn't know about odd, and actually doesn't even
    : know about even. Odd is aware of even though.

    Sure, you just have to remember about The Miracle Of Duck Typing, and
    make sure that both your variables are visible to each other.

    Since a proc is a method, you can call it. Since an object is an
    object, you can send messages to it. One such message is [] (which is
    an alias for Proc#call).

    Also, I found a bug in your code. :-)

    $even = proc { |x|
    case x
    when 0 then true
    when 1 then false
    else $odd[x-1]
    end
    }

    $odd = proc { |x|
    case x
    when 0 then false
    when 1 then true
    else $even[x-1]
    end
    }

    p $odd[3]
    p $even[4]
    p $odd[4]
    p $even[3]

    $odd isn't even defined when $even is set, but that doesn't stop
    Ruby: it doesn't worry about things like that until you're
    actually trying to call methods. By the time it actually gets
    around to trying to call methods against odd, odd is defined and
    you can call [] with no problems.

    --Dave
    Dave Guest

Similar Threads

  1. referencing, closures, classes
    By David McDivitt in forum PERL Miscellaneous
    Replies: 22
    Last Post: September 21st, 02:08 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139