Getting basic data from Ruby itself?

I'm building my study tools for the Ruby certification exam. Is there a way to query Ruby itself for:

  Key words (def, begin, end, etc)
  What those key words do
  The list of built-in modules and classes
  The standard library modules
  
Some things seem to have ri documentation, some I just haven't figured out how to get yet. I do not want a web page with the data, but a web tutorial on how to get it would be great.

Thanks!

Leam

I'm building my study tools for the Ruby certification exam. Is there a
way to query Ruby itself for:

        Key words (def, begin, end, etc)
        What those key words do

No. Keywords aren't objects in Ruby, so there is no way to do anything
with them. Ruby is an object-oriented language, in order to be able to
do anything with something, that something needs to be an object.
(Pretty much the only exception are variables; they aren't objects,
but you can bind them and dereference them. That is however the only
two things you can with them. You can't store a variable in a
variable, you can't send a message to a variable, you can't return a
variable.)

There is a file in the YARV source code repository that briefly lists
and documents keywords:
https://github.com/ruby/ruby/blob/master/doc/keywords.rdoc . This is
also rendered on https://ruby-doc.org/ :
https://ruby-doc.org/core/doc/keywords_rdoc.html . Unfortunately, the
inter-document links don't work, neither on GitHub nor on Ruby-Doc.
You will have to manually follow them, e.g. by using the "Raw" view on
GitHub: https://raw.githubusercontent.com/ruby/ruby/master/doc/keywords.rdoc

There is also a file on https://ruby-doc.org/ that basically uses the
trick of documenting the keywords as methods and then generating RDoc
documentation from it: https://ruby-doc.org/docs/keywords/1.9/ .

Note that both of these resources haven't been updated in a really
long time, although I also cannot remember any new keywords being
added since then. (However, `case` has learnt a new trick in Ruby 2.7,
but that is still experimental and thus technically not "Ruby".) Also,
obviously, neither of the two meets your criteria of "querying Ruby
itself". Both are just documentation written by (fallible) humans.

        The list of built-in modules and classes

You can get somewhat close. You need to make sure that you don't load
any non-core libraries, then just return

    Objectspace.each_object(Module).to_a

E.g. by running

    ruby --disable-gems --disable-did_you_mean --disable-jit -e 'p
ObjectSpace.each_object(Module).to_a'

at a shell prompt.

However, note that this will *not* return all core modules and classes
but rather all modules and classes that exist without explicitly
loading any additional code. Which is not the same thing. For example,
when you run this on YARV, it will among others return the following
modules and classes:

    ::RubyVM
    ::RubyVM::InstructionSequence
    ::RubyVM::AbstractSyntaxTree
    ::RubyVM::AbstractSyntaxTree::Node
    #<Class:RubyVM::AbstractSyntaxTree>
    ::RubyVM::MJIT
    #<Class:RubyVM::MJIT>

These are all private internal implementation details of YARV and are
*not* part of core Ruby. Note that we even get classes related to
MJIT, although we *explicitly disabled* the JIT compiler. (Which is
actually disabled by default, I only added that option for clarity.)

If you were running the same on JRuby, you would get the top-level
`::JRuby` module instead of `::RubyVM`, if you try it on TruffleRuby,
you would get `::TruffleRuby`, if you try it on Rubinius, you would
get `::Rubinius`. In fact, I haven't tried it, but on implementations
like JRuby or Opal, you might even get the whole Java or ECMAScript
class hierarchy as well.

You will also note that there are some *singleton classes* in the
list, but only a few. However, technically, *every object* has
*always* a singleton class. (With very few exceptions such as
`Integer`s, `true`, `false`, `nil`, `Symbol`s.) YARV will instantiate
those lazily, which is why they don't show up in `ObjectSpace` (which
is essentially the garbage-collected memory), but depending on your
exact definition of "class" and "core Ruby", they are part of core
Ruby.

Note also that it isn't even obvious what "core Ruby" *is*. In fact,
it isn't even obvious what "Ruby" is.

We have

* the ISO Ruby Language Specification (https://iso.org/standard/59579.html)
* the book *The Ruby Programming Language* written by David Flanagan
and Yukihiro "matz" Matsumoto
* the book *Programming Ruby*
* the Ruby Spec Suite (https://github.com/ruby/spec)
* what YARV does
* what matz considers to be "Ruby" in his head
* what the community collectively considers to be "Ruby"

Any single one of these, any combination of any of these, the
intersection of some of these, the union of some of these, … they
*all* could, by someone, somewhere, for some reason, reasonably be
called "Ruby".

        The standard library modules

No, there is no way to get those. In order to make them available in
Ruby, you need to load them first. Then, you can get them the same way
as the core ones. Just save the core ones in an array and subtract,
then you get only the newly loaded ones.

But, this will also fail in some cases. E.g some standard libraries
only monkey-patch existing core modules and classes. Obviously, you
won't catch those, since the modules and classes will be the same
before and after loading the library.

Your best bet is to simply look at the documentation.

But also here, we run into a question of definitions. For example,
YARV is currently undergoing a process that is colloquially known as
"the gemification of the standard library", where lots of what used to
be standard libraries are split out into separate gems. Some of those
gems that are split out, are then again turned into "bundled gems",
i.e. gems that are installed together with YARv and don't need to be
explicitly installed. Now, do you count bundled gems as part of the
standard library or not?

For additional complexity, many Ruby implementations have their own
copy of the standard library. For even more complexity, some Ruby
implementations share a common standard library derived from
Rubinius's (which was actually gemified long before YARV started
gemifying its standard library, and this entire standard library is,
in fact, itself a gem: https://github.com/rubysl ). And to make
matters really complex, while this standard library is used by several
Ruby implementations, it is *not* used by YARV, which is the most
widely-used one.

I hope this didn't confuse you too much :smiley:

Cheers,
    Jörg.

···

Leam Hall <leamhall@gmail.com> wrote: