Created
March 8, 2014 11:54
-
-
Save nilium/9429363 to your computer and use it in GitHub Desktop.
Horrible hack to enable _s as placeholders in Ruby, similar to Scala.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A horrible hack to enable _ as placeholders in Ruby, similar to block behavior | |
# in Scala. | |
# | |
# Obviously breaks if used across multiple threads, though probably in subtle | |
# ways. The break can be mitigated by instead wrapping the arguments in an | |
# instance of something and then doing instance_exec, where _ is a method on | |
# the instance, but this messes up the block's binding. | |
# | |
# There's probably a way around it all, but it's honestly not worth the trouble | |
# and the typing saved isn't worth the utter confusion anything like this would | |
# inevitably cause. | |
def __anon_method__(args) | |
if 1 == args.length | |
-> (n = nil) do | |
raise ArgumentError, "No defined argument" unless n.nil? || 0 == n | |
args[0] | |
end | |
else | |
counter = 0 | |
-> (n = nil) do | |
if n.nil? | |
n = counter | |
counter += 1 | |
end | |
raise ArgumentError, "No defined arguments" unless args.length > n && 0 <= n | |
args[n] | |
end | |
end | |
end | |
def __define_shift_arg__(args) | |
method = if Object.method_defined?(:_) | |
Object.instance_method(:_) | |
end | |
Object.__send__(:define_method, :_, __anon_method__(args)) | |
if method | |
-> () { Object.__send__(:define_method, :_, method) } | |
else | |
-> () { Object.__send__(:remove_method, :_) } | |
end | |
end | |
def anon(obvious_block = nil, &block) | |
block ||= obvious_block | |
arity = block.arity | |
return block if arity < 0 | |
-> (*args) do | |
cleanup = __define_shift_arg__(args) | |
begin | |
case arity | |
when 0 then block.call | |
else block.call(*(args.shift(arity))) | |
end | |
ensure | |
cleanup.call | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment