美文网首页
Double Splat operator

Double Splat operator

作者: orcl_zhang | 来源:发表于2015-07-18 11:31 被阅读56次

    分享两篇文章,介绍Splat operator和Ruby2.0引入的Double Splat operator.

    Splat goes Ruby
    Drat! - Ruby has a Double Splat

    Splat的用法:

    • 使用在方法参数中,转化list为Array
    def ahoy(*args)
      p args
    end
    
    ahoy :a, 345, hello: :world # => [:a, 345, {:hello=>:world}]
    
    • 将Array参数转化为list
    def ahoy(from, to)
      puts "#{to.capitalize}, #{from.capitalize} says ahoy!"
    end
    
    even_stephens = %w(steven stephen)
    ahoy even_stephens # Array is interpreted as the first argument, and to_matey won’t be set. An ArgumentError is raised.
    
    ahoy *even_stephens # Array is reversed to a list and all the arguments are filled out.
    # => Stephen, Steven says ahoy!
    
    • splat后面不能有required参数
    def hello(name, *args, options, &block)
      p name
      p args
      p options
      p block
    end
    
    hello('denny', :a, :b, upcase: true) { 'block this!' }
    # name: ”denny”
    # args: [:a, :b]
    # options: {:upcase=>true}
    # => #<Proc:0x007fc1a10afd60>
    
    # Works fine:
    def hello(name = nil, *args)
    
    # Throws SyntaxError:
    def hello(*args, name = nil)
    
    # Using several splats in a definition SyntaxErrors too:
    def hello(a, *args, b, *brgs)
    
    • 可以在yield参数里
    ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
      puts payload
    end
    
    ActiveSupport::Notifications.subscribe('render') do |*, payload|
      puts payload
    end
    
    # It's also easier than:
    ActiveSupport::Notifications.subscribe('render') do |*args|
      payload = args.last
      puts payload
    end
    
    • 赋值时的使用
    a, b = [:a, :b]
    a # => :a
    b # => :b
    
    a, b = [:a, :b, :c] # :c is lost
    a # => :a
    b # => :b
    
    a, *rest = [:a, :b, :c]
    a # => :a
    rest # => [:b, :c]
    
    a, *= [:a, :b, :c]
    a # => :a
    
    a ,= [:a, :b, :c]
    a # => :a
    
    • 如果不关心这个参数就不需要为这个参数命名
    class WhipperSnapper
      def initialize(snap_count, whip_size)
        @snap_count, @whip_size = snap_count, whip_size
      end
    end
    
    class SupremeSnapper < WhipperSnapper
      def initialize(*)
        super
        @agility = 100_000
      end
    end
    

    Double Splat的用法

    • Obligatorily Optional(如何翻译?)
    def hello(**options)
      p options
    end
    
    hello
    # options: {}
    
    hello name: 'Kasper'
    # options: { :name => 'Kasper' }
    

    类似于optional arguments

    def hello(options = {})
    end
    
    • Hash
    def hello(name = nil, **options)
      p name
      p options
    end
    
    hello 'Kasper'
    # name: 'Kasper'
    # options: {}
    
    hello upcase: true
    # name: nil
    # options: { :upcase => true }
    

    **之前的参数必须是可选的!

    def hello(name, **options)
      p name
      p options
    end
    
    hello upcase: true
    # name: { :upcase => true }
    # options: {}
    
    • Off Key Splat
      使用了double splats 之后可以传入或多或少的keys
    def hello(name:)
      p name
    end
    
    hello # raises "ArgumentError: missing keyword: name" as expected
    
    hello name: 'Kasper', play_style: :laces_out 
    # raises "ArgumentError: unknown keyword: play_style"
    
    def hello(name:, **options)
      p name
      p options
    end
    
    hello name: 'Kasper', play_style: :laces_out
    # name: 'Kasper'
    # options: { :play_style => :laces_out }
    
    hello play_style: :laces_out
    # ArgumentError: missing keyword: name
    
    # 加入默认值后
    
    def hello(name: nil, **options)
      p name
      p options
    end
    
    hello play_style: :laces_out
    # nil
    # {:play_style=>:laces_out}
    
    • Exploit a Splat, Expand a Hash
      可以展开一个hash
    options = { a: 'b' }
    { c: 'd', **options } # => { :c => "d", :a => "b" }
    

    *可以展开一个数组,两个用法还是挺接近的。

    a=[1,3]
    # => [1, 3]
    [2, *a]
    # => [2, 1, 3]
    
    • Yield to Splat
      之前可以这么写
    def hello
      yield name: 'Kasper'
    end
    
    hello { |options| p options[:name] }
    # Outputs "Kasper"
    

    可以简写

    hello { |name:| p name }
    # Outputs "Kasper"
    
    def hello
      yield name: 'Kasper', play_style: :laces_out
    end
    
    hello { |name:, **| p name }
    # Outputs "Kasper"
    

    相关文章

      网友评论

          本文标题:Double Splat operator

          本文链接:https://www.haomeiwen.com/subject/klrpqttx.html