2009-10-01 30 views
8

Đây là một thủ thuật thông minh cho phép băm autovivification trong ruby ​​(lấy từ khía cạnh):ruby ​​băm autovivification (khía cạnh)

# File lib/core/facets/hash/autonew.rb, line 19 
    def self.autonew(*args) 
    leet = lambda { |hsh, key| hsh[key] = new(&leet) } 
    new(*args,&leet) 
    end 

Mặc dù nó hoạt động (tất nhiên), tôi thấy nó thực sự bực bội mà tôi có thể' t tìm hiểu làm thế nào hai lớp lót này làm những gì nó làm.

Leet được đặt làm giá trị mặc định. Vì vậy, khi đó, chỉ cần truy cập h['new_key'] bằng cách nào đó sẽ hiển thị và tạo ra 'new_key' => {}

Bây giờ, tôi mong đợi trả về giá trị mặc định của đối tượng mặc định thay vì đánh giá nó. Tức là, 'new_key' => {} không được tạo tự động. Vì vậy, làm thế nào để thực sự gọi là leet? Đặc biệt với hai thông số?

Trả lời

18

Tiêu chuẩn new method for Hash chấp nhận một khối. Khối này được gọi trong trường hợp cố gắng truy cập một khóa trong Hash mà không tồn tại. Khối được thông qua Hash và khóa được yêu cầu (hai tham số) và sẽ trả về giá trị cần trả về cho khóa được yêu cầu.

Bạn sẽ nhận thấy rằng leet lambda thực hiện 2 việc. Nó trả về một Hash mới với leet chính nó như là khối để xử lý mặc định. Đây là hành vi cho phép autonew hoạt động với các Hashes có chiều sâu tùy ý. Nó cũng gán Hash mới này cho hsh[key] để lần sau bạn yêu cầu cùng một khóa, bạn sẽ nhận được Hash hiện tại thay vì một Hash mới được tạo ra.

+0

Câu trả lời hay. – Pesto

+1

Thật vậy. Điều này, đặc biệt, sẽ dạy tôi không bao giờ nhắc đến RubyBook (đi kèm với bản phân phối cửa sổ ruby ​​chuẩn), vì nó không đề cập đến thực tế nhỏ bé liên quan đến các khối và mới. – artemave

8

Nó cũng đáng chú ý là mã này có thể được làm thành một lớp lót như sau:

def self.autonew(*args) 
    new(*args){|hsh, key| hsh[key] = Hash.new(&hsh.default_proc) } 
end 

Các cuộc gọi đến Băm # default_proc trả về proc đã được sử dụng để tạo ra các phụ huynh, vì vậy chúng tôi có một thiết lập đệ quy tốt đẹp ở đây.

Tôi nói về một số similar case cho điều này trên blog của mình.

-1

Hoặc, bạn có thể xem xét số xkeys gem của mình. Đó là một mô-đun mà bạn có thể sử dụng để mở rộng mảng hoặc băm để tạo điều kiện truy cập lồng nhau.

Nếu bạn tìm kiếm thứ gì đó chưa tồn tại, bạn sẽ nhận được giá trị nil (hoặc giá trị khác hoặc ngoại lệ nếu bạn thích) mà không tạo bất kỳ thứ gì bằng cách tìm kiếm. Nó cũng có thể nối thêm vào cuối mảng.

Bạn có thể chọn tự động hóa băm hoặc mảng cho các phím số nguyên (nhưng chỉ một lần cho toàn bộ cấu trúc).

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