Estructuras de datos en programación funcional.

11

Actualmente estoy jugando con LISP (particularmente Scheme y Clojure) y me pregunto cómo se tratan las estructuras de datos típicas en lenguajes de programación funcionales.

Por ejemplo, digamos que me gustaría resolver un problema usando un algoritmo de trazado de ruta de gráfico. ¿Cómo se podría representar ese gráfico en un lenguaje de programación funcional (principalmente interesado en el estilo funcional puro que se puede aplicar a LISP)? ¿Me olvidaría de los gráficos por completo y resolvería el problema de otra manera?

pwny
fuente

Respuestas:

14

Ha pasado un tiempo desde que trabajé en LISP, pero según recuerdo, la estructura básica no atómica es una lista. Todo lo demás se basa en eso. Por lo tanto, podría tener una lista de átomos donde cada átomo es un nodo seguido de una lista de bordes que conectan el nodo con otros nodos. Estoy seguro de que también hay otras formas de hacerlo.

Tal vez algo como esto:

(
  (a (b c)),
  (b (a c)),
  (c (a b d)),
  (d (c))
)

podría dar un gráfico como este:

a <--> b <--> c <--> d
^ ^
El | El |
+ --------- +

Si quieres ponerte elegante, también puedes agregarle peso:

(
  (a (b 1.0 c 2.0)),
  (b (a 1.0 c 1.0)),
  (c (a 1.3 b 7.2 d 10.5)),
  (d (c -10.5))
)

También te puede interesar esto: CL-Graph (encontrado al buscar en Google la frase "estructura gráfica lisp")

FrustratedWithFormsDesigner
fuente
44
Esto es un poco tarde, pero creo que debería advertir que "Todo lo demás se basa en [lista]" es engañoso. Common Lisp, Scheme y Clojure tienen vectores, mapas, cadenas, así como estructuras / clases, no construidas en la parte superior de las listas; el código que escribimos para crearlos generalmente es una lista, por ejemplo (make-array '(2 2): elemento inicial 0), pero la estructura de datos no se implementa mediante listas.
coredump
3

Los lenguajes funcionales manejan las estructuras de datos de la misma manera que los lenguajes no funcionales: separando la interfaz de la implementación, creando tipos de datos abstractos.

Puede crear tipos de datos abstractos en Lisp. Por ejemplo, para un gráfico, es posible que desee un par de funciones:

(define (get-vertices graph) ;; gets all the vertices from a graph
  ...)

(define (get-edges graph) ;; gets all the edges from a graph
  ...)

(define (get-weight vertex-from vertex-to) ;; get the weight of a specific vertex
  ...)

Una vez que haya creado esa interfaz en un gráfico, puede implementar las estructuras de datos reales de muchas maneras diferentes, posiblemente optimizando factores tales como la eficiencia del programador, la flexibilidad y la eficiencia computacional.

La clave es asegurarse de que el código que usa gráficos solo use la interfaz de gráficos y no acceda a la implementación subyacente. Esto mantendrá el código del cliente más simple ya que está desacoplado de la implementación real.


fuente
2

Bueno, dependería de si su gráfico es dirigido / no dirigido, ponderado / no ponderado, pero una forma de representar un gráfico ponderado dirigido (que sería el más general) es con un mapa de mapas (en Clojure)

{
 :a {:b 3 :c 4} 
 :b {:a 1} 
 :c {}
}

representaría un mapa con nodos: a: byc: : a apunta a: b con un peso de 3 y: c con un peso de 4.: b apunta a: a con un peso de 1.: c no apunta a nada.

WuHoUnited
fuente
1

En Common Lisp, si necesito representar un árbol, usaría una lista (si fuera solo para un truco rápido) o definiría una clase de árbol (o estructura, pero las clases interactúan bien con funciones genéricas, entonces ¿por qué no?) .

(defclass tree ()
  ((node :accessor node :initarg :node)
   (children :accessor children :initarg :children)))

Si necesito árboles literales en el código, probablemente también defina una make-treefunción que tome una representación de la lista del árbol que quiero y la convierta en un árbol de objetos de árbol.

Vatine
fuente
-2

En Haskell, la lista es la estructura de datos básica y, si desea estructuras de datos más avanzadas, a menudo utiliza estructuras recursivas como si un árbol es nulo o un nodo y dos árboles

data Tree a = Null | Node Tree a Tree  
nist
fuente