2012-03-29 20 views
39

Với mảng sau a:Làm cách nào để chuyển đối số sang cắt ngắn mảng.một?

a = [1, 2, 3, 4, 5] 

Làm thế nào để làm:

a.map { |num| num + 1 } 

sử dụng các ký hiệu ngắn:

a.map(&:+ 1) 

hay:

a.map(&:+ 2) 

trong đó 1 và 2 là các đối số?

+16

Gian lận: '[1, 2, 3, 4, 5] .map (&: next) # => [2, 3, 4, 5, 6]' –

+0

Bạn có thể quan tâm đến [Enumerators] của Ruby (http://www.ruby-doc.org/core-2.1.2/Enumerator.html). – alxndr

Trả lời

33

Bạn không thể làm điều đó như thế này. Toán tử & là để biến các ký hiệu thành procs.

a = [1, 2, 3, 4, 5] 
puts a.map(&:to_s) # prints array of strings 
puts a.map(&:to_s2) # error, no such method `to_s2`. 

& là viết tắt của to_proc:

def to_proc 
    proc { |obj, *args| obj.send(self, *args) } 
end 

Nó tạo ra và trả về proc mới. Như bạn thấy, bạn không thể chuyển bất kỳ tham số nào cho phương thức này. Bạn chỉ có thể gọi proc được tạo.

+0

bạn nói đúng: vì array.map (&: some_method) là viết tắt của: class Symbol def to_proc proc {| obj, * args | obj.send (self, * args)} kết thúc kết thúc. làm thế nào để bạn vượt qua trong * args? –

+0

@not_nil: bạn thì không. Sử dụng khối bình thường/proc. –

+2

@not_nil: Ruby không hỗ trợ kiểu point-free cho bất kỳ thứ gì vượt quá 'Symbol # to_proc', bởi vì nó thiếu thành phần hàm và currying. Bạn đến từ một nền tảng chức năng? –

24

Bạn không thể làm điều đó với map. Nhưng nhìn vào Facets 'Enumerable#map_send:

require 'facets' 
[1, 2, 3].map_send(:+, 1) 
#=> [2, 3, 4] 

Viết thực hiện của riêng bạn là khá đơn giản:

module Enumerable 
    def map_send(*args) 
    map { |obj| obj.send(*args) } 
    end 
end 
0

Nếu bạn thực sự cần rằng bạn có thể sử dụng thư viện Ampex, nhưng tôi không biết nếu nó vẫn được duy trì.

Các vấn đề liên quan