2009-11-25 18 views
8

Tôi đang học Ruby. Nền của tôi là C++/Java/C#. Nói chung, tôi thích ngôn ngữ, nhưng tôi hơi bối rối về lý do tại sao có rất nhiều cách khác nhau để thực hiện cùng một điều, mỗi với ngữ nghĩa hơi khác nhau của họ. Ví dụ:Tại sao có quá nhiều cách hơi khác nhau để làm điều tương tự trong Ruby?

Tạo chuỗi ký tự. Tôi có thể sử dụng '', "", q%, Q% hoặc chỉ% để tạo chuỗi. Một số hình thức hỗ trợ nội suy. Các hình thức khác cho phép tôi chỉ định các dấu phân tách chuỗi.

Tại sao có năm cách tạo chuỗi ký tự chuỗi? Tại sao tôi lại sử dụng các chuỗi không được nội suy? Cú pháp% có lợi thế nào so với các chữ được trích dẫn?

Tôi biết phải có giá trị trong sự dư thừa trong Ruby, nhưng đôi mắt chưa được đào tạo của tôi không thấy rõ. Vui lòng làm sáng tỏ cho tôi.

Trả lời

15

Tại sao tôi lại sử dụng chuỗi không được nội suy?

Khi bạn không muốn nội suy, tất nhiên. Ví dụ, có lẽ bạn đang xuất ra một số tài liệu về chuỗi suy:

'Use #{x} to interpolate the value of x.' 
=> "Use #{x} to interpolate the value of x." 

lợi thế gì cú pháp% có hơn literals trích dẫn?

Nó cho phép bạn viết chuỗi tự nhiên hơn, không có dấu ngoặc kép hoặc khi bạn không muốn thoát khỏi nhiều thứ, tương tự như tiền tố chuỗi C# @.

%{The % syntax make strings look more "natural".} 
=> "The % syntax makes strings look more \"natural\"." 

%{<basket size="50">} 
=> "<basket size=\"50\">" 

Có rất nhiều% -notations khác:

