-1

I'm trying to write a utility library which tries to call a method on an arbitrary object type. In ruby, I'd do something like:

def foo(object)
  object.public_send(:bar)
rescue NoMethodError
  raise "Method not defined on object"
end

foo(instance_of_my_arbitrary_class)

I'm not sure how to do this in Crystal, as the type us unknown so I get a compiler error of Can't infer the type of instance variable 'object'.

How do I accomplish this without knowing the type of the object which will be passed?

pvg
  • 2,673
  • 4
  • 17
  • 31
Daniel Westendorf
  • 3,375
  • 18
  • 23

2 Answers2

1

I think I figured this out after by utilizing a module and including it.

module ArbitraryObject; end

class Arbitrary
  include ArbitraryObject
end

class MyLib
  def foo(object : ArbitraryObject)
    ... Code here ...
  end
end

MyLib.new(Arbitrary.new).foo
Daniel Westendorf
  • 3,375
  • 18
  • 23
1

In Crystal, you cannot call arbitrary method on arbitrary objects, as methods are resolved at compile time, not runtime. If the user tries to use your library method with an incompatible type he will get a compile-time error:

def foo(object)
  object.bar
end

class MyObj
  def bar
    puts "bar!"
  end
end

foo(MyObj.new) # => "bar!"

Here it works, as an instance of MyObj has the method bar. But if you use something that don't have that method, the user will get a compile-time error:

foo(3) # compile error: undefined method 'bar' for Int32

This error will be showned before the program execution.

bew
  • 483
  • 4
  • 9