Skip to content

Instantly share code, notes, and snippets.

@veelenga
Last active March 9, 2024 18:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veelenga/91fb751286b35f1b497f1a1c41228c06 to your computer and use it in GitHub Desktop.
Save veelenga/91fb751286b35f1b497f1a1c41228c06 to your computer and use it in GitHub Desktop.
Implementation of send method in Crystal using macros and procs. Just a proof of concept.
class Object
macro inherited
@@methods = {} of String => Proc({{@type}}, Nil)
macro method_added(method)
\{% if method.visibility == :public %}
%key = \{{ method.name.stringify }}
@@methods[%key] = ->(obj : \{{@type}}) {
obj.\{{ method.name }}()
nil
}
\{% end %}
end
protected def self.proc(obj, name)
@@methods[name]?.try &.call(obj)
end
end
def send(method_name)
{{@type}}.proc(self, method_name.to_s)
end
end
class Foo
def foo
puts "Foo!"
end
def bar
puts "Bar!"
end
def baz
puts "Baz!"
end
end
foo = Foo.new
[:foo, :bar, :baz].each { |m| foo.send m }
# Foo!
# Bar!
# Baz!
# foo.send ARGV[0]
@veelenga
Copy link
Author

veelenga commented Sep 1, 2017

This is a dummy alternative of send method. Keep in mind, it is inefficient and violates Crystal best practices. Does not allow you to pass arguments, does not work with method overloading and could have other limitations.

Made for fun ;)

How it works

It uses method_added to fill the hash with procs that call methods.

send method just retrieves required proc from the hash and makes a call.

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