Qu'est-ce que la programmation fonctionnelle équivalent du décorateur?
Par exemple, comment voulez-vous écrire cet exemple en particulier, dans un style fonctionnel?
Qu'est-ce que la programmation fonctionnelle équivalent du décorateur?
Par exemple, comment voulez-vous écrire cet exemple en particulier, dans un style fonctionnel?
En programmation fonctionnelle, vous envelopper d'une fonction donnée dans une nouvelle fonction.
Pour donner artificiel, Clojure exemple similaire à celui indiqué dans votre question:
Mon dessin original fonction:
(defn draw [& args]
; do some stuff
)
Ma fonction wrappers:
; Add horizontal scrollbar
(defn add-horizontal-scrollbar [draw-fn]
(fn [& args]
(draw-horizontal-scrollbar)
(apply draw-fn args)))
; Add vertical scrollbar
(defn add-vertical-scrollbar [draw-fn]
(fn [& args]
(draw-vertical-scrollbar)
(apply draw-fn args)))
; Add both scrollbars
(defn add-scrollbars [draw-fn]
(add-vertical-scrollbar (add-horizontal-scrollbar draw-fn)))
Ces renvoyer une nouvelle fonction qui peut être utilisée partout où le dessin original de la fonction est utilisée, mais aussi de dessiner les barres de défilement.
Nourrissage des paramètres fonctionnels / composition est l'équivalent le plus proche. Cependant, c'est une erreur de même poser cette question, parce que des modèles existent pour compenser les faiblesses de la langue d'accueil.
Si C++/Java/C#/toute autre pratiquement identique à la langue a une décoration en fonction de la langue, vous n'y pensez pas comme un modèle. Il se trouve que les "modèles" sont des modèles de structuration des systèmes de liaison anticipée objectif impératif langages orientés, généralement sans l'autoboxing, et avec relativement minces protocoles pour la classe racine.
Vous pouvez "habiller" les fonctions en les enveloppant à l'intérieur d'autres fonctions, en utilisant généralement une certaine forme d'ordre supérieur de la fonction pour effectuer l'emballage.
Exemple Simple en Clojure:
; define a collection with some missing (nil) values
(def nums [1 2 3 4 nil 6 7 nil 9])
; helper higher order function to "wrap" an existing function with an alternative implementation to be used when a certain predicate matches the value
(defn wrap-alternate-handler [pred alternate-f f]
(fn [x]
(if (pred x)
(alternate-f x)
(f x))))
; create a "decorated" increment function that handles nils differently
(def wrapped-inc
(wrap-alternate-handler nil? (constantly "Nil found!") inc))
(map wrapped-inc nums)
=> (2 3 4 5 "Nil found!" 7 8 "Nil found!" 10)
Cette technique est largement utilisée dans des fonctionnelles des bibliothèques. Un bon exemple est l' emballage web, les gestionnaires de demandes à l'aide de l'Anneau de middleware - liés exemple des enveloppements de gestion des paramètres du html, demande autour de l'existant gestionnaire.
Quelque chose comme ceci:
class Window w where
draw :: w -> IO ()
description :: w -> String
data VerticalScrollingWindow w = VerticalScrollingWindow w
instance Window w => Window (VerticalScrollingWindow w) where
draw (VerticalScrollingWindow w)
= draw w >> drawVerticalScrollBar w -- `drawVerticalScrollBar` defined elsewhere
description (VerticalScrollingWindow w)
= description w ++ ", including vertical scrollbars"
En Haskell, ce OO schéma traduit assez bien directement, vous avez seulement besoin d'un dictionnaire. Notez que la traduction n'est pas vraiment une bonne idée. Essayer de forcer une OO concept en Haskell est une sorte de backwords, mais vous l'avez demandé si elle est ici.
L'Interface De La Fenêtre
Haskell a des classes, qui a toutes les fonctionnalités d'une Interface et puis certains. Nous utilisons donc la suivante Haskell classe:
class Window w where
draw :: w -> IO ()
description :: w -> String
Le Résumé WindowDecorator classe
Celui-ci est un peu plus délicate, car Haskell n'a pas de notion d'héritage. Habituellement, nous ne fournirait pas de ce type et de laisser les décorateurs mettre en oeuvre Window
directement, mais permet de suivre l'exemple complètement. Dans cet exemple, un WindowDecorator
est une fenêtre avec un constructeur prenant une fenêtre, permet de compléter ce avec une fonction donnant le décoré de la fenêtre.
class WindowDecorator w where
decorate :: (Window a) => a -> w a
unDecorate :: (Window a) => w a -> a
drawDecorated :: w a -> IO ()
drawDecorated = draw . unDecorate
decoratedDescription :: w a -> String
decoratedDescription = description . unDecorate
instance (WindowDecorator w) => Window w where
draw = drawDecorated
description = decoratedDescription
Notez que nous fournir une implémentation par défaut de Window
, il peut être remplacé, et toutes les instances de l' WindowDecorator
sera Window
.
Les décorateurs
Faire des décorateurs peut alors être effectuée comme suit:
data VerticalScrollWindow w = VerticalScrollWindow w
instance WindowDecorator VerticalScrollWindow where
decorate = VerticalScrollWindow
unDecorate (VerticalScrollWindow w ) = w
drawDecorated (VerticalScrollWindow w ) = verticalScrollDraw >> draw w
data HorizontalScrollWindow w = HorizontalScrollWindow w
instance WindowDecorator HorizontalScrollWindow where
decorate = HorizontalScrollWindow
unDecorate (HorizontalScrollWindow w .. ) = w
drawDecorated (HorizontalScrollWindow w ..) = horizontalScrollDraw >> draw w
Finition
Enfin, nous pouvons définir un certain nombre de fenêtres:
data SimpleWindow = SimpleWindow ...
instance Window SimpleWindow where
draw = simpleDraw
description = simpleDescription
makeSimpleWindow :: SimpleWindow
makeSimpleWindow = ...
makeSimpleVertical = VerticalScrollWindow . makeSimpleWindow
makeSimpleHorizontal = HorizontalScrollWindow . makeSimpleWindow
makeSimpleBoth = VerticalScrollWindow . HorizontalScrollWindow . makeSimpleWindow
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.