tại sao câu chuyện dân gian và ramda lại khác nhau như vậy?


96

Tôi đang học FP javascript bằng cách đọc DrBoolean của cuốn sách .

Tôi đã tìm kiếm thư viện lập trình chức năng xung quanh. Tôi đã tìm thấy Ramda và Folktale. Cả hai đều tuyên bố là thư viện lập trình chức năng.

Nhưng chúng rất khác nhau:

  • Ramda dường như chứa các chức năng tiện ích để xử lý danh sách: bản đồ, thu nhỏ, bộ lọc và các chức năng thuần túy: cà ri, soạn thảo. Nó không chứa bất cứ thứ gì để đối phó với monad, functor.

  • Folktale tuy nhiên không chứa bất kỳ tiện ích nào cho danh sách hoặc chức năng. Nó dường như triển khai một số cấu trúc đại số trong javascript như đơn nguyên: Có thể, Tác vụ ...

Trên thực tế, tôi đã tìm thấy nhiều thư viện hơn, tất cả chúng dường như rơi vào hai loại. Dấu gạch dưới và dấu gạch ngang giống như Ramda. Vùng đất tưởng tượng, không gian ảo tưởng giống như truyện dân gian.

Cả hai thư viện rất khác nhau này đều có thể được gọi là chức năng , và nếu vậy, điều gì làm cho mỗi thư viện trở thành một thư viện chức năng?


1
sử dụng những gì phù hợp với nhu cầu và phong cách của bạn và cũng là tài liệu
charlietfl

1
tôi nhận thấy thực sự có ba ý nghĩa thường dùng cho "lập trình chức năng", đặc biệt là trong JS. 1. sử dụng các hàm thuần túy bậc cao trên các tập hợp như mảng., Ví dụ [1,2,3].map(fnSquare).reduce(fnSum)2. phần lớn là cấu trúc "look ma no var " Y-combinator-esque mang tính học thuật. 3. sử dụng Function.prototypeđể thay đổi hành vi của các chức năng khác, nhưvar isMissingID=fnContains.partial("id").negate();
dandavis

10
Một tác giả Ramda ở đây: Ramda là một thư viện tiện ích cấp thấp. Nó nhằm mục đích làm cho một phong cách hàm nhất định trở nên đơn giản hơn trong JS, đặc biệt là làm việc bằng cách soạn các hàm. Ramda hoạt động tốt với đặc tả FantasyLand, bao gồm cả việc triển khai nó như Folktale. Những thư viện đó được thiết kế cho một mục đích hơi khác. Chúng được xây dựng dựa trên việc nhận biết các kiểu dữ liệu trừu tượng phổ biến và cho phép truy cập nhất quán vào chúng: những thứ như Monoids, Functors và Monads. Ramda sẽ làm việc với họ và có một dự án phụ để tạo ra một số, nhưng như bạn nói, đó là một trọng tâm rất khác.
Scott Sauyet

1
@KeithNicholas: Vâng, có một Phòng Gitter
Scott Sauyet

2
Hãy xem cả Sanctuary - github.com/plaid/sanctuary. Đây là dựa trên ramda nhưng cũng bao gồm các loại đất giả tưởng.
arcseldon

Câu trả lời:


180

Tính năng chức năng

Không có ranh giới rõ ràng về những gì xác định lập trình chức năng hoặc thư viện chức năng. Một số tính năng của ngôn ngữ chức năng được tích hợp trong Javascript:

  • Các hàm bậc nhất, bậc cao hơn
  • Các hàm Lambdas / Anonymous, với các dấu đóng

Những người khác có thể hoàn thành trong Javascript một cách cẩn thận:

  • Bất biến
  • Tính minh bạch tham chiếu

Vẫn còn những người khác là một phần của ES6 và có sẵn một phần hoặc toàn bộ ngay bây giờ:

  • Chức năng nhỏ gọn, đều
  • Đệ quy hiệu suất thông qua tối ưu hóa cuộc gọi đuôi

Và có rất nhiều thứ khác thực sự vượt quá khả năng thông thường của Javascript:

  • Khớp mẫu
  • Đánh giá lười biếng
  • Tính đồng âm

Sau đó, một thư viện có thể chọn và chọn những loại tính năng mà nó đang cố gắng hỗ trợ và vẫn được gọi là "chức năng" một cách hợp lý.

Đặc tả về vùng đất ảo

Vùng đất ảo là đặc điểm kỹ thuật cho một số kiểu tiêu chuẩn được chuyển từ Lý thuyết phạm trù toán học và Đại số trừu tượng sang lập trình hàm, các kiểu như Monoid , FunctorMonad . Những kiểu này khá trừu tượng và có thể mở rộng những khái niệm quen thuộc hơn. Functors, ví dụ, là các thùng chứa có thể được maplặp lại với một chức năng, cách một mảng có thể được mapsử dụngArray.prototype.map .

