J'ai commencé à lire sur F # récemment, et évidemment j'ai très bientôt une question de niveau novice. Il s'agit de listes (collections).

Selon les manuels F #, il y a deux opérations pour construire des listes, ce sont les contre (aka ::) et @. Étant donné le fait que @ est plus polyvalent (peut fusionner des sous-listes, pas des éléments uniques, et peut également s'ajouter à la queue, contrairement à l'opération contre), ma question est la suivante: dans quelle situation nous devons utiliser exactement :: au lieu de @ pour éviter toute ambiguïté, ou des effets secondaires indésirables et ainsi de suite?

En d'autres termes: :: est-il théoriquement redondant ou non?

f#
10
Yury Schkatula 23 mai 2018 à 20:14

3 réponses

Meilleure réponse

Le type list a deux constructeurs: [] et ::. Si :: était supprimé, seul le constructeur [] resterait, rendant impossible la création de listes non vides.

Notez que quelque chose comme [1;2;3] est du sucre syntaxique pour 1::2::3::[], donc il repose sur l'existence de ::.

De même, @ est une fonction qui est définie à l'aide de ::, donc si :: n'existait pas, @ non plus.

Notez que @ ne convient pas pour remplacer :: dans la définition de list car, si vous ne disposez pas déjà d'un moyen de construire des listes non vides, {{X3 }} ne peut pas être utilisé pour les créer ([] @ [] est toujours une liste vide).

Et même si vous ajoutiez un constructeur pour les listes à un seul élément, @ conduirait à une représentation ambiguë car [1;2;3] pourrait être représenté soit par ([1] @ [2]) @ [3] soit par [1] @ ([2] @ [3]) (plus, vous pouvez simplement ajouter @ [] où vous voulez). Vous vous retrouveriez donc avec plusieurs représentations différentes pour des listes sémantiquement équivalentes.

12
sepp2k 23 mai 2018 à 17:43

C'est l'inverse, @ est à toutes fins utiles redondant, et je crois que les raisons pour lesquelles il existe en tant qu'opérateur dans la bibliothèque principale sont purement historiques.

Je dirais qu'il aurait été préférable qu'il soit retiré et que l'utilisation de List.append soit recommandée à sa place.

La situation actuelle est que @ est défini dans prim-types.fs comme équivalent de la fonction suivante:

let rec (@) x y = 
    match x with 
    | [] -> y 
    | (h::t) -> h :: (t @ y)

Et est plus tard réexposé comme List.append:

let append list1 list2 = list1 @ list2

Il y a très peu de raisons pour lesquelles il devrait être exposé en tant qu'opérateur en premier lieu, autre que "OCaml le fait".

En pratique, il est assez rare d'avoir un cas valide pour l'ajout de listes et une grande partie du traitement de la collection en F # se fait à l'aide de séquences ou d'autres types de collection qui sont mieux adaptés à la concaténation, mais qui ne proposent pas d'opérateur dédié pour cela. Les listes à liaison unique sont en grande partie l'exemple classique d'une structure à laquelle vous ne voulez pas ajouter.

De cette façon, @ est purement éducatif - il semble qu'il n'existe que pour faire trébucher les nouveaux arrivants dans la langue (ou leur rappeler de garder à l'esprit les caractéristiques de performance des structures de données qu'ils utilisent).

5
scrwtp 23 mai 2018 à 18:48

Ce sont deux fonctions différentes avec deux comportements qui peuvent être utilisées pour créer une liste.

:: opérateur ajoute un élément à une liste @ fusionne deux listes

Ajouter un élément un par un est facile avec une liste. La fusion de deux listes nécessite plus de travail.

Il est préférable d'utiliser :: operator et de reserve @ operator à des fins de fusion uniquement.

0
Aldrik 31 mai 2018 à 14:25