Is it possible to access "main:Object" in Ruby? - ruby

I really don't know how else to entitle this one. Anyway, I am doing some metaprogramming in Ruby, and while I was debugging I came across a reference to "main:Object".
This got me thinking, if Ruby classes are never fully closed and I can reopen them later for any reason, is it possible to access this "main:Object"? if this is really an Object is should be possible just like any other class/object? If it is not, then why not? Is this a truly protected space? Either way, I want to know if I can access it from anywhere in Ruby. And if so how? And if not why not?
Other than the interpreter complaining about something not being in there, I haven't really many any references or info about this. I mean other than this is the top level scope. But this is not really what I want to know.
There really isn't much out there, these posts below talk about what it is.
Is there a “main” method in Ruby like in C?
What is “main” in Ruby?
I know this doesn't give you action items work with but I do hope that some of the experts the like share their knowledge here in StackOverflow might share it and we (I) can all learn something new.
Anyway, thanks in advance. And if this is not the correct forum please let me know which one is.

It is an instance introduced by irb/pry REPLs or Ruby interpreter on the top level, outside of any other declaration. You might check how does it do:
self
#⇒ main
self.class
#⇒ Object
self.__id__
#⇒ 47421128700280
When you type def foo; 42; end you actually extend this object.

TOPLEVEL_BINDING (definition) is your friend:
def m1
class << TOPLEVEL_BINDING.receiver
def m2
puts 'm2'
end
end
# or
# main = TOPLEVEL_BINDING.receiver
# def main.m2
# puts 'm2'
# end
end
m1
m2 # => m2
Alternatively, you can use TOPLEVEL_BINGING.eval('self') in place of TOPLEVEL_BINGING.receiver.

Related

Specify Ruby method namespace for readability

This is a bit of a weird question, but I'm not quite sure how to look it up. In our project, we already have an existing concept of a "shift". There's a section of code that reads:
foo.shift
In this scenario, it's easy to read this as trying to access the shift variable of object foo. But it could also be Array#shift. Is there a way to specify which class we expect the method to belong to? I've tried variations such as:
foo.send(Array.shift)
Array.shift(foo)
to make it more obvious which method was being called, but I can't get it to work. Is there a way to be more explicit about which class the method you're trying to call belongs to to help in code readability?
On a fundamental level you shouldn't be concerned about this sort of thing and you absolutely can't tell the Array shift method to operate on anything but an Array object. Many of the core Ruby classes are implemented in C and have optimizations that often depend on specific internals being present. There's safety measures in place to prevent you from trying to do something too crazy, like rebinding and applying methods of that sort arbitrarily.
Here's an example of two "shifty" objects to help illustrate a real-world situation and how that applies:
class CharacterArray < Array
def initialize(*args)
super(args.flat_map(&:chars))
end
def inspect
join('').inspect
end
end
class CharacterList < String
def shift
slice!(0, 1)
end
end
You can smash Array#shift on to the first and it will work by pure chance because you're dealing with an Array. It won't work with the second one because that's not an Array, it's missing significant methods that the shift method likely depends on.
In practice it doesn't matter what you're using, they're both the same:
list_a = CharacterArray.new("test")
list_a.shift
# => "t"
list_a.shift
# => "e"
list_a << "y"
# => "sty"
list_b = CharacterList.new("test")
list_b.shift
# => "t"
list_b.shift
# => "e"
list_b << "y"
# => "sty"
These both implement the same interfaces, they both produce the same results, and as far as you're concerned, as the caller, that's good enough. This is the foundation of Duck Typing which is the philosophy Ruby has deeply embraced.
If you try the rebind trick on the CharacterList you're going to end up in trouble, it won't work, yet that class delivers on all your expectations as far as interface goes.
Edit: As Sergio points out, you can't use the rebind technique, Ruby abruptly explodes:
Array.instance_method(:shift).bind(list_b).call
# => Error: bind argument must be an instance of Array (TypeError)
If readability is the goal then that has 35 more characters than list_b.shift which is usually going dramatically in the wrong direction.
After some discussion in the comments, one solution is:
Array.instance_method(:shift).bind(foo).call
Super ugly, but gets across the idea that I wanted which was to completely specify which instance method was actually being called. Alternatives would be to rename the variable to something like foo_array or to call it as foo.to_a.shift.
The reason this is difficult is that Ruby is not strongly-typed, and this question is all about trying to bring stronger typing to it. That's why the solution is gross! Thanks to everybody for their input!

