Weird imoperfection in Ruby blocks [duplicate] - ruby

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the difference or value of these block coding styles in Ruby?
# This works
method :argument do
other_method
end
# This does not
method :argument {
other_method
}
Why?
It seems like the interpreter is confused and thinks that the { ... } is a hash.
I always get angry when an interpreter can't understand a code that is actually valid. It resembles PHP that had many problems of this kind.

It doesn't think it's a hash - it's a precedence issue. {} binds tighter than do end, so method :argument { other_method } is parsed as method(:argument {other_method}), which is not syntactically valid (but it would be if instead of a symbol the argument would be another method call).
If you add parentheses (method(:argument) { other_method }), it will work fine.
And no, the code is not actually valid. If it were, it would work.

Related

Why doesn't my ruby method call work? (yield) [duplicate]

This question already has answers here:
Passing block into a method - Ruby [duplicate]
(2 answers)
Closed 2 years ago.
I can't figure out why I get this error message when I run my file on the console: no block given (yield) (LocalJumpError)
Here my code:
def block_splitter(array)
array.partition { |item| yield(item) }
end
beatles = ["John", "Paul", "Ringo", "George"]
puts block_splitter(beatles) do |beatle|
beatle.start_with?("P")
end
Thanks for your help!
It's a whitespace issue. Your problem is in this line:
puts block_splitter(beatles) do |beatle|
# ...
end
The above code is being interpreted like this:
puts(block_splitter(beatles)) do |beatle|
# ...
end
I.e. the ruby interpreter thinks that the block is being passed to the puts method, not the block_splitter method.
By assigning a variable and printing the result, you'll see that this works as expected:
result = block_splitter(beatles) do |beatle|
beatle.start_with?("P")
end
puts result
Or, you can define this as a 1-liner, and the ruby interpreter handles it like you expected:
puts block_splitter(beatles) { |beatle| beatle.start_with?("P") }
Or, you could wrap it in extra brackets:
puts(block_splitter(beatles) do |beatle|
beatle.start_with?("P")
end)
So there is a problem with missing parentheses. Ruby interpreter allow not to use those, but when You use nested method calls It's better (and sometimes necessary) to use them. To fix it You can do something like this
puts(block_splitter(beatles) do |beatle|
beatle.start_with?("P")
end)
Or even better
puts(block_splitter(beatles) {|beatle| beatle.start_with?("P")})

in ruby, when is a block not a block? [duplicate]

This question already has an answer here:
Ruby block and unparenthesized arguments
(1 answer)
Closed 7 years ago.
Jokes aside, I have a strange situation, I have some code:
def remotes(form,remotes)
personalised_form = form.dup
remotes.each do |ident,remote|
object = yield(ident)
result = remote.call(object)
insert_into_(personalised_form,ident,result)
end
personalised_form
end
And I'm seeing if it works like so:
pp remotes(forms,remotes) do |ident|
case(ident)
when :get_assets
'#Userobject'
end
end
The problem is that ruby seems to think I'm not passing a block to the remotes function.
Why is ruby insisting that I'm not passing a block? (it gives a no block given (yield) (LocalJumpError) specifically).
Thought it's not relevant, remotes is a hash containing key's and Procs, and form is just a specificly structured hash that has the result of the proc inserted into it using the ident to locate the correct insertion point
Ruby thinks you are passing the block to pp method, which simply ignores it. Try:
res = remotes(forms,remotes) do |ident|
case(ident)
when :get_assets
'#Userobject'
end
end
pp res

What does "||=" mean in Ruby? [duplicate]

This question already has answers here:
What does ||= (or-equals) mean in Ruby?
(23 answers)
Closed 7 years ago.
I'm still pretty green when it comes to Ruby and am trying to figure out what this is doing:
command_windows.each {|window| window.hidden ||= window.open? }
The command_windows variable appears to be an array of objects. If someone could explain to me what this line of code means, particularly what the ||= symbol is I would appreciate it.
foo ||= "bar" is the equivalent of doing foo || foo = "bar".
As Mischa explained, it checks for a falsy value before assigning.
In your case, you could think of it as:
command_windows.each {|window| window.hidden || window.hidden = window.open? }
which is another way of saying
command_windows.each {|window| window.hidden = window.open? unless window.hidden }
The ||= operator is used to assign new value to variable. If something was assigned to it before it won't work. It is usually used in hashes, so you don't have to check, if something is already assigned.

What about implicit yield in Ruby? [duplicate]

This question already has answers here:
Can you supply arguments to the map(&:method) syntax in Ruby?
(9 answers)
Closed 8 years ago.
I often write:
some_array.each { |array_element| array_element.some_method(args) }
Why not have an option for an implicit yield so you could write e.g.:
some_array.each { _.some_method(args) }
I am not sure what character _ should actually be, and I imagine it would only be used in the most boilerplate setting, where you're dealing with a one-dimensional array and just trying to yield each item to the block in succession. It would save a lot of redundant typing.
Are you familiar with #to_proc and the & syntax for method calls? They cover some cases similar to the one you show here. For example:
[1, -2, -4].map(&:abs) => [1, 2, 4]
The & is used to pass an object in place of a block. If the object isn't a Proc, #to_proc is automatically called on it to get a Proc before it is used in place of the block. Symbol#to_proc returns a Proc which behaves like: { |obj, *args| obj.symbol_name(*args) }.
In your example, you use args which are presumably captured from the surrounding lexical environment. Symbol#to_proc won't help you there. But it wouldn't be hard to make a new Proc-building method which would. For example:
class Symbol
def with_args(*args)
Proc.new { |x| x.send(self, *args) }
end
end
Then you could do:
some_array.each(&:some_method.with_args(args))
Whether that is any better than an explicit block is up to you. In any case, this is a technique you should be aware of.

What does 'def function=(param)' mean in ruby? [duplicate]

This question already has answers here:
What does the equal ('=') symbol do when put after the method name in a method definition?
(4 answers)
Closed 8 years ago.
I am sorry if this is a noob question, but I can't seem to find the answer neither in stackoverflow, nor anywhere else. The code is:
def full_name=(new_full_name)
# stuff
end
When I define it in the console, and try to evoke it:
full_name # nil
full_name # [hangs, needs ^C]
full_name= arg # works like normal function
full_name # works again with no arguments, as if I passed the previous argument
So, what is going on?
Thanks.
A method ending with an = defines a setter. When defining a setter like that, ruby will always return the method argument regardless of the body definition when you call the setter.
You can then use object.full_name= "Daniel" which returns => "Daniel"
Some other common appendices with your example:
The question mark, e.g.
has_full_name?
is expected to return a boolean value if the object has a full_name
The exclamation mark, e.g.
revert_full_name!
is expected to revert the full_name variable of the object
revert_full_name
in contrast is expected to return the reverted full_name variable but not to change it in the object

Resources