Estruturas de dados em programação funcional

11

Atualmente, estou jogando com o LISP (particularmente Scheme e Clojure) e estou me perguntando como as estruturas de dados típicas são tratadas nas linguagens de programação funcional.

Por exemplo, digamos que eu gostaria de resolver um problema usando um algoritmo de busca de caminhos de gráficos. Como normalmente representaria esse gráfico em uma linguagem de programação funcional (principalmente interessada no estilo funcional puro que pode ser aplicado ao LISP)? Esqueceria completamente os gráficos e resolveria o problema de outra maneira?

pwny
fonte

Respostas:

14

Já faz um tempo desde que trabalhei no LISP, mas pelo que me lembro, a estrutura não atômica básica é uma lista. Tudo o resto é baseado nisso. Portanto, você pode ter uma lista de átomos em que cada átomo é um nó, seguido de uma lista de arestas que conectam o nó a outros nós. Tenho certeza de que há outras maneiras de fazer isso também.

Talvez algo parecido com isto:

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

poderia dar um gráfico como este:

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

Se você quiser ser chique, também pode adicionar pesos a ele:

(
  (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))
)

Você também pode se interessar por: Gráfico CL (encontrado na pesquisa no Google com a frase "estrutura do gráfico lisp")

FrustratedWithFormsDesigner
fonte
4
É um pouco tarde, mas acho que devo avisar que "Tudo o resto é baseado em [lista]" é enganoso. Lisp, Scheme e Clojure comuns têm vetores, mapas, strings, bem como estruturas / classes, não construídos no topo de listas; o código que escrevemos para criá-los geralmente é uma lista, por exemplo (make-array '(2 2): elemento inicial 0), mas a estrutura de dados não é implementada usando listas.
Coredump
3

Linguagens funcionais lidam com estruturas de dados da mesma maneira que linguagens não funcionais: separando a interface da implementação, criando tipos de dados abstratos.

Você pode criar tipos de dados abstratos no Lisp. Por exemplo, para um gráfico, você pode querer algumas funções:

(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
  ...)

Depois de criar essa interface para um gráfico, você pode implementar as estruturas de dados reais de várias maneiras diferentes, possivelmente otimizando fatores como eficiência, flexibilidade e eficiência computacional do programador.

A chave é garantir que o código que usa gráficos use apenas a interface gráfica e não acesse a implementação subjacente. Isso manterá o código do cliente mais simples, pois não está acoplado à implementação real.


fonte
2

Bem, isso dependeria de seu gráfico ser direcionado / não direcionado, ponderado / não ponderado, mas uma maneira de representar um gráfico direcionado e ponderado (que seria o mais geral) é com um mapa de mapas (em Clojure)

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

representaria um mapa com nós: a: be: c. : a aponta para: b com peso 3 e: c com peso 4.: b aponta para: a com peso 1.: c não aponta para nada.

WuHoUnited
fonte
1

No Common Lisp, se eu precisasse representar uma árvore, usaria uma lista (se fosse apenas para um hack rápido) ou definiria uma classe de árvore (ou estrutura, mas as classes interagem bem com funções genéricas, por que não) .

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

Se eu precisar de árvores literais no código, provavelmente definiria uma make-treefunção que pega uma representação em lista da árvore que eu quero e a transformava em uma árvore de objetos de árvore.

Vatine
fonte
-2

Em Haskell, a lista é a estrutura de dados básica e, se você deseja estruturas de dados mais avançadas, costuma usar estruturas recursivas como uma árvore ou é um nulo ou um nó e duas árvores.

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