Truyện dân gian

Folktale là một tập hợp các kiểu thực hiện các phần khác nhau của đặc tả Vùng đất ảo và một tập hợp nhỏ các chức năng tiện ích đồng hành. Những loại này là những thứ như Có thể , Hoặc , Nhiệm vụ (rất giống với những gì ở nơi khác được gọi là Tương lai và là người anh em họ hợp pháp hơn với Lời hứa) và Xác thực

Folktale có lẽ là cách triển khai nổi tiếng nhất của đặc tả Vùng đất giả tưởng, và nó được đánh giá cao. Nhưng không có cái gọi là triển khai dứt khoát hoặc mặc định; fantasy-land chỉ xác định các kiểu trừu tượng và việc triển khai tất nhiên phải tạo ra các kiểu cụ thể như vậy. Tuyên bố của Folktale về việc trở thành một thư viện chức năng là rất rõ ràng: nó cung cấp các kiểu dữ liệu thường được tìm thấy trong các ngôn ngữ lập trình chức năng, những kiểu dữ liệu này làm cho việc lập trình theo cách chức năng dễ dàng hơn đáng kể.

Ví dụ này, từ tài liệu Câu chuyện dân gian ( lưu ý : không có trong các phiên bản gần đây của tài liệu), cho thấy cách nó có thể được sử dụng:

// We load the library by "require"-ing it
var Maybe = require('data.maybe')

// Returns Maybe.Just(x) if some `x` passes the predicate test
// Otherwise returns Maybe.Nothing()
function find(predicate, xs) {
  return xs.reduce(function(result, x) {
    return result.orElse(function() {
      return predicate(x)?    Maybe.Just(x)
      :      /* otherwise */  Maybe.Nothing()
    })
  }, Maybe.Nothing())
}

var numbers = [1, 2, 3, 4, 5]

var anyGreaterThan2 = find(function(a) { return a > 2 }, numbers)
// => Maybe.Just(3)

var anyGreaterThan8 = find(function(a) { return a > 8 }, numbers)
// => Maybe.Nothing

Ramda

Ramda (tuyên bố từ chối trách nhiệm: Tôi là một trong những tác giả) là một loại thư viện rất khác. Nó không cung cấp các loại mới cho bạn. 1 Thay vào đó, nó cung cấp các chức năng giúp vận hành dễ dàng hơn trên các loại hiện có. Nó được xây dựng dựa trên các khái niệm về việc kết hợp các chức năng nhỏ hơn thành các chức năng lớn hơn, làm việc với dữ liệu bất biến, tránh các tác dụng phụ.

Ramda hoạt động đặc biệt trên danh sách, nhưng cũng trên các đối tượng, và đôi khi trên Chuỗi. Nó cũng ủy quyền nhiều cuộc gọi của nó theo cách mà nó sẽ tương tác với Folktale hoặc các triển khai Fantasy-land khác. Ví dụ, hàm của Ramda map, hoạt động tương tự như hàm trên Array.prototype, vì vậy R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16]. Nhưng vì Folktale's Maybetriển khai thông số Fantasy-land Functor, cũng chỉ định bản đồ, bạn cũng có thể sử dụng Ramda mapvới nó:

R.map(square, Maybe.Just(5)); //=> Maybe.Just(25);
R.map(square, Maybe.Nothing); //=> Maybe.Nothing

Ramda tuyên bố trở thành một thư viện hàm nằm ở chỗ giúp bạn dễ dàng soạn các hàm, không bao giờ thay đổi dữ liệu của bạn và chỉ trình bày các hàm thuần túy. Cách sử dụng điển hình của Ramda là xây dựng các chức năng phức tạp hơn bằng cách tạo ra các chức năng nhỏ hơn, như đã thấy trong một bài báo về từ vựng Ramda

// :: [Comment] -> [Number]  
var userRatingForComments = R.pipe(
    R.pluck('username')      // [Comment] -> [String]
    R.map(R.propOf(users)),  // [String] -> [User]
    R.pluck('rating'),       // [User] -> [Number]
);

Thư viện khác

Trên thực tế, tôi đã tìm thấy nhiều thư viện hơn, tất cả chúng dường như rơi vào hai loại. gạch dưới, dấu gạch ngang rất giống Ramda. Vùng đất tưởng tượng, không gian ảo tưởng giống như truyện dân gian.

