Feature #13913
openMethod definition with explicitly callable method names
Description
There are many cases to expect that arguments should respond to a/some methods like this:
def call_foo(arg)
if !(arg.respond_to(:to_s) and arg.respond_to(:to_a) and arg.respond_to(:readpartial))
raise ArgumentError, "interface mismatch"
end
end
This is very frequent pattern, and I'm very happy to write this code in very short lines like this:
def call_foo(arg|to_s,to_a,readpartial)
# ...
end
This feature looks very useful and have space to analyze statically and to optimize dynamically.
And, there may be possibility to allow to have method overriding.
What do you think about this idea?
Updated by matz (Yukihiro Matsumoto) about 7 years ago
Evan Phoenix and others (including me) once discussed structural interface check instead of nominal check done by isa?
. It hasn't become concrete but the idea is similar to your proposal. The discussed API was like:
arg.conform(InterfaceModule)
that checks arg
to have methods described in InterfaceModule
.
At the moment, I am more tempted by type inference. But you may want to discuss the issue further.
Matz.
Updated by tagomoris (Satoshi Tagomori) about 7 years ago
I cannot understand "But you may want to discuss the issue further." correctly... But,
Biggest thing of my idea is "there's no need to name the interface (a set of methods)".
In Ruby ecosystem, there are many cases that an argument is expected to respond to just one method:
-
call
for Rack middleware object -
each
for Rack body object (3rd member of Rack handler return value)
IMO most important thing is there's no need to name them. The only required is just a set of methods.
I think this feature is not easy to implement in Ruby, but I'm happy if it's an option for typing of Ruby3.
Updated by shevegen (Robert A. Heiler) about 7 years ago
I cannot understand "But you may want to discuss the issue further." correctly.
I think it means that matz has not made up his mind completely yet, not so much
about the feature itself, but how to implement it.
I do not have a good proposal either. I think that both suggestions have advantages
and disadvantages. The suggestion with the '|' is simple, so that the information
is right there within the method "signature" - just an array. The disadvantage is
that the '|' is used, and I don't know if this is good or bad, but it is definitely
a change. (If the syntax is changed then I think it should be a target for ruby 3.x)
Matz' suggestion has the advantage of simpler syntax or at the least not a syntax
change (such as no '|') but one disadvantage may be that one has to look to the
module/interface specification yes? To find out what it may require and where that
information may be defined. This may be a very minor issue, but I only mention it
to compare it with the above proposal where the information would be part of the
method signature. (I am not sure if I like the '|' character but I think that this
is a secondary issue - one could, in principle, try to use something else ... or
even attach an additional signature to methods. But I guess that is all for
ruby-3.x ideas).
It is not easy to come up with a better syntax by the way; I tried to, but it is
difficult. Making changes to syntax used within arguments to methods is not trivial.
For example:
def foobar(argument|a,b,c)
def foobar(argument { respond_to: [:a,:b,:c] } )
I find my suggestion on the second line to be too verbose and too packed with sigil
stuff. The {} in Ruby is also already having lots of information ... it can be a
block ... or a hash ... so in the above situation, I guess it would be a block,
and a special Symbol here :respond_to but I do not know how good it will be to
add symbols with special meaning to ruby core, even though I use symbols in my
own code a lot to indicate special behaviour ...) :)
If it is for ruby 3.x then perhaps one could add a signature indication before a
method definition. Matz gave an example of conform(), I think similar alternatives
could perhaps be used. Perhaps a generic way to decorate/modify arguments for a
method, a bit similar to how ruby uses some hook-definitions (included, extended,
prepended, inherited ...) in theory one could also have something similar to this
for methods.
I think that one problem with the '|' variant is ... how many arguments can you
pass into it? It would mean that you can pass in only one argument? Since
foobar('2','3','4') invocation would no longer work? Or would it be more like
*argument, and we would check whether the whole Array conforms to the interface
specification?
I think most will agree that the idea is useful, just how to find a way to make
it integrated is not trivial. To me the biggest difficulty is in finding a good
idiom syntax-wise to express the ruby hacker's wish to specify interface-behaviour
for arguments to some methods (I guess many other methods will not need it, so
this should also be kept in mind).
Updated by hsbt (Hiroshi SHIBATA) about 7 years ago
- Has duplicate Bug #13912: Method definition with explicitly callable method names added
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
- Tracker changed from Bug to Feature
- Backport deleted (
2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN)