def foo(_, _='override')
_
end
p foo("bye bye")
p foo("hello", "world")
Output:
"override"
"hello"
I could understand if the result was:
"override"
"world"
or even:
"bye bye"
"hello"
But the result I'm getting causes me confusion.
Default arguments are evaluated earlier in time than regular arguments if an argument is passed for it, otherwise they are evaluated last. Almost certain but unsure how to prove it.
Meaning in this example:
at time 0 call p foo("hello", "world")
at time 1 _ = 'override'
at time 2 _ = "world"
at time 3 _ = "hello"
at time 4 variables are printed and you see "hello"
EDIT here is some evidence:
def foo(_, _='override',_)
_
end
p foo("bye bye","goodbye")
p foo("hello", "world", "three")
prints
"override"
"three"
Ican't find better explanation than this one
ruby magic underscore
The reason for this is found in Ruby’s parser, in shadowing_lvar_gen. All the normal checks for duplication are skipped iff the variable name consists of exactly one underscore.
One possible explanation is that name _ stands for "unused variable". You're not supposed to even reference it, let alone expect any values of it. As it is a special name, it gets special treatment from the parser (such as suppressing "duplicate parameter" errors). I imagine that no one cared to make this code produce a logical result, because, again, these are unused variables.
If you rename it to anything else (say, a), you'll get an error, because now this method signature doesn't make sense.
Related
If I assign a value to the variable pp and then call pp pp in the console why doesn't pretty print loop?
$ irb
pp = "hello world"
=> "hello world"
pp pp
"hello world"
=> "hello world"
According to this explanation I think it should
https://blog.brycekerley.net/2014/08/27/Working-with-pp-the-Ruby-Pretty-Printer.html
Edit: I didn't mean that it must loop, I just wanted to know the method call order that happened that prevented it from looping.
Ruby is an interpreted language, meaning that, instead of compiling, it executes the code as written, interpreting the code line by line, word by word (or rather token by token).
When ruby interpreter encounters a line pp pp, it needs to resolve two tokens. First one is clearly a method as it takes an argument, the other one can be either a method OR local variable (there are no brackets nor arguments).
So, during execution, ruby will start resolution from the second token. When it is not clear whether token denotes variable or method, ruby always searches for variable first. In this case, the variable is there as you assigned a value to pp creating a local variable (let's say by pp = 1).
Then ruby has still to process the second token, but now it looks like pp(1) (because first token has been resolved already). In this case this is, again, clearly a method so ruby just send a pp message to self (which in this context is (main) object). Method pp is defined on Kernel, so each object - including (main) can access it.
The key point here is to understand that you have not overridden method pp - that method is still there. The only thing that happened is different resolution of pp token. Even with pp hidden (or shadowed) by local variable, you can still invoke it either by using explicit self.pp or by making sure that it looks like a method pp()
I'm going far on a limb here (for fun mostly) and guessing you do something like this
>> pp "this is a test"
"this is a test"
=> "this is a test"
>> pp = pp
=> nil
>> pp pp
nil
=> nil
>> pp "this is another test"
"this is another test"
=> "this is another test"
So here's what happens
pp = pp
You've created a local variable pp which got assigned a value of whatever pp method returned (nil in this case)
>> pp pp
here you call pp method and passing it pp variable, which holds nil
>> pp "this is another test"
"this is another test"
=> "this is another test"
you still can call pp method as usually.
Not sure why would you expect it to loop. Expressions are evaluated (right to left in general), so they will evaluate eventually. No infinite loops should generally happen. Take this example:
x = y = z = x
It will first evaluate right-most x (which has not been defined, so defaults to nil, so next step conceptually will be:
x = y = z = nil
assigns nil to z, and result of this evaluation is also nil
x = y = nil
assigns nil to y
and so on...
country =
["UK", "US", "RS", "EU", "UK", "US"].
group_by{ |e| e }.
keep_if{ |_, e | e.length > 1 }
#⇒ {"UK"=>["UK", "UK"], "US"=>["US", "US"]}
What is the use of _ (underscore) in the second block. Can someone explain in details?
There are three answers to this on two levels.
The first answer is on the level of the Ruby language: there is no use of the underscore in Ruby. It has no meaning. It is just a legal identifier like any other legal identifier. It could have been named foo or bar instead, and it would not in any way change the meaning of this code.
The second answer is on the level of the Ruby community: in the Ruby community, the underscore is used to communicate to other programmers reading the code "I need to put an identifier here because the rules of the Ruby language force me to, but I am not actually interested in it, I will in fact never use it." So, it has no meaning to Ruby, but it does have meaning to Ruby programmers. It's just like methods ending in ! or ?: they have no special meaning, they are just used to communicate intent from one Ruby programmer to another.
The third answer is again on the level of the Ruby language: because of #2, there were two changes made in Ruby 1.9+ that codify the uses of the underscore as an "ignore me" identifier:
Normally, unused local variables generate warnings. Unused local variables that start with an underscore, or are simply named _ do not generate warnings.
Normally, an identifier can only be used once in a parameter list. Identifiers that start with an underscore, or are simply named _ can be used multiple times.
See:
#!/usr/bin/ruby -w
foo = nil
bar = nil
baz = nil
Running:
./test.rb
./test.rb:3: warning: assigned but unused variable - foo
./test.rb:4: warning: assigned but unused variable - bar
./test.rb:5: warning: assigned but unused variable - baz
But:
#!/usr/bin/ruby -w
_foo = nil
_bar = nil
_ = nil
Running:
./test.rb
And:
#!/usr/bin/ruby -w
def foo(bar, bar) end
Running:
./test.rb
./test.rb:3: duplicated argument name
def foo(bar, bar); end
[The second bar is underlined in the console, which is hard to reproduce here.]
But:
#!/usr/bin/ruby -w
def foo(_bar, _bar) end
Running:
./test.rb
So, the only difference between an underscore and no underscore is that the underscore turns off certain errors and warnings, in line with its common usage within the Ruby community.
This convention is generally also respected by linters, static analyzers, editors, and IDEs providing semantic analysis of Ruby code, e.g. IDEs that highlight and warn about unused variables will not do so for variables whose name begins with or is _.
By convention, underscore is used as a variable name for a value that is not used. Unlike other variable names, it can be used multiple times in a single parallel assignment.
In this particular case, the filter in the block is not interested in the key of the hash, but only the value of the hash, which is an array generated by group_by.
In IRB/Pry console this variable is used as last returned value. There could be interesting cases beyond just being a placeholder, like:
1
_ + 2
_ * 3
_.to_f / 2
which returns:
1
=> 1
_ + 2
=> 3
_ * 3
=> 9
_.to_f / 2
=> 4.5
or
[:flowers]
_ << :leaves
which results in:
[:flowers]
=> [:flowers]
_ << :leaves
=> [:flowers, :leaves]
You can use it for variables/classes/methods basically _ contains the result of previous line you types, this is very convenient when called some LongRunning.method while in console and forgot to assign to a variable like result = ... for later inspection, so you can just type result = _ or simply _ and assign your data to the variable.
I am trying to halt input from a user when their input is 42.
The correct answer on the website I'm working on is:
while line = gets
break if (/42/ =~ line)
x << line
end
The code I tried that does not work is:
while line = gets.chomp
break if (line == 42)
x << line
end
Why is this the case? Am I missing some limitations to what I can use in my if statement?
The problem is that 42 is an integer, but line is a string:
1.9.3p392 :001 > "42" == 42
=> false
So it's never the case that your if statement is getting triggered, because it's comparing two different kinds of things. Matching with a Regex fixes it, though it's looking for "42" to appear anywhere in the input (e.g. "3427"). I think what you meant to say was
while line = gets.chomp
break if (line == "42")
x << line
end
In other words, break when the input is a string with the characters 4 and 2 in it.
I suspect it's because you're comparing a number to a string. The example uses a regular expression it appears. "42" == 42 will give you false in ruby.
<< is a method(Append) on Array or String class objects. But your x not holding any referencing to such objects. Thus you are getting undefined local variable or method 'x' for main:Object (NameError).
Try this instead(by fixing local variable x to hold a practical object and converting line value to Fixnum object:
x = "hi"
while line = gets.chomp
break if (line.to_i == 42)
x << line
end
This program will help you to halt input from a user when their input is 42.
until (line = gets.chomp).to_i == 42
x << line
end
This of course bypasses the if statement you were asking about.
Your limitation for the if is based solely on the fact that you are comparing a string that will always be a string to a number, and this will never be equal. (as others have mentioned)
So we must reconsider the conditional statement. In this case, I considered it "out of place" and moved the comparison to the 'while' loop, and then inverted it to an 'until' statement, to be able to positively express the condition to end the loop on. Whenever I see a 'break' in a loop, I try to get rid of that smell, as the condition to leave a loop should really be expressed in the loop condition if possible.
I hope this helps.
Is there a nice way how to write:
a = one.two.three.four
where "one" - assigned, "two" - nil. This statement makes an exception.
I want to have "a" nil if any of "two", "three", "four" are nil, otherwise to have result of "four" in "a".
Is it possible to do this without writing condition statements?
First of all, you need to find out if this code violates the Law of Demeter. If that is the case, then the correct solution to this problem is to not write code this way.
How would you find out if its breaking it? Here is one article that tries to explain how that applies to Ruby language.
In your case, you would break it down into multiple calls, with guard clauses around it. In the call one.two.three.four, we can assume that four is a property of three (rather, the object returned by three). And three would be a property of two. So you would add a method in two:
# Note: This is an over-simplified example
def three_four
return unless three
three.four
end
And in one you would have:
def two_three_four
return unless two
two.three_four
end
A more relevant example:
invoice.customer.primary_address.zipcode
So you would have Customer#primary_address_zipcode and Invoice#customer_primary_address_zip_code (Or a better abbreviated name, that would make more sense)
a = one.try(:two).try(:three).try(:four)
Does anybody why I can write this:
ruby-1.8.7-p302 > a = %w( a b c)
=> ["a", "b", "c"]
ruby-1.8.7-p302 > while (i = a.shift) do; puts i ; end
a
b
c
=> nil
Which looks like passing a block to while.
And not:
while(i = a.shift) { puts i; }
Is it because the "do" of the while syntax is just syntaxic sugar and as nothing to do with the "do" of a block?
Is it because the do of the while syntax is just syntaxic sugar and as nothing to do with the do of a block?
More or less, yes. It's not syntactic sugar, it's simply a built-in language construct, like def or class, as #meagar already wrote.
It has nothing to do with the do of a block, except that keywords are expensive and so reusing keywords makes sense. (By "expensive" I mean that they limit the programmer in his expressiveness.)
In a while loop, there are two ways to separate the block from the condition:
the do keyword and
an expression separator.
There are, in turn, two different expression separators in Ruby:
the semicolon ; and
a newline
So, all three of the following are valid:
while i = a.shift do puts i end # do
while i = a.shift; puts i end # semicolon
while i = a.shift
puts i end # newline
[Obviously, that last one wouldn't be written that way, you would put the end on a new line, dedented to match the while. I just wanted to demonstrate what is the minimum needed to separate the parts of the while loop.]
By the way: it is highly un-idiomatic to put the condition in parentheses. There's also a lot of superfluous semicolons in your code. And the variable name i is usually reserved for an index, not an element. (I normally use el for generic elements, but I much prefer more semantic names.)
It is also highly un-idiomatic to iterate a collection manually. Your code would be much better written as
a.each(&method(:puts)).clear
Not only is it much easier to understand what this does (print all elements of the array and delete all items from it), it is also much easier to write (there is no way to get the termination condition wrong, or screw up any assignments). It also happens to be more efficient: your version is Θ(n2), this one is Θ(n).
And actually, that's not really how you would write it, either, because Kernel#puts already implements that behavior, anyway. So, what you would really write is this
puts a
a.clear
or maybe this
a.tap(&method(:puts)).clear
[Note: this very last one is not 100% equivalent. It prints a newline for an empty array, all the other ones print nothing.]
Simple. Clear. Concise. Expressive. Fast.
Compare that to:
while (i = a.shift) do; puts i ; end
I actually had to run that multiple times to be 100% clear what it does.
while doesn't take a block, it's a language construct. The do is optional:
while (i = a.shift)
puts i
end