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 | lambda Anonymous 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 | => Orfunction Anonymous function using |
f(a)(a)・ ・ ・(a) |
|
Scala | => Anonymous function using |
f(a)(a)・ ・ ・(a) |
With currying method, static typing |
Perl | sub Anonymous subroutine using |
f(a)->(a)・ ・ ・->(a) |
$f->(a)・ ・ ・ May be |
Go language | func Anonymous function using |
f(a)(a)・ ・ ・(a) |
Static typing |
PHP | function Whenuse Anonymous function using |
f(a)(a)・ ・ ・(a) |
7.From 4fn When=> Anonymous function using |
Standard ML | Whitespace delimited | f a a ・ ・ ・ a |
|
Julia | -> Anonymous function using |
f(a)(a)・ ・ ・(a) |
|
Emacs Lisp | lambda Anonymous function by |
(funcall ・ ・ ・(funcall (f a) a)・ ・ ・ A) |
24.Enable lexical scope after 1 |
Common Lisp | lambda Anonymous function by |
(funcall ・ ・ ・(funcall (f a) a)・ ・ ・ A) |
|
R language | function Anonymous 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
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
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
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
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.
lambda
expression deprecation is still difficult even with currying.Recommended Posts