Modelli per la condivisione delle variabili di contesto tra le funzioni

3

Sto cercando modi per aggirare una serie di variabili contestuali richieste dalle funzioni.

Come programmatore Python, in questo momento posso vedere tre modi per risolvere il problema: passandoli intorno come argomenti espliciti, incapsulamento di classe e chiusure (factory di funzioni).

Trovo che gli argomenti espliciti tendano a oscurare la logica della funzione, l'incapsulamento di classe tende a condurre le classi del do-it-all, migliaia di linee, mentre le chiusure tendono a creare un sovraccarico di programmazione a causa della creazione di fabbrica.

Mi chiedevo se esistessero altri pattern che permettessero la condivisione di variabili contestuali definite dinamicamente tra funzioni prive di tali carenze? Ad esempio, come si risolverebbe questo problema nel contesto della programmazione funzionale?

    
posta Andrei Kucharavy 11.08.2015 - 15:22
fonte

1 risposta

3

Potresti esaminare le monadi Reader o State; possono essere usati per condividere dati tra funzioni (pure, monadiche), senza ricorrere a parametri espliciti o simili.

C'è una serie di tutorial su F # per divertimento e profitto sulla monade di Stato (AKA Workflow in F # parlence). Ho anche fornito una descrizione in questa risposta SO che sembra abbastanza accessibile.

Esistono alcune implementazioni di altre monade in python che puoi anche fare riferimento, se devi implementare il tuo.

Molte persone (me compreso) trovano le monadi difficili all'inizio, quindi se non hai familiarità con il concetto, ti consiglio di guardare alcune delle monadi più semplici come Forse o Either, e quindi forse Reader o Writer, prima affrontare lo stato. Le implementazioni Python collegate sopra possono rendere le cose più chiare per te rispetto a quelle che probabilmente troverai altrove online (che probabilmente sarebbe Haskell).

Alcuni avvertimenti: c'è ancora un po 'di overhead sulle funzioni, dal momento che la monade è coinvolta, e questa deve essere usata con le funzioni ; Non penso che potresti farlo con i metodi di classe (anche se potrei sbagliarmi - non l'ho mai provato!)

UPDATE:

La pagina "monads in python" / lib ho linkato sopra in realtà fa ha un'implementazione monad di stato; controlla il codice a partire da ###### StateChanger Monad ######### per la definizione e gli esempi.

MODIFICA in risposta alla domanda nel commento:

Sì, è così che lo faresti - per essere più chiaro, gli argomenti con cui dichiari la funzione non dovrebbero includere le variabili di ambiente, solo quelle che la funzione avrebbe bisogno normalmente; le variabili di ambiente saranno accessibili tramite le funzioni monadico get e set .

Un esempio di Python che usa la notazione data nel link "monads in python" sopra:

@do(StateChanger) # <-- this makes makes it a stateful computation
def my_stateful_function1(arg):
    # do something with 'arg' here
    # then put it in the state:
    yield dict_state_set(key, var_from_arg)
    # I believe you can leave out 'mreturn' for this

@do(StateChanger)
def my_stateful_function2(arg1, arg2):
    # something with 'arg1' here
    # get the state chained via the monad:
    state = yield get_state()
    # do something else stateful:
    yield my_stateful_function1(arg2)
    # do something with 'state' dict here
    # return; you have to use 'mreturn' instead of 'return':
    mreturn(some_value)

Per eseguirlo chiameresti:

ret_val = my_stateful_function2("hello","world").run(initial_state_dict)

e il tuo valore di ritorno sarebbe una tupla:

(return_value_of_function, final_state_dict) = ret_val

Ricorda di usare yield quando chiami altre funzioni stateful.

Ammonizione: fai attenzione a modificare lo stato delle tue funzioni poiché il tipo di dizionario Python è mutabile. È possibile ottenere e impostare le vars dello stato, nonché applicare una funzione (lambda) a loro; potresti desiderare di attenervisi piuttosto che tirare fuori lo stato e mutarlo volenti o nolenti.

    
risposta data 11.08.2015 - 16:23
fonte

Leggi altre domande sui tag