fun longComputation(x: Int): Int {
return x * x // 🤡
}
fun parametricPredicate(x: Int, y: Int): Boolean {
val c = longComputation(x)
return y % c == 0
}
Kotlin
fun main() {
val aList = 1..100
val filteredList = aList.filter { y -> parametricPredicate(3, y) }
println(filteredList)
/* [9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99] */
}
Kotlin
fun longComputation(x: Int): Int {
return x * x // 🤡
}
fun parametricPredicate(x: Int, y: Int): Boolean {
val c = longComputation(x)
return y % c == 0
}
Kotlin
fun main() {
val aList = 1..100
val filteredList = aList.filter { y -> parametricPredicate(3, y) }
println(filteredList)
/* [9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99] */
}
Kotlin
Curryfication
$f: (A, B) \rightarrow C$
$f: A \rightarrow (B \rightarrow C)$
fun parametricPredicate(x: Int, y: Int): Boolean {
val c = longComputation(x)
return y % c == 0
}
Kotlin
fun main() {
val aList = 1..100
val predicate = { y -> parametricPredicate(3, y) }
println(aList.filter(predicate))
/* [9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99] */
}
Kotlin
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
Kotlin
fun main() {
val aList = 1..100
val predicate = parametricPredicate(3)
println(aList.filter(predicate))
/* [9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99] */
}
Kotlin
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
Kotlin
fun main() {
val aList = 1..100
val predicate = parametricPredicate(3)
println(aList.filter(predicate))
/* [9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99] */
}
Kotlin
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
Kotlin
fun main() {
val aList = 1..100
val predicate = parametricPredicate(3)
println(aList.filter(predicate))
/* [9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99] */
}
Kotlin
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
Kotlin
fun main() {
val aList = 1..100
val predicate = parametricPredicate(3)
println(aList.filter(predicate))
/* [9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99] */
}
Kotlin
Lisp 1.5
1958
John MacCarthy
Funarg Problem
fun longComputation(x: Int): Int {
return x * x
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
Kotlin
Les fonctions (récursives) décortiquées
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
Scheme
1975
Guy L. Steele Jr.
$x$
Variable
$\lambda x.\,M$
Abstraction
$M\,N$
Application
$\lambda x.\,(f\,x) \rightarrow f$
$\eta$-reduction
$\lambda x.\,M[x] \rightarrow \lambda y.\,M[y]$
$\alpha$-conversion
$(\lambda x.\,M)\:E \rightarrow M[x:=E]$
$\beta$-reduction
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
fun main() {
val c = 42
val predicate: (Int) -> Boolean = parametricPredicate(3)
if (predicate(81)) println("Ok") else println("Ko")
}
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
fun longComputation(x: Int): Int {
return x * x
}
Clojure
2007
Rich Hickey
$\lambda$-lifting
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
Kotlin
fun parametricPredicateLambda(c: Int, y: Int): Boolean = y % c == 0
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> parametricPredicateLambda(c, y) }
}
Kotlin
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
Kotlin
fun parametricPredicateLambda(c: Int, y: Int): Boolean = y % c == 0
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> parametricPredicateLambda(c, y) }
}
Kotlin
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> y % c == 0 }
}
Kotlin
fun parametricPredicateLambda(c: Int, y: Int): Boolean = y % c == 0
fun parametricPredicate(x: Int): (Int) -> Boolean {
val c = longComputation(x)
return { y -> parametricPredicateLambda(c, y) }
}
Kotlin
Closure conversion
data class Closure<C, I, O>(val capture: C, val code: (C, I) -> O)
Kotlin
data class Closure<C, I, O>(val capture: C, val code: (C, I) -> O)
Kotlin
data class Closure<C, I, O>(val capture: C, val code: (C, I) -> O)
Kotlin
data class Closure<C, I, O>(val capture: C, val code: (C, I) -> O)
Kotlin
fun parametricPredicate(x: Int): Closure<Int, Int, Boolean> {
val c = longComputation(x)
return Closure(c, ::parametricPredicateLambda)
}
fun main() {
val c = 42
val predicate: Closure<Int, Int, Boolean> = parametricPredicate(3)
if (predicate.code(predicate.capture, 81)) println("Ok") else println("Ko")
}
Kotlin
data class Closure<C, I, O>(val capture: C, val code: (C, I) -> O)
Kotlin
fun parametricPredicate(x: Int): Closure<Int, Int, Boolean> {
val c = longComputation(x)
return Closure(c, ::parametricPredicateLambda)
}
fun main() {
val c = 42
val predicate: Closure<Int, Int, Boolean> = parametricPredicate(3)
if (predicate.code(predicate.capture, 81)) println("Ok") else println("Ko")
}
Kotlin
data class Closure<C, I, O>(val capture: C, val code: (C, I) -> O)
Kotlin
fun parametricPredicate(x: Int): Closure<Int, Int, Boolean> {
val c = longComputation(x)
return Closure(c, ::parametricPredicateLambda)
}
fun main() {
val c = 42
val predicate: Closure<Int, Int, Boolean> = parametricPredicate(3)
if (predicate.code(predicate.capture, 81)) println("Ok") else println("Ko")
}
Kotlin
Java 8
2014
public static int longComputation(int x) {
return x * x;
}
public static IntPredicate parametricPredicate(int x) {
var c = longComputation(x);
return y -> y % c == 0;
}
void main() {
var aStream = IntStream.rangeClosed(0, 100);
var predicate = parametricPredicate(3);
IntStream filteredStream = aStream.filter(predicate);
System.out.println(
filteredStream.
mapToObj(Integer::toString).
collect(Collectors.joining(",", "[", "]")));
}
// [0,9,18,27,36,45,54,63,72,81,90,99]
Java
public static int longComputation(int x) {
return x * x;
}
public static IntPredicate parametricPredicate(int x) {
var c = longComputation(x);
return y -> y % c == 0;
}
void main() {
var aStream = IntStream.rangeClosed(0, 100);
var predicate = parametricPredicate(3);
IntStream filteredStream = aStream.filter(predicate);
System.out.println(
filteredStream.
mapToObj(Integer::toString).
collect(Collectors.joining(",", "[", "]")));
}
// [0,9,18,27,36,45,54,63,72,81,90,99]
Java
public static int longComputation(int x) {
return x * x;
}
public static IntPredicate parametricPredicate(int x) {
var c = longComputation(x);
return y -> y % c == 0;
}
void main() {
var aStream = IntStream.rangeClosed(0, 100);
var predicate = parametricPredicate(3);
IntStream filteredStream = aStream.filter(predicate);
System.out.println(
filteredStream.
mapToObj(Integer::toString).
collect(Collectors.joining(",", "[", "]")));
}
// [0,9,18,27,36,45,54,63,72,81,90,99]
Java
@FunctionalInterface
public interface IntPredicate {
boolean test(int value);
}
Java
@FunctionalInterface
public interface IntPredicate {
boolean test(int value);
}
Java
@FunctionalInterface
public interface IntPredicate {
boolean test(int value);
}
Java
public static boolean parametricPredicateLambda(int c, int y) { return y % c == 0; }
public static class Closure implements IntPredicate {
private final int c;
public Closure(int c) {
this.c = c;
}
@Override
public boolean test(int value) {
return parametricPredicateLambda(c, value);
}
}
Java
public static boolean parametricPredicateLambda(int c, int y) { return y % c == 0; }
public static class Closure implements IntPredicate {
private final int c;
public Closure(int c) {
this.c = c;
}
@Override
public boolean test(int value) {
return parametricPredicateLambda(c, value);
}
}
Java
public static boolean parametricPredicateLambda(int c, int y) { return y % c == 0; }
public static class Closure implements IntPredicate {
private final int c;
public Closure(int c) {
this.c = c;
}
@Override
public boolean test(int value) {
return parametricPredicateLambda(c, value);
}
}
Java
public static boolean parametricPredicateLambda(int c, int y) { return y % c == 0; }
public static class Closure implements IntPredicate {
private final int c;
public Closure(int c) {
this.c = c;
}
@Override
public boolean test(int value) {
return parametricPredicateLambda(c, value);
}
}
Java
public static boolean parametricPredicateLambda(int c, int y) { return y % c == 0; }
public static class Closure implements IntPredicate {
private final int c;
public Closure(int c) {
this.c = c;
}
@Override
public boolean test(int value) {
return parametricPredicateLambda(c, value);
}
}
Java
public static int longComputation(int x) {
return x * x;
}
public static IntPredicate parametricPredicate(int x) {
var c = longComputation(x);
return new Closure(c);
}
Java
var predicate = parametricPredicate(3);
predicate(81);
Java
public static int longComputation(int x) {
return x * x;
}
public static IntPredicate parametricPredicate(int x) {
var c = longComputation(x);
return new Closure(c);
}
Java
var predicate = parametricPredicate(3);
predicate(81);
predicate.test(81);