about 10 years ago

Proc 與 yield 的差別在於,proc 會將 block 給暫存起來,等到需要用的時候,再以 block.call 的方式呼叫出來,yield 則是自動執行 block.call 。

新增一個 proc object 的做法有兩種,proc & lambda。
  #Proc New

  my_proc = Proc.new { puts "tweet" }
  my_proc.call
  
  #Lambda

  my_proc = lambda { puts "tweet" }  #1.9以上版本也可以寫成 my_proc = -> { puts "tweet" }

  my_proc.call      
  
  #result

  "twitter"
Proc 也可讓你執行兩個以上的 block
  class Tweet
    def post(success, error)
      if current_user
        success.call
      else
        error.call
      end
    end
  end

  tweet = Tweet.new
  success = lambda { puts "Sent!"}
  error = lambda { puts "No user login"}
  tweet.post(success, error)
Proc 如果要轉換成 block
  tweets = ["First tweet", "Second tweet"]
  printer = lambda { |tweet| puts tweet }
  tweets.each(printer) # 會噴錯誤,因為each吃的是block

  tweets.each(&printer) # 加上 '&' 就可將proc轉換成block
而 proc 和 lambda 到底有哪些差異的地方?

Lambdas 會檢查傳入的參數,而Procs不會

  def puts_parameters(code)
    code.call(1, 2)
  end
  
  l = lambda { |a, b, c| puts "#{a} is a #{a.class}, #{b} is a #{b.class}, #{c} is a #{c.class}" }
  p = Proc.new { |a, b, c| puts "#{a} is a #{a.class}, #{b} is a #{b.class}, #{c} is a #{c.class}" }
  
  puts_parameters(l)
  #result

  "ArgumentError: wrong number of arguments (2 for 3)"
  
  puts_parameters
  #result

  "1 is a Fixnum, 2 is a Fixnum,  is a NilClass"

Lambdas 會直接skip return,而 Procs不會

  def return_using_proc
    Proc.new { return "Hi from proc!"}.call
    puts "end of proc call"
  end
  
  def return_using_lambda
    lambda {return "Hi from lambda!"}.call
    puts "end of lambda call"
  end

  return_using_proc
  #result

  "Hi from proc!"
  
  return_using_lambda
  #result

  "end of lambda call"
← What is yield 哪種情況需要寫測試? →
 
comments powered by Disqus