Perché gli operatori ReactiveX sono considerati funzionali?

-1

Sto facendo fatica a capire come un operatore ReactiveX può essere considerato funzionale. Gli operatori sono implementati come funzioni, ma con l'eccezione di semplici operatori come la mappa e la riduzione di molti operatori, non mi sembrano implementabili come pure funzioni.

Un semplice operatore di buffer che memorizza 2 elementi alla volta può produrre un output diverso a parità di input. L'output dipende da tutti gli eventi precedenti, ad es. la prima volta che passo un evento attraverso l'operatore non emette eventi, la seconda volta emette 2 eventi:

1)  E -> []
2)  E -> [E,E]

Capisco che quando si considera l'intero flusso di eventi - Buffer è concettualmente puro, cioè E -> E -> [E, E] . Il calcolo non avviene su tutto il flusso in una sola volta, tuttavia accade evento per evento e l'implementazione deve mantenere uno stato per poter fornire il flusso di output.

È possibile implementare un tale operatore di buffer in modo puramente funzionale? Ne consegue che tutti gli altri operatori "funzionali" di ReactiveX possono anche essere implementati funzionalmente?

O quando diciamo che ReactiveX è funzionale, intendiamo solo un livello di flusso e non l'evento. Una funzione implementata utilizzando funzioni non pure può essere pura?

Modifica : aggiunta di ulteriori dettagli come richiesto nei commenti

Una funzione pura ha due proprietà: Da Wikipedia

  • Il suo valore di ritorno è sempre lo stesso per gli stessi argomenti
  • La sua valutazione non ha effetti collaterali

Nel mio esempio, l'output del Buffer può essere diverso per gli stessi input, a seconda di quali altri eventi nel flusso.

In termini di implementazione, una classe in cui il buffer di due elementi farebbe fondamentalmente qualcosa di simile al seguente:

class Buffer2 {
   item = null;

   onNext(next) {
      if(this.item == null) {
         this.item = next;
         return [];
      } else {
         let emit = [this.item, next];
         this.item = null;
         return emit;
      } 
   }
}

L'effettiva implementazione di Buffer in Rx è abbastanza diversa - ma penso che questo catturi l'essenza di ciò che sta facendo in uno scenario di buffer a 2 item.

Per me la funzione onNext(next) viola chiaramente il "valore di ritorno è lo stesso per gli stessi argomenti" - il valore di ritorno dipende dal fatto che item sia nullo o no.

    
posta Brian Flynn 13.11.2018 - 07:18
fonte

1 risposta

2

In primo luogo l'argomento pedante ... Mi chiedi come buffer , ad esempio, possa essere considerato funzionale, ma poi continua a parlare, non della funzione buffer stessa, ma le funzioni onNext e subscribe (perché inizi a parlare degli eventi che attraversano il tubo invece del tubo stesso.) Come un'analogia, i tubi dell'acqua di una casa sono completamente statici, nonostante il fatto che l'acqua che li attraversa sia dinamico. Nello stesso modo in cui gli operatori sono funzionali nonostante i dati siano in esecuzione.

Secondo argomento monadico ... Fintanto che ciò che accade nella monade rimane nella monade, la monade stessa può essere considerata funzionale (la monade di Haskell mi viene in mente qui.) Una funzione map su una matrice è funzionale anche se la funzione è implementata internamente come loop for. Discutere di ciò è affermare che il linguaggio di programmazione no è funzionale, perché quando si arriva a spingere tutti loro operano su una macchina intrinsecamente imperativa. In altre parole, qualsiasi struttura di programmazione che sia "funzionale" a un certo livello di astrazione è "imperativa" a un livello inferiore.

    
risposta data 14.11.2018 - 03:16
fonte

Leggi altre domande sui tag