`

关于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

分享到:
评论

相关推荐

    block在ios中的具体用法与解析

    "OCLesson6_Block"可能是一个关于Block的示例项目或教程,包含具体的代码示例和实践练习,帮助学习者深入理解和应用Block。 总之,Block是iOS开发中不可或缺的一部分,它提供了更灵活的代码组织方式和强大的功能。...

    GCD_demo __ 练习

    Block是Objective-C和Swift中的一种闭包表达形式,可以捕获和存储执行上下文中的局部变量。在GCD中,Block是定义任务的简单且强大的工具。我们可以将Block作为参数传递给GCD函数,例如`dispatch_async`,来异步地...

    OC练习题(全套)

    6. **块(Block)**:OC中的闭包实现,可以捕获并存储执行环境中的变量,常用于异步操作和回调。 7. **内存管理**:理解ARC(Automatic Reference Counting)自动引用计数的工作原理,以及强引用、弱引用的区别,...

    练习:Ruby课堂练习

    通过练习,你会了解它们在迭代、回调函数和闭包中的应用。 在完成这些练习后,你将能够更熟练地运用Ruby语言解决问题,为将来开发更复杂的项目打下坚实的基础。同时,不断实践是提升编程能力的关键,因此,不要害怕...

    2018-js算法练习题-精选word文档 (7页).pdf

    - 显示/隐藏DOM元素:通过改变元素的CSS样式,如`display:none`来隐藏,或`display:block`来显示。 - 横向居中对齐布局:使用CSS实现,如设置`margin: 0 auto`,并确保元素的左右边距自动调整。 2. **CSS布局**:...

    IOS试题&amp;object;-c试题

    7. **Block(闭包)**:Block是一种内联函数,可以捕获和存储其所在上下文的局部变量,常用于异步编程。 ### 二、iOS应用开发 1. **UIKit框架**:iOS应用的核心是UIKit框架,它包含创建用户界面、处理用户输入、...

    JS30Days:30天的Javascript练习。 担任复习

    3. **函数**:函数声明与表达式,参数传递,作用域(global, local, block)和闭包。 4. **数组与对象**:数组方法(push, pop, shift, unshift, slice, splice等),对象属性操作,以及数组和对象的遍历。 5. **...

    OC语言源代码

    Block是Objective-C的一个重要特性,它允许在代码中定义匿名函数或者闭包。Block可以捕获和存储其所在上下文的变量,这使得它在处理异步操作、迭代、以及函数式编程风格时非常有用。 2. **Categories**: `...

    Homework_JavaScript_Block_3

    【标题】"Homework_JavaScript_Block_3" 指的是一份关于JavaScript编程的作业集合,可能是一个课程或训练项目的第三部分。这个标题暗示了这个作业涉及到一系列的JavaScript练习,旨在帮助学习者深入理解和掌握...

    2-4章的所有代码

    3. **Block(块)**:Block是Objective-C的闭包实现,用于创建匿名函数。学习Block的定义、存储和使用,以及Block的循环引用问题。 4. **GCD(Grand Central Dispatch)**:介绍苹果的并行编程框架,学习如何使用...

    ruby 快速开发web项目的教程

    Ruby语言的核心特性包括动态类型、垃圾回收机制、块(block)、闭包(closure)以及元编程。动态类型意味着变量的类型是在运行时确定的,这使得代码更简洁。Ruby的垃圾回收机制自动管理内存,开发者无需手动释放。块...

    Objective-C2.0基础教程课后 答案

    Block可以方便地实现回调和闭包功能,简化异步操作的处理。 Foundation框架是Objective-C开发的基础,包含了如NSArray、NSDictionary、NSString等常用数据结构和工具类。Core Foundation框架则提供了C语言级别的API...

    Programming in Objective-C 2.0

    6. **块(Block)**:Objective-C 2.0引入了块(Block)的概念,它是一种内联函数,可以捕获并存储其作用域内的变量,常用于异步编程和闭包操作。 7. **内存管理**:Objective-C使用引用计数进行内存管理,通过`...

    study:练习编程问题及其解决方案的存储库

    "study:练习编程问题及其解决方案的存储库"是一个专门为编程爱好者和学习者提供的宝贵资源,它包含了多种编程语言的实战练习题目以及对应的解题思路和代码示例。特别地,这个存储库强调了对Ruby语言的支持,这使得对...

    ruby经典

    3. **块、迭代器与闭包**:Ruby中的块(block)是一种特殊的语法结构,可以配合迭代器(iterator)使用,实现类似函数的功能。块可以嵌套,且与闭包(lambda)有密切关系,理解这些对于编写高效代码至关重要。 4. *...

    在Ruby中使用块:一份脑友好的报告(Jay McGavren)Using Blocks in Ruby: A Brain-Friendly Report (Jay McGavren)

    本书的目标是帮助读者从不同角度审视块,通过一系列的练习来理解和记忆块如何工作。这样的教学方式有助于读者以一种更加放松和自然的方式掌握Ruby块的使用,避免在编程中犯下令人尴尬的错误。 Ruby块有以下几种应用...

    oc中数组排序

    为了更好地复习和巩固OC中的数组排序,可以创建一个练习项目,模拟实际场景,比如根据用户输入的年龄排序一个人物数组,或者根据日期对事件进行排序等。通过编写测试用例,检查不同排序方法的正确性和性能差异。 ...

    ruby源代码7

    5. **闭包(Closure)**:Ruby的块和Proc具有闭包特性,即它们能记住定义时的作用域,即使在其他地方调用也能访问到。 6. **元编程**:Ruby的元编程能力强大,允许在运行时修改类和对象。`class用于打开当前对象的...

    GCD Trainer 0[1].0.0.4.rar

    GCD的核心概念包括队列(Queue)和工作块(Block)。队列分为串行队列和并行队列,前者保证了任务的执行顺序,而后者则可以同时处理多个任务。工作块则是一种轻量级的闭包,可以封装代码逻辑,方便地提交到队列中...

    ruby语言基础

    9. **闭包**:Ruby的块和Proc都是闭包,能够捕获并记住它们定义时的作用域,即使在其他地方执行也能访问这些变量。 10. **元编程**:Ruby的元编程能力强大,允许在运行时动态地创建和修改类、方法和对象。`Class....

Global site tag (gtag.js) - Google Analytics