ruby / rbs

Type Signature for Ruby
Other
1.95k stars 214 forks source link

_Callable interface in builtin #420

Open HoneyryderChuck opened 4 years ago

HoneyryderChuck commented 4 years ago

I was looking at https://github.com/ruby/rbs/blob/c64d1f5ba5a4fbc95ffb1d72d783ee39b17d60fe/stdlib/builtin/builtin.rbs, where a lot of common knownn interfaces are stored. I was wondering whether there should be one for "callable" objects, that is: implements #call. Objects implementing this interface can already be passed to places where are expected, for example.


interface _Callable
  def call: (*untyped) -> void
  alias [] call
end
marcandre commented 4 years ago

Maybe, but very few builtin methods take such a parameter. I can think of Enumerable#find (which is currently badly defined)

Note that the return type should not be void but top. Also the interface should not depend on []:

interface _Call
  def call: (*top) -> top
end

Still, it might be best not to, since the above interface is too lax, usually you will want to specify the type of inputs the call method should be expecting.

HoneyryderChuck commented 4 years ago

In the benefit of understanding, what does "top" stand for? I struggled a bit with the meaning of it.

Perhaps you're right, but a Callable with a T reference seems more suitable to my example. All things considered I might backtrack a bit on this until I come up with compelling use cases.

soutaro commented 4 years ago

If you have a specific method in your mind, like Enumerable#find, defining an interface would be better.

interface _NotFound[A]
  def call: () -> A
end

module Enumerable[X, Y]
  def find: [T] (_NotFound[T]) -> (X | T)
  ...
end
HoneyryderChuck commented 3 years ago

I had this in mind: https://docs.python.org/3/library/typing.html#callable

HoneyryderChuck commented 3 years ago

After thinking more about this, I think that I do not necessarily want a Callable interface, rather an "inline" way of saying "something implementing #call", i.e. I think that rbs could have syntactic sugar for defining these 1 method-interfaces.

  def callables: () -> Array[Imp[call:(*untyped) -> top]]

How that would look like, I have no idea :)