Skip to content

Instantly share code, notes, and snippets.

@samnang
Created October 12, 2011 18:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save samnang/dd8f3d26546d506df6fe to your computer and use it in GitHub Desktop.
Save samnang/dd8f3d26546d506df6fe to your computer and use it in GitHub Desktop.
Method takes multiple blocks

MethodCallbacks

MethodCallbacks helps you to pass multi blocks to a method, and lets the method calls yeild for each one. Let's see examples:

require_relative 'ext_proc.rb'

def sum(a, b, &block)
  result = a + b
  block.yield(:success, result)
rescue Exception => e
  block.yield(:failure, e)
end

sum(3, 2) do
  _(:success){ |result|
    puts "Total sum is: #{result}"
  }

  _(:failure){ |exception|
    # Never get calls because calculation went ok
  }
end

sum('3', 2) do
  _(:success){ |result|
    # Never get calls because calculation went bad
  }

  _(:failure){ |exception|
    puts "Something went wrong with calculation: #{exception.message}"
  }
end
class Proc
def _(name, &block)
@_callbacks ||= Hash.new
@_callbacks[name] = block
end
def yield(name, *args)
instance_eval(&self) unless @_callbacks
@_callbacks[name] and @_callbacks[name].call(*args)
args
end
end
@rogerbraun
Copy link

Like the simplicity!

@JEG2
Copy link

JEG2 commented Oct 17, 2011

Why not just support the names directly, without the leading _?

@jeremyevans
Copy link

Use of instance_eval limits the usefulness in more complex cases, and monkey-patching Proc isn't great, but I like the simplicity.

@Keoven
Copy link

Keoven commented Oct 18, 2011

Real nice and clean.... was wanting to use some special character as a definition name for my entry but dropped it. The use of _ is nifty although I usually relate that to private methods, if only & or * can be used as definition names. :))

@samnang
Copy link
Author

samnang commented Oct 18, 2011

@JEG2, I thought to use only method name in my first start here:
https://gist.github.com/dd8f3d26546d506df6fe/a5838ff29238faa533158ae83d1c88f50abcb611

But later on I realize, I have to define those method(:success and :failure) in Proc class before hand, so I don't like that because it doesn't scale. After that I was thinking about using method_missing to get it supports that, but I feel not good about method_missing because it could make Proc class becomes messy. Finally, I found _(underscore) is valid syntax for method calls for minimun character and doesn't conflict with others, that's why I choose it.

@ericgj
Copy link

ericgj commented Oct 18, 2011

I like this a lot @samnang. Did you think about subclassing Proc rather than monkey-patching? I think this would also help with Jeremy's concern about instance_eval, because then you could call super instead.

You might also take an idea from Jeremy's solution, and allow blocks to be passed to
your #yield method and then pass them on to your callbacks (if you can do it without getting dizzy!)

PS. I can't think of a case it would be a conflict, but IRB uses _; what about unary minus or something (I forget the syntax - def -@ or something?)

@samnang
Copy link
Author

samnang commented Oct 19, 2011

@ericgj, I'm not so fun of monkey-patch as well, that's why I try to keep it minimum. The reason I use it because I want to get in defined methods and client codes looks simplicity. I don't come up idea how to use subclassing to make client code calls still look the same.

You are right, I forget in IRB, it is used for last result for evaluation. I tried different characters of those as well, but they are invalid for method calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment