0

I'm trying to implement currying as per the the Little Schemer example eq? given below. eq( test, testFor) takes in a test condition and an atom and returns a function based on the passed function test, which takes one argument to return a boolean.

Here is my code:

def eq( test, s)
    Proc.new { |x| test(s,x)}
end

eqToCarrot = eq(Proc.new{|x,y| x==y},"carrot")

if eqToCarrot.call("carrot")
    puts "Equal!"
end

The if condition is not executed. Can someone tell me why?

sawa
  • 165,429
  • 45
  • 277
  • 381
Aman Gupta
  • 557
  • 1
  • 8
  • 23

1 Answers1

2

To call test within your eq method, you need to use test.call instead of just test.

As is, the reason you're not getting an Undefined method or other error from your test(..) expression in eq is that there is a Kernel method named test which accepts 2 or 3 parameters.

To answer the question in your comment about how to return a proc which returns a proc, you "just do it". For example, you can return Proc.new {Proc.new {puts 'foo'}}.

And since proc variables can be passed around and returned like any other variable without concern for them being accidentally "invoked", if you pass in a proc variable as an argument, you can simply return that variable, as in Proc.new {|proc| proc}.

In your case, though, if you're trying to create a predicate based on an argument passed in, you can do the following:

def make_eq_proc(match_string)
  Proc.new {|arg_string| arg_string == match_string}
end

eq_carrot = make_eq_proc('carrot')

eq_carrot.call('carrot') # => true
Peter Alfvin
  • 28,599
  • 8
  • 68
  • 106
  • so how does a function return a proc which returns a proc? – Aman Gupta Sep 12 '13 at 18:24
  • I can't answer now, but if no one else gets back to you, I'll reply in a couple of hours. – Peter Alfvin Sep 12 '13 at 18:37
  • Actually I wanted to pass in the predicate as a proc also, is that possible? – Aman Gupta Sep 13 '13 at 17:25
  • @AmanGupta Sure. I'm a little lost, though, in terms of which proc in your "proc which returns a proc" accepts the predicate as a parameter. What are the method signatures of your two procs and the method signature of the predicate you want to pass in? – Peter Alfvin Sep 13 '13 at 17:30
  • okay basically I want a function that takes in a predicate ( a function that returns a bool) and an argument and returns a function that takes an argument that applies the predicate to the original argument. Am I being clear enough? – Aman Gupta Sep 13 '13 at 18:07
  • @AmanGupta Almost. :-) Does the predicate take two parameters - the original argument and the argument passed in to the function being returned? – Peter Alfvin Sep 13 '13 at 18:47
  • @AmanGupta Ok, what you just described matches your original definition of `eq`, modified to use `test.call` instead of `test`. But that's just a function that takes a proc and returns a proc that returns a boolean (resulting from an invocation of a predicate). That's not the same as returning a proc that returns a proc. – Peter Alfvin Sep 13 '13 at 18:52