Is there a short way to write `{|x| x}`?

We often shorten a block using the & notation on a symbol like this:
some_array.group_by(&:foo)
Is there a similar way to shorten expressions like {|x| x}?
some_array.group_by{|x| x}
If there were a method Object#self that returns self, then we can do
some_array.group_by(&:self)
but unfortunately, there is no such method. In terms of the number of characters, it may be longer, but readability improves.
Yes. #itself was implemented in Ruby 2.2.0.
You can access the Ruby core team discussion about this feature here.
As an interesting analogue, the #ergo method has been proposed, which would yield the receiver to a given block.
If you haven't yet upgraded to Ruby 2.2.0, you may wish to backport #itself and/or define #ergo as follows:
class Object
def itself; self end
def ergo
fail ArgumentError, "Block expected!" unless block_given?
yield self
end
end
And then:
some_array.group_by &:itself
Well, there's no built-in as far as I know, but you can make a reusable identity block:
id = Proc.new {|x| x}
some_array.group_by(&id)
And then if you really wish this were a language feature:
class Object
def it
Proc.new {|x| x}
end
end
And then you can do:
some_array.group_by(&it)
wherever you like. This may void your warranty.
Yes! The method Kernel#itself was added in Ruby 2.2.0. This method simply returns the object it was called on, so you can write:
some_array.group_by(&:itself)
You can see the extensive discussion of this feature here: https://bugs.ruby-lang.org/issues/6373. The patch was submitted by Rafael França in message #53. You can see it in the official Ruby source by looking in object.c.
If you are using a version of Ruby older than 2.2.0, you can easily add Kernel#itself into your project by putting this code somewhere in your project and making sure it gets required:
module Kernel
def itself
self
end
end if !Kernel.instance_methods.include?(:itself)
However, monkey-patching a part of the Ruby core like that can be dangerous and I would not recommend it if you are making reusable code, like a gem. Instead I would recommend just making your own identity function, as suggested by user2246674:
module MyLibrary
IDENT = Proc.new { |x| x }
array.group_by(&IDENT)
end

Is type conversion possible with inheritance in Ruby?

I'm using Ruby, and writing classes with inheritance.
For example:
class Canine
def initialize
end
def make_noise
puts "whoosh whoosh"
end
end
class Dog < Canine
def initialize
end
def make_noise
puts "wong wong"
super
end
end
Now I have a dog object:
jack = Dog.new
Is it possible to call the make_noise() method of Canine through the dog object?
In other languages it would be a typecast, something like:
(Canine)jack.make_noise
Note this is not Ruby syntax, hence, my question.
Is it possible to do this in Ruby? And if so, how?
You can do something like this:
Canine.instance_method(:make_noise).bind(jack).call
A better plan would be to just give the method in the super class an alias, or rename it.
Ruby does not allow casting or conversion in this fashion, at least not in the conventional sense. This is rarely necessary anyway, since Ruby is based on duck typing and not a rigid type system.
Are you expecting "whoosh whoosh" from the call? That's something that would only happen with non-virtual methods in a more strictly typed language like C++. It goes against proper object oriented design.
If you explore the design patterns employed in object-oriented design, you can always solve this sort of problem another way.
What you might want here is a presenter to handle the make_noise functionality.
Otherwise you'll need to write a to_canine method that can convert to the base type, though it's still not clear why you'd need such a thing.
You can do it like this:
d = Dog.new
d.class.superclass.instance_method(:make_noise).bind(d).call
or
Canine.instance_method(:make_noise).bind(d).call
. . . not pretty! I'm not sure if there's a better way
Edit: I think I agree with other answers here, in that Ruby's approach to OO will give you access to other patterns that achieve whatever goals this construct might help you with (perhaps in other languages). I don't see this kind of class/superclass method munging in practice on projects I have been involved in.
I am not sure why you need this, depending on needs it may be done totally differently, but with limited knowledge I would suggest this
class Dog < Canine
def initialize
end
def make_noise only_parent=false
puts "wong wong" if !only_parent
super
end
end
or
class Dog < Canine
def initialize
end
alias :make_super_noise :make_noise
def make_noise
puts "whoosh whoosh"
super
end
end

