What's this Ruby syntax? - ruby

I just read the following code:
class Dir
def self.create_uniq &b ### Here, & should mean b is a block
u = 0
loop do
begin
fn = b[u] ### But, what does b[u] mean? And b is not called.
FileUtils.mkdir fn
return fn
rescue Errno::EEXIST
u += 1
end
end
io
end
end
I put my confusion as comment in the code.

Defining method with &b on the end allows you to use block passed to the method as Proc object.
Now, if you have Proc instance, [] syntax is shorthand to call:
p = Proc.new { |u| puts u }
p['some string']
# some string
# => nil
Documented here -> Proc#[]

The & prefix operator allow a method to capture a passed block as a named parameter. e.g:
def wrap &b
3.times(&b)
print "\n"
end
now if you call above method like this:
wrap { print "Hi " }
then output would be:
Hi Hi Hi

Related

Ruby code explanation

I found following code at the internet
class Test
def value
'string'
end
def inspect
'value'
end
end
def test(arg)
arg.tap { |i| i.value }
end
p test(Test.new)
Could anyone explain why it returns
p test(Test.new)
# >> value
Because arg.tap returns arg itself, and p prints arg.inspect, since you have overwritten theinspect method of Test, it returns a string 'value', so you the print result is value
see also:
- p vs puts in Ruby
- tap method
tap used for chain of methods. It runs the passed blocked and returns the input without any change.
It means
arg.tap { |i| i.value } will return arg
p method runs inspect method of passed object

Use a block to set variables in parent scope

