2017-06-07 2 views
0

Je suis nouveau à reason/ocaml/programmation fonctionnelle.ajouter à la liste/tableau existant

Je connais environ List.append et [] @ [] mais ces fonctions vont créer une nouvelle liste mais comment remplir une liste/tableau existant?

  1. Quelle est la meilleure façon de remplir la liste?
  2. Quelle est la meilleure façon de remplir un tableau? Moyens si le type de coords est let coords: array point = [];
  3. Ou est-ce un mauvais flux (algorithme) pour un tel cas?

Code Raison:

type point = {x: int, y: int}; 

let coords: list point = []; 

let append raw => 
    Array.iter 
    (
     fun data => { 
     let p = {x: data.x, y: data.y}; 
     /* how to append p to coords */ 
     () 
     } 
    ) 
    raw; 

JS analogique:

const coords = []; 
const append = raw => raw.forEach({x, y} => { 
    coords.push({ 
    x: process(x), 
    y: process(y) 
    }); 
}); 
+0

La réponse très simple: dans FP, vous n'avez pas besoin de 'coords' séparés, puisque c'est une copie exacte de' raw'. Continuez à utiliser cru. – Yawar

+0

@Yawar J'ai le code des mises à jour. Par exemple - coords contient xy traité (signifie que copie pas exacte) – tuchk4

+0

Voir la réponse de Cheng Lou, c'est complet, mais en bref vous feriez quelque chose comme 'List.map (fun {x, y} => {x: processus x , y: processus y}) raw' – Yawar

Répondre

6

Bienvenue à la raison!

Dans Reason/OCaml, les listes sont immuables. Sous le capot, ils sont une liste simple et simple. Vous en créez de nouveaux chaque fois que vous les "modifiez". Voici un exemple:

let a = [1, 2, 3]; 
let b = [0, ...a]; 

Cela ressemble à un tableau de JavaScript « spread », sauf qu'ici vous prenez le a actuel, qui relie un nouveau noeud 0 à l'avant, et de l'appeler b. a pointe toujours vers [1, 2, 3] (donc "immuable"). b est maintenant [0, 1, 2, 3]. C'est efficace puisque la partie [1, 2, 3] est partagée.

L'avantage de ceci est que vous n'avez pas à vous soucier de faire passer votre liste et que vous avez accidentellement une fonction obscure qui la modifie. L'immutabilité de List vous permet de raisonner sur votre code uniquement en regardant la valeur que vous regardez en ce moment (puisque cela ne changera jamais!).

L'inconvénient de la liste est qu'il est inefficace d'ajouter quelque chose à la fin:

let c = a @ [4] 

Cette opération prend essentiellement une liste d'un élément, [4] et fixer successivement chaque élément de [1, 2, 3] à lui. Donc linéaire en termes de perf. Mais à en juger par la simplicité de la mise en œuvre de la liste, il a historiquement été jugé digne d'un compromis.

Donc 3. c'est le mauvais flux si vous essayez de définir un élément de liste.

  1. La meilleure façon de remplir une liste dans votre cas est par cartographie dessus non mutatively, de la liste ancienne: let newList = List.map (fun blabla => ...) raw
  2. même pour le tableau. Carte sur elle. Il y a Array.of_list et Array.to_list si jamais vous êtes coincé.

Plus d'informations sur array: OCaml array est modifiable, et sa taille est inchangeable. Pensez-y comme un bloc de mémoire. Vous devez allouer un nouveau tableau via Array.make newSize, puis le remplir via Array.set. Cela n'aurait pas de sens si vous redimensionniez beaucoup le tableau, alors choisissez la bonne structure de données.

Pour la compilation JS, BuckleScript compile un tableau ocaml dans un tableau JS. Il est donc mutable et redimensionnable. En tant qu'heuristique générale, si vous souhaitez modifier la longueur, essayez filter. Si vous souhaitez modifier la longueur et les éléments contenus, essayez fold_left. Sinon, map. Plus récemment, nous avons commencé à implémenter un tableau immuable, redimensionnable, éventuellement mutable. Restez à l'écoute!

+0

'List.map (fun blabla => ...) raw' - mais dans ce cas le résultat devrait être assigné à une nouvelle variable et selon l'exemple fourni - scopes (où liste a été créée, et où la liste doit être mappée) sont différents. Donc, un tel flux n'est pas correct selon le flux FP? – tuchk4

+0

Oui, je l'ai assigné à une nouvelle variable. J'ai ajouté une clarification. BTW si vous n'utilisez pas la valeur de retour, le système de type vous avertira. Alors tout va bien. – chenglou

+0

Avec 'Js.Array' tout va bien mais je veux utiliser le plus possible le flux et la structure de la raison. Comment être avec ce cas https://gist.github.com/tuchk4/7130405338a41a7a91b6de22356c072e Le principal problème que je pense que je ne sais pas comment travailler avec FP :) – tuchk4