In /rails/lib/rails.rb there is an idiom with the logical && operator:
def root
application && application.config.root
end
What is the meaning of this idiom? It seems to do some control flow, to only return application.config.root if application exists or something like that?
In ruby, logical operators are "lazy".
Consider the following:
def one
puts "Called method one"
false
end
def two
puts "Called method two"
true
end
puts "Calling one, then two:"
one && two
puts
puts "Calling two, then one:"
two && one
It gives this output:
Calling one, then two:
Called method one
Calling two, then one:
Called method two
Called method one
See what happened? When it called one and got false, it didn't even bother calling method two -- because it already knew that the final result would be false. (false && false == false && true == false.)
Now let's look back at the original code you posted:
def root
application && application.config.root
end
What happens if application == nil? This code doesn't even bother evaluating the right hand side. Since nil && literally_anything == nil.
In other words, this is a safe-guard. It prevents the code from failing if application == nil. It's (not exactly, but basically) equivalent to writing this:
def root
return nil if application == nil
application.config.root
end
According to widely-used ruby style guides, https://github.com/rubocop-hq/ruby-style-guide#if-as-a-modifier, need to prefer modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/|| (i.e. what you're asking about).
# bad
if some_condition
do_something
end
# good
do_something if some_condition
# another good option
some_condition && do_something
Avoiding NoMethodError
Ruby code can throw a NoMethodError when invoking methods on an expression that evaluates to nil, or on an object that doesn't #respond_to? a particular method. While newer versions of Ruby support the safe navigation operator to guard against invoking methods on instances of NilClass, older code often needs this type of construct to avoid raising exceptions.
In peudocode:
define method "root":
if application does not evaluate to nil, then
invoke method config on application, then
invoke method root on application.config
In Ruby >= 2.3, you could potentially rewrite this method as:
def root
application&.config.root
end
However, there are cases where &. isn't fully equivalent to obj && obj.method. The former just protects against calling methods on nil. For example, if application.nil? and application.respond_to? :config are both false, using the safe navigator when calling application&.config will still raise an exception.
Whether the logical AND in your example is necessary because of how the application variable is set or used, just a legacy idiom, or kept for backwards compatibility with earlier versions of Ruby is something you'd have to investigate in the Rails code base. In any case, the logical AND in your example guards against NoMethodError exceptions.
Related
I wrote the following recursive function in order to parse some settings and correctly populate some log file objects I have.
When I run this code against Code Climate it tells me that (of course) the use of eval is not encouraged. Is there a way I can rewrite this method so I do not need eval and also do not need a case statement? Nothing comes to mind.
def parse(settings, logfile = nil)
settings.each do |key, value|
if value.is_a?(Hash)
logfile = Logmsg::LogFile.new
parse(value, logfile)
else
eval("logfile.#{key} = value")
end
end
end
Any ideas?
I am trying the instance_variable_set meta-programming method however I am still running into some issues with it. For some reason my tests are all failing now due to
Argument Error: comparison of Fixnum with String failed
I am still trying to figure that out.
Since assignment to an object's attribute is just syntactic sugar for a method call (i.e obj.foo = bar is the same as calling the foo= method on obj with the argument bar), use Object#public_send:
logfile.public_send(:"#{key}=", value)
In older code you often see send instead of public_send, but you should use the latter since it will raise an error if you try to call a private method.
I was working on serializing values when found out about this one. Ruby has a TrueClass class, and a FalseClass class, but it has no Boolean class. I'd like to know why is this.
I see some advantages in using a Boolean; for example, string parsing could be centralized on it.
Ruby developers are smarter than me, so there must be a lot of good reasons that I just don't see. But right now it looks to me like having OneClass and a TwoClass instead of Fixnum.
The purpose of a class is to group similar objects, or objects with similar behavior together. 1 and 2 are very similar, therefore it makes perfect sense for them to be in the same class. true and false however are not similar. In fact, their whole point is that they are exactly the opposite of each other and have opposite behavior. Therefore, they don't belong in the same class.
Can you give an example of what sort of common behavior you would implement in a Boolean class? I can't think of anything.
Let's just look at the behavior that TrueClass and FalseClass have: there's exactly four methods there. No more. And in every single case, the two methods do exactly the opposite. How and why would you put that in a single class?
Here's how you implement all those methods:
class TrueClass
def &(other)
other
end
def |(_)
self
end
def ^(other)
!other
end
def to_s
'true'
end
end
And now the other way around:
class FalseClass
def &(_)
self
end
def |(other)
other
end
def ^(other)
other
end
def to_s
'false'
end
end
Granted, in Ruby, there is a lot of "magic" that is going on behind the scenes and that is not actually handled by TrueClass and FalseClass but rather hardwired into the interpreter. Stuff like if, &&, || and !. However, in Smalltalk, from which Ruby borrowed a lot including the concept of FalseClass and TrueClass, all of these are implemented as methods as well, and you can do the same thing in Ruby:
class TrueClass
def if
yield
end
def ifelse(then_branch=->{}, _=nil)
then_branch.()
end
def unless
end
def unlesselse(_=nil, else_branch=->{})
ifelse(else_branch, _)
end
def and
yield
end
def or
self
end
def not
false
end
end
And again the other way around:
class FalseClass
def if
end
def ifelse(_=nil, else_branch=->{})
else_branch.()
end
def unless
yield
end
def unlesselse(unless_branch=->{}, _=nil)
ifelse(_, unless_branch)
end
def and
self
end
def or
yield
end
def not
true
end
end
A couple of years ago, I wrote the above just for fun and even published it. Apart from the fact that the syntax looks different because Ruby uses special operators while I use only methods, it behaves exactly like Ruby's builtin operators. In fact, I actually took the RubySpec conformance testsuite and ported it over to my syntax and it passes.
It seems that Matz himself answered this question on a mailing list message in 2004.
Short version of his answer: "right now it works ok, adding a Boolean doesn't give any advantage".
Personally I don't agree with that; the aforementioned "string parsing" is one example. Another one is that when you are applying different treatment to a variable depending on its type, (i.e. a yml parser) having a "Boolean" class is handy - it removes one "if". It also looks more correct, but that's a personal opinion.
Quoting Matz on Ruby forum (2013):
...There's nothing true and false commonly share, thus no Boolean class.
Besides that, in Ruby, everything behave as Boolean value....
true and false could be managed by a Boolean class that held multiple values, but then the class object would have to have internal values, and therefore have to be de-referenced with every use.
Instead, Ruby treats true and false as long values (0 and 1), each of which corresponds to a type of object class (FalseClass and TrueClass). By using two classes instead of a single Boolean class, each class does not require any values and therefore can be distinguished simply by its class identifier (0 or 1). I believe this translates to significant speed advantages internal to the Ruby engine, because internally Ruby can treat TrueClass and FalseClass as long values that require zero translation from their ID value, whereas a Boolean object would have to be de-referenced before it could be evaluated.
Since everything but false and nil evaluate to true in Ruby by default, you would only need to add parsing to String.
Something like this could work:
class Object
## Makes sure any other object that evaluates to false will work as intended,
## and returns just an actual boolean (like it would in any context that expect a boolean value).
def trueish?; !!self; end
end
class String
## Parses certain strings as true; everything else as false.
def trueish?
# check if it's a literal "true" string
return true if self.strip.downcase == 'true'
# check if the string contains a numerical zero
[:Integer, :Float, :Rational, :Complex].each do |t|
begin
converted_number = Kernel.send(t, self)
return false if converted_number == 0
rescue ArgumentError
# raises if the string could not be converted, in which case we'll continue on
end
end
return false
end
end
When used, this would give you:
puts false.trueish? # => false
puts true.trueish? # => true
puts 'false'.trueish? # => false
puts 'true'.trueish? # => true
puts '0'.trueish? # => false
puts '1'.trueish? # => true
puts '0.0'.trueish? # => false
puts '1.0'.trueish? # => true
I believe part of the “big idea” behind Ruby is to just make the behavior you desire inherent to your program (e.g. boolean parsing), rather creating a fully encapsulated class that lives in it's own namespace world (e.g. BooleanParser).
The main reason is simply the fact that this is far quicker and simpler to implement boolean expressions as it is currently than with a Boolean class which would imply a conversion.
As Mongus Pong told you, when you write "if ", you ask the interpretor to evaluate the thing and then branch. If you had Boolean class, you'd have to convert the evaluation of thing into a Boolean before branching (one more step).
Remember that such a ->Boolean conversion would be available as a Ruby method in the Boolean class. This method could then be changed dynamically as any other Ruby method, allowing developer to mess up things completely (which is not so serious indeed) but clearly, this wouldn't allow the interpretor to optimize tests as they should.
Do you realize that it would replace a few CPU instructions operation by a complete method call, which is costly in Ruby (remember the "send" method processing)...
Joining TrueClass and FalseClass with a kind of Boolean super-class breaks the LSP (Liskov Substitution Principle, lsp) - then "any code using Boolean should be able use any it's descendant transparently". It is not achievable for TrueClass and FalseClass since they have opposite behavior.
Btw, LSP is the (L) of SOLID.
Looks like it is the good example of LSP in real life.
UPD#1: regarding does LSP broken or not
COMMON_EXPECTED_VALUE = x
def test_LSP(klass)
assert klass.new.value == COMMON_EXPECTED_VALUE
end
test_LSP(FooClass)
test_LSP(BarClass)
Once you have got both green - you have chances to not break the LSP joining this classes with the common superclass, of course if you will get double green for all features of future superclass.
In Ruby nil and false are false and everything else is true. Hence there is no need for a specific boolean class.
You can try it :
if 5
puts "5 is true"
end
5 evaluates to true
if nil
puts "nil is true"
else
puts "nil is false"
end
Will print "nil is false"
As others have said, you could "patch" Ruby. Create your own class. Here is something I came up with. The methods on the Boolean class are a bit silly, but they could be useful programmatically at some point.
class Boolean
def self.new(bool)
bool
end
def self.true
true
end
def self.false
false
end
end
class FalseClass
def is_a?(other)
other == Boolean || super
end
def self.===(other)
other == Boolean || super
end
end
class TrueClass
def is_a?(other)
other == Boolean || super
end
def self.===(other)
other == Boolean || super
end
end
In python there is a pass keyword for defining an empty function, condition, loop, ...
Is there something similar for Ruby?
Python Example:
def some_function():
# do nothing
pass
No, there is no such thing in Ruby. If you want an empty block, method, module, class etc., just write an empty block:
def some_method
end
That's it.
In Python, every block is required to contain at least one statement, that's why you need a "fake" no-op statement. Ruby doesn't have statements, it only has expressions, and it is perfectly legal for a block to contain zero expressions.
nil is probably the equivalent of it:
def some_function
nil
end
It's basically helpful when ignoring exceptions using a simple one-line statement:
Process.kill('CONT', pid) rescue nil
Instead of using a block:
begin
Process.kill('CONT')
rescue
end
And dropping nil would cause syntax error:
> throw :x rescue
SyntaxError: (irb):19: syntax error, unexpected end-of-input
from /usr/bin/irb:11:in `<main>'
Notes:
def some_function; end; some_function returns nil.
def a; :b; begin; throw :x; rescue; end; end; a; also returns nil.
You always have end statements, so pass is not needed.
Ruby example:
def some_function()
# do nothing
end
Ruby 3.0
As of Ruby 3.0, so-called "endless" method definitions are now supported -- we no longer require end statements with every single method definition. This means the most concise way of expressing an empty method like the example above is now arguably something like this:
def some_function = nil
Alternatively, there has always been an uglier one-line option using the much-hated semicolon:
def some_function; end
Note that this doesn't really change anything about the first solution except how the code can be written.
Single line functions and classes
def name ; end
class Name ; end
works fine for pseudocode.
As answered before everything in ruby is an expression so it is fine to leave it blank.
def name
end
class Name
end
A ruby alternative for python programmers who love the pass keyword
def pass
end
# OR
def pass; end
Note that it is useless to do this in Ruby since it allows empty methods but if you're that keen on pass, this is the simplest and cleanest alternative.
and now you can use this function inside any block and it will work the same.
def name
pass
end
# OR
class Name
pass
end
Keep in mind that pass is a function that returns, so it is up to you how you can use it.
If you want to be able to use it freely with any number of arguments, you have to have a small trick on the arguments:
def gobble *args, ≺ end
As others have said, in Ruby you can just leave a method body empty. However, this could prove a bit different than what Python accomplishes with pass.
In Ruby, everything is an object. The absence of value, which some programming languages indicate with null or nil is actually an object of NilClass in Ruby.
Consider the following example (in irb):
class A
def no_op
end
end
A.new.no_op
# => nil
A.new.no_op.class
# => NilClass
A.new.no_op.nil?
# => true
Here's Ruby's NilClass documentation for reference.
I believe Python's pass is used mainly to overcome the syntactic limitations of the language (indentation), although I'm not that experienced in Python.
Ruby's equivalent to pass can be ().
if 1 == 1
()
else
puts "Hello"
end
=> nil
lambda do
()
end.call
=> nil
You can also use it as part of condition ? true-expr : false-expr ternary operator.
Is it possible to create a method in Ruby that takes a block and runs each statement in the block until one of them returns false?
done = prepare_it do |x|
method_1
method_2
method_3
end
puts "Something did not work" unless done
I wanted the function prepare_it to run each statement but if one of them fails, the function quits. If the function returns true, it means that all steps were successful.
This seems to be calling for an Exception, but I'm not sure how to trigger and process it. I wish I did not have to modify the method_x functions to throw an Exception upon failure, but rather make prepare_it throw the exception if one of the method_x fails (returns false)
Edit:
Thanks for the suggestions, I think I need to add more details to my question. This is my first stab at metaprogramming and creating a DSL. :)
I have a class to send commands to a router. There are many steps that always need to be executed in sequence (connect, login, pass, etc). I thought it would be nice to give the user the ability to change the order of the commands if they wish to do so. For example, some routers don't ask for a user and go directly to the password prompt. Others skip the login altogether. In some cases you need to elevate the privilege or set terminal options.
However, there should be a mechanism to fail the entire block if any of the commands failed. So, if for some reason the password failed (the method returns false/nil), it makes no sense to continue with the rest of the commands.
And I should flag it that something failed.
The && method works, but I don't think it would be a nice interface.
Maybe instead of getting a big block, maybe I should force users to give me smaller blocks, one at a time, which are put in a stack and a run command yields then one by one?
my_router.setup do {send_pass}
my_router.setup do {set_terminal}
my_router.setup do {enable_mode}
my_router.run_setup
I think it would be super cleaner if I could do
my_router.setup do |cmd|
cmd.send_pass
cmd.set_terminal
end
puts "Done" if my_router.ready?
So any magic trickery that happens behind the scene is welcome! :)
Solution
done = prepare_it do |x|
method_1 && method_2 && method_3
end
puts "Something did not work" unless done
Explanation
The && operator "short-circuits" so if method_1 returns false, 2 and 3 won't be called and done will be false.
Example
http://gist.github.com/1115117
There isn't a good way to hack things to work like that. I would do something like one of the following:
done = prepare_it do |x|
method_1 && method_2 && method_3
end
Now, in some specific cases, you can do magic trickery to make this work. For instance, if the methods are supposed to be called on the block argument x: you could do something like this:
class SuccessProxy
def initialize(obj)
#object = obj
end
def method_missing(meth, *args, &block)
#object.send(meth, *args, &block) || raise SuccessProxy::Exception
end
class Exception < ::Exception
end
end
def prepare_it
# however you usually generate x
yield SuccessProxy.new(x)
rescue SuccessProxy::Exception
false
end
prepare_it do |x|
x.method_1
x.method_2
x.method_3
end
Or alternatively, if the methods are to be called just like method_1 on the default object in context, you could use instance_eval instead of yield to put the proxy in scope.
Finally, if you really wanted to be fancy, you could actually parse the separate statements out using a Ruby parser.
But honestly, I'm not convinced you really want to be going to metaprogramming as a tool for this. Maybe if you provide better detail, I can be more helpful as to what the best solution is, but it's probably similar to the first code sample above.
Naturally compactness will be your highest priority, so I believe this is the best answer:
done = (1..3).all? { |n| send "method_#{n}" }
puts "Something did not work" unless done
If you use exceptions, it's not as pretty, but you don't have to rely on returning values:
done = prepare_it do |x|
begin
method_1
method_2
method_3
true
rescue
false
end
end
puts "Something did not work" unless done
def method_1
# No issues, doesn't matter what we return
return true
end
def method_2
# Uh-oh, problem
raise
end
At first I thought, "wouldn't it be nice if this was Lisp..." but that made me realize the exact problem. Doing what you want (executing each step in a block until one is false) would be nice, but requires the access to the AST.
Your idea to do
my_router.setup do {send_pass}
my_router.setup do {set_terminal}
my_router.setup do {enable_mode}
my_router.run_setup
is trying to do exactly what you would do in Lisp--build a list and hand the list off to something else to execute each thing until you get a false return value.
If you're just calling methods in your class without any arguments, then how about as a workaround defining something that takes symbols?:
class Router
def run_setup *cmds
# needs error handling
while c = cmds.shift
return false unless send(c)
end
end
end
my_router.run_setup :send_pass, :set_terminal, :enable_mode
I was working on serializing values when found out about this one. Ruby has a TrueClass class, and a FalseClass class, but it has no Boolean class. I'd like to know why is this.
I see some advantages in using a Boolean; for example, string parsing could be centralized on it.
Ruby developers are smarter than me, so there must be a lot of good reasons that I just don't see. But right now it looks to me like having OneClass and a TwoClass instead of Fixnum.
The purpose of a class is to group similar objects, or objects with similar behavior together. 1 and 2 are very similar, therefore it makes perfect sense for them to be in the same class. true and false however are not similar. In fact, their whole point is that they are exactly the opposite of each other and have opposite behavior. Therefore, they don't belong in the same class.
Can you give an example of what sort of common behavior you would implement in a Boolean class? I can't think of anything.
Let's just look at the behavior that TrueClass and FalseClass have: there's exactly four methods there. No more. And in every single case, the two methods do exactly the opposite. How and why would you put that in a single class?
Here's how you implement all those methods:
class TrueClass
def &(other)
other
end
def |(_)
self
end
def ^(other)
!other
end
def to_s
'true'
end
end
And now the other way around:
class FalseClass
def &(_)
self
end
def |(other)
other
end
def ^(other)
other
end
def to_s
'false'
end
end
Granted, in Ruby, there is a lot of "magic" that is going on behind the scenes and that is not actually handled by TrueClass and FalseClass but rather hardwired into the interpreter. Stuff like if, &&, || and !. However, in Smalltalk, from which Ruby borrowed a lot including the concept of FalseClass and TrueClass, all of these are implemented as methods as well, and you can do the same thing in Ruby:
class TrueClass
def if
yield
end
def ifelse(then_branch=->{}, _=nil)
then_branch.()
end
def unless
end
def unlesselse(_=nil, else_branch=->{})
ifelse(else_branch, _)
end
def and
yield
end
def or
self
end
def not
false
end
end
And again the other way around:
class FalseClass
def if
end
def ifelse(_=nil, else_branch=->{})
else_branch.()
end
def unless
yield
end
def unlesselse(unless_branch=->{}, _=nil)
ifelse(_, unless_branch)
end
def and
self
end
def or
yield
end
def not
true
end
end
A couple of years ago, I wrote the above just for fun and even published it. Apart from the fact that the syntax looks different because Ruby uses special operators while I use only methods, it behaves exactly like Ruby's builtin operators. In fact, I actually took the RubySpec conformance testsuite and ported it over to my syntax and it passes.
It seems that Matz himself answered this question on a mailing list message in 2004.
Short version of his answer: "right now it works ok, adding a Boolean doesn't give any advantage".
Personally I don't agree with that; the aforementioned "string parsing" is one example. Another one is that when you are applying different treatment to a variable depending on its type, (i.e. a yml parser) having a "Boolean" class is handy - it removes one "if". It also looks more correct, but that's a personal opinion.
Quoting Matz on Ruby forum (2013):
...There's nothing true and false commonly share, thus no Boolean class.
Besides that, in Ruby, everything behave as Boolean value....
true and false could be managed by a Boolean class that held multiple values, but then the class object would have to have internal values, and therefore have to be de-referenced with every use.
Instead, Ruby treats true and false as long values (0 and 1), each of which corresponds to a type of object class (FalseClass and TrueClass). By using two classes instead of a single Boolean class, each class does not require any values and therefore can be distinguished simply by its class identifier (0 or 1). I believe this translates to significant speed advantages internal to the Ruby engine, because internally Ruby can treat TrueClass and FalseClass as long values that require zero translation from their ID value, whereas a Boolean object would have to be de-referenced before it could be evaluated.
Since everything but false and nil evaluate to true in Ruby by default, you would only need to add parsing to String.
Something like this could work:
class Object
## Makes sure any other object that evaluates to false will work as intended,
## and returns just an actual boolean (like it would in any context that expect a boolean value).
def trueish?; !!self; end
end
class String
## Parses certain strings as true; everything else as false.
def trueish?
# check if it's a literal "true" string
return true if self.strip.downcase == 'true'
# check if the string contains a numerical zero
[:Integer, :Float, :Rational, :Complex].each do |t|
begin
converted_number = Kernel.send(t, self)
return false if converted_number == 0
rescue ArgumentError
# raises if the string could not be converted, in which case we'll continue on
end
end
return false
end
end
When used, this would give you:
puts false.trueish? # => false
puts true.trueish? # => true
puts 'false'.trueish? # => false
puts 'true'.trueish? # => true
puts '0'.trueish? # => false
puts '1'.trueish? # => true
puts '0.0'.trueish? # => false
puts '1.0'.trueish? # => true
I believe part of the “big idea” behind Ruby is to just make the behavior you desire inherent to your program (e.g. boolean parsing), rather creating a fully encapsulated class that lives in it's own namespace world (e.g. BooleanParser).
The main reason is simply the fact that this is far quicker and simpler to implement boolean expressions as it is currently than with a Boolean class which would imply a conversion.
As Mongus Pong told you, when you write "if ", you ask the interpretor to evaluate the thing and then branch. If you had Boolean class, you'd have to convert the evaluation of thing into a Boolean before branching (one more step).
Remember that such a ->Boolean conversion would be available as a Ruby method in the Boolean class. This method could then be changed dynamically as any other Ruby method, allowing developer to mess up things completely (which is not so serious indeed) but clearly, this wouldn't allow the interpretor to optimize tests as they should.
Do you realize that it would replace a few CPU instructions operation by a complete method call, which is costly in Ruby (remember the "send" method processing)...
Joining TrueClass and FalseClass with a kind of Boolean super-class breaks the LSP (Liskov Substitution Principle, lsp) - then "any code using Boolean should be able use any it's descendant transparently". It is not achievable for TrueClass and FalseClass since they have opposite behavior.
Btw, LSP is the (L) of SOLID.
Looks like it is the good example of LSP in real life.
UPD#1: regarding does LSP broken or not
COMMON_EXPECTED_VALUE = x
def test_LSP(klass)
assert klass.new.value == COMMON_EXPECTED_VALUE
end
test_LSP(FooClass)
test_LSP(BarClass)
Once you have got both green - you have chances to not break the LSP joining this classes with the common superclass, of course if you will get double green for all features of future superclass.
In Ruby nil and false are false and everything else is true. Hence there is no need for a specific boolean class.
You can try it :
if 5
puts "5 is true"
end
5 evaluates to true
if nil
puts "nil is true"
else
puts "nil is false"
end
Will print "nil is false"
As others have said, you could "patch" Ruby. Create your own class. Here is something I came up with. The methods on the Boolean class are a bit silly, but they could be useful programmatically at some point.
class Boolean
def self.new(bool)
bool
end
def self.true
true
end
def self.false
false
end
end
class FalseClass
def is_a?(other)
other == Boolean || super
end
def self.===(other)
other == Boolean || super
end
end
class TrueClass
def is_a?(other)
other == Boolean || super
end
def self.===(other)
other == Boolean || super
end
end