2016-02-26 23 views
14

Từ ReactiveX introduction page:ReactiveX có được coi là chương trình phản ứng không?

Đôi khi nó được gọi là "lập trình phản ứng chức năng" nhưng đây là từ sai. ReactiveX có thể hoạt động, và nó có thể phản ứng, nhưng “lập trình phản ứng chức năng” là một động vật khác nhau. Một điểm khác biệt chính là lập trình hoạt động chức năng hoạt động trên các giá trị thay đổi liên tục theo thời gian, trong khi ReactiveX hoạt động trên các giá trị rời rạc được phát ra theo thời gian.

Trong khi đó, từ Wikipedia's Functional Reactive Programming page, ReactiveX được liệt kê trong "Triển khai" phần:

Triển khai [sửa]

  • cellx, thực hiện cực nhanh của phản ứng cho javascript
  • Ngôn ngữ soạn thảo, FRP biên dịch sang HTML, CSS và JavaScript
  • Triển khai FraPuccino FRP trong Chà y
  • Flapjax, thực hiện hành vi FRP/sự kiện trong JavaScript
  • Reactive.jl, thực hiện FRP trong Julia
  • ReactiveX, thực hiện FRP bằng nhiều ngôn ngữ, bao gồm cả Java, JavaScript, Python, Swift và nhiều hơn nữa
  • phản ứng-chuối thực hiện FRP trong Haskell
  • ReactiveCocoa FRP thực hiện trong Swift và Objective-C
  • ReactiveKit FRP thực hiện trong tinh khiết Swift
  • thực hiện phản xạ FRP trong Haskell
  • thực hiện
  • Scala.Rx FRP trong Scala (và Scala.js)
  • Sodium, thực hiện FRP trong C#, C++, Haskell (bị phản đối [12]), Java,> Rust, và Scala
  • Yampa FRP thực hiện trong Haskell

tôi khá hiểu những gì ReactiveX có, và cũng đã làm một số nghiên cứu về "Lập trình phản ứng" và "Lập trình phản ứng chức năng", nhưng tôi vẫn không thể phân biệt các mối quan hệ giữa chúng. Trong thực tế, tôi tin rằng trang Wikipedia là nhầm lẫn, hoặc liệt kê không chính xác các ví dụ trong phần "Triển khai", vì tôi biết rằng cellxReactiveX (được liệt kê trong các ví dụ) được xây dựng để giải quyết hoàn toàn khác nhau các vấn đề.

Trả lời

14

Tác giả của thư viện phản ứng chuối ở đây.

Sự khác biệt chính giữa lập trình phản ứng chức năng (FRP) và lập trình phản ứng (RP) là cựu có ngữ nghĩa denotational rõ ràng, thường thu được từ các loại

type Behavior a ~= Time -> a 
type Event a ~= [(Time, a)] 

trong khi sau này không không có một ngữ nghĩa xác định rõ ràng.Cụ thể, tất cả các triển khai của RX mà tôi biết đều gặp phải sự cố khi hợp nhất luồng sự kiện là không xác định: Khi các luồng chứa các sự kiện đồng thời, đôi khi một lần xuất hiện được hợp nhất trước sự kiện kia và đôi khi theo cách khác.

Hơn nữa, tuyên bố rằng "FRP hoạt động trên các giá trị mà thay đổi liên tục theo thời gian" là cả một cách tinh tế không chính xác và không phải là sự khác biệt quan trọng:

  • Thứ nhất, phân tích cú pháp có thể xảy ra nhất đối với tuyên bố này là "Hành vi là chức năng liên tục Time -> a ", điều này không đúng: Hành vi có thể là dis liên tục, ví dụ chúng có thể là các hàm bước. Điều đúng là thay vào đó là Time trong FRP thường được lấy là một số thực, tức là liên tục giá trị.
  • Thứ hai, hoàn toàn có thể có FRP khi thời gian rời rạc. Đó không phải là sự khác biệt quan trọng đối với RP, thay vào đó là tất cả về việc liệu các hoạt động của bạn trên các giá trị có một ngữ nghĩa định nghĩa được xác định rõ hay không.
+0

Xin chào, cảm ơn bạn đã phản hồi, bạn có thể giải thích những loại bạn đưa vào khối mã không? – TrungDQ

+0

@TrungDQ Vâng, loại 'Thời gian -> a' biểu thị một hàm với một tham số kiểu' Thời gian' và một giá trị kết quả của kiểu 'a'. Nó có thể được hiểu là một giá trị thay đổi theo thời gian. Kiểu '[(Time, a)]' biểu thị một danh sách các cặp giá trị kiểu 'Time' và các giá trị kiểu' a'. Nó có thể được hiểu là một tập hợp các sự kiện xảy ra tại các thời điểm riêng biệt. –

5

Theo như tôi hiểu, từ quan điểm của ReactiveX (hay còn gọi là RX), đơn giản là không thể có hai sự kiện xảy ra cùng một lúc "thời gian". Đây chỉ là các cuộc gọi lại được kích hoạt nội bộ, theo thứ tự, theo thứ tự đăng ký. RX không "quản lý" thời gian.

RX có thể hoạt động khá điên rồ như được thấy qua đôi mắt của một lập trình viên FRP thuần túy. Xem xét các mã RXJS sau:

const xs = Rx.Observable 
    .interval(0) 
    //.share(); 

xs.combineLatest(xs, (a,b) => [a,b]) 
    .filter(ab => ab[1] > ab[0]) 
    .take(1) 
    .subscribe(ab => alert(ab)); 

Dưới đây là một xs lạnh khoảng quan sát rằng đám cháy càng nhanh càng tốt. Vì xs.combineLatest (ys, f) luôn đăng ký trước xs trước, sau đó đến ys, bạn có thể mong đợi xs.combineLatest(xs, (a,b) => [a,b]) để tạo [0,0], [1,0], [1,1], [2,1], ... Vì vậy, ab[1] > ab[0] phải luôn là sai. Tuy nhiên, trên máy tính của tôi, nếu tôi giữ mã này chạy trong một thời gian, nó kết thúc tại một số điểm it could take a while, try it yourself

Đó là bởi vì xs là một lạnh thể quan sát được: mỗi thuê bao interval sẽ tạo ra một bộ đếm thời gian định kỳ chạy một cách độc lập. Những giờ có thể và sẽ tại một số điểm cháy theo một thứ tự khác nhau (đặc biệt là trên các môi trường đa luồng như NET)

Nếu chúng ta nhận xét ra dòng //share, làm xsnóng, trình tự không bao giờ hoàn tất, như [0,0], [1,0], [1,1], ... ,[i,i-1],[i,i]... là bây giờ được tạo ra một cách xác định. Điều này là do một quan sát nóng có thể chia sẻ một đăng ký duy nhất. Trong trường hợp này chỉ một bộ hẹn giờ được tạo.

Trong hệ thống FRP thực, hành vi này sẽ là xác định. Tuy nhiên, nếu bạn thực sự kết nối với các bộ định thời phần cứng khác nhau trong hệ thống FRP thực, bạn cũng sẽ nhận được cùng một hành vi như RX, vì các sự kiện bên ngoài này sẽ kích hoạt theo thứ tự ngẫu nhiên, trừ khi hai bộ hẹn giờ hoàn toàn được đồng bộ hóa theo số

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