Ruby có phải là một ngôn ngữ chức năng không?


88

Wikipedia nói rằng Ruby là một ngôn ngữ chức năng, nhưng tôi không bị thuyết phục. Tại sao hoặc tại sao không?


4
Có lẽ vì câu hỏi của bạn rất ngắn, mặc dù cá nhân tôi không có vấn đề gì với nó!
ljs

Đã có những câu trả lời hay, vì vậy chỉ để bổ sung cho chúng, một cặp nội dung thảo luận về FP và Ruby: code.google.com/p/tokland/wiki/RubyF Chức năngProgramming slideshare.net/tokland/f Chức năng-programming-with-
tokland

1
Nếu ai quan tâm đến chủ đề này, hãy xem phần này và bạn sẽ biết cách ruby ​​có thể được sử dụng theo cách chức năng, nguồn gốc của lập trình chức năng là gì, tại sao ruby ​​không phải là ngôn ngữ chức năng ngay cả khi nó có khả năng lập trình chức năng: youtube .com / watch? v = 5ZjwEPupybw
maddin2code

Câu trả lời:


29

Tôi chắc chắn rằng bạn có thể sử dụng kiểu hàm trong Ruby.

Một trong những khía cạnh quan trọng nhất để có thể lập trình theo kiểu hàm là ngôn ngữ có hỗ trợ các hàm bậc cao hơn hay không ... mà Ruby làm.

Điều đó nói rằng, thật dễ dàng để lập trình trong Ruby theo kiểu phi chức năng. Một khía cạnh quan trọng khác của kiểu hàm là không có trạng thái và có các hàm toán học thực sự luôn trả về cùng một giá trị cho một tập hợp đầu vào nhất định. Điều này có thể được thực hiện trong Ruby, nhưng nó không được thực thi trong ngôn ngữ giống như một thứ có chức năng nghiêm ngặt hơn như Haskell.

Vì vậy, vâng, nó hỗ trợ phong cách chức năng, nhưng nó cũng sẽ cho phép bạn lập trình theo phong cách phi chức năng.


4
Sử dụng tiêu chí này, bạn có thể nói rằng Smalltalk hoạt động tốt vì nó có các khối không?
OscarRyz

Câu trả lời tốt nhưng một nitpick - các chức năng bậc cao hơn không bắt buộc phải có cho một kiểu chức năng. Ví dụ: Bạn có thể đạt được kiểu hàm trong Java (không có hàm hạng nhất / hàm bậc cao hơn) bằng cách xác định các đối tượng hàm và soạn thảo chúng để có được hiệu ứng tương tự như hàm bậc cao hơn.
mikera

2
Chỉ muốn nói rằng @peter đã hỏi Is ruby a functional language?và câu trả lời thẳng thắn là không. Ruby là một ngôn ngữ hướng đối tượng với một số tính năng chức năng.
Elias Perez

58

Một ngôn ngữ có phải là ngôn ngữ chức năng hay không là điều không quan trọng. Lập trình chức năng là một luận án, được giải thích tốt nhất bởi Philip Wadler (Bản chất của Lập trình Chức năng) và John Hughes (Tại sao Các vấn đề Lập trình Chức năng).

Một câu hỏi có ý nghĩa là, 'Ruby có thể đạt được luận điểm về lập trình hàm như thế nào?' Câu trả lời là 'rất kém'.

Tôi đã nói chuyện về điều này vừa rồi. Đây là các slide.


3
Các trang trình bày bạn đưa ra không đề cập đến lý do tại sao Ruby "rất kém khả năng đạt được luận điểm của FP." Tại sao C # dễ sử dụng hơn Java (OK, các hàm ẩn danh dễ dàng hơn?)? Có phải vì bạn có thể có các biến toàn cục trong Ruby không?
kizzx2 19/09/10

7
Không có slide nào không đi sâu vào chi tiết này, vì đây là một chủ đề khá rộng. Ví dụ, trước nguy cơ đơn giản hóa quá mức, Ruby thực thi một mô hình đánh giá (gọi theo giá trị) để đảm bảo tính không kết hợp của các chương trình. Tác động của điều này có thể dễ dàng được ước tính dưới mức. Ruby cũng kết hôn với ý tưởng rằng một chương trình là một chuỗi các hiệu ứng. Có nghĩa là, Ruby đã cố gắng làm cho việc sử dụng bất kỳ mô hình tính toán nào khác trở nên khó khăn / không thể thực hiện được. Tôi hy vọng bình luận ngắn này sẽ giúp ích.
Tony Morris