How do string literals in ruby bypass new/initialize, and is there a way to instrument this?

I was playing with an idea this afternoon, and stumbled into something I don't quite understand. Basically what I'm trying to achieve in this experiment is to somehow know every time a string is created (for later use, such as in some kind of DSL). The following works fine for any String that is created via String.new:
class ::String
class << self
alias_method :new_orig, :new
def new(*args)
o = new_orig(*args)
puts "newing '#{o}'"
o
end
end
alias_method :initialize_orig, :initialize
def initialize(*args)
initialize_orig(*args)
puts "initializing '#{self}'"
end
end
e.g.
irb > String.new("foo")
initializing 'foo'
newing 'foo'
=> "foo"
What I can't figure out is how a String object is created when you use a literal. For example, why does this not go through the same initialization and setup:
irb > "literal string"
=> "literal string"
I realize that the compiler is doing something or other differently when a string is literal, but doesn't it need to be initialized, simply to be a fully functional object? Are there any tricks that I could use to determine when a string is created using a literal, or is that impossible to do?
Thanks!
I think that from the discussion it follows, that hardly anyone here will give you genuine answer, unless Chris Heald wakes up and actually looks at that source code as he promised. But if, as you say in your comment to your question, the purpose is 'testing the boundaries of what the language can do to have some fun and learn something new', then let me introduce you - as much as I hate SlideShare - to this Ruby presentation by famous esoteric programmer Yusuke Endoh.

How can I splattify an anonymous object so I can use &method on it?

I'm wanting to use the &method(:method_name) idiom when there's more than one object required by method_name. Can I do this under Ruby 1.9?
For example, if I've got
def move_file(old_filename, new_filename)
STDERR.puts "Moving #{old_filename.inspect} to #{new_filename.inspect}"
# Implementation for careful moving goes here
end
old_filenames = ["foo.txt", "bar.txt", "hoge.ja.txt"]
new_filenames = ["foo_20110915.txt", "bar_20110915.txt", "hoge_20110915.ja.txt"]
the code
old_filenames.zip(new_filenames).each(&method(:move_file))
works under Ruby 1.8, but not under Ruby 1.9. Under Ruby 1.9, it's trying to do move_file(["foo.txt", "foo_20110915.txt"]) instead of move_file("foo.txt", "foo_20110915.txt").
How do I splattify it so it has the correct arity?
Workarounds I'm aware of:
Replace def move_file(old_filename, new_filename) with def move_file(*arguments)
Replace each(&method(:move_file)) with
each{|old_filename, new_filename| move_file(old_filename, new_filename)}
Instead
each{|old_filename, new_filename| move_file(old_filename, new_filename)}
you should be able to do
each{|pair| move_file(*pair)}
But I don't know how you'd pull off blockless variant (I needed it couple of times as well). I guess &-shorthand was made to make the syntax simpler, and is not meant to be clogged much (whether it will be passed an array as an array, or splatted, for example). :)
How do I splattify it so it has the correct arity?
I don't think there is a way to do this while being compatible to both Ruby versions. What you could do is wrap it into a lambda
move_from_to = Proc.new {|*both| move_files(*both) }
The thing is - block and proc arity is something that got addressed in Ruby 1.9 so there might be a difference in behavior there. Also see prc.lambda? here http://www.ruby-doc.org/core/classes/Proc.html for info on what it does to the arity.
This question is also related to what you want to do (the solution there is to resplat and unsplat manually): Inconsistency of arity between Hash.each and lambdas

Resources