关于block和闭包的练习

关于block和闭包的练习

def example(num)
puts
puts "------ Example #{num} ------"
end

example 1

def thrice
yield
yield
yield
end

x = 5
puts "value of x before: #{x}"
thrice { x += 1 }
puts "value of x after: #{x}"

example 2

def thrice_with_local_x
x = 100
yield
yield
yield
puts "value of x at end of thrice_with_local_x: #{x}"
end

x = 5
thrice_with_local_x { x += 1}
puts "value of outer x after: #{x}"

example 3

thrice do
y = 10
puts "Is y defined inside the block where it is first set?"
puts "Yes." if defined? y
end
puts "Is y defined in the outer context after being set in the block?"
puts "No!" unless defined? y

example 4

def six_times(&block)
thrice(&block)
thrice(&block)
end

x = 4
six_times { x += 10 }
puts "value of x after: #{x}"

example 4.5

def nine_times(block)
thrice(&block)
thrice(&block)
thrice(&block)
end

x = 5
nine_times lambda{ x += 10}
puts "value of x after: #{x}"

example 5

def save_for_later(&b)
@saved = b
end

save_for_later { puts "Hello!" }
puts "Deferred execution of a block:"
@saved.call
@saved.call

example 6

def save_for_later(&b)
@saved = Proc.new(&b)
end

save_for_later { puts "Hello again!"}
puts "Deferred execution of a Proc works just the same with Proc.new:"
@saved.call

example 6.5

def save_for_later(&b)
@saved = lambda(&b)
end

save_for_later { puts "Hello again!"}
puts "Deferred execution of a Proc works just the same with Proc.new:"
@saved.call


example 7

@saved_proc_new = Proc.new { puts "I'm declared on the spot with Proc.new."}
puts "Deferred execution of a Proc works just the same with ad-hoc Proc.new:"
@saved_proc_new.call

example 8

@saved_proc_new = Proc.new { puts "I'm declared with Proc.new." }
@saved_proc = proc { puts "I'm declared with proc." }
@saved_lambda = lambda { puts "I'm declared with lambda." }
def some_method
puts "I'm declared as a method."
end
@method_as_closure = method(:some_method)
puts "Here are four superficially identical forms of deferred execution:"
@saved_proc_new.call
@saved_proc.call
@saved_lambda.call
@method_as_closure.call

example 9

def f(closure)
puts
puts "About to call closure"
result = closure.call
puts "Closure returned: #{result}"
"Value from f"
end

puts "f returned: " + f(Proc.new { "Value from Proc.new" })
puts "f returned: " + f(proc { "Value from proc" })
puts "f returned: " + f(lambda { "Value from lambda" })
def another_method
"Value from method"
end
puts "f returned: " + f(method(:another_method))

example 10

begin
f(Proc.new { return "Value from Proc.new" })
rescue Exception => e
puts "Failed with #{e.class}: #{e}"
end

example 11

def g
result = f(Proc.new { return "Value from Proc.new" })
puts "f returned: " + result
"Value from g"
end

puts "g returned: #{g}"

example 12

def make_proc_new
begin
Proc.new { return "Value from Proc.new" } # this "return" will return from make_proc_new
ensure
puts "make_proc_new exited"
end
end

begin
puts make_proc_new.call
rescue Exception => e
puts "Failed with #{e.class}: #{e}"
end

example 13

def g
result = f(lambda { return "Value from lambda" })
puts "f returned: " + result
"Value from g"
end

puts "g returned: #{g}"

example 14

def make_lambda
begin
lambda { return "Value from lambda" }
ensure
puts "make_lambda exited"
end
end

puts make_lambda.call

example 15

def g
result = f(proc { return "Value from proc" })
puts "f returned: " + result
"Value from g"
end

puts "g returned: #{g}"

example 16

puts "One-arg lambda:"
puts (lambda {|x|}.arity)
puts "Three-arg lambda:"
puts (lambda {|x,y,z|}.arity)

puts "No-args lambda: "
puts (lambda {}.arity)
puts "Varargs lambda: "
puts (lambda {|*args|}.arity)

example 17

def call_with_too_many_args(closure)
begin
puts "closure arity: #{closure.arity}"
closure.call(1,2,3,4,5,6)
puts "Too many args worked"
rescue Exception => e
puts "Too many args threw exception #{e.class}: #{e}"
end
end

