Quelqu'un at-il un exemple décent, de préférence pratique/utile, ils pourraient poster la démonstration du concept?F # Fermeture
Répondre
Les fermetures peuvent être utilisées pour un certain nombre de raisons, dont l'une est de réduire la portée des fonctions auxiliaires ou des valeurs. Ainsi, plutôt que de polluer le module/espace de noms avec des conneries aléatoires, vous pouvez les placer juste là où ils sont nécessaires.
open System
let isStrongPassword password =
let isLongEnough (str : string) = str.Length > 10
let containsNumber str =
str |> Seq.tryfind (fun c -> Char.IsDigit(c)) |> Option.is_some
let containsUpper str =
str |> Seq.tryfind (fun c -> Char.IsUpper(c)) |> Option.is_some
if isLongEnough password &&
containsNumber password &&
containsUpper password then
true
else
false
Edit: Voici un autre exemple qui capture les valeurs et les amène dans un champ intérieur sans être passé en tant que paramètres. Dans l'exemple, myPassword est utilisé dans toutes les fonctions internes, mais il n'a pas été transmis en tant que paramètre.
Le premier exemple de Chris Smith offre un aperçu utile de identifier scope in F#. Cependant, il ne tire pas parti des bound variables disponibles pour les fonctions imbriquées. Dans la variante suivante, minLength est disponible pour la fonction interne car il s'agit d'une fermeture.
open System.Text.RegularExpressions
let isStrongPassword minLength =
fun (password : string) ->
password.Length >= minLength &&
Regex.IsMatch(password, "\\d") &&
Regex.IsMatch(password, "[A-Z]")
Ceci est une utilisation triviale d'une fermeture parce que vous pouvez accomplir la même chose par currying en F #.
ESV - si je comprends bien (ce qui est également limité par une perspective OO) la fermeture a à voir avec la limitation de vos fonctions (comme isLongEnough) à la portée de la méthode qui les utilise. Cela ferme effectivement (d'où le terme de fermeture) ces fonctions du reste du code de votre application.
Je pense que je comprends les choses, sinon je vais me détromper, espérons aussi bien;)
@ Alex - qui est juste portée des fonctions. les fermetures se construisent là-dessus cependant.
@ESV -
la forme (fun c...
une fermeture --Même si elle est une application directe et non passé autour. Je ne dirais pas que c'est un bon exemple. Quelque chose, plus simple et simple:
let derivative dx =
(fun f x -> (f (x+dx)) - (f x)/dx)
Nous revenions un environnement (dx) et la fonction anonyme. Maintenant, vous n'avez pas nécessairement à retourner une fonction, comme l'exemple de Chris. Mais cela a toujours à voir avec l'utilisation de variables plus étendues (ou liées) - l'environnement - dans un contexte local.
let filter lst f_critera =
let rec loop_ = function
| hd :: tl ->
if f_critera hd then hd :: (loop_ tl)
else (loop_tl)
| [] -> []
in
loop_ lst
Donc, c'est une fermeture, bien que je l'ai forcé un peu, mais pour le bien de les définir c'est un cadre décent. f_criteria
est lié, dans loop_
- c'est la variable d'environnement.
@ESV, les fermetures sont les trois let
définitions qui sont en retrait (ie. isLongEnough
, containsNumber
et containsUpper
). Ce sont des fermetures car ce sont des fonctions définies dans le cadre de la fonction isStrongPassword
.
Dans le texte Functional Programming il y a cette définition:
Les fermetures sont des fonctions qui portent autour de certains des « environnement » dans lequel ils ont été définis. En particulier, une fermeture peut faire référence à des variables qui étaient disponibles au moment de sa définition.
Cette définition n'est probablement pas complète, mais est facile à comprendre pour quelqu'un du langage impératif/objectif.
Les fermetures sont utiles pour la mise en cache et la mémoisation. Par exemple:
let isWord (words: string list) =
let wordTable = Set.Create(words)
fun w -> wordTable.Contains(w)
> let isCapital = isWord ["London";"Paris";"Warsaw";"Tokyo"];;
val isCapital : (string -> bool)
> isCapital "Paris";;
val it : bool = true
> isCapital "Manchester";;
val it : bool = false
Remarquez comment l'wordTable
est calculé qu'une seule fois, lorsque la fermeture est créée. Plus généralement, les fermetures sont utiles pour garder un état privé. Par conséquent, vous pouvez même recréer des cellules avec des fonctions purement.
let cons a b = function
| true -> a
| false -> b
let car p = p true
let cdr p = p false
> (car (cons 1 2))
val it : int = 1
> (cdr (cons 1 2))
val it : int = 2
Eh bien, ici les cellules contre sont immuables. Mais vous pouvez imaginer avoir un état mutable aussi. Faisons un petit comptoir:
let makeCounter() =
let x = ref 0
let tick() =
x := !x + 1
!x
tick
let c1 = makeCounter()
let c2 = makeCounter()
> c1()
val it : int = 1
> c1()
val it : int = 2
> c2()
val it : int = 1
On sait que les fermetures sont les objets d'un pauvre homme, parce que les objets sont les fermetures d'un pauvre homme :) Vous pouvez simuler un avec l'autre.
J'ai aussi eu du mal avec ça - voir le mot «fermeture» lancé par les experts F #. Cela ressemble à "scope" (et portée imbriquée) qui sont familiers, mais il a en fait peu à voir avec cela, et n'est pertinent que dans le code qui passe autour des fonctions comme valeurs en dehors de sa portée originale.
a une bonne @ Robert citation ...
Les fermetures sont des fonctions qui portent autour de certains des « environnement » dans lequel ils ont été définis. En particulier, une fermeture peut faire référence à des variables qui étaient disponibles au moment de sa définition.
Le meilleur exemple que je l'ai vu ...
let Counter =
let count = ref 0
// *Return a function that carries the current context* (ie. "count", on
// the heap). Each time it is called, it will reference, and increment,
// the same location
(fun() -> incr count; !count)
> Counter()
val it : int = 1
> Counter()
val it : int = 2 <-- !! The anonymous function has retained the context
Cela ne fonctionne que parce que le nombre est une variable "ref" (ie. Sur le tas), et parce que contre retourne une fonction (plutôt que d'un nombre entier)
Suivant est la mauvaise façon - en utilisant la pile à la place du tas ...
let Counter2 =
let mutable count = 0
// Attempt to reference mutable variable, from within a closure, is invalid
(fun() -> count <- count+1; count)
Ce produit un message d'erreur très utile, qui nous en dit beaucoup sur les fermetures ..
La variable mutable 'count' est utilisée d'une manière invalide. Les variables mutables peuvent ne pas être capturées par des fermetures. Envisagez d'éliminer cette utilisation de la mutation ou d'utiliser une cellule de référence mutable allouée par tas via 'ref' et '!'
(Bravo à l'auteur de ce message!)
Syme, et al, "Expert F #", dit, sur l'utilisation des fermetures ...
C'est une technique puissante pour se cacher et d'encapsulation état mutable sans avoir recours à l'écriture de nouvelles définitions de type et classe . C'est une bonne pratique de programmation dans le code poli à s'assurer que tous les éléments connexes de l'état mutable sont collectés sous une structure de données nommée ou autre entité telle qu'une fonction.
La fermeture est formée lorsque des variables libres d'une fonction sont fixées. Ceci est similaire à une méthode de classe liée à une instance d'objet et faisant référence à des variables membres.
Les variables libres sont des variables qui ne sont pas transmises à la fonction en tant que paramètres, c'est-à-dire qui sont prises dans l'environnement où la fonction est définie.
Les fermetures sont très utiles pour les rappels et les gestionnaires d'événements, car ils permettent de former un objet temporaire sans en déclarer un. C'est un énorme bonus de programmation fonctionnelle sur OOP. Notez que la correction fait une chose similaire, mais c'est un concept différent: elle corrige certaines variables liées (c'est-à-dire, les paramètres de fonction). En revanche, la fermeture corrige des variables libres.
Voici un exemple très simple
let rememberTheEvens =
let theList = List<int>()
fun n ->
if n%2 = 0 then theList.Add(n)
theList
Et voici une écriture correcte que je vous ai fait un certain temps qui utilise une fermeture pour Memoization http://www.devjoy.com/2013/05/learning-to-think-functionally-memoization/
espoir qui aide.
- 1. Invoke méthode comme fermeture
- 2. javascript fermeture évaluation immédiate
- 3. fermeture Javascript
- 4. comment obtenir la fermeture à lua?
- 5. Permutations F #
- 6. F # Constructeur
- 7. convertir amp; à & et? F Degré F Vb.net
- 8. Java Syntaxe: octet f() [] par rapport à l'octet [] f()
- 9. F # - Afficher les résultats complets dans F # fenêtre interactive
- 10. paramètres de fermeture groovy
- 11. jQuery et la fermeture
- 12. Fermeture d'un modal JInternalFrame
- 13. Fermeture d'une connexion
- 14. wxNotebook Bouton de fermeture?
- 15. F # 2010 Seq.generate_using
- 16. F # int64 à int
- 17. F # fonction au curry
- 18. Séquence d'impression en F #
- 19. F # Méthodes statiques multilignes
- 20. Catégories F-Script
- 21. F # et ASP.NET
- 22. Visual Studio F # Erreur
- 23. F # Méthode Définition Syntaxe
- 24. Seq.unfold explication in F #
- 25. F # tuyau fourche
- 26. F # Résolution d'opérateur
- 27. F # étrange problème printfn
- 28. Sémantique de l'instruction F #
- 29. F # équivalent de ToLookup
- 30. OrderBy ThenBy en F #
Note de côté: la dernière instruction 'if-then-else' est équivalente à juste' mineIsLongerThan yourPassword && mineHasMoreNumsThan yourPassword' –