当前位置 博文首页 > 深入讲解Ruby中Block代码快的用法

    深入讲解Ruby中Block代码快的用法

    作者:pringwq 时间:2021-02-11 09:03

    Block
    定义

    some_array.each { |value| puts value + 3 }
    
    sum = 0
    other_array.each do |value|
     sum += value
     puts value / sum
    end
    
    
    •     A block is somewhat like the body of an anonymous method
    •     Block can take parameters
    •     Block 只有被 method 调用时才会起作用,如果 method 中有参数,block 出现在最后面

    Block 中的变量
    如果 block 的本地变量的名字和 block 之外但是在同样 scope 里面的 变量名字一样,那他们两个是一样的。block 内变量的值会改变 block 外变量的值。

    sum = 0
    [1,2,3,4].each do |value|
     sum += value
     puts value / sum
    end
    puts sum # => 30
    
    

    如果 block 中的变量只出现在 block 中,那么它只是 block 中本地变量,无法在 block 之外被引用。

    sum = 0
    [1,2,3,4].each do |value|
     square = value * value
     sum += square
    end
    puts sum # => 30
    puts square # undefined local variable or method 'square' for main:Object <NameError>
    
    Parameters to a block are always local to a block, even if they have the same name as locals in the surrounding scope.
    
    value = "some shape"
    [1,2].each { |value| puts value }
    puts value
    
    # 1
    # 2
    # some shape
    
    You can define a block-local variables by putting them after s semicolon in the block's parameter list
    
    square = "some shape"
    sum = 0
    [1,2,3,4].each do |value; square|
      square = value * value
      sum += square
    end
    puts sum # 30
    puts square # some shape
    
    
    • By making square block-local, values assigned inside the block will not affect the value of the variable with the same name in the outer scope.
    • Blocks for Transactions
    • You can use blocks to define a chunk of code that must be run under some kind of transnational control
    class File
     def self.open_and_process(*args)
      f = File.open(*args)
      yield f
      f.close
     end
    end
    
    File.open_and_process("testfile","r") do |file|
     while line = file.gets 
      puts line
     end
    end
    
    

    Blocks Can Be Objects

    You can convert a block into an object, store it in variables, pass it around, and then invoke its code later.

    如果 method 的最后一个参数前面有 & 符号 (&action), 那么当此 method 被调用时,Ruby 会找一个 code block, 这个 code block 被转换成 class Proc 的一个对象。

    class ProcExample
     def pass_in_block(&action)
      @stored_proc = action
     end
    
     def use_proc(parameter)
      @store_proc.call(parameter)
     end
    end
    
    eg = ProcExample.new
    eg.pass_in_block { |param| puts "The parameter is #{param}" }
    eg.use_proc(99)
    # => The parameter is 99
    
    def create_block_object(&block)
     block
    end
    
    bo = create_block_object { |param| puts "You called me with #{param}" }
    bo.call 99 # => You called me with 99
    bo.call "cat" # => You called me with cat
    
    Ruby have two built-in methods that convert a block to an object: lambda and Proc.new
    
    bo = lambda { |param| puts "You called me with #{param}" }
    bo.call 99 # => You called me with 99
    
    
    • Blocks Can Be Closures
    • Closure: Variables in the surrounding scope that are referenced in a block remain accessible accessible for the life of that block and the life on any Proc object created from that block.
    def n_times(thing)
     lambda {|n| thing * n}
    end
    
    p1 = n_times(23)
    p1.call(3) #=> 69
    p2.call(4) #=> 92
    
    def power_proc_generator
     value = 1
     lambda { value += value }
    end
    
    power_proc = power_proc_generator
    puts power_proc.call # 2
    puts power_proc.call # 4
    
    lambda 表达式的另一种简写方式
    
    lambda { |params| ... }
    # 与下面的写法等价
    -> params { ... }
    # parmas 是可选的
    
    proc1 = -> arg1, arg2 {puts "#{arg1} #{arg2}"}
    
    proc1.call "hello", "world"
    # => hello world
    
    proc2 = -> { "Hello World" }
    proc2.call # => Hello World
    
    

    Block Parameter List

    Blocks can take default values, splat args, keyword args and a block parameter

    proc = -> a, *b, &block do 
     puts "a = #{a.inspect}"
     puts "b = #{b.inspect}"
     block.call
    end
    
    proc.call(1,2,3,4) {puts "in block"}
    # a = 1
    # b = [2,3,4]
    # in block
    
    

    js
    下一篇:没有了