def two_arg_method(x,y)
end

puts; puts "Proc.new:"; call_with_too_many_args(Proc.new {|x,y|})
puts; puts "proc:" ; call_with_too_many_args(proc {|x,y|})
puts; puts "lambda:" ; call_with_too_many_args(lambda {|x,y|})
puts; puts "Method:" ; call_with_too_many_args(method(:two_arg_method))

def call_with_too_few_args(closure)
begin
puts "closure arity: #{closure.arity}"
closure.call()
puts "Too few args worked"
rescue Exception => e
puts "Too few args threw exception #{e.class}: #{e}"
end
end

puts; puts "Proc.new:"; call_with_too_few_args(Proc.new {|x,y|})
puts; puts "proc:" ; call_with_too_few_args(proc {|x,y|})
puts; puts "lambda:" ; call_with_too_few_args(lambda {|x,y|})
puts; puts "Method:" ; call_with_too_few_args(method(:two_arg_method))

example 18

def one_arg_method(x)
end

puts; puts "Proc.new:"; call_with_too_many_args(Proc.new {|x|})
puts; puts "proc:" ; call_with_too_many_args(proc {|x|})
puts; puts "lambda:" ; call_with_too_many_args(lambda {|x|})
puts; puts "Method:" ; call_with_too_many_args(method(:one_arg_method))
puts; puts "Proc.new:"; call_with_too_few_args(Proc.new {|x|})
puts; puts "proc:" ; call_with_too_few_args(proc {|x|})
puts; puts "lambda:" ; call_with_too_few_args(lambda {|x|})
puts; puts "Method:" ; call_with_too_few_args(method(:one_arg_method))

example 19

def no_arg_method
end

puts; puts "Proc.new:"; call_with_too_many_args(Proc.new {||})
puts; puts "proc:" ; call_with_too_many_args(proc {||})
puts; puts "lambda:" ; call_with_too_many_args(lambda {||})
puts; puts "Method:" ; call_with_too_many_args(method(:no_arg_method))

example 20

class LispyEnumerable
include Enumerable

def initialize(tree)
@tree = tree
end

def each
while @tree
car,cdr = @tree
yield car
@tree = cdr
end
end
end

list = [1, [2, [3]]]
LispyEnumerable.new(list).each do |x|
puts x
end

example 21

class LazyLispyEnumerable
include Enumerable

def initialize(tree)
@tree = tree
end

def each
while @tree
car, cdr = @tree.call
yield car
@tree = cdr
end
end
end

list = lambda{[1, lambda {[2, lambda {[3]}]}]}
LazyLispyEnumerable.new(list).each do |x|
puts x
end

example 22

list = lambda do
puts "first lambda called"
[1, lambda do
puts "second lambda called"
[2, lambda do
puts "third lambda called"
[3]
end]
end]
end

puts "List created; about to iterate:"
LazyLispyEnumerable.new(list).each do |x|
puts x
end

example 23

def fibo(a,b)
lambda { [a, fibo(b, a+b)]}
end

LazyLispyEnumerable.new(fibo(1,1)).each do |x|
puts x
break if x > 100
end

class Lazy
def initialize(&generator)
@generator = generator
end

def method_missing(method, *args, &block)
evaluate.send(method, *args, &block)
end

def evaluate
@value = @generator.call unless @value
@value
end
end

def lazy(&b)
Lazy.new &b
end

example 24

x = lazy do
puts "<<< Evaluating lazy value >>>"
"lazy value"
end

puts "x has now been assigned"
puts "About to call one of x's methods:"
puts "x.size: #{x.size}"
puts "x.swapcase: #{x.swapcase}"

example 25

def fibo(a,b)
lazy { [a, fibo(b, a+b)] }
end

LispyEnumerable.new(fibo(1,1)).each_with_index do |x|
puts x
break if x > 100
end

example 26

car,cdr = fibo(1,1)
puts "car=#{car} cdr=#{cdr}"


class Lazy
def initialize(&generator)
@generator = generator
end

def method_missing(method, *args, &block)
evaluate.send(method, *args, &block)
end

def respond_to?(method)
evaluate.respond_to?(method)
end

def evaluate
@value = @generator.call unless @value
@value
end
end

example 27

LispyEnumerable.new(fibo(1,1)).each do |x|
puts x
break if x > 200
end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值