2011-12-15 12 views
13

Estoy implementando un algoritmo punto-en-polígono de fundición de rayos javascript de una manera puramente funcional (sin ninguna razón particular detrás de esto).¿Es posible implementar una versión js del descomprimido de Haskell de una manera puramente funcional?

Me quedé atrapado ya que necesitaba obtener dos matrices de una matriz bidimensional (que reproduce una lista de tuplas); algo parecido a Haskell's unzip.

¿Es posible, comenzando desde algo como [[a,b],[c,d],[e,f]] obtener [[a,c,e],[b,d,f]] sin usar iteradores de estilo de procedimiento?

(Sé que es una pregunta trivial, y tan sólo pudiera implementar la función de procedimiento y luego olvidarse de él, pero tenía curiosidad por saber si había una solución)


EDIT: Para aclarar, Sé cómo implementar zip y unzip: me preguntaba si sería posible implementarlos sin for loops y reasignaciones variables.

+0

Dada la diferencia entre JavaScript y la representación de Haskell de una lista, no se pueden implementar de la misma manera. Haskell implementa listas como una estructura inmutable unida individualmente. Java implementa listas como una matriz mutable. Para el primero, usa recursividad y coincidencia de patrones. Para este último, usa bucles e índices. –

+0

Hm, sé que Js no tiene listas. Me refería a una función en particular, en un dominio restringido: no lo necesitaba para trabajar en "arreglos infinitos" (lulz) o tal. – cbrandolino

Respuesta

6

Su descompresión es solo un zip pero con múltiples argumentos. La única razón por la que la mayoría de las personas no usa la misma función es porque la mayoría de las veces zip recibe una lista variada de argumentos en lugar de una matriz, por lo que debe descomprimir elementos con apply en la función de descompresión.

En Dojo, la biblioteca que estoy usando, prevean la aplicación de comprimir y descomprimir como

unzip: function(/*Array*/ a){ 
    // summary: similar to dojox.lang.functional.zip(), but takes 
    // a single array of arrays as the input. 
    // description: This function is similar to dojox.lang.functional.zip() 
    // and can be used to unzip objects packed by 
    // dojox.lang.functional.zip(). It is here mostly to provide 
    // a short-cut for the different method signature. 

    return df.zip.apply(null, a); 
} 

zip: function(){ 
    // summary: returns an array of arrays, where the i-th array 
    // contains the i-th element from each of the argument arrays. 
    // description: This is the venerable zip combiner (for example, 
    // see Python documentation for general details). The returned 
    // array is truncated to match the length of the shortest input 
    // array. 
    var n = arguments[0].length, 
     m = arguments.length, 
     i = 1, 
     t = new Array(n), 
     j, 
     p; 
    for(; i < m; n = Math.min(n, arguments[i++].length)); 
    for(i = 0; i < n; ++i){ 
     p = new Array(m); 
     for(j = 0; j < m; p[j] = arguments[j][i], ++j); 
     t[i] = p; 
    } 
    return t; 
}, 

Tenga en cuenta que la cremallera recibe múltiples argumentos por lo que se parece más a la cremallera Python y menos como el que Haskell.


No debería ser difícil convertir este código a un estilo "puramente funcional" sin asignaciones variables. Su código existente ya debería estar manejando el trabajo de los dos primeros fors en el ejemplo que publiqué (truncando el zip en la longitud mínima e iterando a través de los índices de una de las listas). Todo lo que queda es hacer algo similar para el tercero: recolectar el valor i-ésimo de una lista de listas en lugar de recolectar dos valores de dos listas.

+0

¡Gracias! Estaba vagando, sin embargo, si eso podría implementarse sin usar iteradores de procedimiento como 'for'. – cbrandolino

+0

Su código ya debería estar haciendo el trabajo de los dos primeros fors en el ejemplo que publiqué (truncando el zip en la longitud mínima e iterando a través de los índices de una de las listas). Todo lo que tiene que hacer es el trabajo del tercero: recopilar el valor i-és de una lista de listas en lugar de recopilar dos valores de dos listas. – hugomg

+0

No recomendaría código altamente recursivo en este tipo de función de biblioteca sensible al rendimiento. Pero entonces supongo que realmente no te importa en este caso. – hugomg

Cuestiones relacionadas