%w{apple banana #{1}cucumber} # [w]hitespace-separated array, no interpolation 
=> ["apple", "banana", "\#{1}cucumber"] 

%W{apple banana #{1}cucumber} # [W]hitespace-separated array with interpolation 
=> ["apple", "banana", "1cucumber"] 

# [r]egular expression (finds all unary primes) 
%r{^1?$|^(11+?)\1+$} 
=> /^1?$|^(11+?)\1+$/ 

(1..30).to_a.select{ |i| ("1" * i) !~ %r{^1?$|^(11+?)\1+$} } 
=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] 

%x{ruby --version} # [s]hell command 
=> "ruby 1.9.1p129 (2009-05-12 revision 23412) [x86_64-linux]\n" 

Ngoài ra còn có %s (cho các ký hiệu) và một số người khác.

Tại sao có năm cách tạo chuỗi ký tự chuỗi?

Điều này không quá bất thường. Hãy xem xét C#, ví dụ, trong đó có một số cách khác nhau để tạo ra các chuỗi: new String(); ""; @""; StringBuilder.ToString(), v.v.

+1

"tự nhiên" rất có tính chủ quan. "khủng khiếp bất thường" không phải là một động lực để tạo ra một tính năng ngôn ngữ. – skrat

+1

"tự nhiên" là rất chủ quan, nhưng "ít hơn và dễ dàng gõ các ký tự để nói chính xác cùng một điều" không phải là, và là một động lực khá tốt để tạo ra một tính năng ngôn ngữ. –

1

Rất nhiều cú pháp của Ruby có nguồn gốc từ perl's, như sử dụng q để trích dẫn một vài từ thành một chuỗi. Đó có lẽ là lý do chính cho sự đa dạng lớn như vậy.

3

Tôi không phải là chuyên gia về Ruby, nhưng bạn đã bao giờ nghe thuật ngữ "cú pháp" chưa? Về cơ bản một số ngôn ngữ lập trình cung cấp cú pháp khác nhau để thực hiện cùng một nhiệm vụ. Một số người có thể tìm thấy một cách dễ dàng hơn những người khác do kinh nghiệm lập trình/cú pháp trước đó của mình.

+0

Thật vậy. Rõ ràng, Ruby đang sử dụng bí danh/từ đồng nghĩa nhiều lần. Ví dụ, số lượng các phần tử trong một mảng có thể được lấy với 'count',' length', hoặc 'size'. Các từ khác nhau cho cùng một thuộc tính của một mảng, nhưng bằng cách này, Ruby cho phép bạn chọn từ thích hợp nhất cho mã của bạn: bạn có muốn _number_ của các mục bạn đang thu thập, _length_ của một mảng hay _size_ hiện tại của cấu trúc. Về cơ bản, chúng đều giống nhau, nhưng việc chọn đúng từ có thể làm cho mã của bạn dễ đọc hơn, đó là một thuộc tính tốt đẹp của ngôn ngữ. –

2

Trong hầu hết các trường hợp, bạn sẽ sử dụng các dấu phân tách chuỗi bình thường. Sự khác biệt chính giữa dấu ngoặc đơn và dấu ngoặc kép là dấu ngoặc kép cho phép bạn nội suy các biến.

puts 'this is a string' 
# => this is a string 
puts "this is a string" 
# => this is a string 
v = "string" 
puts 'this is a #{v}' 
# => this is a #{v} 
puts "this is a #{v}" 
# => this is a string 

%q%Q rất hữu ích khi bạn không thể sử dụng dấu ngoặc kép, vì họ là một phần của chuỗi nội bộ. Ví dụ, bạn có thể kết thúc bằng văn bản

html = %Q{this is a <img src="#{img_path}" class="style" /> image tag} 

Trong trường hợp này, bạn không thể sử dụng dấu ngoặc kép như delimiters trừ khi bạn muốn thoát khỏi delimiters thuộc tính nội bộ. Ngoài ra, bạn không thể sử dụng trích dẫn đơn vì biến số img_path sẽ không được nội suy.

0

Bạn sẽ sử dụng các chuỗi không được nội suy nếu chuỗi của bạn chứa nhiều ký tự đặc biệt (như dấu gạch chéo ngược, #{} v.v.) và bạn không muốn thoát khỏi tất cả các chuỗi đó.

Bạn muốn sử dụng các dấu phân tách khác nhau nếu chuỗi của bạn chứa nhiều dấu ngoặc kép mà bạn phải thoát ra.

Bạn sẽ sử dụng heredocs nếu chuỗi của bạn có nhiều dòng để làm cho cú pháp chuỗi bình thường trở nên khó sử dụng.

0

Ruby xây dựng các kiến ​​trúc và ý tưởng từ nhiều ngôn ngữ. Hai ảnh hưởng rõ ràng nhất là Smalltalk và Perl.

Tùy thuộc vào sự thoải mái của bạn với Smalltalk hoặc Perl bạn cũng có thể chọn các cấu trúc khác nhau để thực hiện tương tự.

1

Một lý do nữa là tăng hiệu suất nhỏ đối với các chuỗi không được nội suy. Sử dụng '' vs '' có nghĩa là Ruby không phải xem xét những gì bên trong chuỗi. Vì vậy, bạn sẽ thấy mọi người sử dụng dấu nháy đơn cho các khóa mảng hoặc biểu tượng vì chúng nhanh hơn. Đối với những gì nó có giá trị tôi sẽ bao gồm một điểm chuẩn nhỏ.

require 'benchmark' 

Benchmark.bmbm(10) do |x| 
    x.report("single-quote") do 
    for z in 0..1000000 
     zf = 'hello' 
    end 
    end 

    x.report("double-quote") do 
    for z in 0..1000000 
     zf = "hello" 
    end 
    end 

    x.report("symbol") do 
    for z in 0..1000000 
     zf = :hello 
    end 
    end 
end 

sản lượng:

Rehearsal ------------------------------------------------ 
single-quote 0.610000 0.000000 0.610000 ( 0.620387) 
double-quote 0.630000 0.000000 0.630000 ( 0.627018) 
symbol   0.270000 0.000000 0.270000 ( 0.309873) 
--------------------------------------- total: 1.580000sec 
0

Dọc theo dòng câu trả lời của John: Trong hacks nhanh chóng, tôi thường kết thúc chạy perl hoặc sed one-liner với cú pháp grep từ bên trong kịch bản ruby ​​của tôi. Có thể sử dụng cú pháp loại %[ ] có nghĩa là tôi có thể chỉ cần sao chép-dán regexp của mình từ thiết bị đầu cuối

0

Câu hỏi ban đầu là tại sao có quá nhiều cách làm việc khác nhau trong Ruby. Đôi khi những điều khác nhau là hợp lý: trích dẫn là một trường hợp tốt khi hành vi khác nhau đòi hỏi cú pháp khác nhau - không/nội suy, ký tự trích dẫn thay thế, vv - và dấu hiệu lịch sử gây ra các từ đồng nghĩa như% x() so với ``, trong Perl.

Vấn đề đồng nghĩa - [] .size [] .length [] .count - cảm thấy như một nỗ lực hữu ích trong một thế giới mà ngôn ngữ quá ngẫu nhiên đối với IDE để có thể trợ giúp: vá khỉ và kết hợp kỳ lạ của đánh máy chặt chẽ nhưng năng động với nhau làm cho lỗi thời gian chạy là một phần không thể tránh khỏi và bực bội của mã hóa, do đó, folks cố gắng giảm vấn đề bằng cách cung cấp từ đồng nghĩa. Thật không may, họ kết thúc lập trình khó hiểu, những người đã quen với các phương pháp khác nhau làm những việc khác nhau.

Vấn đề 'như vậy tương tự nhưng không hoàn toàn', ví dụ ...

$ ruby -le 'e=[]; e << (*[:A, :B])' 
-e:1: syntax error, unexpected ')', expecting :: or '[' or '.' 
$ ruby -le 'e=[]; e << *[:A, :B]' 
-e:1: syntax error, unexpected * 
$ ruby -le 'e=[]; e.push(*[:A, :B])' 
$ 

... chỉ có thể thực sự được xem như là một lỗ hổng. Mọi ngôn ngữ đều có chúng, nhưng chúng thường phức tạp hơn thế này.

Và sau đó có tùy ý sử dụng đồng bằng thất bại thay vì tăng trừ khi bạn chỉ cần sửa lại một ngoại lệ 'vô nghĩa trong các tiêu chuẩn mã hóa của Rubocop.

Có một số bit tốt đẹp trong Ruby, nhưng thực sự - tôi muốn thay vì được viết mã trong một cái gì đó tốt hơn thành lập.

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