The gem binding_of_caller has an example for how to set a variable in a parent scope:
(this just pasted from their readme)
def a
var = 10
b
puts var
end
def b
c
end
def c
binding.of_caller(2).eval('var = :hello')
end
a()
# OUTPUT
# => hello
This is useful, but it's limited by the need to do all variable initialization in a string.
I gave it a little thought and realized that I could use YAML to serialize/deserialize objects.
Take, for example, the following example:
def c
value = YAML.dump [ { a: "b" } ]
binding.of_caller(2).eval("var = YAML.load('#{value}')")
end
a()
# => {a: "b"}
This is cool, but it'd be better if I could avoid serialization altogether and just write a proper do; end; block like so:
# doesnt work
def c
binding.of_caller(2).eval do
# ideally this would set the variable named "var" in the scope of method "a"
var = [ { a: "b" } ]
end
end
How can I accomplish the functionality of this last example? I don't need to use binding_of_caller if there's another way.
This is the best I could do and, I suspect (though I'd truly love to be proven wrong), the best you'll find short of writing your own C extension a la binding_of_caller:
require 'binding_of_caller'
module BindingExtensionEvalBlock
def eval_block(&block)
eval("ObjectSpace._id2ref(%d).call(binding)" % block.object_id)
end
end
class ::Binding
include BindingExtensionEvalBlock
end
The magic is here, of course:
eval("ObjectSpace._id2ref(%d).call(binding)" % block.object_id)
We get the object ID of the Proc and then, in our Binding#eval, use ObjectSpace#_id2ref to retrieve it from wherever it is in memory and call it, passing in the local binding.
Here it is in action:
def a
var = 10
b
puts var
end
def b
c
end
def c
binding.of_caller(2).eval_block do |bnd|
bnd.local_variable_set(:var, [ { a: "b" } ])
end
end
a # => {:a=>"b"}
As you can see, instead of var = [ { a: "b" } ] in our block we must do bnd.local_variable_set(:var, [ { a: "b" } ]). There's no way to change the binding of a block in Ruby, so we have to pass in a binding (bnd) and call Binding#local_variable_set.

Ruby check if block is nil

I call a method with a block;
method do
"Hello"
end
and the method is defined as;
def method
yield
end
and when defining method; i want to check if given block is empty (nil) or not, because the variable in the method may end up like this;
method do
""
end
So in definition, i want to check if the yield block is nil or not. Like;
def method
if yield ? yield : "Empty block? Seriously?"
end
I know the above does not work. Bu it is what i want to achieve.
Also keep in mind that block_given? will always be "true" since the block is given even if it is nil or empty string.
UPDATE: As most of the comments/answers state that the question is unclear; here is the problem simplified by #ndn:
I want to check if the result of executing a block is "empty"(nil or "") without
invoking it first.
It is unclear what you are asking, because a block itself can not be empty. Therefore, you might mean a few different things:
A missing block. You can check if a block is given
block_given?
Block with empty body (aka {} or do end). This is not impossible, but requires some advanced voodoo ruby metaprogramming magic. Generally, if this is what you are looking for, either you are writing something very interesting or your approach is completely wrong.
You want to check if the result of executing a block is "empty" without invoking it first. This is impossible. For example, consider the following block:
{ [nil, "", true].sample }
Obviously, there is no way to know in advance.
You are ok with calling the block. Then you can assign the result to a variable and make checks on it:
def some_method
evaluation_result = yield if block_given?
if evaluation_result.nil? or evaluation_result == ""
# do something if the block was not given or the result is nil/empty
puts "Empty block? Seriously?"
else
# do something if the block was given and the result is non nil/empty
puts evaluation_result
end
end
Now when you invoke some_method:
some_method { "something" } # => "something"
some_method { 3 + 5 } # => 8
some_method { nil } # => "Empty block? Seriously?"
some_method { "" } # => "Empty block? Seriously?"
some_method { } # => "Empty block? Seriously?"
some_method # => "Empty block? Seriously?"
EDIT:
A workaround for case #3 might be to create two procs, one with what you want to do if the block is "empty" and one - if it is not, then pass them around to the endpoint where you will finally invoke the block. This might or might not be applicable depending on your exact situation.
EDIT2:
Another workaround can be to redefine the Proc#call method for your proc instances. However, this doesn't work for yield:
def secure(&block)
insecure_call = block.method(:call)
block.define_singleton_method(:call) do
insecure_call_result = insecure_call.call
if insecure_call_result.nil? or insecure_call_result == ""
"<b>Bummer! Empty block...</b>"
else
insecure_call_result
end
end
end
x = proc { }
y = proc { "" }
z = proc { nil }
a = proc { 3 + 5 }
b = proc { "something" }
u = proc { [nil, "", true].sample }
[x, y, z, a, b, u].each { |block| secure &block }
# some method that uses the block
def user(&block)
"What I got is #{block.call}!"
end
user &x # => "What I got is <b>Bummer! Empty block...</b>!"
user &y # => "What I got is <b>Bummer! Empty block...</b>!"
user &z # => "What I got is <b>Bummer! Empty block...</b>!"
user &a # => "What I got is 8!"
user &b # => "What I got is something!"
user &u # => Different each time
EDIT3: Another alternative, which is sort of cheating, is to wrap the given proc in another proc. This way, it will work for yield too.
def wrap(&block)
proc do
internal_proc_call_result = block.call
if internal_proc_call_result.nil? or internal_proc_call_result == ""
"<b>Bummer! Empty block...</b>"
else
internal_proc_call_result
end
end
end
Now using the result of wrap and will get you behavior similar to secure.
If I understand correctly, you want to statically determine what the runtime value of a block is. This is one of the many known impossible problems resulting from the undecidability of the Halting Problem.
In other words: it can't be done.
Not "it can't be done in Ruby", not "it is hard", it simply can't be done, period. And it can be (and has been) mathematically proven that it can't be done. Ever.
UPDATED Answer
My last effort to simplify the answer based on comments..
You can check for block emptiness with block_given? and you need to explicitly check for yield output for emptiness like below
def method(&block)
# Below if condition is to prove that block can be accessed
if block_given?
p block
p block.yield
end
b = yield if block_given?
(b.nil? || b.empty?) ? "Empty block? Seriously?" : b
end
p method {"Hello"} # inline block
result = method do
"World"
end
p result
p method # No blocks provided
p method {""} # Block that returns empty string
Output of the program
"Hello"
"World"
"Empty block? Seriously?"
"Empty block? Seriously?"

Ruby: Why is 'while (p || (p=exns.shift))' not the same as 'while p ||= exns.shift'?

What's wrong here? I don't see how the two fragments can behave differently, yet they do.
Full code, try with one or the other while:
class T
def initialize
#e=[4,2]
end
def shift
r=#e.shift
puts "[#{r.inspect}]"
r
end
end
exns=T.new
while (p || (p=exns.shift))
#while p ||= exns.shift
puts "p: #{p.inspect}"
p -= 1
p=nil if p<1
puts " #{p.inspect}"
puts "T" if p
end
The 'while (p || (p=exns.shift))' never seems to short-circuit for some reason. I'd like to know the reason.
Your problem is with the letter you chose to name your variable - p is not like other letters (say q), since it is also the name of the Kernel method p():
p
# => nil
q
# NameError: undefined local variable or method `q' for main:Object
for that reason, because you did not define a local variable names p before the while loop, it is actually declared only inside the scope of the loop.
To see how this matters, simply add the following line before the loop:
p = nil
Now, both options act the same.

Use of yield and return in Ruby

Can anyone help me to figure out the the use of yield and return in Ruby. I'm a Ruby beginner, so simple examples are highly appreciated.
Thank you in advance!
The return statement works the same way that it works on other similar programming languages, it just returns from the method it is used on.
You can skip the call to return, since all methods in ruby always return the last statement. So you might find method like this:
def method
"hey there"
end
That's actually the same as doing something like:
def method
return "hey there"
end
The yield on the other hand, excecutes the block given as a parameter to the method. So you can have a method like this:
def method
puts "do somthing..."
yield
end
And then use it like this:
method do
puts "doing something"
end
The result of that, would be printing on screen the following 2 lines:
"do somthing..."
"doing something"
Hope that clears it up a bit. For more info on blocks, you can check out this link.
yield is used to call the block associated with the method. You do this by placing the block (basically just code in curly braces) after the method and its parameters, like so:
[1, 2, 3].each {|elem| puts elem}
return exits from the current method, and uses its "argument" as the return value, like so:
def hello
return :hello if some_test
puts "If it some_test returns false, then this message will be printed."
end
But note that you don't have to use the return keyword in any methods; Ruby will return the last statement evaluated if it encounters no returns. Thus these two are equivelent:
def explicit_return
# ...
return true
end
def implicit_return
# ...
true
end
Here's an example for yield:
# A simple iterator that operates on an array
def each_in(ary)
i = 0
until i >= ary.size
# Calls the block associated with this method and sends the arguments as block parameters.
# Automatically raises LocalJumpError if there is no block, so to make it safe, you can use block_given?
yield(ary[i])
i += 1
end
end
# Reverses an array
result = [] # This block is "tied" to the method
# | | |
# v v v
each_in([:duck, :duck, :duck, :GOOSE]) {|elem| result.insert(0, elem)}
result # => [:GOOSE, :duck, :duck, :duck]
And an example for return, which I will use to implement a method to see if a number is happy:
class Numeric
# Not the real meat of the program
def sum_of_squares
(to_s.split("").collect {|s| s.to_i ** 2}).inject(0) {|sum, i| sum + i}
end
def happy?(cache=[])
# If the number reaches 1, then it is happy.
return true if self == 1
# Can't be happy because we're starting to loop
return false if cache.include?(self)
# Ask the next number if it's happy, with self added to the list of seen numbers
# You don't actually need the return (it works without it); I just add it for symmetry
return sum_of_squares.happy?(cache << self)
end
end
24.happy? # => false
19.happy? # => true
2.happy? # => false
1.happy? # => true
# ... and so on ...
Hope this helps! :)
def cool
return yield
end
p cool {"yes!"}
The yield keyword instructs Ruby to execute the code in the block. In this example, the block returns the string "yes!". An explicit return statement was used in the cool() method, but this could have been implicit as well.

Resources