[PYTHON] Curry cheat sheet

I started writing it as a supplementary explanation of my work "Summary of execution of anonymous recursive function using fixed point combinator", to describe and use the currying function. It seemed that it would be useful for at least about one person (myself) to use the independent cheat sheet of, so I wrote a new article. The definition of the function that curries [not **](#% E3% 82% AB% E3% 83% AA% E3% 83% BC% E5% 8C% 96% E3% 81% AE% Note that E6% A6% 82% E8% A6% 81). Due to the fact that it spans multiple languages, we welcome people who are familiar with each language and paradigm, including [Explanation of currying](#Overview of currying).

The list of notation only is as follows. f is a function and ʻa` is an argument.

language Change arguments Argument specification Remarks
Haskell Whitespace delimited f a a ・ ・ ・ a
Scheme lambdaAnonymous function by (・ ・ ・((f a) a)・ ・ ・a)
Python Function defined in the function f(a)(a)・ ・ ・(a) Anonymous functions can also be used
Ruby ->Anonymous function using f.(a).(a)・ ・ ・.(a)Orf[a][a]・ ・ ・[a] There is a currying method
JavaScript =>OrfunctionAnonymous function using f(a)(a)・ ・ ・(a)
Scala =>Anonymous function using f(a)(a)・ ・ ・(a) With currying method, static typing
Perl subAnonymous subroutine using f(a)->(a)・ ・ ・->(a) $f->(a)・ ・ ・May be
Go language funcAnonymous function using f(a)(a)・ ・ ・(a) Static typing
PHP functionWhenuseAnonymous function using f(a)(a)・ ・ ・(a) 7.From 4fnWhen=>Anonymous function using
Standard ML Whitespace delimited f a a ・ ・ ・ a
Julia ->Anonymous function using f(a)(a)・ ・ ・(a)
Emacs Lisp lambdaAnonymous function by (funcall ・ ・ ・(funcall (f a) a)・ ・ ・ A) 24.Enable lexical scope after 1
Common Lisp lambdaAnonymous function by (funcall ・ ・ ・(funcall (f a) a)・ ・ ・ A)
R language functionAnonymous function by f(a)(a)・ ・ ・(a)

Haskell(GHC) If you specify a space-separated argument without using (,) when defining a function, it will be curried. The argument specification of the currying function is function argument argument ・ ・ ・ 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) It is realized by using an anonymous function using lambda as a return value. The argument specification of the currying function is (・ ・ ・ ((function argument) argument) ・ ・ ・ argument). Depending on the processing system (such as Gauche), it is also possible to define a function (without lambda) according to the format when the argument is specified.

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) Anonymous functions using lambda can be used, but since it is not recommended for PEP8 to assign anonymous functions directly to variables, it is common to use the function defined inside the function as the return value. .. The argument specification of the currying function is function (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 deprecated
>>> func(-100)(0)(-1)
-1

Ruby(CRuby,JRuby) In Ruby, a method curry to curry is prepared. However, define a multi-argument anonymous function once with -> and then apply curry. The argument specification of the currying function is function. (Argument). (Argument) ・ ・ ・. (Argument) or function [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

The method realized by an anonymous function using only -> is as follows.

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

JavaScript(Node.js) It is realized by the method of returning an anonymous function using => or function. The argument specification of the currying function is function (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 provides a currying method curried. However, a multi-argument anonymous function is defined once by => and then curried is applied. The argument specification of the currying function is function (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

The method realized by an anonymous function using only => is as follows. Since it is a statically typed language, it is necessary to clarify the type transition of the entire function.

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) It is realized by using an anonymous function (subroutine) using sub as a return value. The argument specification of the currying function is function (argument)-> (argument) ...-> (argument). If the name of the function body is also an anonymous function, it is $ 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

Go language (gc)

It is realized by using an anonymous function using func as a return value. The argument specification of the currying function is function (argument) (argument) ... (argument). Since it is a statically typed language, as the number of arguments handled increases, the type description for the return value of the function of each argument increases.

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) Up to PHP7.3, it is realized by the method of returning an anonymous function using function and ʻuse. The argument specification of the currying function is function (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

Starting with PHP 7.4, anonymous functions using fn and=>are available.

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

Standard ML(SML/NJ) If you specify a space-separated argument without using (,) when defining a function, it will be curried. The argument specification of the currying function is function argument argument ・ ・ ・ 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) It is realized by using an anonymous function using -> as a return value. The argument specification of the currying function is function (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 or later)

If you enable lexical-binding (set t with setq), you will be in lexical scope mode, and closures will be available including lambda expressions. The argument specification for currying is (funcall ・ ・ ・ (funcall (function argument) 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) It is realized by using an anonymous function using lambda as a return value. The argument specification of the currying function is (funcall ・ ・ ・ (funcall (function argument) 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

R language (4.0.2)

It is realized by using an anonymous function using function as a return value. The argument specification of the currying function is function (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

Remarks

Overview of currying

Currying is a [higher-order function]( Specify multiple arguments using the function of https://ja.wikipedia.org/wiki/%E9%AB%98%E9%9A%8E%E9%96%A2%E6%95%B0) Converting a function into a function iteration that specifies only one argument. It is famous as a means of "partial application" that allows sharing of processing descriptions, but it is just one of the usage examples. The characteristics of currying itself are that it is easy to apply mathematical theories such as lambda calculus, define general-purpose functions that receive arguments recursively, adjust the application of values for each argument, and data. By receiving the structure element by element, more concise and flexible programming becomes possible.

Regarding the merits of currying, the following words in this article are easy to understand.

In currying, in addition to hiding $ x $ and seeing $ y $ as a variable like partial application, you can hide $ y $ and see $ x $ as a variable.

An example in Python would be:

>>> def func(x):
...     def func(y): return (x - y)
...     return func
... 
>>> fx = func(5)
>>> [fx(y) for y in range(10)]           #Value of x(5)When hiding and seeing y as a variable (0-9)
[5, 4, 3, 2, 1, 0, -1, -2, -3, -4]
>>> fy = [func(x) for x in range(10)]    #Value of y(5)When hiding and seeing x as a variable (0-9)
>>> [f(5) for f in fy]
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]

By using this description method, it is possible to easily curry an existing function with multiple arguments. However, it is not possible to create a function or macro that converts an existing function with multiple arguments into a currying function. The reason is that the number of arguments of the existing function is indefinite, and it is not possible to generate any number of anonymous functions and internal functions (including closure function). Currying methods in Ruby and Scala convert from anonymous functions with individually defined multiple arguments.

Supplementary information about the article

change history

Recommended Posts

Curry cheat sheet
SQLite3 cheat sheet
pyenv cheat sheet
Curry cheat sheet [Description example list version]
PIL / Pillow cheat sheet
Linux command cheat sheet
ps command cheat sheet
Spark API cheat sheet
Python3 cheat sheet (basic)
PySpark Cheat Sheet [Python]
Python sort cheat sheet
Go language cheat sheet
tox configuration file cheat sheet
numpy memory reuse cheat sheet
[Python3] Standard input [Cheat sheet]
Data Science Cheat Sheet (Python)
Slack API attachments cheat sheet
Python Django Tutorial Cheat Sheet
scikit learn algorithm cheat sheet
Apache Beam Cheat Sheet [Python]
Google Test / Mock personal cheat sheet
Continuation Passing Style (CPS) Cheat Sheet
Python cheat sheet (for C ++ experienced)
Python Computation Library Cheat Sheet ~ itertools ~
AtCoder cheat sheet in python (for myself)
Blender Python Mesh Data Access Cheat Sheet
Mathematical Optimization Modeler (PuLP) Cheat Sheet (Python)
A brief description of pandas (Cheat Sheet)
OpenFOAM post-processing cheat sheet (updated from time to time)
[Updating] Python Syntax cheat sheet for Java shop
Cheat sheet that does not cause an accident
Cheat sheet when scraping with Google Colaboratory (Colab)