[PYTHON] Aide-mémoire au curry

J'ai commencé à écrire comme une explication supplémentaire de mon travail "Résumé de l'exécution d'une fonction récursive anonyme utilisant un combinateur de points immobile", pour décrire et utiliser la fonction curry. Il semblait qu'il serait utile pour au moins une personne (moi-même) d'en faire une feuille de triche indépendante, j'ai donc écrit un nouvel article. La définition de la fonction qui gère [pas **](#% E3% 82% AB% E3% 83% AA% E3% 83% BC% E5% 8C% 96% E3% 81% AE% Notez que E6% A6% 82% E8% A6% 81). En raison du fait qu'il couvre plusieurs langues, nous accueillons les personnes qui connaissent chaque langue et paradigme, y compris [Explication of curryization](#Overview of curryization).

La liste de notation uniquement est la suivante. f est une fonction et ʻa` est un argument.

Langue Changer les arguments Spécification d'argument Remarques
Haskell Délimiteur vide f a a ・ ・ ・ a
Scheme lambdaFonction anonyme par (・ ・ ・((f a) a)・ ・ ・a)
Python Fonction définie dans la fonction f(a)(a)・ ・ ・(a) Des fonctions anonymes peuvent également être utilisées
Ruby ->Fonction anonyme utilisant f.(a).(a)・ ・ ・.(a)Ouf[a][a]・ ・ ・[a] Il existe une méthode au curry
JavaScript =>OufunctionFonction anonyme utilisant f(a)(a)・ ・ ・(a)
Scala =>Fonction anonyme utilisant f(a)(a)・ ・ ・(a) Méthode Curly disponible, typée statiquement
Perl subSous-programme anonyme utilisant f(a)->(a)・ ・ ・->(a) $f->(a)・ ・ ・Peut être
Aller langue funcFonction anonyme utilisant f(a)(a)・ ・ ・(a) Typage statique
PHP functionQuanduseFonction anonyme utilisant f(a)(a)・ ・ ・(a) 7.À partir de 4fnQuand=>Fonction anonyme utilisant
Standard ML Délimiteur vide f a a ・ ・ ・ a
Julia ->Fonction anonyme utilisant f(a)(a)・ ・ ・(a)
Emacs Lisp lambdaFonction anonyme par (funcall ・ ・ ・(funcall (f a) a)· · · UNE) 24.Activer la portée lexicale après 1
Common Lisp lambdaFonction anonyme par (funcall ・ ・ ・(funcall (f a) a)· · · UNE)
Langue R functionFonction anonyme par f(a)(a)・ ・ ・(a)

Haskell(GHC) Si vous spécifiez un argument séparé par des espaces sans utiliser (,) lors de la définition d'une fonction, elle sera organisée. La spécification d'argument de la fonction de curling est «argument d'argument de fonction ・ ・ ・ argument».

Prelude> func (x,y,z) = if x > 0 then y else z
Prelude> func((-100),0,(-1))
-1
Prelude> func x y z = if x > 0 then y else z
Prelude> func (-100) 0 (-1)
-1

Scheme(Gauche) Il est réalisé en utilisant une fonction anonyme utilisant lambda comme valeur de retour. La spécification d'argument de la fonction de curling est (・ ・ ・ ((argument de fonction) argument) ・ ・ ・ argument). En fonction du système de traitement (comme Gauche), il est possible de définir une fonction (sans lambda) selon le format lorsque l'argument est spécifié.

gosh> (define (func x y z) (if (> x 0) y z))
func
gosh> (func -100 0 -1)
-1
gosh> (define func (lambda (x) (lambda (y) (lambda (z) (if (> x 0) y z)))))
func
gosh> (((func -100) 0) -1)
-1
gosh> (define (((func x) y) z) (if (> x 0) y z))
func
gosh> (((func -100) 0) -1)
-1

Python(Python3,Python2) Les fonctions anonymes utilisant lambda peuvent être utilisées, mais comme il n'est pas recommandé pour PEP8 d'assigner directement une fonction anonyme à une variable, il est courant d'utiliser la fonction définie à l'intérieur de la fonction comme valeur de retour. .. La spécification d'argument de la fonction de curling est «fonction (argument) (argument) ... (argument)».

>>> def func(x, y, z): return y if x > 0 else z
... 
>>> func(-100, 0, -1)
-1
>>> def func(x):
...     def func(y):
...         def func(z): return y if x > 0 else z
...         return func
...     return func
... 
>>> func(-100)(0)(-1)
-1
>>> func = lambda x: lambda y: lambda z: y if x > 0 else z    #PEP8 non recommandé
>>> func(-100)(0)(-1)
-1

Ruby(CRuby,JRuby) En Ruby, une méthode curry «curry» est préparée. Cependant, une fonction anonyme multi-arguments est définie une fois par -> puis curry est appliqué. La spécification d'argument de la fonction de curling est fonction. (Argument). (Argument) ... (argument) ou fonction [argument] [argument] ... [argument].

def func1(x,y,z) x > 0 ? y : z end
p func1(-100,0,-1)              # => -1

func2 = -> x,y,z { x > 0 ? y : z }
p func2.curry.(-100).(0).(-1)    # => -1
p func2.curry[-100][0][-1]       # => -1

La méthode réalisée par une fonction anonyme utilisant uniquement -> est la suivante.

func3 = -> x { ->  y { -> z { x > 0 ? y : z } } }
p func3.(-100).(0).(-1)          # => -1
p func3[-100][0][-1]             # => -1

JavaScript(Node.js) Il est réalisé par la méthode de retour d'une fonction anonyme en utilisant => ou function. La spécification d'argument de la fonction de curling est «fonction (argument) (argument) ... (argument)».

function func1(x,y,z) { return x > 0 ? y : z }
console.log(func1(-100,0,-1))      // => -1

func2 = x => y => z => x > 0 ? y : z
console.log(func2(-100)(0)(-1))    // => -1

function func3(x) {
  return function (y) {
    return function (z) {
      return x > 0 ? y : z
    }
  }
}
console.log(func3(-100)(0)(-1))    // => -1

Scala(Scala 2.11 + Java VM 12) Scala propose une méthode de curry «curry». Cependant, une fonction anonyme multi-arguments est définie une fois par => puis curried est appliqué. La spécification d'argument de la fonction de curling est «fonction (argument) (argument) ... (argument)».

scala> def func(x: Int, y: Int, z: Int): Int = if (x > 0) y else z
func: (x: Int, y: Int, z: Int)Int

scala> func(-100,0,-1)
res0: Int = -1

scala> val func = (x: Int, y: Int, z: Int) => if (x > 0) y else z
func: (Int, Int, Int) => Int = <function3>

scala> val func_curried = func.curried
func_curried: Int => (Int => (Int => Int)) = <function1>

scala> func_curried(-100)(0)(-1)
res1: Int = -1

La méthode réalisée par une fonction anonyme utilisant uniquement => est la suivante. Puisqu'il s'agit d'un langage à typage statique, il est nécessaire de clarifier la transition de type de la fonction entière.

scala> val func: Int => (Int => (Int => Int)) = (x: Int) => (y: Int) => (z: Int) => if (x > 0) y else z
func: Int => (Int => (Int => Int)) = <function1>

scala> func(-100)(0)(-1)
res2: Int = -1

Perl(perl 5) Il est réalisé en utilisant une fonction anonyme (sous-section) utilisant sub comme valeur de retour. La spécification d'argument de la fonction de curling est fonction (argument) -> (argument) ...-> (argument). Si le nom du corps de la fonction est également une fonction anonyme, c'est $ function-> (argument) -> (argument) ...-> (argument).

sub func { my ($x,$y,$z) = @_; $x > 0 ? $y : $z; };
print func(-100,0,-1), "\n";    # => -1

sub func_curried { my $x = shift; return sub { my $y = shift; return sub { my $z = shift; return $x > 0 ? $y : $z; }; }; };
print func_curried(-100)->(0)->(-1), "\n";    # => -1

my $func_curried2 = sub { my $x = shift; return sub { my $y = shift; return sub { my $z = shift; return $x > 0 ? $y : $z; }; }; };
print $func_curried2->(-100)->(0)->(-1), "\n";    # => -1

Aller langue (gc)

Il est réalisé en utilisant une fonction anonyme utilisant func comme valeur de retour. La spécification d'argument de la fonction de curling est «fonction (argument) (argument) ... (argument)». Puisqu'il s'agit d'un langage de type statique, plus il gère d'arguments, plus il a de descriptions typées pour la valeur de retour de la fonction de chaque argument.

package main
import "fmt"

func func1 (x, y, z int) int { if x > 0 { return y } else { return z } }
func func2 (x int) func(int) func(int) int {
    return func(y int) func(int) int {
        return func(z int) int {
            if x > 0 { return y } else { return z }
        }
    }
}

func main() {
    fmt.Println(func1(-100,0,-1))      // => -1
    fmt.Println(func2(-100)(0)(-1))    // => -1
}

PHP(PHP 7.3,PHP 7.4) Jusqu'à PHP7.3, il est réalisé par la méthode de retour d'une fonction anonyme en utilisant function et ʻuse`. La spécification d'argument de la fonction de curling est «fonction (argument) (argument) ... (argument)».

<?php

function func1($x,$y,$z) {
    return ($x > 0) ? $y : $z;
}
echo func1(-100,0,-1) . PHP_EOL;
// => -1

function func2($x) {
    return function($y) use ($x) {
        return function($z) use ($x,$y) {
            return ($x > 0) ? $y : $z;
        };
    };
}
echo func2(-100)(0)(-1) . PHP_EOL;
// => -1

Depuis PHP 7.4, les fonctions anonymes utilisant fn et` => ʻ sont disponibles.

function func2($x) { return fn($y) => fn($z) =>  ($x > 0) ? $y : $z; }
echo func2(-100)(0)(-1) . PHP_EOL;
// => -1

Standard ML(SML/NJ) Si vous spécifiez un argument séparé par des espaces sans utiliser (,) lors de la définition d'une fonction, elle sera organisée. La spécification d'argument de la fonction de curling est «argument d'argument de fonction ・ ・ ・ argument».

- fun func (x, y, z) = if x > 0 then y else z;
val func = fn : int * 'a * 'a -> 'a
- func (~100, 0, ~1);
val it = ~1 : int
- fun func x y z = if x > 0 then y else z;
val func = fn : int -> 'a -> 'a -> 'a
- func ~100 0 ~1;
val it = ~1 : int
- func (~100)(0)(~1);
val it = ~1 : int

Julia(Version 1.0.5) Il est réalisé en utilisant une fonction anonyme utilisant -> comme valeur de retour. La spécification d'argument de la fonction de curling est «fonction (argument) (argument) ... (argument)».

julia> func1(x,y,z) = x > 0 ? y : z
func1 (generic function with 1 method)

julia> func1(-100,0,-1)
-1

julia> func2 = x -> y -> z -> x > 0 ? y : z
#3 (generic function with 1 method)

julia> func2(-100)(0)(-1)
-1

Emacs Lisp (GNU Emacs 24.1 ou version ultérieure)

Si vous activez lexical-binding (set t avec setq), vous serez en mode de portée lexicale, et vous pouvez utiliser des fermetures comprenant des expressions lambda. La spécification d'argument pour le curry est (funcall ・ ・ ・ (funcall (argument de fonction) argument) ・ ・ ・ argument).

ELISP> (defun func (x y z) (if (> x 0) y z))
func
ELISP> (func -100 0 -1)
-1 (#o7777777777, #x3fffffff)
ELISP> (defun func (x) (lambda (y) (lambda (z) (if (> x 0) y z))))
func
ELISP> (funcall (funcall (func -100) 0) -1)
*** Eval error ***  Symbol’s value as variable is void: x
ELISP> (setq lexical-binding t)
t
ELISP> (defun func (x) (lambda (y) (lambda (z) (if (> x 0) y z))))
func
ELISP> (funcall (funcall (func -100) 0) -1)
-1 (#o7777777777, #x3fffffff)

Common Lisp(SBCL 2.0.0) Il est réalisé en utilisant une fonction anonyme utilisant lambda comme valeur de retour. La spécification d'argument de la fonction de curling est (funcall ・ ・ ・ (funcall (argument de fonction) argument) ・ ・ ・ argument).

* (defun func (x y z) (if (> x 0) y z))
FUNC
* (func -100 0 -1)
-1
* (defun func (x) (lambda (y) (lambda (z) (if (> x 0) y z))))
FUNC
* (funcall (funcall (func -100) 0) -1)
-1

Langage R (4.0.2)

Il est réalisé en utilisant une fonction anonyme utilisant function comme valeur de retour. La spécification d'argument de la fonction de curling est «fonction (argument) (argument) ... (argument)».

> func <- function(x,y,z) { if (x > 0) y else z }
> func(-100,0,-1)
[1] -1
> func <- function(x) { function(y) { function(z) { if (x > 0) y else z } } }
> func(-100)(0)(-1)
[1] -1

Remarques

Vue d'ensemble du curry

Curry est une [fonction d'ordre supérieur]( Spécifiez plusieurs arguments à l'aide de la fonction https://ja.wikipedia.org/wiki/%E9%AB%98%E9%9A%8E%E9%96%A2%E6%95%B0) Conversion d'une fonction en répétition d'une fonction qui ne spécifie qu'un seul argument. Il est connu comme un moyen d '"application partielle" qui permet le partage des descriptions de traitement, mais ce n'est qu'un des exemples d'utilisation. Les caractéristiques du curry lui-même sont qu'il est facile d'appliquer des théories mathématiques telles que le calcul lambda, de définir des fonctions à usage général qui reçoivent des arguments de manière récursive, d'ajuster l'application de valeurs pour chaque argument et de données. En recevant la structure élément par élément, une programmation plus concise et plus flexible devient possible.

En ce qui concerne les mérites du curry, les mots suivants dans cet article sont faciles à comprendre.

Dans curry, en plus de masquer $ x $ et de voir $ y $ comme une variable comme une application partielle, vous pouvez masquer $ y $ et voir $ x $ comme une variable.

Un exemple en Python serait:

>>> def func(x):
...     def func(y): return (x - y)
...     return func
... 
>>> fx = func(5)
>>> [fx(y) for y in range(10)]           #Valeur de x(5)Lorsque vous masquez et voyez y comme une variable (0-9)
[5, 4, 3, 2, 1, 0, -1, -2, -3, -4]
>>> fy = [func(x) for x in range(10)]    #Valeur de y(5)Pour masquer et voir x comme une variable (0-9)
>>> [f(5) for f in fy]
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]

En utilisant cette méthode de description, il est possible de curry facilement une fonction existante avec plusieurs arguments. Cependant, il n'est pas possible de créer une fonction ou une macro qui convertit une fonction existante avec plusieurs arguments en une fonction curry. La raison en est que le nombre d'arguments des fonctions existantes est indéfini et qu'il n'est pas possible de générer un nombre quelconque de fonctions anonymes et de fonctions internes (y compris la fonction de fermeture). Les méthodes Curry de Ruby et Scala sont converties à partir de fonctions anonymes avec plusieurs arguments définis individuellement.

Informations complémentaires sur l'article

modifier l'historique

Recommended Posts

Aide-mémoire au curry
Aide-mémoire SQLite3
feuille de triche pyenv
Aide-mémoire sur le curry [liste de la version de l'exemple de description]
Aide-mémoire PIL / Pillow
feuille de triche de commande ps
Aide-mémoire de l'API Spark
Aide-mémoire Python3 (basique)
Fiche technique PySpark [Python]
Feuille de triche de tri Python
feuille de triche de fichier de réglage tox
feuille de triche de réutilisation de la mémoire numpy
[Python3] Entrée standard [Cheet sheet]
Fiche technique de la science des données (Python)
Aide-mémoire sur les pièces jointes de l'API Slack
Fiche technique du didacticiel Python Django
feuille de triche de l'algorithme scikit learn
Apache Beam Cheet Sheet [Python]
Aide-mémoire personnel Google Test / Mock
Aide-mémoire sur le style de livraison continue (CPS)
Aide-mémoire Python (pour les expérimentés C ++)
Fiche de triche AtCoder en python (pour moi-même)
Fiche technique de l'accès aux données Blender Python Mesh
Feuille de calcul du modélisateur d'optimisation mathématique (PuLP) (Python)
Aide-mémoire pour le post-traitement d'OpenFOAM (mis à jour de temps en temps)
[Mise à jour] Aide-mémoire de la syntaxe Python pour la boutique Java
Enroulement de tigre qui ne provoque pas d'accident
Cheet sheet lors du scraping avec Google Colaboratory (Colab)