Function executed without being called - ruby

I have a function func, and it executes automatically; I have never called it.
BEGIN {
print "Start"
}
*data = gets;
test = true
for i in 0...data.length
if i==0
print data[i]
end
if i==0 and !test
print "test"
else
print "uu"
end
end
END {
print "End"
}
def func()
print "test1"
yield
print "test2"
end
func {
print "func block"
}
Output of above code:
StartUSERINPUT
USERINPUT
uutest1func blocktest2End
I don't want that function to be executed by itself but only when I call it. I can't use a function with parameters due to this automatic calling.

func {} is actually calling the function func.
Why? {} is for accepting block. You can think of blocks as arguments.
See how the BEGIN and END works.
They got called with the parameters passed in (via blocks).

I'm not sure what you were trying to achieve, but this:
func {
print "func block"
}
in Ruby is a function call, exactly like this:
func() {
print "func block"
}

Related

Return doesn't output the method to the console

When I call the greeter method, it doesn't output the string to the console. I'm having a hard time understanding why. Can anyone help?
def greeter(name)
return "Hello #{name}!!"
end
def by_three?(num)
if num % 3 == 0
puts true
else
puts false
end
end
greeter("Michael")
by_three?(4)
return returns value from method, but doesn't print it. You need:
puts greeter("Michael")
Also you don't need this return, at all, method returns value of the last executed line.

What's this Ruby syntax?

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

Ruby - lambda vs. Proc.new [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What's the difference between a proc and a lambda in Ruby?
When run this Ruby code:
def func_one
proc_new = Proc.new {return "123"}
proc_new.call
return "456"
end
def func_two
lambda_new = lambda {return "123"}
lambda_new.call
return "456"
end
puts "The result of running func_one is " + func_one
puts ""
puts "The result of running func_two is " + func_two
The result that I get is as follows:
The result of running func_one is 123
The result of running func_two is 456
As for func_two, where is the the value of the first return, that is, 123?
Thanks.
This is one of the main differences between Procs and lambdas.
A return in a Proc returns from its enclosing block/method, while a return in a lambda simply returns from the lambda. When you call the lambda inside the func_two, it simply returns its value in place, which is not saved.
Read on Procs v. lambdas here:
http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls
See duplicate SO question:
Why does explicit return make a difference in a Proc?
EDIT:
To further illustrate this difference, swap func_one and func_two for blocks and see what happens:
> begin; lambda { return 1 }.call end
1
> begin; Proc.new { return 1 }.call end
LocalJumpError: unexpected return
...
In the proc, the return "123" is bubbling up and returning from the outer function, func_one. Therefore the second return statement is never encountered.
In the lambda, the return "123" is returning only from the lambda. You're not setting an variable to the return value of the lambda (when you do lambda_new.call, so the value is basically just thrown out. Then, the return "456" is called and returns from the function. If, instead of returning "456", you returned lambda_new.call, the return value of func_two would be "123".
123 is a value of lambda_new.call statement, but it is not used and not shows up.

Closures in Ruby

Sample code:
def func(a, &closure)
return a if a
closure ||= lambda{ |words| puts "!!! " + words }
closure.call("1")
closure.call("2")
end
func(false){ |words| puts "??? " + words }
Please explain. I can not understand this line:
closure ||= lambda{ |words| puts "!!! " + words }
If you remove || will be permanently displayed as follows: "!!! 1", "!!! 2". Why?
And also explain this:
def func(a, &closure)
where did &closure.
def func(a, &closure)
return a if a
closure ||= lambda{ |words| puts "!!! " + words }
closure.call("1")
closure.call("2")
end
func(false){ |words| puts "??? " + words }
In "&closure" the ampersand (&) means that the function takes a block as a parameter. What is happening is you are passing a Proc (a block is just a Proc defined with a different syntax) to the func function which is then called with the variable 1 and 2.
The ||= means "or equals." It is used to assign a value to a variable if the current value is nil. It is shorthand for:
closure = lamda{ |words| puts "!!! " + words } if closure.nil
This blog post explains blocks, Procs and lamdas well.
The token closure here does not have any significance at all. It is just a local block variable given as an argument. When func is used with a block, closure will refer to that block. If not, it will initially be nil. What ||= does is, when the variable is nil, it assigns what comes to the right. So if you use func with a block, closure will be that block; if you use it without a block, closure will be lambda{...}. Now, if you replace ||= with =, then closure will always be lambda{...} irrespective of whether you use it with a block. closure.call(1) will substiture 1 to words in closure, and you will get the output !!!1; similarly with closure.call(2), which outputs !!!2.
This is nothing to do with the closures
closure ||= lambda{ |words| puts "!!! " + words }
|| says that, if the variable closure alreay initialized just use it, otherwise initialize the new lambda ambda{ |words| puts "!!! " + words }
since you are passing the lambda already
func(false){ |words| puts "??? " + words }
default lambda (having !!!) not initialized
But if you remove the ||, it always initialize the new lambda
You can print the !!! without removing ||, just call
func(false)

Understanding Ruby Enumerable#map (with more complex blocks)

Let's say I have a function
def odd_or_even n
if n%2 == 0
return :even
else
return :odd
end
end
And I had a simple enumerable array
simple = [1,2,3,4,5]
And I ran it through map, with my function, using a do-end block:
simple.map do
|n| odd_or_even(n)
end
# => [:odd,:even,:odd,:even,:odd]
How could I do this without, say, defining the function in the first place? For example,
# does not work
simple.map do |n|
if n%2 == 0
return :even
else
return :odd
end
end
# Desired result:
# => [:odd,:even,:odd,:even,:odd]
is not valid ruby, and the compiler gets mad at me for even thinking about it. But how would I implement an equivalent sort of thing, that works?
edit
In reality, the solution to my problem matters to me a lot less than the motivation/reasoning behind it, to help me understand more how ruby blocks work :)
You're so close. Just remove the returns and you're golden.
This is because the block passed to map is a proc (i.e. created with Proc.new), and not a lambda. A return within a proc doesn't just jump out of the proc- it jumps out of the method that executed (i.e. called call on) the proc. A return within a lambda, on the other hand, jumps out of only the lambda.
The proc method returns a lambda in Ruby 1.8, and a Proc in Ruby 1.9. It's probably best to just not use this method and be explicit with which construct you want to use.
I'm guessing you were either in IRB or a plain ruby script when you were trying this out.
a = Proc.new { return }
a.call # fails. Nothing to return from.
def foobar
a = Proc.new { return }
a.call
puts 'hello' # not reached. The return within the proc causes execution to jump out of the foobar method.
end
foobar # succeeds, but does not print 'hello'. The return within the proc jumps out of the foobar method.
b = lambda { return }
b.call # succeeds. The return only returns from the lambda itself.
def bazquux
b = lambda { return }
b.call
puts 'hello' # this is reached. The lambda only returned from itself.
end
bazquux # succeeds, and prints 'hello'
The lesson to learn from this is to use implicit returns unless you can't, I guess.
I suspect this may be a duplicate question, but to give a value out of a block, use next
simple.map do |n|
if n%2 == 0
next :even
else
next :odd
end
end
Shortest variant using Andrew's answer:
simple.map { |n| next :even if n % 2 == 0; :odd }

Resources