2010-02-10 40 views
13

tôi đang tìm kiếm thông qua một số mã nguồn Rails và đã xem quaChuỗi * có nghĩa là gì trong Ruby?

# File vendor/rails/activesupport/lib/active_support/vendor/builder-2.1.2/builder/css.rb, line 129 
129:  def target! 
130:  @target * '' 
131:  end 

nào * '' làm gì? Đó là phép nhân bằng một chuỗi rỗng ...? Và tại sao bạn sẽ làm điều đó.

Trả lời

13

Đây là cú pháp kỳ quái. Đây là tương đương:

>> [1, 2, 3] * 'joiner' 
=> "1joiner2joiner3" 

>> [1, 2, 3].join 'joiner' 
=> "1joiner2joiner3" 

như vậy trong trường hợp này nó tham gia tất cả các mục của @target thành một chuỗi, không có gì giữa các mục.

Lưu ý: nếu bạn làm điều gì đó như [1, 2, 3] * 3 (sử dụng int thay vì str), bạn sẽ nhận được ba bản sao được ghép nối của mảng thay thế.

+0

Huh ?! Không có gì "kỳ dị" về cú pháp toán tử infix (trừ khi bạn là người cuồng nhiệt của Lisp hay Forth). Khá nhiều * mọi ngôn ngữ lập trình trên hành tinh này có một toán tử *. –

+5

@ Jörg: Nó không phải là một phần infix đó là kỳ quái, đó là một thực tế là nó nhân một mảng bằng một chuỗi ...? –

+0

Tôi đồng ý rằng ngữ nghĩa gây nhầm lẫn và thực sự kỳ lạ, nhưng những gì cả Peter và crudson đang phàn nàn không phải là ngữ nghĩa, đó là cú pháp *, và tôi hơi bối rối bởi điều đó. –

5

Nó làm điều tương tự như: đề nghị

["foo","bar","baz"].join 

http://ruby-doc.org/core/classes/Array.html#M002210

mỗi Z.E.D., bạn sẽ sử dụng nó nếu bạn muốn nhầm lẫn giữa con người và làm cho mã lỗi của bạn nhiều hơn dễ bị.

+2

Tôi có thể sẽ nói khác. Nó kết quả tương tự như một [] .join, nhưng sử dụng phương thức join() là rõ ràng hơn và thường được sử dụng hơn. Tôi đã thấy một số khuyến nghị rằng chúng tôi không sử dụng toán tử '*' với mảng vì rất ít người sử dụng nó khiến nó khó hiểu. So sánh đầu ra của [1,2] * ',' với [1,2] * 2 để biết ví dụ về lý do tại sao nó không hoạt động tốt với bộ não của chúng tôi. –

+0

Bạn đang tranh luận rằng nó không làm điều tương tự? RDoc nói "tương đương với". Khả năng đọc là trực giao để thực hiện. – klochner

3

Thực sự mã khó hiểu.

Sau khi kiểm tra mã nguồn, tôi nhận ra rằng @target thực sự là một thể hiện Array, tôi biết bạn có thể làm những thứ như thế này

[5] * 5 # => [5,5,5,5,5] 

Tôi không biết nơi Array#* được xác định (có thể trong ActiveSupport), nhưng những gì tôi có thể nói với bạn là, đây là hành vi khi nó được nhân với một String

[1,2,3] * 'comma' # => "1comma2comma3" 
[1,2,3] * '' # => '123' 

Vì vậy, tôi có thể suy ra nó được concatanating tất cả các yếu tố của mảng mà không bất kỳ dấu phân cách nào.

1

Hai nhận xét:

  1. Có! kết thúc một tên phương thức ngụ ý rằng đó là một hoạt động đột biến, mà ví dụ này dường như không.

  2. Như những người khác đã tuyên bố nó thực sự khó hiểu. Tôi sẽ đi cho @ target.to_s hoặc @ target.join

+1

Ngoài ra, loại mã ruby ​​này làm tôi buồn vì ruby ​​rất dễ đọc và tự nhiên đẹp, và cú pháp như thế này mang lại cho tôi những hồi tưởng của Perl. – user253455

+0

Bạn là người thứ hai trong câu hỏi này để khiếu nại về cú pháp toán tử infix. Tôi không hiểu lắm. Ngoại trừ Lisp và Forth, khá nhiều * mọi ngôn ngữ lập trình trên hành tinh có một toán tử «*». Không có gì "kỳ lạ" hay "buồn" về các nhà khai thác. –

+0

Tất nhiên, nhưng ví dụ này làm cho người ta phải suy nghĩ một thời gian ngắn để có được dòng mã. Tạo một chuỗi rỗng để nối một mảng là một chút sử dụng tối nghĩa *. Tôi hoàn toàn không có gì chống lại nhà điều hành. – user253455

2

Array#* với một cuộc tranh luận String tương đương với Array#join.

0

Lý do duy nhất tôi muốn thấy ai đó muốn sử dụng * để tham gia một chuỗi các chuỗi là nếu họ muốn tránh từ join, cũng được sử dụng trên chuỗi.

Với những điều sau đây:

strings = ["John", "Smith"] 
threads = [Thread.new{puts "hai"}, Thread.new{ puts "world!"}] 
strings.join(" ") # Legit 
threads.each {|thread| thread.join} # Legit 

bạn có thể mắc sai lầm khi làm

threads.join # Not legit, but won't raise an error 

Nếu bạn thay thế strings.join với strings.*, sau đó bạn sẽ có ít join s trong mã của bạn. Bây giờ bạn có thể làm một grep cho họ, và kiểm tra xem mỗi cái đang được thực hiện cho một chủ đề, không phải một mảng. Trong thực tế, bạn có thể chọn để làm cho Array#join ném một ngoại lệ.