2
+1 để chỉ ra sự không rõ ràng trong việc phân loại ngôn ngữ là chức năng. Chết tiệt, tôi đã viết chức năng C!
Eli

1
Tại sao C # dễ sử dụng hơn Ruby?
dan_l

1
Hiệu quả là một câu trả lời chỉ có liên kết vì nó đưa phần quan trọng của lời giải thích (thực tế là toàn bộ phần giải thích) cho một liên kết bên ngoài. Bây giờ liên kết đã chết, câu trả lời đã trở nên vô dụng.
ivan_pozdeev

34

Ruby có hỗ trợ các hàm cấp cao hơn (xem Array # map, injection, & select), nhưng nó vẫn là một ngôn ngữ hướng đối tượng, bắt buộc.

Một trong những đặc điểm chính của ngôn ngữ chức năng là nó tránh trạng thái có thể thay đổi. Các ngôn ngữ hàm không có khái niệm về một biến như bạn sẽ có trong Ruby, C, Java hoặc bất kỳ ngôn ngữ mệnh lệnh nào khác.

Một đặc điểm chính khác của ngôn ngữ chức năng là nó tập trung vào việc xác định một chương trình dưới dạng "cái gì", chứ không phải "như thế nào". Khi lập trình bằng ngôn ngữ OO, chúng ta viết các lớp & phương thức để ẩn việc triển khai ("cách") khỏi "cái gì" (tên lớp / phương thức), nhưng cuối cùng các phương thức này vẫn được viết bằng một chuỗi các câu lệnh. Trong ngôn ngữ chức năng, bạn không chỉ định trình tự thực thi, ngay cả ở cấp thấp nhất.


3
Tôi đồng ý với hầu hết tuyên bố của bạn, tuy nhiên, tôi không đồng ý về "Ngôn ngữ chức năng không có khái niệm về biến như bạn sẽ có trong Java, v.v." Trong haskell, bạn có thể sử dụng các biến trong các hàm thuần túy, thậm chí bạn có thể gán một hàm cho một biến, sự khác biệt lớn nhất là khi một biến được gán thì nó không thể được sửa đổi sau đó.
HHC

6
HHC, theo định nghĩa, một biến là một giá trị có thể thay đổi . Những gì bạn đang nói đến là các giá trị.
Scala Newb

Thật vậy "các biến không thể thay đổi" của Haskell chỉ là các hàm hằng không có tham số (định nghĩa).
raindev

16

Tôi gửi rằng hỗ trợ hoặc có khả năng lập trình bằng một ngôn ngữ theo phong cách chức năng không phải là ngôn ngữ chức năng tạo ra.

Tôi thậm chí có thể viết mã Java theo kiểu chức năng nếu tôi muốn làm hại đồng nghiệp của mình và bản thân tôi sau vài tháng .

Có một ngôn ngữ chức năng không chỉ là về những gì bạn có thể làm, chẳng hạn như các chức năng bậc cao hơn, các chức năng hạng nhất và cách đọc. Nó cũng là về những gì bạn không thể làm, như tác dụng phụ trong các chức năng thuần túy.

Điều này rất quan trọng bởi vì nó là một phần lớn lý do tại sao các chương trình chức năng, hay mã chức năng trong genrel lại dễ lý giải hơn. Và khi mã dễ lập luận hơn, các lỗi trở nên nông hơn và nổi lên bề mặt khái niệm nơi chúng có thể được sửa chữa, do đó mang lại ít mã lỗi hơn.

Ruby là hướng đối tượng ở cốt lõi của nó, vì vậy mặc dù nó có hỗ trợ khá tốt cho một phong cách chức năng, nhưng bản thân nó không phải là một ngôn ngữ chức năng.

Dù sao đó cũng là ý kiến ​​phi khoa học của tôi.

Chỉnh sửa: Khi nhìn lại và xem xét những nhận xét tốt mà tôi đã nhận được cho câu trả lời này cho đến nay, tôi nghĩ rằng so sánh hướng đối tượng so với chức năng là một trong những quả táo và trái cam.

Điểm khác biệt thực sự là có thể so sánh được trong thực thi hay không. Các ngôn ngữ chức năng có biểu thức là cấu trúc ngôn ngữ chính của chúng và thứ tự thực hiện thường không được xác định hoặc được định nghĩa là lười biếng. Có thể thực hiện nghiêm ngặt nhưng chỉ được sử dụng khi cần thiết. Trong một ngôn ngữ so sánh, thực thi nghiêm ngặt là mặc định và trong khi thực thi lười biếng là có thể xảy ra, việc thực hiện này thường khó thực hiện và có thể có kết quả không thể đoán trước trong nhiều trường hợp phức tạp.

Bây giờ, đó là ý kiến ​​phi khoa học của tôi.


Tôi nghĩ rằng bạn có thể tạo ra một trường hợp tốt hơn nhiều để gọi hàm Ruby so với Java .... không, Ruby không phải là chức năng nghiêm ngặt, nhưng nó khá dễ dàng để sử dụng một kiểu chức năng trong đó ... và một đồng nghiệp kiểu phi chức năng có thể dễ dàng thay đổi nó trở lại không có chức năng
Mike Stone

1
Vâng, Mike, nếu bạn muốn viết mã theo phong cách chức năng, thì Ruby là một cải tiến rất lớn so với Java. Tôi chỉ sử dụng Java để phóng đại và đưa điểm về nhà.
Chris Vest

Vì vậy, vì D có các hàm thuần túy, bạn sẽ gọi D là một ngôn ngữ hàm? digitalmars.com/d/2.0/ Chức năng.html
Peter Burns

3
Nhiều người coi các ngôn ngữ hàm Lisp và Scheme, phần lớn là do việc sử dụng phổ biến các hàm ẩn danh. Tuy nhiên, chúng thiếu các chức năng thuần túy được đảm bảo. Giới hạn thuật ngữ đối với các ngôn ngữ hỗ trợ các chức năng thuần túy dường như quá hạn chế.
skymt

13

Ruby sẽ phải đáp ứng các yêu cầu sau để có thể hoạt động "THẬT SỰ".

Giá trị bất biến: một khi "biến" được đặt, nó không thể thay đổi được. Trong Ruby, điều này có nghĩa là bạn phải xử lý các biến như hằng số. Ngôn ngữ này không được hỗ trợ đầy đủ, bạn sẽ phải đóng băng từng biến theo cách thủ công.

Không có tác dụng phụ: khi được truyền một giá trị nhất định, một hàm phải luôn trả về cùng một kết quả. Điều này đi đôi với việc có những giá trị bất biến; một hàm không bao giờ có thể nhận một giá trị và thay đổi nó, vì điều này sẽ gây ra một tác dụng phụ có liên quan đến việc trả về một kết quả.

Các hàm bậc cao hơn: đây là các hàm cho phép các hàm làm đối số hoặc sử dụng các hàm làm giá trị trả về. Đây được cho là một trong những tính năng quan trọng nhất của bất kỳ ngôn ngữ chức năng nào.

Currying: được kích hoạt bởi các hàm bậc cao hơn, currying là biến đổi một hàm nhận nhiều đối số thành một hàm nhận một đối số. Điều này đi đôi với ứng dụng hàm từng phần, tức là chuyển đổi một hàm nhiều đối số thành một hàm nhận ít đối số hơn so với ban đầu.

Đệ quy: lặp lại bằng cách gọi một hàm từ bên trong chính nó. Khi bạn không có quyền truy cập vào dữ liệu có thể thay đổi, đệ quy được sử dụng để xây dựng và xây dựng chuỗi dữ liệu. Điều này là do vòng lặp không phải là một khái niệm chức năng, vì nó yêu cầu các biến được truyền xung quanh để lưu trữ trạng thái của vòng lặp tại một thời điểm nhất định.

Đánh giá chậm, hoặc đánh giá chậm : trì hoãn việc xử lý các giá trị cho đến thời điểm thực sự cần thiết. Ví dụ: nếu bạn có một số mã tạo danh sách các số Fibonacci với tính năng đánh giá lười biếng, điều này sẽ không thực sự được xử lý và tính toán cho đến khi một trong các giá trị trong kết quả được yêu cầu bởi một hàm khác, chẳng hạn như giá trị đặt.

Đề xuất (Chỉ là một suy nghĩ) Tôi sẽ rất tuyệt nếu có một số loại định nghĩa để có một modechỉ thị để khai báo các tệp với mô hình chức năng, ví dụ

chế độ 'chức năng'


2
Không có gì. Tôi muốn mời bạn đọc về ngôn ngữ chức năng. Lisp là ông bà của tất cả các ngôn ngữ chức năng, ML (CAML) và Erlang / Elixir. Nó thực sự thay đổi quan điểm của bạn về mọi thứ. Tôi không phải là chuyên gia nhưng là một sinh viên khoa học máy tính thường xuyên thích đọc và học những thứ mới.
Elias Perez

Câu trả lời được tổ chức tốt. Sẽ rất thích một số khám phá bổ sung về cách ruby ​​hỗ trợ những điều này. Tôi tin rằng các chức năng bậc cao hơn, currying và đệ quy đều được hỗ trợ / có thể có trong ruby, vui lòng sửa cho tôi nếu tôi sai.
Michael Dorst

9

Ruby là một ngôn ngữ đa mô hình hỗ trợ một phong cách lập trình chức năng.


8
cung cấp bằng chứng
Mirzhan Irkegulov

4

Ruby là một ngôn ngữ hướng đối tượng, có thể hỗ trợ các mô hình khác (hàm, mệnh lệnh, v.v.). Tuy nhiên, vì mọi thứ trong Ruby đều là một đối tượng nên nó chủ yếu là ngôn ngữ OO.

thí dụ:

"hello" .reverse () = "olleh", mỗi chuỗi là một cá thể đối tượng chuỗi, v.v.

Đọc tại đây hoặc tại đây


Tôi chưa bao giờ thực sự hiểu "mọi thứ là một đối tượng" làm cho Ruby trở nên OO hơn như thế nào. Tôi đồng ý rằng Ruby chủ yếu là OO, nhưng "mọi thứ đều là một đối tượng" thực sự chỉ có nghĩa là không có kiểu "nguyên thủy", điều này có rất ít ảnh hưởng đến khả năng của nhà phát triển trong việc viết chương trình theo kiểu OO, vì sự tồn tại của nguyên thủy các loại thường chỉ có nghĩa là có bốn hoặc năm loại không có bất kỳ phương thức nào.
Michael Dorst

4

Nó phụ thuộc vào định nghĩa của bạn về “ngôn ngữ chức năng”. Cá nhân tôi nghĩ rằng bản thân thuật ngữ này khá có vấn đề khi được sử dụng như một điều tuyệt đối. Có nhiều khía cạnh để trở thành một “ngôn ngữ chức năng” hơn là các tính năng ngôn ngữ đơn thuần và hầu hết phụ thuộc vào nơi bạn đang tìm kiếm. Ví dụ, văn hóa xung quanh ngôn ngữ là khá quan trọng trong vấn đề này. Nó có khuyến khích một phong cách chức năng không? Điều gì về các thư viện có sẵn? Họ có khuyến khích bạn sử dụng chúng theo cách có chức năng không?

Ví dụ, hầu hết mọi người gọi Scheme là một ngôn ngữ chức năng. Nhưng những gì về Common Lisp? Ngoài vấn đề không gian tên nhiều / đơn và loại bỏ lệnh gọi đuôi được đảm bảo (mà một số triển khai CL cũng hỗ trợ, tùy thuộc vào cài đặt trình biên dịch), không có nhiều điều khiến Scheme trở thành một ngôn ngữ phù hợp với lập trình chức năng hơn Common Lisp, và vẫn còn, hầu hết các Lispers sẽ không gọi CL là một ngôn ngữ chức năng. Tại sao? Bởi vì văn hóa xung quanh nó phụ thuộc rất nhiều vào các tính năng bắt buộc của CL (ví dụ như macro LOOP, điều mà hầu hết các Lập trình viên có thể sẽ cau mày).

Mặt khác, một lập trình viên C cũng có thể coi CL là một ngôn ngữ chức năng. Hầu hết các mã được viết bằng bất kỳ phương ngữ Lisp nào chắc chắn có nhiều chức năng hơn nhiều so với khối mã C thông thường của bạn. Tương tự như vậy, Scheme là một ngôn ngữ bắt buộc rất nhiều so với Haskell. Do đó, tôi không nghĩ rằng có thể có một câu trả lời có / không rõ ràng. Việc gọi một ngôn ngữ có chức năng hay không phụ thuộc nhiều vào quan điểm của bạn.


Theo cách nào thì Haskell không phải là một ngôn ngữ chức năng thuần túy? Hoặc làm thế nào về Miranda (một ngôn ngữ lập trình chức năng ít được biết đến hơn)? courses.cs.washington.edu/courses/cse505/99au/functional/... "Haskell là một ngôn ngữ tiêu chuẩn tinh khiết chức năng,"
barlop

2

Ruby cũng không thực sự là một ngôn ngữ đa mô hình, tôi nghĩ vậy. Đa mô hình có xu hướng được sử dụng bởi những người muốn gắn nhãn ngôn ngữ yêu thích của họ như một thứ hữu ích trong nhiều lĩnh vực khác nhau.

Tôi mô tả Ruby là một ngôn ngữ kịch bản hướng đối tượng. Đúng, các hàm là các đối tượng hạng nhất (loại), nhưng điều đó không thực sự khiến nó trở thành một ngôn ngữ hàm. IMO, tôi có thể thêm.


4
Loại ngôn ngữ được xác định bởi các kiểu lập trình mà nó hỗ trợ; đến lượt nó, được quyết định bởi các tính năng nó có. Các hàm hạng nhất và ẩn danh = lập trình hàm tối thiểu. Ruby hỗ trợ lập trình OO nhưng không yêu cầu: bạn không bao giờ cần xác định một lớp. Do đó, đa mô hình.
skymt

2

Đệ quy phổ biến trong lập trình hàm. Hầu hết mọi ngôn ngữ đều hỗ trợ đệ quy, nhưng các thuật toán đệ quy thường không hiệu quả nếu không có tối ưu hóa lệnh gọi đuôi (TCO).

Các ngôn ngữ lập trình hàm có khả năng tối ưu hóa đệ quy đuôi và có thể thực thi mã như vậy trong không gian không đổi. Một số triển khai Ruby tối ưu hóa đệ quy đuôi, một số khác thì không, nhưng nói chung các triển khai Ruby không bắt buộc phải thực hiện TCO. Xem Ruby có thực hiện Tối ưu hóa cuộc gọi đuôi không?

Vì vậy, nếu bạn viết một số kiểu hàm Ruby và dựa vào TCO của một số triển khai cụ thể, mã của bạn có thể rất kém hiệu quả trong một trình thông dịch Ruby khác. Tôi nghĩ đây là lý do tại sao Ruby không phải là một ngôn ngữ chức năng (Python cũng vậy).


TCO rất thú vị, vì về cơ bản nó thay đổi hành vi của chương trình. Trong một số trường hợp nhất định, điều này không hiển thị với chương trình, nhưng trong các trường hợp khác, nó là, ví dụ như dấu lùi ngoại lệ. Do đó, nó không phải lúc nào cũng là một tối ưu hóa thích hợp.
ioquatix

2

Nói một cách chính xác, sẽ không hợp lý khi mô tả một ngôn ngữ là "chức năng"; hầu hết các ngôn ngữ đều có khả năng lập trình chức năng. Ngay cả C ++ cũng vậy.

Phong cách chức năng ít nhiều là một tập hợp con của các tính năng ngôn ngữ mệnh lệnh, được hỗ trợ với đường cú pháp và một số tối ưu hóa trình biên dịch như tính bất biến và làm phẳng đệ quy đuôi,

Điều sau được cho là một kỹ thuật nhỏ dành riêng cho việc triển khai và không liên quan gì đến ngôn ngữ thực tế. Trình biên dịch x64 C # 4.0 thực hiện tối ưu hóa đệ quy đuôi, trong khi trình biên dịch x86 không vì bất kỳ lý do ngu ngốc nào.

Đường cú pháp thường có thể hoạt động ở một mức độ nào đó hay cách khác, đặc biệt nếu ngôn ngữ có trình biên dịch trước có thể lập trình được (tức là #define của C).

Có thể có ý nghĩa hơn một chút khi hỏi, "ngôn ngữ __ có hỗ trợ lập trình mệnh lệnh không?", Và câu trả lời, chẳng hạn với Lisp, là "không".


1

Xin hãy xem phần đầu của cuốn sách: "A-Great-Ruby-eBook" . Nó thảo luận về chủ đề rất cụ thể mà bạn đang hỏi. Bạn có thể thực hiện các kiểu lập trình khác nhau trong Ruby. Nếu bạn muốn lập trình như chức năng, bạn có thể làm điều đó. Nếu bạn muốn lập trình giống như theo cấp bậc, bạn có thể làm điều đó. Cuối cùng thì đó là một câu hỏi định nghĩa về chức năng của Ruby. Vui lòng xem câu trả lời của người dùng ngụy trang.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.