This question already has answers here:
What does &. (ampersand dot) mean in Ruby?
(8 answers)
Closed 5 years ago.
action&.!=:click
Can somebody please explain to me what is the meaning of this in ruby and where I can get some explanations? I try to search ruby documentation, but no luck with this kind of 'chaining' operators
:click is symbol
!= is not equal
but I have no idea about &.
What looks like one operator in the middle (&.!=) is actually 1 operator and 1 method call : &. followed by != with :click as argument:
action &. != :click
It checks if action is not nil but distinct from :click:
action = nil
action&.!=:click
# => nil
action = :not_click
action&.!=:click
# => true
action = :click
action&.!=:click
# => false
action = false
action&.!=:click
# => true
It's an abusive way to use &. in my humble opinion. &. is called a "safe navigation operator", because it prevents you from calling undefined methods on nil objects.
!= is defined for any object though, so there's nothing safe about using &. before !=.
You could write :
!(action.nil? || action == :click)
or
!action.nil? && action != :click
or even:
![nil, :click].include?(action)
Related
This question already has answers here:
Why does `defined?` return a string or nil?
(2 answers)
Closed 7 years ago.
In ruby, most methods or keywords that end with ? return boolean values. And we except them to behave like this. Why does defined? keyword return somethings else? Or why is there ? at the end of it?
This question can be understood in two ways:
Why doesn't it simply return true or false?
It's because it encodes more information than simply if something is defined or not:
defined? Class # => "constant"
defined? 42 # => "expression"
defined? nil # => "nil"
defined? x # => nil
Why does it have ? at the end since as the convention goes, the question mark is reserved for predicates?
You are right that this is inconsistent. The most likely reasons are:
Almost always, you will use it as predicate anyway
if defined? x
# do something
end
The shortest alternative, which doesn't sound like a predicate I can think of is definition_type_of. Generally, you want to keep the reserved words in your language short
Developers chose to return something more meaningfull than true or false because the only case that breaks by not having boolean returned is explicit comparison:
defined?(:x) == true
# => always `false`
Such comparison is something you should usually not do, as logical operators like || and && are just as likely to return some truthy object instead of true. This is barely needed for anything.
The "defined?"-method can return more than "true" or "false". It tells you what type of variable it is if it's defined at all.
Check
Checking if a variable is defined?
and
http://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-defined-3F
Here are two tests:
if [1,2,3,4].include? 2 && nil.nil?
puts :hello
end
#=>
and
if [1,2,3,4].include?(2) && nil.nil?
puts :hello
end
#=> hello
The above tells me that && has higher precedence than method arguments so it logically ands 2 && nil.nil? which is true and passes that as an argument to include?.
However, there is this test:
if [1,2,3,4].include? 2 and nil.nil?
puts :hello
end
#=> hello
So this is telling me that method arguments and 'and' have the same precedence (or method args are higher than 'and') since it passed 2 to include? before it processed 'and'.
Note: I understand that && and and have different precedence. The question is not regarding this but regarding and or or vs the arguments to a ruby method.
I can't find documentation that affirms this. For instances, this doesn't mention method arguments at all: http://phrogz.net/programmingruby/language.html#table_18.4 or http://romhack.wikia.com/wiki/Ruby_operators.
Could anyone explain this behavior? Namely in that how does ruby know to pass values as arguments to a method vs. process operators?
As you said && and and have different precedence, however the explanation for the following example:
if [1,2,3,4].include? 2 and nil.nil?
puts :hello
end
#=> hello
is the binding strenght of the and as you can read here:
Difference between "and" and && in Ruby?
This basically explains that 2 and nil.nil? will be evaluated as nil, however it will return 2 as can be seen in this example:
foo = :foo
bar = nil
a = foo and bar
# => nil
a
# => :foo
a = foo && bar
# => nil
a
# => nil
I've never seen any documentation about method argument precedence, but one rule of thumb I use when seeing method arguments is to mentally strip the whitespace wherever possible in the arguments and still have the same expression. This normally gives me the precedence:
[1,2,3,4].include? 2&&nil.nil? is the same expression, but you cannot strip the whitespace in
[1,2,3,4].include? 2 and nil.nil? and therefore, the precedence is left to right ... I.e. Method argument is 2.
Anyway, the better question is why on earth would you write statements like this?
Omitting method parenthesis is only useful for code readability. However, your statements are hardly readable and makes one pause over the code and think about it more than he should. If I was to review code like this, I would definitely fail the code review due to poor readability.
In fact, many style guides explicitly state that most methods with arguments should be parenthesized (is this even a word ;). For example:
Ruby style guide
This question already has answers here:
Confusion with the assignment operation inside a falsy `if` block [duplicate]
(3 answers)
Closed 5 years ago.
Try the following in irb: (I'm using Ruby 2.0.0-p247)
blah
#=> NameError: undefined local variable or method `blah' for main:Object
if false
blah = 'blah'
end
#=> nil
blah
#=> nil
I'm surprised that blah is assigned nil even when the if condition evaluates to false.
I thought the code within if is skipped as the condition evaluates to false.
Could someone with Ruby internals knowledge kindly explain how this happened?
Thank you
Local variables in ruby are created during parsing/compilation of code (not execution). They are lexically scoped, so a local variable is not visible before the line where it's assigned to.
defined?(foo) # => nil
if false
defined?(foo) # =>
foo = 'blah'
defined?(foo) # =>
end
defined?(foo) # => "local-variable"
foo # => nil
defined?(foo) lines inside of if return nothing, because they didn't run. The assignment wasn't executed as well. However, the compiler saw the assignment to local variable and created one (with default value of nil).
This behaviour explains the trick from WAT talk:
a = a # => nil
Even though variable a doesn't exist, it is created (and set to nil) right before this line, simply because there is an assignment expression in the code (target of which is yet unknown local variable). So by the time the right hand side of this expression is evaluated, a exists.
This question already has answers here:
How to test if a string is basically an integer in quotes using Ruby
(19 answers)
Test if string is a number in Ruby on Rails
(13 answers)
Closed 9 years ago.
I have a string "1234223" and I want to check whether the value is an integer/number.
How can I do that in one line?
I have tried
1 =~ /^\d+$/
=> nil
"1a" =~ /^\d+$/
=> nil
Both line are returning nil
If you're attempting to keep similar semantics to the original post, use either of the following:
"1234223" =~ /\A\d+\z/ ? true : false
#=> true
!!("1234223" =~ /\A\d+\z/)
#=> true
A more idiomatic construction using Ruby 2.4's new Regexp#match? method to return a Boolean result will also do the same thing, while also looking a bit cleaner too. For example:
"1234223".match? /\A\d+\z/
#=> true
How about Integer("123") rescue nil ?
You can use regex
"123".match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
It will also check for decimals.
"1234223".tap{|s| break s.empty? || s =~ /\D/}.!
I could not find anywhere a formal specification of the if (or unless) modifier:
123 if x > 0
what is the value of the above statement if x is not above zero? irb suggests nil, but is it documented anywhere?
(yes, this is perhaps a stupid question, sorry, could not find a spec).
An expression that is not evaluated is the same as not existing. And your condition should be part of some code block such as definition or the main environment, etc. A code block without a content is evaluated to nil.
class A; end
# => nil
def foo; end
foo
# => nil
()
# => nil
begin; end
# => nil
eval("")
# => nil
So the reason your example returns nil has nothing to do with condition itself. It is just due to there being no evaluation.
Yes, it is nil. What else could it return? The statement in the if clause is used for the if itself, and the then statement is not executed. There is nothing to return, so nil.
Relevant spec
it "returns nil if else-body is empty and expression is false" do
if false
123
else
end.should == nil
end