In the following code I have two classes. When the Nation class is instantiated to an object, it also instantiates an object for the Population class with a reference to the nation object.
class Nation
def initialize(name)
#name = name
#population = Population.new(self)
end
end
class Population
def initialize(nation)
#nation = nation
end
end
pry(main)> n = Nation.new("Germany")
=> #<Nation:0x0000000b3179e0 #name="Germany", #population=#<Population:0x0000000b3179b8 #nation=#<Nation:0x0000000b3179e0 ...>>>
Is this the case of circular reference?
Is it something that should be avoided?
Why is the Ruby interpreter not giving any errors? Isn't this leading to a kind of infinite recursion? When I create object n, it comes with a reference to object p, which comes with a reference to object n, which comes with a reference to object p... so how is the interpreter not going is some kind of infinite loop, as when you have a recursive function, which eventually terminates with a stack too deep error?
How could I refactor code like this where objects need to know about each others?
It's an old question, but I didn't see a good answer, so taking a crack at it.
Having two objects reference each other is not a problem, just like having two people point finger at each other is not a problem. However, if somebody tries to follow these pointers, never realizing that they are going back and forth, then it's a problem.
When you ran this code:
pry(main)> n = Nation.new("Germany")
You created 2 objects that point at each other, there is no problem. However, because you wrote the above line in an pry session, ruby tried to output the resulting object for you to see…
=> #<Nation:0x0000000b3179e0 #name="Germany", #population=#<Population:0x0000000b3179b8 #nation=#<Nation:0x0000000b3179e0 ...>>>
… and this is a problem. When ruby renders and object like that, it traverses all the instance variables in the object recursively, and prints them out. Since your variables have a circular reference, this traversing could make ruby go back and forth forever. That is, if ruby never realizes that it's going back and forth.
So why did it stop?
Ruby's inspect can realize it's going back and forth. When ruby recursively traverses objects, it keeps track of objects it's already seen. As soon as it encounters the same object twice, it stops and outputs the ... to prevent any further looping.
Are circular references to be avoided?
It depends on what you're doing, and with which libraries. The most common reason to traverse objects recursively (besides inspecting them) is serialization into JSON, YAML, etc.
If you are going to serialize objects, it's best to avoid circular references. There are some libraries out there that have clever techniques to serialize circular references, but if you can help it, avoid additional complexity. Serialization is complex enough as it is.
Bottom line: circular references are good for runtime convenience, and bad for recursively traversing or serializing objects. Use it like a sharp knife, with extra care.
Isn't this leading to a kind of infinite recursion?
Nope, there's no infinite loop/recursion. You create a nation, it creates a population and that's it. However, if, when created, population were to create a nation too, that would lead to an infinite recursion. But in this form, the code is fine.
Is this the case of circular reference?
In most langs, yes, but not in ruby. Why?, ruby is an interpreted lang. Ruby check if a class exist only when it's required, if, for example, when you run one of both initialize. Before run initialize, ruby only check if there is no syntax error only
Is it something that should be avoided?
No IMHO.
Related
Although I agree that extending native types and objects is a bad practice, inheriting from them should not be.
In a supposedly supporting gem (that I could not find), the way that the native types were to be used would be as follows:
require 'cool-unkown-light-gem'
class MyTypedArray < CoolArray # would love to directly < Array
def initialize(*args)
super(*args)
# some inits for DataArray
#caches_init = false
end
def name?(name)
init_caches unless !#caches_init
!!#cache_by_name[name]
end
def element(name)
init_caches unless !#caches_init
#cache_by_name[name]
end
private
# overrides the CoolArray method:
# CoolArray methods that modify self will call this method
def on_change
#caches_init = false
super
end
def init_caches
return #cache_by_name if #caches_init
#caches_init = true
#cache_by_name = self.map do |elem|
[elem.unique_name, elem]
end.to_h
end
end
Any method of the parent class not overridden by the child class that modifies self would call, let's say (in this case), the on_change function. Which would allow to do not have to re-define every single one of those methods to avoid losing track on changes.
Let's say the MyTypedArray would array Foo objects:
class Foo
attr_reader :unique_name
def initialize(name)
#unique_name = name
end
end
a short example of the expected behaviour of its usage:
my_array = MyTypedArray.new
my_array.push( Foo.new("bar") ).push( Foo.new("baz") )
my_array.element("bar").unique_name
# => "bar"
my_array.shift # a method that removes the first element from self
my_array.element("bar").unique_name
# => undefined method `unique_name' for nil:NilClass (NoMethodError)
my_array.name?("bar")
# => false
I understand that we should search for immutable classes, yet those native types support changes on the same object and we want a proper way to do an inheritance that is as brief and easy as possible.
Any thoughts, approaches, or recommendations are more than welcome, of course. I do not think I am the only one that have thought on this.
The reason why I am searching for a maintained gem is because different ruby versions may offer different supported methods or options for native types / classes.
[Edit]
The aim of the above is to figure out a pattern that works. I could just follow the rules and suggestions of other posts, yet would not get things work the way I am intended and when I see it proper (a coding language is made by and for humans, and not humans made for coding languages). I know everyone is proud of their achievements in learning, developing and making things shaped in a pattern that is well known in the community.
The target of the above is because all the methods of Array are more than welcome. I do not care if in the version 20 of Ruby they remove some methods of Array. By then my application will be obsolete or someone will achieve the same result in far less code.
Why Array?
Because the order matters.
Why an internal Hash?
Because for the usage I want to make of it, in overall, the cost of building the hash compensates the optimization it offers.
Why not just include Enumerable?
Because we just reduce the number of methods that change the object, but we do not actually have a pattern that allows to change #caches_init to false, so the Hash is rebuilt on next usage (so same problem as with Array)
Why not just whitelist and include target Array methods?
Because that does not get me where I want to be. What if I want anyone to still use pop, or shift but I do not want to redefine them, or even having to bother to manage my mixins and constantly having to use responds_to?? (perhaps that exercise is good to improve your skills in coding and read code from other people, but that is not what it should be)
Where I want to be?
I want to be in a position that I can re-use / inherit any, I repeat, any class (no matter if it is native or not). That is basic for an OOP language. And if we are not talking about an OOP language (but just some sugar at the top of it to make it appear as OOP), then let's keep ourselves open to analyse patterns that should work well (no matter if they are odd - for me is more odd that there are no intermediate levels; which is symptom of many conventional patterns, which in turn is symptom of poor support for certain features that are more widely required than what is accepted).
Why should a gem offer the above?
Well, let's humble it. The above is a very simple case (and even though not covered). You may gain in flexibility at some point by using what some people want to call the Ruby way. But at a cost when you move to bigger architectures. What if I want to create intermediate classes to inherit from? Enriched native classes that boost simple code, yet keeping it aligned with the language. It is easier to say this is not the Ruby way than trying to make the language closer to something that escalates well from the bottom.
I am not surprised that Rails and Ruby are almost "indistinctly" used by many. Because at some point, without some Rails support, what you have with Ruby is a lot of trouble. As, consequently, I am not surprised that Rails is so maintained.
Why should I redefine a pop, or a last, or first methods? For what? They are already implemented.
Why should I whitelist methods and create mixins? is that a object or method oriented programming?
Anyway... I do not expect anyone to share my view on this. I do see other patterns, and I will keep allowing my mind to find them. If anyone is open enough, please, feel free to share. Someone may criticize the approach and be right, but if you got there is because it worked.
To answer your question as it is written, no, there is no gem for this. This is not a possibility of the language, either in pure Ruby or in C which is used internally.
There is no mechanism in detect when self is changed, nor any way to detect if a method is pure (does not change self) or impure (does change self). It seems you want a way to "automatically" be able to know when a method is one or the other, and that, to put simply, is just not possible, nor is it in any language that I am aware of.
Internally (using your example) an Array is backed by a RArray structure in C. A struct is simple storage space: a way to look at an arbitrary block of memory. C does not care how you choose to look at memory, I could just as easily cast the pointer of this struct and say it is a now a pointer to an array of integers and change it that way, it will happily manipulate the memory as I tell it to, and there is nothing that can detect that I did so. Now add in the fact that anyone, any script, or any gem can do this and you have no control over it, and it just shows that this solution is fundamentally and objectively flawed.
This is why most (all?) languages that need to be notified when an object is changed use an observer pattern. You create a function that "notifies" when something changes, and you invoke that function manually when needed. If someone decides to subclass your class, they need only continue the pattern to raise that function if it changes the object state.
There is no such thing as an automatic way of doing this. As already explained, this is an "opt-in" or "whitelist" solution. If you want to subclass an existing object instead of using your own from scratch, then you need to modify its behavior accordingly.
That said, adding the functionality is not as daunting as you may think if you use some clever aliasing and meta-programming with module_eval, class_eval or the like.
# This is 100% untested and not even checked for syntax, just rough idea
def on_changed
# Do whatever you need here when object is changed
end
# Unpure methods like []=, <<, push, map!, etc, etc
unpure_methods.each do |name|
class_eval <<-EOS
alias #{name}_orig #{name}
def #{name}(*args, &block)
#{name}_orig(*args, &block)
on_changed
end
EOS
end
In ruby, Array#delete(obj) will search and remove the specified object from the array. However, may be I'm missing something here but I found the returning value --- the obj itself --- is quite strange and a even a little bit useless.
My humble opinion is that in consistent with methods like sort/sort! and map/map! there should be two methods, e.g. delete/delete!, where
ary.delete(obj) -> new array, with obj removed
ary.delete!(obj) -> ary (after removing obj from ary)
For several reasons, first being that current delete is non-pure, and it should warn the programmer about that just like many other methods in Array (in fact the entire delete_??? family has this issue, they are quite dangerous methods!), second being that returning the obj is much less chainable than returning the new array, for example, if delete were like the above one I described, then I can do multiple deletions in one statement, or I can do something else after deletion:
ary = [1,2,2,2,3,3,3,4]
ary.delete(2).delete(3) #=> [1,4], equivalent to "ary - [2,3]"
ary.delete(2).map{|x|x**2"} #=> [1,9,9,9,16]
which is elegant and easy to read.
So I guess my question is: is this a deliberate design out of some reason, or is it just a heritage of the language?
If you already know that delete is always dangerous, there is no need to add a bang ! to further notice that it is dangerous. That is why it does not have it. Other methods like map may or may not be dangerous; that is why they have versions with and without the bang.
As for why it returns the extracted element, it provides access to information that is cumbersome to refer to if it were not designed like that. The original array after modification can easily be referred to by accessing the receiver, but the extracted element is not easily accessible.
Perhaps, you might be comparing this to methods that add elements, like push or unshift. These methods add elements irrespective of what elements the receiver array has, so returning the added element would be always the same as the argument passed, and you know it, so it is not helpful to return the added elements. Therefore, the modified array is returned, which is more helpful. For delete, whether the element is extracted depends on whether the receiver array has it, and you don't know that, so it is useful to have it as a return value.
For anyone who might be asking the same question, I think I understand it a little bit more now so I might as well share my approach to this question.
So the short answer is that ruby is not a language originally designed for functional programming, neither does it put purity of methods to its priority.
On the other hand, for my particular applications described in my question, we do have alternatives. The - method can be used as a pure alternative of delete in most situations, for example, the code in my question can be implemented like this:
ary = [1,2,2,2,3,3,3,4]
ary.-([2]).-([3]) #=> [1,4], or simply ary.-([2,3])
ary.-([2]).map{|x|x**2"} #=> [1,9,9,9,16]
and you can happily get all the benefits from the purity of -. For delete_if, I guess in most situations select (with return value negated) could be a not-so-great pure candidate.
As for why delete family was designed like this, I think it's more of a difference in point of view. They are supposed to be more of shorthands for commonly needed non-pure procedures than to be juxtaposed with functional-flavored select, map, etc.
I’ve wondered some of these same things myself. What I’ve largely concluded is that the method simply has a misleading name that carries with it false expectations. Those false expectations are what trigger our curiosity as to why the method works like it does. Bottom line—I think it’s a super useful method that we wouldn’t be questioning if it had a name like “swipe_at” or “steal_at”.
Anyway, another alternative we have is values_at(*args) which is functionally the opposite of delete_at in that you specify what you want to keep and then you get the modified array (as opposed to specifying what you want to remove and then getting the removed item).
I am working on a solution for technical drawings (svg/ruby). I want to manipulate rectangles, and have an add! method in this class:
class Rect
def add!(delta)
#x1+=delta
... # and so on
self
end
end
I also need an add method returning a Rect, but not manipulating self:
def add(delta)
r=self.dup/clone/"copy" # <-- not realy the 3 and no quotes, just in text here
r.add! delta
end
dup and clone don't do my thing but:
def copy; Marshal.load(Marshal.dump(self)); end
does.
Why does such a basic functionality not exist in plain Ruby? Please just don't tell me that I could reverse add and add!, letting add do the job, and add! calling it.
I'm not sure why there's no deep copy method in Ruby, but I'll try to make an educated guess based on the information I could find (see links and quotes below the line).
Judging from this information, I could only infer that the reason Ruby does not have a deep copy method is because it's very rarely necessary and, in the few cases where it truly is necessary, there are other, relatively simple ways to accomplish the same task:
As you already know, using Marshal.dump and Marshal.load is currently the recommended way to do this. This is also the approach recommended by Programming Ruby (see excerpts below).
Alternatively, there are at least 3 available implementations found in these gems: deep_cloneable, deep_clone and ruby_deep_clone; the first being the most popular.
Related Information
Here's a discussion over at comp.lang.ruby which might shed some light on this. There's another answer here with some associated discussions, but it all comes back to using Marshal.
There weren't any mentions of deep copying in Programming Ruby, but there were a few mentions in The Ruby Programming Language. Here are a few related excerpts:
[…]
Another use for Marshal.dump and Marshal.load is to create deep copies
of objects:
def deepcopy(o)
Marshal.load(Marshal.dump(o))
end
[…]
… the binary format used by Marshal.dump and Marshal.load is
version-dependent, and newer versions of Ruby are not guaranteed to be
able to read marshalled objects written by older versions of Ruby.
[…]
Note that files and I/O streams, as well as Method and Binding
objects, are too dynamic to be marshalled; there would be no reliable
way to restore their state.
[…]
Instead of making a defensive deep copy of the array, just call
to_enum on it, and pass the resulting enumerator instead of the array
itself. In effect, you’re creating an enumerable but immutable proxy
object for your array.
Forget marshalling. The deep_dive gem will solve your problems.
https://rubygems.org/gems/deep_dive
Why can't you use something like this:
new_item = Item.new(old_item.attributes)
new_item.save!
This would copy all the attributes from existing item to new one, without issues. If you have other objects, you can just copy them individually.
I think it's the quickest way to copy an object
I'm working on a code visualization tool and I'd like to be able to display the size(in lines) of each Class, Method, and Module in a project. It seems like existing parsers(such as Ripper) could make this info easy to get. Is there a preferred way to do this? Is there a method of assessing size for classes that have been re-opened in separate locations? How about for dynamically (Class.new {}, Module.new {}) defined structures?
I think what you're asking for is not possible in general without actually running the whole Ruby program the classes are part of (and then you run into the halting problem). Ruby is extremely dynamic, so lines could be added to a class' definition anywhere, at any time, without necessarily referring to the particular class by name (e.g. using class_eval on a class passed into a method as an argument). Not that the source code of a class' definition is saved anyway... I think the closest you could get to that is the source_locations of the methods of the class.
You could take the difference of the maximum and minimum line numbers of those source_locations for each file. Then you'd have to assume that the class is opened only once per file, and that the size of the last method in a file is negligible (as well as any non-method parts of the class definition that happen before the first method definition or after the last one).
If you want something more accurate maybe you could run the program, get method source_locations, and try to correlate those with a separate parse of the source file(s), looking for enclosing class blocks etc.
But anything you do will most likely involve assumptions about how classes are generally defined, and thus not always be correct.
EDIT: Just saw that you were asking about methods and modules too, not just classes, but I think similar arguments apply for those.
I've created a gem that handles this problem in the fashion suggested by wdebaum. class_source. It certainly doesn't cover all cases but is a nice 80% solution for folks that need this type of thing. Patches welcome!
According to Wikipedia, a monkey patch is:
a way to extend or modify the runtime
code of dynamic languages [...]
without altering the original source
code.
The following statement from the same entry confused me:
In Ruby, the term monkey patch was
misunderstood to mean any dynamic
modification to a class and is often
used as a synonym for dynamically
modifying any class at runtime.
I would like to know the exact meaning of monkey patching in Ruby. Is it doing something like the following, or is it something else?
class String
def foo
"foo"
end
end
The best explanation I heard for Monkey patching/Duck-punching is by Patrick Ewing in RailsConf 2007
...if it walks like a duck and talks like a duck, it’s a duck, right? So
if this duck is not giving you the noise that you want, you’ve got to
just punch that duck until it returns what you expect.
The short answer is that there is no "exact" meaning, because it's a novel term, and different folks use it differently. That much at least can be discerned from the Wikipedia article. There are some who insist that it only applies to "runtime" code (built-in classes, I suppose) while some would use it to refer to the run-time modification of any class.
Personally, I prefer the more inclusive definition. After all, if we were to use the term for modification of built-in classes only, how would we refer to the run-time modification of all the other classes? The important thing to me is that there's a difference between the source code and the actual running class.
In Ruby, the term monkey patch was
misunderstood to mean any dynamic
modification to a class and is often
used as a synonym for dynamically
modifying any class at runtime.
The above statement asserts that the Ruby usage is incorrect - but terms evolve, and that's not always a bad thing.
Monkey patching is when you replace methods of a class at runtime (not adding new methods as others have described).
In addition to being a very un-obvious and difficult to debug way to change code, it doesn't scale; as more and more modules start monkey patching methods, the likelihood of the changes stomping each other grow.
You are correct; it's when you modify or extend an existing class rather than subclass it.
This is monkey patching:
class Float
def self.times(&block)
self.to_i.times { |i| yield(i) }
remainder = self - self.to_i
yield(remainder) if remainder > 0.0
end
end
Now I imagine this might be useful sometimes, but imagine if you saw routine.
def my_method(my_special_number)
sum = 0
my_special_number.times { |num| sum << some_val ** num }
sum
end
And it breaks only occasionally when it gets called. To those paying attention you already know why, but imagine that you didn't know about the float type having a .times class-method and you automatically assumed that my_special_number is an integer. Every time the parameter is a whole number, integer or float, it would work fine (whole ints are passed back except when there is a floating-point remainder). But pass a number with anything in the decimal area in and it'll break for sure!
Just imagine how often this might happen with your gems, Rails plugins, and even by your own co-workers in your projects. If there's one or two little methods in there like this and it could take some time to find and correct.
If you wonder why it breaks, note that sum is an integer and a floating-point remainder could be passed back; in addition, the exponential sign only works when types are the same. So you might think it's fixed, because you converted bother numbers to floats ... only to find that the sum can't take the floating-point result.
In Python monkeypatching is referred to a lot as a sign of embarrassment: "I had to monkeypatch this class because..." (I encountered it first when dealing with Zope, which the article mentions). It's used to say that it was necessary to take hold of an upstream class and fix it at runtime instead of lobbying to have the unwanted behaviors fixed in the actual class or fixing them in a subclass. In my experience Ruby people don't talk about monkeypatching that much, because it's not considered especially bad or even noteworthy (hence "duck punching"). Obviously you have to be careful about changing the return values of a method that will be used in other dependencies, but adding methods to a class the way that active_support and facets do is perfectly safe.
Update 10 years later: I would amend the last sentence to say "is relatively safe". Extending a core library class with new methods can lead to problems if somebody else gets the same idea and adds the same method with a different implementation or method signature, or if people confuse extended methods for core language functionality. Both cases often happen in Ruby (especially regarding active_support methods).
Explanation of the concept without code:
It means you can "dynamically" modify code. Wanna add a method "dynamically" to a particular class known only at "runtime"? No problem. It's powerful, yes: but can be misused. The concept "dynamically" might be a little too esoteric to understand, so I have prepared an example below (no code, I promise):
How to monkey patch a car:
Normal Car Operations
How do you normally start a car? It’s simple: you turn the ignition, the car starts!
Great, but how can we "monkey patch" the car class?
This is what Fabrizzio did to poor Michael Corleone. Normally, if you want to change how a car operates, you would have to make those changes in the car manufacturing plant (i.e. at "compile" time, within the Car class ^**). Fabrizzio ain't got no time for that: he monkey patches cars by getting under the bonnet to surreptitiously and sneakily rewire things. In other words, he re-opens the Car class, makes the changes he wants, and he's done: he's just monkey patched a car. he done this "dynamically".
You have to really know what you are doing when you monkey patch otherwise the results could be quite explosive.
“Fabrizzio, where are you going?”
Boom!
Like Confucius Say:
"Keep your source code close, but your monkey patches closer."
It can be dangerous.
^** yes i know, dynamic languages.
Usually it is meant about ad-hoc changes, using Ruby open classes, frequently with low quality code.
Here's a good follow-up on the subject.