Question A quoi sert la fonction `id` dans FSharp.Core?


De Operators.id <'T> Fonction (F #):

La fonction identité

Paramètres: x Type: 'T (La valeur d'entrée)

Valeur de retour: la même valeur

Versions F # Core Library, prises en charge dans: 2.0, 4.0, Portable

Pourquoi existe-t-il une fonction qui renvoie son entrée?


20
2018-06-14 12:53


origine


Réponses:


Lorsque vous travaillez avec des fonctions d'ordre supérieur (c'est-à-dire des fonctions qui renvoient d'autres fonctions et / ou prennent d'autres fonctions comme paramètres), vous devez toujours fournir quelque chose en paramètre, mais il n'y a pas toujours une transformation de données réelle à appliquer.

Par exemple, la fonction Seq.collect aplatit une séquence de séquences et prend une fonction qui renvoie la séquence "imbriquée" pour chaque élément de la séquence "externe". Par exemple, voici comment vous pouvez obtenir la liste de tous les petits-enfants d'un contrôle de l'interface utilisateur:

let control = ...
let allGrandChildren = control.Children |> Seq.collect (fun c -> c.Children)

Mais souvent, chaque élément de la séquence sera déjà une séquence en soi - par exemple, vous pouvez avoir une liste de listes:

let l = [ [1;2]; [3;4]; [5;6] ]

Dans ce cas, la fonction de paramètre que vous transmettez à Seq.collect doit juste retourner l'argument:

let flattened = [ [1;2]; [3;4]; [5;6] ] |> Seq.collect (fun x -> x)

Cette expression fun x -> x est une fonction qui renvoie simplement son argument, également appelé "fonction d'identité".

let flattened = [ [1;2]; [3;4]; [5;6] ] |> Seq.collect id

Son utilisation se présente si souvent lorsque vous travaillez avec des fonctions de niveau supérieur (telles que Seq.collect ci-dessus) qu'il mérite une place dans la bibliothèque standard.

Un autre exemple convaincant est Seq.choose - une fonction qui filtre une séquence de Option les valeurs et les déballe en même temps. Par exemple, voici comment vous pouvez analyser toutes les chaînes sous forme de nombres et ignorer celles qui ne peuvent pas être analysées:

let tryParse s = match System.Int32.TryParse s with | true, x -> Some x | _ -> None
let strings = [ "1"; "2"; "foo"; "42" ]
let numbers = strings |> Seq.choose tryParse  // numbers = [1;2;42]

Mais si vous avez déjà une liste de Option valeurs pour commencer? La fonction d'identité à la rescousse!

let toNumbers optionNumbers =
   optionNumbers |> Seq.choose id

26
2018-06-14 13:15



Il est utile pour certaines fonctions d'ordre supérieur (fonctions qui prennent des fonctions comme arguments) pour que vous puissiez passer id comme argument au lieu d'écrire le lambda (fun x -> x).

[[1;2]; [3]] |> List.collect id  // [1; 2; 3]

11
2018-06-14 13:11



Cela peut être extrêmement utile lorsque vous travaillez avec des options.

J'ai écrit un petit JSON-Helper idiomatique, indiquant tous les champs optionnels comme Option, en lançant des erreurs, si une chaîne est passée en tant que null, sinon de type 'string option'.

Maintenant, il y a une fonction fournissant une valeur de sortie en boîte, qui peut être

  1. 'a -> tout type mais pas d'option
  2. 'b ->' option x

Pour encaisser correctement la valeur, j'utilise

val |> if isOption then fnOptTransform else id

Donc, j'applique la fonction d'ordre élevé fnOptTransform, et en appelant id sinon, évitez la laideur de coder un lambda séparé (j'essaie de l'éviter, où je peux ..). Je l'ai trouvé utile.


0
2017-07-18 18:34