What is ARGF.class in Ruby 1.9?
ARGF
is implemented in C and you can do weird things in it. The ARGF
class is defined there first. It is not set to any constant in Ruby, but its name is set to "ARGF.class".Then ARGF
constant is set to an instance of that class.
rb_cARGF = rb_class_new(rb_cObject);rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");/* ... */argf = rb_class_new_instance(0, 0, rb_cARGF);rb_define_global_const("ARGF", argf);
Here is a Ruby code that is doing roughly the same thing.
argf_class = Class.newdef argf_class.name "ARGF.class"endargf = argf_class.newARGF = argf
It does not look reasonable in Ruby, but in C it is fine. Although, I think the class could be set to ARGFClass
like NilClass
, TrueClass
, FalseClass
, so that it is not confusing.
I don't know the history of the change. I think Ruby core folks wanted to get ARGF
into the docs and this was the simplest way. (RDoc can't show documentation for singleton objects.)
It seems correct that ARGF
is not a class or a module.
class ARGFend# => TypeError: ARGF is not a classmodule ARGFend# => TypeError: ARGF is not a module
The documentation lists ARGF
under class, but other than that, it does not say it is a class. Probably, it was not intended that ARGF
handled as a class, and it is wrong of the documentation to have listed as such. It is the documentation's bug.
It looks like ARGF
if the only instance of a certain class, which lacks a literal, and the only way to refer to it is to call ARGF.class
.
ARGF.class.class# => ClassARGF.class.ancestors# => [ARGF.class, Enumerable, Object, Kernel, BasicObject]
The usual relation between class and its instance holds for ARGF.class
and ARGF
.
ARGF.is_a?(ARGF.class)# => trueARGF.kind_of?(ARGF.class)# => true
If we capture the objects and look at them using just pure Ruby we can see a few things:
1.9.3 (Object#main):0 > ARGFClass = ARGF.class => ARGF.class1.9.3 (Object#main):0 > ARGFClass.name => "ARGF.class"1.9.3 (Object#main):0 > ARGFClass.class => Class1.9.3 (Object#main):0 > ARGFClass.superclass => Object1.9.3 (Object#main):0 > ARGFClass.ancestors => [ARGF.class, Enumerable, Object, JSON::Ext::Generator::GeneratorMethods::Object, PP::ObjectMixin, Kernel, BasicObject]
For some reason, the developers have explicitly set the class.name value to return ARGF.class
, which is generally uncommon but is used internally in Ruby for constants that should never be accessed directly.
We can instantiate objects with the ARGFClass exactly the same as any other class. That means it is a real Ruby class:
1.9.3 (Object#main):0 > argfinstance = ARGFClass.new => ARGF1.9.3 (Object#main):0 > argfinstance.inspect => "ARGF"
It's not just returning the singleton when you call #new either:
1.9.3 (Object#main):0 > argfinstance == ARGF => false1.9.3 (Object#main):0 > argfinstance.object_id => 703465565074201.9.3 (Object#main):0 > ARGF.object_id => 70346552343460
The Ruby developers have intentionally named the ARGF.class
in such a way that it can't be referenced directly by name, but it is a real class and ARGF
is a real object.
It has a lot of the same methods as an IO object, and in fact is defined in the io.c
source file. It also has the Enumerable module mixed in so it supports all the each/inject/map functionality.
edit: The documentation lists ARGF
as a class. However, its actually a constant referencing a singleton instance of the oddly named ARGF.class
class.