SciRuby / iruby

Official gem repository: Ruby kernel for Jupyter/IPython Notebook
https://github.com/SciRuby/iruby
MIT License
890 stars 27 forks source link

Can a standard class method be overridden in Jupyter/Iruby? #326

Closed mrtodd closed 1 year ago

mrtodd commented 1 year ago

I was following along in the Programming Ruby book using a Jupyter notebook. One of the sample code snippets added (more likely modified -- I'm not sure they existed at the time the book was written) two methods, Array.sum and Array.product. When run inside a notebook, the results of the standard class definitions are displayed and not the methods defined in the notebook session. I copied the code from the cell with the new defs to a file and printed the results before and after the new definitions were made. This yielded the expected result when run in the command line ruby interpreter. I've attached the src and output files. Just the "class Array" block was what appeared in the notebook cell.

Is it possible to get an equivalent behavior in a notebook or are you stuck with the standard class definitions that exist when the backend is started?

test.rb.txt

#!/usr/bin/env ruby

a = [1,2,3,4,5]

puts "Before override:"
puts a.sum
puts a.product

class Array
  def inject(n)
    each { |value| n = yield(n, value) }
    n
  end

  def sum
    inject(0) { |n, value| n + value }
  end

  def product
    inject(1) { |n, value| n * value }
  end
end

puts "After override:"
puts a.sum
puts a.product

test.rb.out.txt

Before override:
15
1
2
3
4
5
After override:
15
120
kojix2 commented 1 year ago

Hi. @mrtodd Good question.

I ran your script and I too was a bit surprised at the results.

image

Yes I admit that the behavior is somewhat unexpected, but the reason why this occurs is easy to find out. type self, and you will see the result.

image

self is not main. So the monkey patch fails and instead Object::Array is defined.

If you use ::Array instead of Array, it works as expected.

image

mrtodd commented 1 year ago

@kojix2 Thank you for your for your very quick response. That makes it work. I haven't yet seen anything about "::" so I'll have to investigate that. -- Todd