2012-08-13 16 views
5

Todavía estoy aprendiendo este paradigma funcional ajena ...¿Cómo debería crear una lista y devolverla en clojure?

¿Cómo voy a escribir el siguiente código en Clojure, y de una manera funcional? asume que las partes faltantes están definidas en otra parte y se comportan como se describe en los comentarios. Aquí está en Python, con el que estoy familiarizado.

usernames = [] 
# just the usernames of all the connections I want to open. 
cancelfunctions = {} 
# this global contains anonymous functions to cancel connections, keyed by username 

def cancelAll(): 
    for cancel in cancelfunctions.values(): 
     cancel() 

def reopenAll(): 
    cancelfunctions = {} 
    for name in usernames: 
     # should return a function to close the connection and put it in the dict. 
     cancelfunctions[name] = openConnection() 

Todo lo que realmente necesita saber es cómo construir una nueva dict de devoluciones de llamada, al igual que en la función reopenAll, pero estoy incluyendo un poco más de contexto aquí porque lo más probable es que estoy cometiendo algún tipo de funcionalidad la atrocidad del paradigma, y ​​lo más probable es que desee arreglar todo el programa. :)

+0

Sé que esto probablemente no sea apropiado, pero no pude resistirme a compartir cuando vi su referencia al "[paradigma funcional alienígena] (http://landoflisp.com/#guilds)". – DaoWen

Respuesta

6

La construcción de estructuras de datos en Clojure implica a menudo reduce, que alimenta una secuencia de entradas a una función que acumula un valor de retorno final. Aquí hay dos formas de escribir una función que construye un mapa (es decir, un diccionario) de nombre de usuario con el valor de retorno open-connection.

;; Using reduce directly 
(defn reopen-all [usernames] 
    (reduce 
    (fn [m name] (assoc m name (open-connection))) 
    {} usernames)) 

;; Using into, which uses reduce under the hood 
(defn reopen-all [usernames] 
    (into {} (for [name usernames] 
      [name (open-connection)]))) 

Tenga en cuenta que estas dos funciones devuelven un valor y no mutan estado global, por ejemplo el código Python hace. El estado global no es inherentemente malo, pero es bueno separar la generación de valor de la manipulación de estado. Para el estado, es probable que desee un atom:

(def usernames [...]) 
(def cancel-fns (atom nil)) 

(defn init [] 
    (reset! cancel-fns (reopen-all usernames))) 

Y aquí es cancel-all por causa integridad:

(defn cancel-all [] 
    (doseq [cancel-fn (vals @canel-fns)] 
    (cancel-fn))) 
+0

¡Gracias, esta es una muy buena respuesta! – user1552512

2

Aquí es un enfoque funcional en Python:

def reopen(usernames): 
    return dict((name, openConnection()) for name in usernames) 

Usted puede encontrar es más fácil "traducir" a un estilo funcional en Python antes de intentar utilizar un lenguaje principalmente funcional.

Cuestiones relacionadas