Something I find extremely useful with Ruby is the ability to explore a class via a handful of reflection methods, such as .methods, .private_methods, .instance_methods, .private_instance_methods, etc.
In Ruby these methods are defined in Object and Module and are available to all classes, so one can, for example, use puts "I am a string".methods.sort to see what sorts of things you can do to a string
So, this is a wishlist request for an equivalent in Crystal. I don't know if this feasible to implement or not, but it would be awesome to have one day if possible.
This is something that we could add. However, I find that those methods are really useful in combination with a REPL, which is something that we lack and that we might not have for a long time.
In Ruby methods returns an array of symbols. In Crystal we could do the same, I guess...
Besides using it in a REPL to learn an API, what would you use it for?
By the way, we will allow listing a type's methods at compile time for metaprogramming, but that's a different issue :-)
I mostly use it as a quick reference, because sometimes I find what I want faster that way than going through API docs. Like when I was posting this feature request, I wanted to see what the whole list was (I usually only use a couple), and I found it faster to do ruby -e 'puts Object.methods.grep(/methods/).sort' than to search through ruby's API docs for the same information.
It's also useful for inspecting classes you've made, along with the methods used for inspecting class and instance variables (as shown with Object.methods.grep(/variables/).sort in Ruby), because you can see what methods and variables you inherited or mixed in with a quick one-liner instead of poking around in API docs and code.
Just a convenience thing I was surprised wasn't already implemented. If it's a PITA to implement or something nobody else would find useful, I won't lose any sleep over not having it. I just like my laziness enablers because I come from a Perl background. :)
You're right about it being useful with a REPL, but even without one, you can still do one-liners with crystal eval, or use a tool like _entr_ or _iwatch_ on a throwaway scratch file. For example, a quick echo test.cr | entr crystal test.cr sets up entr to watch the file test.cr for changes and, when the file changes, entr runs crystal test.cr, so you can write some quick test-code, save the file, and see the results pop up in the other term.
(The file watch trick works great as a substitute for a REPL, give it a try if you haven't before)
Another use case: minitest-like testing:
class MyTest < Minitest::Test
def test_something
end
end
With current Crystal, I can't extract the list of methods that start with test_ but with .methods we could. Thought it would be useless without the ability to self.send(:test_something). ie. that sounds like the same requirements than for a REPL.
You can already get the methods from within macros. This is enough for metaprogramming purposes, and I don't think we'll need these at runtime.
ICR is a pretty functional REPL and is starting to appear in frameworks like amber. It'd be really useful to be able to interrogate classes for their methods from the console. Would it be difficult or expensive to expose the access available in macros at runtime too?
@sgargan You can already do that if you need it in the context of ICR:
class Object
macro methods
{{ @type.methods.map &.name.stringify }}
end
end
puts Bool.methods
Most helpful comment
@sgargan You can already do that if you need it in the context of ICR:
https://carc.in/#/r/2nh7