Is there any possibility to establish in method_missing declaration in Ruby whether a given missing_method was called (without any arguments) using parentheses notation, ie:
foo.non_existing_method()
or using parentheses-less notation:
foo.non_existing_method
?
I need this to solve my very specific testing problem.
No.
Since both are exactly the same, there cannot possibly be a way to detect the difference.
It doesn't make sense anyway, since both are exactly the same, so there cannot possibly any behavorial difference, either.
If you could detect the difference, then you could also have your method behave differently, which would be extremely surprising to any user of that method.
Related
I thought it was kinda cool that super and super() offer different behaviours, with the latter calling the parent method without passing it arguments.
This is the first case I'm aware of of a ruby method/keyword that behaves differently depending on whether the () are included (more on that here).
Are there any other methods/keywords in the ruby programming language which exhibit different behaviour depending on whether the () are included?
It is impossible for a Ruby method to know what syntax was used for the message send, therefore, a method cannot possibly behave different depending on whether or not the message send includes ().
Methods in Ruby behave same whether you use parenthesis or not. According to the Ruby style guide, you can omit parenthesis after a method call when you don't pass any arguments. It's true that some Ruby programmers liberally omit parenthesis but this will not make their methods behave differently.
For example, array.pop doesn't need a bang to permanently alter the array. Why is this so and what was the reasoning behind developing these certain Ruby methods without this conformity?
Bang methods are most commonly used to distinguish between a dangerous and a safe version of the same method. Here are some example cases that one might want to distinguish with a bang/no-bang combination:
mutator methods - one version changes the object, the other one returns a copy and leaves the original object unchanged
when encountering an error, one version throws an exception while the other one only writes an error message to the log or does nothing
However, the convention is to leave the bang off if there is only one version that makes sense. For example, poping an array without actually changing it makes no sense. In this case, it would end up being a different operation: Array#last. A lot of methods change the object they are called on, for example setters. We don't need to write these with a bang either, because it's clear that they change the object.
Lastly, there are a few exceptions to this, where some developers might use a bang method without implementing a bang-less counterpart. In these cases, the bang is simply used as a way to making the method calls stand out visually. For example:
the method does something dangerous or destructive
the method does something unexpected
the method has a significant performance impact
The bang is used to distinguish between a dangerous and less dangerous version of the same method. There is only one pop method, so there is nothing to distinguish.
Note: the name of the method has absolutely nothing whatsoever to do with what it does. Whether a method is destructive or not depends on what code it executes, not what name it has.
A suffix of ! means that a method is a dangerous version of another method. For example, save! is the dangerous version of save. Dangerous could mean editing in place, doing something with more strict errors, etc. It is not required to use the ! suffix on a method that is dangerous, but doesn't need a safer counterpart. Additionally, this is just a naming convention, so Ruby does not restrict what you can and can't do if a method does or doesn't end with !.
There is a common misconception that every method that edits something in place should end with !. This is not true, ! is only needed when there is a more dangerous version of a method that already exists, and this does not necessarily mean that the dangerous method edits in place. For example, in Rails, ActiveRecord::Base#save! is a version of ActiveRecord::Base#save that performs validations.
The meaning of bang in Ruby is "caution". It means you should use the method with caution, nothing more. I cannot find the reference anymore, but people of authority said explicitly that bang ≠ destructive method. Bang is just a semantic element associated with caution. It is up to the programmer to weigh in everything and decide when to use bang.
For example, in my simulation gem, I use #step method to obtain the step size.
simulation.step #=> 0.42
and step! method to actually perform the simulation step.
simulation.step! #=> takes the simulation to the next time step
But as for #reset method, I decided that the word "reset" it's verbose enough and it is not necessary to use bang to warn the user that the simulation state will be destroyed:
simulation.reset #=> resets the simulation back to the initial state
P.S.: Now I remember, once upon a time, Matz said half jokingly that he regrets introducing methods with bang into Ruby at all, because bang is semantically so ambiguous.
I am submitting solutions to Ruby puzzles on codewars.com and experimenting with how locked into the testing enviroment I am for one of the challenges.
I can redefine the classes used to test my solution but they are defined by the system after I submit my code. If I freeze these objects, the system cannot write over them but a RunTime error is raised when it tries to.
I'm fairly new to Ruby, so I'm not sure which parts (other than falsiness and truthiness) are impossible to override. Can I use Ruby code to force modification of frozen objects to silently fail instead of terminate the program or is that bound up in untouchable things like the assignment operator or similar?
The real answer here is that if you might want to modify an object later, you shouldn't freeze it. That's inherent in the whole concept of "freezing" an object. But since you asked, note that you can test whether an object is frozen with:
obj.frozen?
So if those pesky RuntimeErrors are getting you down, one solution is to use a guard clause like:
obj.do_something! if !obj.frozen?
If you want to make the guard clauses implicit, you can redefine the "problem" methods using a monkey patch:
class Array
# there are a couple other ways to do this
# read up on Ruby metaprogramming if you want to know
alias :__pop__ :pop
def pop
frozen? ? nil : __pop__
end
end
If you want your code to work seamlessly with any and all Ruby libraries/gems, adding behavior to built-in methods like this is probably a bad idea. In this case, I doubt it will cause any problems, but whenever you choose to start hacking on Ruby's core classes, you have to be ready for the possible consequences.
In Ruby, there is a convention to have a method name end with a question mark to indicate that its return value is boolean. Why is boolean considered so special? Is there anything convenient if you know that a method's return value is particularly boolean? After all, in Ruby, you can insert all kinds of value returning (getter) methods into a conditional without caring whether it is boolean or not.
I think it is a waste to use the question mark just for indicating a boolean value. There should be more useful uses. I have plenty of use case where I want to have a pair of getter and setter methods, where the setter method should return self so that I can use it in a method chain. And naming them something like get_foo and set_foo looks cumbersome. Rather than following the convention, I am tempted to name a pair of getter and setter methods like this:
def foo?; #foo end
def foo v; #foo = v end
where the value of #foo is not (necessarily) boolean. (Besides potential criticism that breaking the convention will confuse other programmers), is there something wrong with doing that?
There is nothing special at all, it's just a convention. A question can be answered with "yes" or "no", but also with another stuff like someone's name.
By returning a boolean on methods with a question mark, it indicates it to be an explicit behavior.
If you make the answer be "yes" or "no", it's easy for the reader of your code to identify the behavior of your method without even looking at the implementation. On the other hand, if you make it return any other type, it is more difficult for the reader to understand your code without reading your class and method definition.
With a boolean there are only two possible answers. If the return value is not boolean it can be anything, which would not help at all. You would still need to look at the method implementation. You should always look further to understand some piece of code, but using this convention makes it simpler.
There is a convention to use question mark in method names to indicate that a method is a predicate. AFAIK, this predicate is not required (by the convention) to return a boolean value, thanks to simple rules for truthy/falsey values.
Besides potential criticism that breaking the convention will confuse other programmers, is there something wrong with doing that?
Confusing and surprising fellow programmers is bad. Ruby couldn't care less. It's just a convention. And conventions exist for a reason.
You can put anything in a flow control construct, but semantically booleans are appropriate. "If" in real human language typically takes a boolean, and the same is true of the construct in many programming languages. Ruby likes to make things convenient and assigns a "truthiness" value to everything in the language, which affects how it behaves in a boolean context.
In other words, booleans are the only things that are almost exclusively used for flow control, so the convention is to make them look "right" for flow-control constructs. It's their native environment.
(Besides potential criticism that breaking the convention will confuse other programmers), is there something wrong with doing that?
In the same sense that there is nothing wrong with naming all your variables after 1920s comedians, no, there's nothing wrong with that. But also in the same sense as naming all your variables after 1920s comedians, it isn't a very good idea. Nowhere in any language that I know of -- human or computer -- does the question mark mean "get." So the semantics of your code are off with that convention.
This question and the answers boil down to "POLS" AKA "Principle of Least Surprise".
A method name can be a random choice of letters and numbers separated by underscores, with '!', '?' and '=' sprinkled through them, if we chose to do so. They could be randomly created by the code at run time, and, as long as the rest of the code used the same arrangement of characters, the program would run and Ruby would be happy.
We humans, the programmers, determine the name of the methods used, to represent something, a characteristic or an action. Trying to use randomly named methods would lead to madness, or at least a very hard to maintain program. So, instead, we try to use sensible names for things. Sometimes they're verbs or adjectives, sometimes they're more descriptive because the method does several things.
As part of that naming, sometimes we want to provide additional hints about the behavior of the method. By convention in Ruby, we use "!" to warn the coder that the method changes something or is destructive. "=" indicates the method takes a parameter and assigns it to the receiver/object. It's a setter method and in many other languages it'd be idiomatic to use "set_flag..." or "set_value..." as the name. It's just a convention in that language, and followed by developers in the language.
We use "?" in Ruby to ask a question about an object, whether it is, or isn't, true about that object. We could say "is_true?" or "true?" and indicate we are testing whether something is true about it. If it's true, or false, it's a Boolean response so we return a true/false value.
As a Ruby programmer did you feel any time about any feature which is a bit risky to use, may be because of it's strange behaviour? It might be well documented but hard to find while debugging or counterintuitive to remember?
I generally try to stay away from String#gsub!. The doc says "Performs the substitutions of String#gsub in place, returning str, or nil if no substitutions were performed." So if there's nothing to substitute then it'll return nil. Practically I didn't see any use case where this comes handy.
SO, with your experience, is there anything else you'd like to add?
Using return in a lambda, Proc or block. The semantics are well defined, but you will get it wrong, and you will get a LocalJumpError.
The meta programming features of Ruby can be used in very dangerous ways. I've seen code that attempts to runtime-redefine common methods on code classes like String, or Array, and while I can see this being MAYBE acceptable for a tiny temporary script, I don't think it is remotely a good idea in a complex application with many dependancies, or many maintainers.
Well, the most widely abused dangerous feature of Ruby is certainly evaling strings. In vast majority of cases (if not all) it can be avoided using other methods, usually define_method, const_get, const_set etc.
throw/catch (not the same as begin/rescue!) is basically GOTO, and that could be considered to be a risky feature to use in any language.