Điều đó không thực sự chính xác. Trước hết, Fantasy-land chỉ đơn giản là một thông số kỹ thuật mà các thư viện có thể quyết định triển khai cho nhiều loại khác nhau. Câu chuyện dân gian là một trong nhiều cách triển khai của thông số kỹ thuật đó, có lẽ là bản hoàn thiện nhất, chắc chắn là một trong những bản hoàn thiện nhất. Pointfree-fantasyramda-fantasy là những thứ khác, và còn nhiều thứ khác nữa .

Underscorelodash bề ngoài giống Ramda ở chỗ chúng là các thư viện túi, cung cấp một số lượng lớn các chức năng với ít liên kết hơn nhiều so với những thứ như Folktale. Và ngay cả chức năng cụ thể cũng thường trùng lặp với Ramda. Nhưng ở mức độ sâu hơn, Ramda có những mối quan tâm rất khác với những thư viện đó. Họ hàng gần gũi nhất của Ramda có lẽ thư viện như FKit , Fnuc , và Wu.js .

Bilby nằm trong danh mục của riêng nó, cung cấp cả một số công cụ như công cụ do Ramda cung cấp và một số loại phù hợp với Fantasy-land. (Tác giả của Bilby cũng là tác giả gốc của Fantasy-land.)

Cuộc gọi của bạn

Tất cả các thư viện này đều có quyền được gọi là chức năng, mặc dù chúng khác nhau rất nhiều về cách tiếp cận chức năng và mức độ cam kết chức năng.

Một số thư viện này thực sự hoạt động tốt với nhau. Ramda sẽ hoạt động tốt với Folktale hoặc các triển khai Fantasy-land khác. Vì mối quan tâm của họ hầu như không trùng lặp, chúng thực sự không xung đột, nhưng Ramda làm vừa đủ để làm cho việc tương tác tương đối suôn sẻ. Điều này có lẽ ít đúng hơn đối với một số tổ hợp khác mà bạn có thể chọn, nhưng cú pháp hàm đơn giản hơn của ES6 cũng có thể giải quyết một số khó khăn khi tích hợp.

Việc lựa chọn thư viện, hoặc thậm chí kiểu thư viện để sử dụng, sẽ phụ thuộc vào dự án và sở thích của bạn. Có rất nhiều lựa chọn tốt có sẵn và số lượng đang tăng lên và nhiều lựa chọn trong số đó đang được cải thiện rất nhiều. Đây là thời điểm tốt để thực hiện lập trình chức năng trong JS.


1 Chà, có một dự án phụ, ramda-fantasy đang làm điều gì đó tương tự như những gì Folktale làm, nhưng nó không phải là một phần của thư viện cốt lõi.


1
Có công bằng nếu nói ES6 có khả năng đánh giá lười biếng với việc giới thiệu Yield? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Marcel Lamothe

8
Không. Làm yieldcho nó dễ dàng hơn để thực hiện các loại xử lý danh sách lười được thực hiện bởi Lazyhoặc lz.js. Nhưng nó không giúp ích gì cho sự lười biếng về trình độ ngôn ngữ. someFunc(a + b)trong JS đầu tiên thêm các giá trị của ab sau đó cung cấp kết quả là tham số cho someFunc. Tương tự trong Haskell không làm được điều đó. Nếu hàm được gọi không bao giờ sử dụng giá trị đó, nó sẽ không bao giờ thực hiện phép cộng. Nếu cuối cùng nó sử dụng nó, nó được coi là một biểu thức được tính toán cho đến khi cần kết quả của nó. Nếu bạn không bao giờ làm bất cứ điều gì buộc nó (như IO), nó sẽ không bao giờ thực sự thực hiện phép tính.
Scott Sauyet

@ScottSauyet có lẽ bạn có thể tranh luận rằng "đánh giá lười biếng" ở một số hình thức có sẵn thông qua trình tạo ES6 chẳng hạn - rất nhiều khung JS có đặc điểm "lười biếng" - RxJs, ImmutableJs, v.v.
arcseldon 19/02/16

8
Câu trả lời này phải là một chương hoặc một phần trong sách của DrBoolean. :)
Seth

1
Tài liệu Ramda có xu hướng sử dụng "danh sách" như một cách viết tắt cho những gì gần nhất mà JS cung cấp cho các danh sách, các mảng dày đặc. Chúng có các đặc điểm hiệu suất khác với danh sách thuần túy và tất nhiên là một API hơi khác, nhưng chúng có thể được sử dụng cho nhiều mục đích giống nhau và chúng là loại gốc gần nhất (nhưng xem github.com/funkia/list ) có sẵn cho Ramda's API, về mặt khái niệm muốn làm việc với các danh sách thuần túy. Tôi sẽ tranh luận về quan điểm mảng không đúng, vì mảng kiểu C không chính tắc hơn mảng JS và không có mảng nào thực sự gần với mảng toán học, nhưng đó là một điểm nhỏ.
Scott Sauyet
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.