SlideShare a Scribd company logo
1 of 50
Tailrec Through
The Ages
Until Kotlin
1950 through to 2016
By João Esperancinha (2024/03/01)
Who am I?
Overview
Understanding the problems
Project objective
Target audience
Market trends
Cycle diagram
Introducing: Lorem ipsum
Spotlight on desktop
Spotlight on mobile
Spotlight on landscape view on mobile
Spotlight on wearables
Spotlight on tablet
Spotlight on landscape view on tablet
Spotlight on wearables
João Esperancinha
● Java
● Kotlin
● Groovy
● Scala
● Software Engineer 10+ years
● JESPROTECH owner for 1 year
● Kong Champion/Java Professional/Spring Professional
Project timeline
What is Tail
Recursivity?
Tail
What is tailrec?
● Recursivity
No, not just any
recursivity
Any Recursivity?
● Tail recursivity
● The last function call!
And then?
What defines a tail recursive function?
A recursive function is said to be tail recursive
when:
● The last function call is the call to the
recursive function
● The last function call doesn’t occur in
combination with any calculated value or
any other function call
● In other words nothing should be stored per
stack frame
Awesome!
When did Tailrec become a thing?
01 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur eleifend a diam
quis suscipit. Class aptent taciti sociosqu ad litora et nec torquent per conubia
nostra.
02 Amet, consectetur adipiscing elit. Curabitur eleifend a diam quis suscipit. Class
aptent taciti The ad litora torquent per conubia nostra.fd
03 Consectetur adipiscing elit. Curabitur eleifend lorem a diam quis suscipit. Class
aptent taciti sociosqu ad litora torquent ipsum per conubia nostra.
Late 1950’s computing studies showed that tail
recursive algorithms could be easily reimplemented
with iterative alternatives, making them more
efficient
No more usage of Stack Frames
No need to hold values in memory for every iteration
Tail Recursivity
Became a thing!
Space complexity reduced to O(1)
Recursivity
through the
years
The 1950’s
1957 - IBM Mathematical Formula Translating System, or
Fortran. Created by John Backus team
1959 - COBOL by CODASYL
(Conference/Committee on Data Systems Languages)
1958 - LISP by John McCarthy
By Jooja
CC BY-SA 4.0 DEED
By PIerre.Lescanne
CC BY-SA 4.0 DEED
John Backus
By WikiPedant
CC BY-SA 2.0 DEED
John McCarthy
By Jonathan Schilling
CC BY-SA 4.0 DEED
COBOL punch cards
The 1970’s to the 90’s
● 1983-84 - Standard ML(Meta Language) by Robin Milner,
Mads Tofte, and others at the University of Edinburgh
● 1975 - Scheme by Gerald Jay Sussman and Guy L. Steele Jr
● 1990 - Haskell named after Haskell
Curry and released by committee of
researchers and academics
● 1986 - Erlang by Joe Armstrong,
Robert Virding, and Mike Williams at
Ericsson
By Magnus Manske
CC BY-SA 1.0 DEED
Gerald Jay Sussman
By George Ruban
CC BY-SA 4.0 DEED
Guy L. Steele Jr
By Flavbeli
CC BY 2.0 DEED
University of Edinburgh
The 1990’s to 2016 - JVM Evolution
● 2007 Clojure by Rich Hickey
● 1995 - Java by Sun Microsystems,
however the invention of Java is attributed to James Gosling
and colleagues Mike Sheridan, and Patrick Naughton
● 2016 by the team led by Andrey
Breslav
● 2003 Scala by Martin Odersky
James Gosling
By Peter Campbell
CC BY-SA 4.0 DEED
Rich Hickey
By Tapestry Dude - Flickr
CC BY-SA 2.0 DEED
Martin Odersky
By LindaPoengPhotography
CC BY 3.0 DEED
By Lightbend, Inc.
CC BY 4.0 DEED
What was the whole point?
● Function Simplification
● Use recursivity without impacting performance
● Make code easy to read
● Avoid the usage of global variables
● Adhere to immutability principles
Much later on…
Pseudo-code
Example
A pseudo-code example
function fibonacci(n) = {
var result = 0
var next = 1
var i = 0
while (i < n) {
val temp = next
next = result + next
result = temp
i += 1
}
return result
}
Leonardo of Pisa
By Hans-Peter Postel
CC BY 2.5 DEED
Statue of Fibonacci (1863) by
Giovanni Paganucci in the
Camposanto di Pisa
Fibonacci Sequence
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 … etc
F(n) = F(n-1) + F(n-2)
Iterations
● Efficient 👍
● Difficult to Read 👎
O(n) time / O(1) space
By Romain
CC BY-SA 4.0 DEED
Graphical
representation
A pseudo-code example
function fibonacci(n) {
if (n <= 1) {
return n
} else {
return fibonacci(n - 1) + fibonacci(n - 2)
}
}
Fibonacci Sequence
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 … etc
F(n) = F(n-1) + F(n-2)
Recursivity
● Not very efficient 👎
● Easier to read 👍
O(2^n) time / O(2^n) space
function fibonacci(n) {
if (n <= 1) {
return n
} else {
return fibonacci(n - 1) + fibonacci(n - 2)
}
}
function fibonacci(n) {
if (n <= 1) {
return n
} else {
return fibonacci(n - 1) + fibonacci(n - 2)
}
}
function fibonacci(n) {
if (n <= 1) {
return n
} else {
return fibonacci(n - 1) + fibonacci(n - 2)
}
}
function fibonacci(n) {
if (n <= 1) {
return n
} else {
return fibonacci(n - 1) + fibonacci(n - 2)
}
}
function fibonacci(n) {
if (n <= 1) {
return n
} else {
return fibonacci(n - 1) + fibonacci(n - 2)
}
}
function fibonacci(n) {
if (n <= 1) {
return n
} else {
return fibonacci(n - 1) + fibonacci(n - 2)
}
}
(…) (…) (…) (…)
A pseudo-code example
Fibonacci Sequence
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 … etc
F(n) = F(n-1) + F(n-2)
Tail Recursivity
● Back to being efficient 👍
● Still easy to read, but less 👎
O(n) time / O(1) space
function fibonacci(n) {
function fiboHelper(n, result, next) {
if (n == 0) result
else return fiboHelper(n - 1, next, result + next)
}
return fiboHelper(n, 0, 1)
}
● Efficiency isn’t 100% guaranteed 👎
function fibonacci(n) {
function fiboHelper(n, result, next) {
if (n == 0) result
else return fiboHelper(n - 1, next, result + next)
}
return fiboHelper(n, 0, 1)
}
function fibonacci(n) {
function fiboHelper(n, result, next) {
if (n == 0) result
else return fiboHelper(n - 1, next, result + next)
}
return fiboHelper(n, 0, 1)
}
function fibonacci(n) {
function fiboHelper(n, result, next) {
if (n == 0) result
else return fiboHelper(n - 1, next, result + next)
}
return fiboHelper(n, 0, 1)
}
function fibonacci(n) {
function fiboHelper(n, result, next) {
if (n == 0) result
else return fiboHelper(n - 1, next, result + next)
}
return fiboHelper(n, 0, 1)
}
function fibonacci(n) {
function fiboHelper(n, result, next) {
if (n == 0) result
else return fiboHelper(n - 1, next, result + next)
}
return fiboHelper(n, 0, 1)
}
function fibonacci(n) {
function fiboHelper(n, result, next) {
if (n == 0) result
else return fiboHelper(n - 1, next, result + next)
}
return fiboHelper(n, 0, 1)
}
(…)
Applying TCO
Tail Call Optimization
function fibonacci(n) {
function fiboHelper(n, result, next) {
if (n == 0) next
else return fiboHelper(n - 1, next, result + next)
}
return fiboHelper(n, 0, 1)
}
function fibonacci(n) {
function fiboHelper(n) = {
var result = 0
var next = 1
var i = 0
while (i < n) {
val temp = next
next = result + next
result = temp
i += 1
}
return result
}
}
How we implement…
… how we would have implemented in the result
Fortran
Example
The Beginnings with Fortran - 1957
● Fortran I: 1957
● Fortran II: 1958
● Fortran III: Not released
● Fortran IV: 1962
● Fortran 66: 1966
● Fortran 77: 1977
● Fortran 90: 1991
● Fortran 95: 1997
● Fortran 2003: 2004
● Fortran 2008: 2010
● Fortran 2018: 2018
PROGRAM FIBONACCI
INTEGER N, I
REAL F1, F2, FIB
N = 100
F1 = 0
F2 = 1
DO I = 2, N
FIB = F1 + F2
F1 = F2
F2 = FIB
END DO
WRITE(*,*) FIB
END
PROGRAM RECURSIVE_FIBONACCI_REAL
INTEGER N
N = 100
DO I = 0, N - 1
CALL fibonacci_real(I, Result)
END DO
WRITE(*, *) Result
CONTAINS
RECURSIVE SUBROUTINE fibonacci_real(N, Result)
INTEGER N
REAL Result
IF (N <= 1) THEN
Result = REAL(N)
ELSE
CALL fibonacci_real(N - 1, Result1)
CALL fibonacci_real(N - 2, Result2)
Result = Result1 + Result2
END IF
END SUBROUTINE fibonacci_real
END
Recursivity
Fortran nowadays (since 1991)
program Fibonacci
implicit none
integer :: n, i
real :: fib_prev, fib_current, result
n = 100
fib_prev = 0
fib_current = 1
do i = 1, n
if (i <= 1) then
result = i
else
result = fib_prev + fib_current
fib_prev = fib_current
fib_current = result
end if
end do
print *, "The result is", result
end program Fibonacci
program FibonacciTailRecursive
implicit none
integer :: n, i
real :: result
n = 100
result = fibonacci(n)
print *, "The result is", result
contains
recursive function fibonacci(n) result(fib)
integer, intent(in) :: n
integer :: fib
if (n == 0) then
fib = 0
else if (n == 1) then
fib = 1
else
fib = fibonacci(n - 1) + fibonacci(n - 2)
end if
end function fibonacci
end program FibonacciTailRecursive
program FibonacciTailRecursive
implicit none
integer :: n
real :: result
n = 100
result = fibonacci(n)
print *, "The result is", result
contains
recursive function fibonacci(n) result(fib)
integer, intent(in) :: n
real :: fib
if (n <= 1) then
fib = n
else
fib = fibonacci_helper(n, 0.0, 1.0)
end if
end function fibonacci
recursive function fibonacci_helper(n, a, b) result(fib)
integer, intent(in) :: n
real :: fib, a, b
if (n == 0) then
fib = a
else if (n == 1) then
fib = b
else
fib = fibonacci_helper(n - 1, b, a + b)
end if
end function fibonacci_helper
end program FibonacciTailRecursive
Lisp
Example
LISP 1958
(defun fibonacci-iterative (n)
(if (<= n 1)
n
(fib-iter 0 1 n)))
(defun fib-iter (a b count)
(loop repeat (- count 1)
do (setf (values a b) (values b (+ a b)))
finally (return b)))
(defun fibonacci-recursive (n)
(if (<= n 1)
n
(+ (fibonacci-recursive (- n 1))
(fibonacci-recursive (- n 2)))))
● Lisp: 1958
● Lisp 1.5: 1962
● MacLisp: Late 1960s
● InterLisp: 1966
● Common Lisp: 1984
(defun fibonacci-tail-recursive (n)
(if (<= n 1)
n
(fib-tail-recursive 0 1 n)))
(defun fib-tail-recursive (a b count)
(if (= count 0)
a
(fib-tail-recursive b (+ a b) (- count 1))))
COBOL
Example
COBOL 1959
IDENTIFICATION DIVISION.
PROGRAM-ID. Fibonacci.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 F1 PIC 9(21)V9(1) VALUE 0.0.
01 F2 PIC 9(21)V9(1) VALUE 1.0.
01 FIB PIC 9(21)V9(1).
01 N PIC 9(5) VALUE 100.
01 I PIC 9(5) VALUE 3.
PROCEDURE DIVISION.
MAIN-LOGIC.
PERFORM VARYING I FROM 2 BY 1 UNTIL I
> N
COMPUTE FIB = F1 + F2
COMPUTE F1 = F2
COMPUTE F2 = FIB
END-PERFORM.
DISPLAY FIB.
STOP RUN.
IDENTIFICATION DIVISION.
PROGRAM-ID. FibonacciRecursive.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 F1 PIC 9(21)V9(1) VALUE 0.0.
01 F2 PIC 9(21)V9(1) VALUE 1.0.
01 FIB PIC 9(21)V9(1).
01 N PIC 9(5) VALUE 100.
01 I PIC 9(5) VALUE 0.
PROCEDURE DIVISION.
MOVE N TO I
CALL 'FIBONACCI'.
DISPLAY "Fibonacci of " I " is " F1.
STOP RUN.
ENTRY 'FIBONACCI'.
IF N = 0 THEN
EXIT PROGRAM
ELSE
COMPUTE FIB = F1 + F2
COMPUTE F1 = F2
COMPUTE F2 = FIB
SUBTRACT 1 FROM N
CALL 'FIBONACCI'
END-IF.
● COBOL 60 - 1960.
● COBOL 61 - 1961.
● COBOL 65 - 1965.
● COBOL 68 - 1968
● COBOL 74 - 1974
● COBOL 85 - 1985
● COBOL 2002 - 2002
● COBOL 2014 - 2014
Recursivity
Scheme
Example
Scheme - 1975
(define (fibonacci n)
(fibonacci-iter n 0 1))
(define (fibonacci-iter n a b)
(do ((i n (- i 1))
(x a b)
(y b (+ a b)))
((= i 0) x)
(set! a x)
(set! b y)))
(define (fibonacci n)
(if (or (= n 0) (= n 1))
n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
(display (fibonacci 100))
● Scheme 75: 1975
● Scheme 84: 1984
● Several follow up
releases until 2013
(define (fibonacci n)
(define (fib-helper n a b)
(if (= n 0)
a
(fib-helper (- n 1) b (+ a b))))
(fib-helper n 0 1))
(display (fibonacci 100))
SML
Example
Standard Meta Language - 1983/84
● Moby: Moby - 1980’s
● SML/NJ - 1983/1984
● MLton - 1999
● SML '90 - 1990
● SML '97 - 1997
● SML 2007 - 2007
● SML 2022 - 2022
fun fibonacci n =
if n < 2 then n
else fibonacci (n - 1) + fibonacci (n - 2);
structure IntInf = IntInf
fun fibonacci n =
let
fun fibIter n a b =
if n = 0 then
a
else
fibIter (n - 1) b (IntInf.+(a, b))
in
fibIter n 0 1
end;
Erlang
Example
Erlang - 1986
● Erlang 1986 - First
proprietary release
● Erlang/OTP R1
(1996) - First
commercial release
● Erlang/OTP 24 -
Erlang until 2021
-module(fibonacci_recursive).
-export([fib/1]).
fib(0) -> 0;
fib(1) -> 1;
fib(N) when N > 1 ->
fib(N - 1) + fib(N - 2).
-module(fibonacci_recursive_tco).
-export([fib/1]).
fib(N) when N < 2 ->
N;
fib(N) ->
fib_iter(N, 0, 1).
fib_iter(0, A, _) ->
A;
fib_iter(N, A, B) ->
fib_iter(N - 1, B, A + B).
Haskell
Example
Haskell - 1990
● First draft - 1987
● Haskell 1.0 - 1990
● Haskell 1.1 - 1991
● Haskell 1.2 - 1992
● Haskell 1.3 - 1996
● Haskell 1.4 - 1997
● Haskell 98 - 1998
● Haskell 2010 - 2010
● Haskell 2022 - 2022
fibonacci :: Integer -> Integer
fibonacci 0 = 0
fibonacci 1 = 1
fibonacci n = fibonacci (n - 1) + fibonacci (n -
2)
main :: IO ()
main = do
let result = fibonacci 1000
putStrLn $ "Fibonacci of the order of 1000:
" ++ show result
fibonacciTailRec :: Integer -> Integer
fibonacciTailRec n = fibonacciHelper n 0 1
where
fibonacciHelper 0 a _ = a
fibonacciHelper 1 _ b = b
fibonacciHelper n a b = fibonacciHelper
(n - 1) b (a + b)
main :: IO ()
main = do
let result = fibonacciTailRec 1000
putStrLn $ "Fibonacci of the order of
1000: " ++ show result
Java
Example
About Java - 1995
Java deliberately doesn’t support Tail Call Optimization because:
● Backward compatibility
● It might not go well with the JVM architecture because of overhead and potential side-effects.
● Performance and complexity
● The iterative alternative is always possible
● Not very clear if TCO is the best idea for Java
But this didn’t stop JVM alternative
languages to explore TCO possibilities...
Scala
Example
Scala - 2003
● Scala 1.0 - 2003
● Scala 2.0 - 2006
● Scala 2.7 - 2009
● Scala 2.8 - 2010
● Scala 2.9 - 2011
● Scala 2.10 - 2012
● Scala 2.11 - 2014
● Scala 2.12 - 2016
● Scala 2.13 - 2019
● Scala 3 (previously
known as Dotty) -
2020
def fibonacciIterative(n: Double): Double = {
var a = 0f
var b = 1f
var i = 0f
while (i < n) {
val temp = b
b = a + b
a = temp
i += 1
}
a
}
def fibonacciRecursive(n: Double): Double = {
if (n <= 1f) {
n
} else {
fibonacciRecursive(n - 1f) + fibonacciRecursive(n - 2f)
}
}
def fibonacciTailRec(n: Double): Double = {
def fibHelper(n: Double, a: Double, b:
Double): Double = {
if (n == 0.0) a
else fibHelper(n - 1.0, b, a + b)
}
fibHelper(n, 0.0, 1.0)
}
Scala - 2003
● Scala 1.0 - 2003
● Scala 2.0 - 2006
● Scala 2.7 - 2009
● Scala 2.8 - 2010
● Scala 2.9 - 2011
● Scala 2.10 - 2012
● Scala 2.11 - 2014
● Scala 2.12 - 2016
● Scala 2.13 - 2019
● Scala 3 (previously
known as Dotty) -
2020
def fibonacciTailRecTCO(n: Double): Double
= {
@annotation.tailrec
def fibHelper(n: Double, a: Double, b:
Double): Double = {
if (n == 0f) a
else fibHelper(n - 1f, b, a + b)
}
fibHelper(n, 0f, 1f)
}
def fibonacciTailRecManualTCO(n: Double):
Double = {
def fibHelper(n: Double, a: Double, b:
Double): Double = {
var a = 0f
var b = 1f
var i = 0f
while (i < n) {
val temp = b
b = a + b
a = temp
i += 1
}
a
if (n == 0.0) a
else fibHelper(n - 1.0, b, a + b)
}
fibHelper(n, 0.0, 1.0)
}
Scala - 2003
def fibonacciTailRecTCO(n: Double): Double = {
@annotation.tailrec
def fibHelper(n: Double, a: Double, b: Double): Double =
{
if (n == 0f) a
else fibHelper(n - 1f, b, a + b)
}
fibHelper(n, 0f, 1f)
}
def factorialUnMarked(n: Double): Double = {
def factorialHelper(n: Double): Double = {
if (n <= 1f) 1f
else n * factorialHelper(n - 1f)
}
factorialHelper(n)
}
public static double factorialUnMarked(double var0) {
return Fibonacci$.MODULE$.factorialUnMarked(var0);
}
public double factorialUnMarked(final double n) {
return this.factorialHelper$1(n);
}
private final double factorialHelper$1(final double n) {
return n <= 1.0 ? 1.0 : n * this.factorialHelper$1(n - 1.0);
}
public static double fibonacciTailRecTCO(double var0) {
return Fibonacci$.MODULE$.fibonacciTailRecTCO(var0);
}
public double fibonacciTailRecTCO(final double n) {
return this.fibHelper$3(n, 0.0, 1.0);
}
private final double fibHelper$3(final double n, final double a, final
double b) {
while(n != 0.0) {
double var7 = n - 1.0;
double var11 = a + b;
n = var7;
a = b;
b = var11;
}
return a;
}
Clojure
Example
Clojure - 2007
(defn fibonacci-iterative [n]
(if (<= n 1)
n
(loop [a 0
b 1
i 1]
(if (= i n)
(+ a b)
(recur b (+ a b) (inc i))))))
(defn fibonacci-recursive [n]
(let [n (if (instance? String n)
(Double/parseDouble n)
n)]
(if (<= n 1.0)
n
(+ (fibonacci-recursive (- n 1.0)) (fibonacci-recursive (- n 2.0))))))
(defn fibonacci-tail-rec [n]
(let [n (if (instance? String n)
(Double/parseDouble n)
n)]
(letfn [(fib-tail [n a b]
(if (zero? n)
a
(fib-tail (dec n) b (+ a b))))]
(fib-tail n 0.0 1.0))))
● First version - 2007
● Clojure 1.0 - 2009
● Clojure until 1.11.1 in
2022
Clojure - 2007
● First version - 2007
● Clojure 1.0 - 2009
● Clojure until 1.11.1 in
2022
(defn fibonacci-tail-rec-tco [n]
(let [n (if (instance? String n)
(Double/parseDouble n)
n)]
(letfn [(fib [n a b]
(if (zero? n)
a
(recur (dec n) b (+ a b))))]
(fib n 0.0 1.0))))
Kotlin
Example
Kotlin - 2016
● Kotlin 1.0 - 2016
● Kotlin 1.1 - 2017
● Kotlin 1.2 - 2017
● Kotlin 1.3 - 2018
● Kotlin 1.4 - 2020
● Kotlin 1.5 - 2021
● Kotlin 1.6 - 2021
● Kotlin 1.7 - 2022
● Kotlin 1.8 - 2023
● Kotlin 1.9 - 2023
private fun fibonacciIterative(n: Int): Double
{
if (n <= 1) {
return n.toDouble()
}
var a = 0.0
var b = 1.0
for (i in 2..n) {
val temp = a + b
a = b
b = temp
}
return b
}
fun fibonacciRecursive(n: Int): Double =
if (n <= 1) n.toDouble()
else
fibonacciRecursive(n - 1) +
fibonacciRecursive(n - 2)
private fun fibonacciTailRecursive(
n: Int,
a: Double = 0.0,
b: Double = 1.0
): Double = if (n == 0) a
else fibonacciTailRecursive(n - 1, b, a + b)
Kotlin - 2016
private tailrec fun fibonacciTailRecursiveTCO(
n: Int,
a: Double = 0.0,
b: Double = 1.0
): Double = if (n == 0) a
else fibonacciTailRecursiveTCO(n - 1, b, a + b)
● Kotlin 1.0 - 2016
● Kotlin 1.1 - 2017
● Kotlin 1.2 - 2017
● Kotlin 1.3 - 2018
● Kotlin 1.4 - 2020
● Kotlin 1.5 - 2021
● Kotlin 1.6 - 2021
● Kotlin 1.7 - 2022
● Kotlin 1.8 - 2023
● Kotlin 1.9 - 2023
Kotlin - 2016
private tailrec fun fibonacciTailRecursiveTCO(
n: Int,
a: Double = 0.0,
b: Double = 1.0
): Double = if (n == 0) a
else fibonacciTailRecursiveTCO(n - 1, b, a + b)
private fun fibonacciTailRecursive(
n: Int,
a: Double = 0.0,
b: Double = 1.0
): Double = if (n == 0) a
else fibonacciTailRecursive(n - 1, b, a + b)
private final double fibonacciTailRecursive(int n, double a, double b) {
return n == 0 ? a : ((Companion)this).fibonacciTailRecursive(n - 1, b, a + b);
}
// $FF: synthetic method
static double fibonacciTailRecursive$default(Companion var0, int var1,
double var2, double var4, int var6, Object var7) {
if ((var6 & 2) != 0) {
var2 = 0.0;
}
if ((var6 & 4) != 0) {
var4 = 1.0;
}
return var0.fibonacciTailRecursive(var1, var2, var4);
}
private final double fibonacciTailRecursiveTCO(int n, double a, double b) {
while(n != 0) {
Companion var10000 = (Companion)this;
int var10001 = n - 1;
double var10002 = b;
b += a;
a = var10002;
n = var10001;
}
return a;
}
// $FF: synthetic method
static double fibonacciTailRecursiveTCO$default(Companion var0, int var1,
double var2, double var4, int var6, Object var7) {
if ((var6 & 2) != 0) {
var2 = 0.0;
}
if ((var6 & 4) != 0) {
var4 = 1.0;
}
return var0.fibonacciTailRecursiveTCO(var1, var2, var4);
}
Conclusion
Conclusions
● Which direction is this all taking?
● Is programming still a challenge?
● Why do we do software development?
● Are we being forced into thinking recursively?
● Is Mutability something to be completely removed from a programming language?
● Productivity vs The Joy of Coding
● What happens when we keep thinking only recursively when implementing algorithms?
● Can we blindly rely on the TCO algorithms in the way that we already trust Garbage Collection?
● Do we trust Garbage Collection?
● Can we manually implement a better algorithm with better performance than TCO?
● Would we still be able to do it, if we don’t practice?
● Can we still produce without challenges in the long run?
Questions?
Resources for this presentation
Image sources
● https://commons.wikimedia.org/wiki/File:John_McCarthy_Stanford.jpg
● https://commons.wikimedia.org/wiki/File:John_Backus_2.jpg
● https://commons.wikimedia.org/wiki/File:Guy_Steele.jpg
● https://commons.wikimedia.org/wiki/File:Jerry_Sussman.jpg
● https://nl.wikipedia.org/wiki/Rij_van_Fibonacci#/media/Bestand:Fibonacci_Spiral.svg
● https://en.wikipedia.org/wiki/File:Fortran_logo.svg
● https://en.m.wikipedia.org/wiki/File:Lisp_logo.svg
● https://commons.wikimedia.org/wiki/File:IBM_keypunch_deck_for_Cobol_student_program_at_New_York_Universi
ty_1979.jpg
● https://commons.wikimedia.org/wiki/File:Lambda_lc.svg
● https://commons.wikimedia.org/wiki/File:Informatics_Forum_Atrium_turned.jpg
● https://commons.wikimedia.org/wiki/File:Ericsson_logo.svg
● https://commons.wikimedia.org/wiki/File:Erlang_logo.png
● https://en.wikipedia.org/wiki/File:Haskell-Logo.svg
● https://commons.wikimedia.org/wiki/File:James_Gosling_2008.jpg
● https://commons.wikimedia.org/wiki/File:Mark_Odersky_photo_by_Linda_Poeng.jpg
● https://commons.wikimedia.org/wiki/File:Scala-full-color.svg
● https://en.m.wikipedia.org/wiki/File:Clojure_logo.svg
● https://commons.wikimedia.org/wiki/File:Kotlin_logo_2021.svg
Resources for this presentation
● https://www.smlnj.org/sml.html
● https://en.wikibooks.org/wiki/Standard_ML_Programming/Types
● https://en.wikipedia.org/wiki/Standard_ML
● https://www.smlnj.org/
● https://www.scala-lang.org/
● https://kotlinlang.org/
● https://en.wikipedia.org/wiki/COBOL
● https://fortran-lang.org/
● https://www.java.com/en/
● https://developer.ibm.com/languages/cobol/
● https://www.haskell.org/
● https://www.erlang.org/
● https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gfortran/Code-Gen-Options.html
Data sources
Thank you!

More Related Content

Similar to Exploring Tailrec Through Time Until Kotlin.pptx

Functional IO and Effects
Functional IO and EffectsFunctional IO and Effects
Functional IO and EffectsDylan Forciea
 
lecture4-recursion.pptx
lecture4-recursion.pptxlecture4-recursion.pptx
lecture4-recursion.pptxLizhen Shi
 
Class 18: Measuring Cost
Class 18: Measuring CostClass 18: Measuring Cost
Class 18: Measuring CostDavid Evans
 
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015Codemotion
 
Line Search Techniques by Fibonacci Search
Line Search Techniques by Fibonacci SearchLine Search Techniques by Fibonacci Search
Line Search Techniques by Fibonacci Searchinventionjournals
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologiesit-people
 
Introduction to Python Programming | InsideAIML
Introduction to Python Programming | InsideAIMLIntroduction to Python Programming | InsideAIML
Introduction to Python Programming | InsideAIMLVijaySharma802
 
Drinking the free kool-aid
Drinking the free kool-aidDrinking the free kool-aid
Drinking the free kool-aidDavid Hoyt
 
Functional Programming You Already Know
Functional Programming You Already KnowFunctional Programming You Already Know
Functional Programming You Already KnowKevlin Henney
 
Concept of scoping in programming languages
Concept of scoping in programming languagesConcept of scoping in programming languages
Concept of scoping in programming languagesMd. Jafar Sadik
 
orders of_growth
orders of_growthorders of_growth
orders of_growthRajendran
 
Introduction to Python Programming
Introduction to Python ProgrammingIntroduction to Python Programming
Introduction to Python ProgrammingVijaySharma802
 
02 functions, variables, basic input and output of c++
02   functions, variables, basic input and output of c++02   functions, variables, basic input and output of c++
02 functions, variables, basic input and output of c++Manzoor ALam
 
Efficient Hill Climber for Multi-Objective Pseudo-Boolean Optimization
Efficient Hill Climber for Multi-Objective Pseudo-Boolean OptimizationEfficient Hill Climber for Multi-Objective Pseudo-Boolean Optimization
Efficient Hill Climber for Multi-Objective Pseudo-Boolean Optimizationjfrchicanog
 

Similar to Exploring Tailrec Through Time Until Kotlin.pptx (20)

Functional IO and Effects
Functional IO and EffectsFunctional IO and Effects
Functional IO and Effects
 
lecture4-recursion.pptx
lecture4-recursion.pptxlecture4-recursion.pptx
lecture4-recursion.pptx
 
Sync considered unethical
Sync considered unethicalSync considered unethical
Sync considered unethical
 
Class 18: Measuring Cost
Class 18: Measuring CostClass 18: Measuring Cost
Class 18: Measuring Cost
 
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
 
Recursion
RecursionRecursion
Recursion
 
Functional go
Functional goFunctional go
Functional go
 
Line Search Techniques by Fibonacci Search
Line Search Techniques by Fibonacci SearchLine Search Techniques by Fibonacci Search
Line Search Techniques by Fibonacci Search
 
6-Python-Recursion.pdf
6-Python-Recursion.pdf6-Python-Recursion.pdf
6-Python-Recursion.pdf
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
 
Chapter 02 functions -class xii
Chapter 02   functions -class xiiChapter 02   functions -class xii
Chapter 02 functions -class xii
 
Introduction to Python Programming | InsideAIML
Introduction to Python Programming | InsideAIMLIntroduction to Python Programming | InsideAIML
Introduction to Python Programming | InsideAIML
 
Drinking the free kool-aid
Drinking the free kool-aidDrinking the free kool-aid
Drinking the free kool-aid
 
Functional Programming You Already Know
Functional Programming You Already KnowFunctional Programming You Already Know
Functional Programming You Already Know
 
Concept of scoping in programming languages
Concept of scoping in programming languagesConcept of scoping in programming languages
Concept of scoping in programming languages
 
orders of_growth
orders of_growthorders of_growth
orders of_growth
 
Introduction to Python Programming
Introduction to Python ProgrammingIntroduction to Python Programming
Introduction to Python Programming
 
02 functions, variables, basic input and output of c++
02   functions, variables, basic input and output of c++02   functions, variables, basic input and output of c++
02 functions, variables, basic input and output of c++
 
Efficient Hill Climber for Multi-Objective Pseudo-Boolean Optimization
Efficient Hill Climber for Multi-Objective Pseudo-Boolean OptimizationEfficient Hill Climber for Multi-Objective Pseudo-Boolean Optimization
Efficient Hill Climber for Multi-Objective Pseudo-Boolean Optimization
 
functions
functionsfunctions
functions
 

More from João Esperancinha

Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxJoão Esperancinha
 
Kuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialKuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialJoão Esperancinha
 
Fields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptxFields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptxJoão Esperancinha
 
Demystifying Co, Contra, In Kotlin modifier keywords.pptx
Demystifying Co, Contra, In Kotlin modifier keywords.pptxDemystifying Co, Contra, In Kotlin modifier keywords.pptx
Demystifying Co, Contra, In Kotlin modifier keywords.pptxJoão Esperancinha
 
Unlocking the Power of Kotlin Channels.pptx
Unlocking the Power of Kotlin Channels.pptxUnlocking the Power of Kotlin Channels.pptx
Unlocking the Power of Kotlin Channels.pptxJoão Esperancinha
 
Reactive programming with Spring Webflux.pptx
Reactive programming with Spring Webflux.pptxReactive programming with Spring Webflux.pptx
Reactive programming with Spring Webflux.pptxJoão Esperancinha
 
KONNECT Kong-Presentation How to protect web applications
KONNECT Kong-Presentation How to protect web applicationsKONNECT Kong-Presentation How to protect web applications
KONNECT Kong-Presentation How to protect web applicationsJoão Esperancinha
 

More from João Esperancinha (7)

Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
 
Kuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialKuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorial
 
Fields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptxFields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptx
 
Demystifying Co, Contra, In Kotlin modifier keywords.pptx
Demystifying Co, Contra, In Kotlin modifier keywords.pptxDemystifying Co, Contra, In Kotlin modifier keywords.pptx
Demystifying Co, Contra, In Kotlin modifier keywords.pptx
 
Unlocking the Power of Kotlin Channels.pptx
Unlocking the Power of Kotlin Channels.pptxUnlocking the Power of Kotlin Channels.pptx
Unlocking the Power of Kotlin Channels.pptx
 
Reactive programming with Spring Webflux.pptx
Reactive programming with Spring Webflux.pptxReactive programming with Spring Webflux.pptx
Reactive programming with Spring Webflux.pptx
 
KONNECT Kong-Presentation How to protect web applications
KONNECT Kong-Presentation How to protect web applicationsKONNECT Kong-Presentation How to protect web applications
KONNECT Kong-Presentation How to protect web applications
 

Recently uploaded

"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 

Recently uploaded (20)

"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 

Exploring Tailrec Through Time Until Kotlin.pptx

  • 1. Tailrec Through The Ages Until Kotlin 1950 through to 2016 By João Esperancinha (2024/03/01)
  • 2. Who am I? Overview Understanding the problems Project objective Target audience Market trends Cycle diagram Introducing: Lorem ipsum Spotlight on desktop Spotlight on mobile Spotlight on landscape view on mobile Spotlight on wearables Spotlight on tablet Spotlight on landscape view on tablet Spotlight on wearables João Esperancinha ● Java ● Kotlin ● Groovy ● Scala ● Software Engineer 10+ years ● JESPROTECH owner for 1 year ● Kong Champion/Java Professional/Spring Professional Project timeline
  • 4. What is tailrec? ● Recursivity No, not just any recursivity Any Recursivity? ● Tail recursivity ● The last function call! And then?
  • 5. What defines a tail recursive function? A recursive function is said to be tail recursive when: ● The last function call is the call to the recursive function ● The last function call doesn’t occur in combination with any calculated value or any other function call ● In other words nothing should be stored per stack frame Awesome!
  • 6. When did Tailrec become a thing? 01 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur eleifend a diam quis suscipit. Class aptent taciti sociosqu ad litora et nec torquent per conubia nostra. 02 Amet, consectetur adipiscing elit. Curabitur eleifend a diam quis suscipit. Class aptent taciti The ad litora torquent per conubia nostra.fd 03 Consectetur adipiscing elit. Curabitur eleifend lorem a diam quis suscipit. Class aptent taciti sociosqu ad litora torquent ipsum per conubia nostra. Late 1950’s computing studies showed that tail recursive algorithms could be easily reimplemented with iterative alternatives, making them more efficient No more usage of Stack Frames No need to hold values in memory for every iteration Tail Recursivity Became a thing! Space complexity reduced to O(1)
  • 8. The 1950’s 1957 - IBM Mathematical Formula Translating System, or Fortran. Created by John Backus team 1959 - COBOL by CODASYL (Conference/Committee on Data Systems Languages) 1958 - LISP by John McCarthy By Jooja CC BY-SA 4.0 DEED By PIerre.Lescanne CC BY-SA 4.0 DEED John Backus By WikiPedant CC BY-SA 2.0 DEED John McCarthy By Jonathan Schilling CC BY-SA 4.0 DEED COBOL punch cards
  • 9. The 1970’s to the 90’s ● 1983-84 - Standard ML(Meta Language) by Robin Milner, Mads Tofte, and others at the University of Edinburgh ● 1975 - Scheme by Gerald Jay Sussman and Guy L. Steele Jr ● 1990 - Haskell named after Haskell Curry and released by committee of researchers and academics ● 1986 - Erlang by Joe Armstrong, Robert Virding, and Mike Williams at Ericsson By Magnus Manske CC BY-SA 1.0 DEED Gerald Jay Sussman By George Ruban CC BY-SA 4.0 DEED Guy L. Steele Jr By Flavbeli CC BY 2.0 DEED University of Edinburgh
  • 10. The 1990’s to 2016 - JVM Evolution ● 2007 Clojure by Rich Hickey ● 1995 - Java by Sun Microsystems, however the invention of Java is attributed to James Gosling and colleagues Mike Sheridan, and Patrick Naughton ● 2016 by the team led by Andrey Breslav ● 2003 Scala by Martin Odersky James Gosling By Peter Campbell CC BY-SA 4.0 DEED Rich Hickey By Tapestry Dude - Flickr CC BY-SA 2.0 DEED Martin Odersky By LindaPoengPhotography CC BY 3.0 DEED By Lightbend, Inc. CC BY 4.0 DEED
  • 11. What was the whole point? ● Function Simplification ● Use recursivity without impacting performance ● Make code easy to read ● Avoid the usage of global variables ● Adhere to immutability principles Much later on…
  • 13. A pseudo-code example function fibonacci(n) = { var result = 0 var next = 1 var i = 0 while (i < n) { val temp = next next = result + next result = temp i += 1 } return result } Leonardo of Pisa By Hans-Peter Postel CC BY 2.5 DEED Statue of Fibonacci (1863) by Giovanni Paganucci in the Camposanto di Pisa Fibonacci Sequence 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 … etc F(n) = F(n-1) + F(n-2) Iterations ● Efficient 👍 ● Difficult to Read 👎 O(n) time / O(1) space By Romain CC BY-SA 4.0 DEED Graphical representation
  • 14. A pseudo-code example function fibonacci(n) { if (n <= 1) { return n } else { return fibonacci(n - 1) + fibonacci(n - 2) } } Fibonacci Sequence 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 … etc F(n) = F(n-1) + F(n-2) Recursivity ● Not very efficient 👎 ● Easier to read 👍 O(2^n) time / O(2^n) space function fibonacci(n) { if (n <= 1) { return n } else { return fibonacci(n - 1) + fibonacci(n - 2) } } function fibonacci(n) { if (n <= 1) { return n } else { return fibonacci(n - 1) + fibonacci(n - 2) } } function fibonacci(n) { if (n <= 1) { return n } else { return fibonacci(n - 1) + fibonacci(n - 2) } } function fibonacci(n) { if (n <= 1) { return n } else { return fibonacci(n - 1) + fibonacci(n - 2) } } function fibonacci(n) { if (n <= 1) { return n } else { return fibonacci(n - 1) + fibonacci(n - 2) } } function fibonacci(n) { if (n <= 1) { return n } else { return fibonacci(n - 1) + fibonacci(n - 2) } } (…) (…) (…) (…)
  • 15. A pseudo-code example Fibonacci Sequence 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 … etc F(n) = F(n-1) + F(n-2) Tail Recursivity ● Back to being efficient 👍 ● Still easy to read, but less 👎 O(n) time / O(1) space function fibonacci(n) { function fiboHelper(n, result, next) { if (n == 0) result else return fiboHelper(n - 1, next, result + next) } return fiboHelper(n, 0, 1) } ● Efficiency isn’t 100% guaranteed 👎 function fibonacci(n) { function fiboHelper(n, result, next) { if (n == 0) result else return fiboHelper(n - 1, next, result + next) } return fiboHelper(n, 0, 1) } function fibonacci(n) { function fiboHelper(n, result, next) { if (n == 0) result else return fiboHelper(n - 1, next, result + next) } return fiboHelper(n, 0, 1) } function fibonacci(n) { function fiboHelper(n, result, next) { if (n == 0) result else return fiboHelper(n - 1, next, result + next) } return fiboHelper(n, 0, 1) } function fibonacci(n) { function fiboHelper(n, result, next) { if (n == 0) result else return fiboHelper(n - 1, next, result + next) } return fiboHelper(n, 0, 1) } function fibonacci(n) { function fiboHelper(n, result, next) { if (n == 0) result else return fiboHelper(n - 1, next, result + next) } return fiboHelper(n, 0, 1) } function fibonacci(n) { function fiboHelper(n, result, next) { if (n == 0) result else return fiboHelper(n - 1, next, result + next) } return fiboHelper(n, 0, 1) } (…)
  • 16. Applying TCO Tail Call Optimization function fibonacci(n) { function fiboHelper(n, result, next) { if (n == 0) next else return fiboHelper(n - 1, next, result + next) } return fiboHelper(n, 0, 1) } function fibonacci(n) { function fiboHelper(n) = { var result = 0 var next = 1 var i = 0 while (i < n) { val temp = next next = result + next result = temp i += 1 } return result } } How we implement… … how we would have implemented in the result
  • 18. The Beginnings with Fortran - 1957 ● Fortran I: 1957 ● Fortran II: 1958 ● Fortran III: Not released ● Fortran IV: 1962 ● Fortran 66: 1966 ● Fortran 77: 1977 ● Fortran 90: 1991 ● Fortran 95: 1997 ● Fortran 2003: 2004 ● Fortran 2008: 2010 ● Fortran 2018: 2018 PROGRAM FIBONACCI INTEGER N, I REAL F1, F2, FIB N = 100 F1 = 0 F2 = 1 DO I = 2, N FIB = F1 + F2 F1 = F2 F2 = FIB END DO WRITE(*,*) FIB END PROGRAM RECURSIVE_FIBONACCI_REAL INTEGER N N = 100 DO I = 0, N - 1 CALL fibonacci_real(I, Result) END DO WRITE(*, *) Result CONTAINS RECURSIVE SUBROUTINE fibonacci_real(N, Result) INTEGER N REAL Result IF (N <= 1) THEN Result = REAL(N) ELSE CALL fibonacci_real(N - 1, Result1) CALL fibonacci_real(N - 2, Result2) Result = Result1 + Result2 END IF END SUBROUTINE fibonacci_real END Recursivity
  • 19. Fortran nowadays (since 1991) program Fibonacci implicit none integer :: n, i real :: fib_prev, fib_current, result n = 100 fib_prev = 0 fib_current = 1 do i = 1, n if (i <= 1) then result = i else result = fib_prev + fib_current fib_prev = fib_current fib_current = result end if end do print *, "The result is", result end program Fibonacci program FibonacciTailRecursive implicit none integer :: n, i real :: result n = 100 result = fibonacci(n) print *, "The result is", result contains recursive function fibonacci(n) result(fib) integer, intent(in) :: n integer :: fib if (n == 0) then fib = 0 else if (n == 1) then fib = 1 else fib = fibonacci(n - 1) + fibonacci(n - 2) end if end function fibonacci end program FibonacciTailRecursive program FibonacciTailRecursive implicit none integer :: n real :: result n = 100 result = fibonacci(n) print *, "The result is", result contains recursive function fibonacci(n) result(fib) integer, intent(in) :: n real :: fib if (n <= 1) then fib = n else fib = fibonacci_helper(n, 0.0, 1.0) end if end function fibonacci recursive function fibonacci_helper(n, a, b) result(fib) integer, intent(in) :: n real :: fib, a, b if (n == 0) then fib = a else if (n == 1) then fib = b else fib = fibonacci_helper(n - 1, b, a + b) end if end function fibonacci_helper end program FibonacciTailRecursive
  • 21. LISP 1958 (defun fibonacci-iterative (n) (if (<= n 1) n (fib-iter 0 1 n))) (defun fib-iter (a b count) (loop repeat (- count 1) do (setf (values a b) (values b (+ a b))) finally (return b))) (defun fibonacci-recursive (n) (if (<= n 1) n (+ (fibonacci-recursive (- n 1)) (fibonacci-recursive (- n 2))))) ● Lisp: 1958 ● Lisp 1.5: 1962 ● MacLisp: Late 1960s ● InterLisp: 1966 ● Common Lisp: 1984 (defun fibonacci-tail-recursive (n) (if (<= n 1) n (fib-tail-recursive 0 1 n))) (defun fib-tail-recursive (a b count) (if (= count 0) a (fib-tail-recursive b (+ a b) (- count 1))))
  • 23. COBOL 1959 IDENTIFICATION DIVISION. PROGRAM-ID. Fibonacci. DATA DIVISION. WORKING-STORAGE SECTION. 01 F1 PIC 9(21)V9(1) VALUE 0.0. 01 F2 PIC 9(21)V9(1) VALUE 1.0. 01 FIB PIC 9(21)V9(1). 01 N PIC 9(5) VALUE 100. 01 I PIC 9(5) VALUE 3. PROCEDURE DIVISION. MAIN-LOGIC. PERFORM VARYING I FROM 2 BY 1 UNTIL I > N COMPUTE FIB = F1 + F2 COMPUTE F1 = F2 COMPUTE F2 = FIB END-PERFORM. DISPLAY FIB. STOP RUN. IDENTIFICATION DIVISION. PROGRAM-ID. FibonacciRecursive. DATA DIVISION. WORKING-STORAGE SECTION. 01 F1 PIC 9(21)V9(1) VALUE 0.0. 01 F2 PIC 9(21)V9(1) VALUE 1.0. 01 FIB PIC 9(21)V9(1). 01 N PIC 9(5) VALUE 100. 01 I PIC 9(5) VALUE 0. PROCEDURE DIVISION. MOVE N TO I CALL 'FIBONACCI'. DISPLAY "Fibonacci of " I " is " F1. STOP RUN. ENTRY 'FIBONACCI'. IF N = 0 THEN EXIT PROGRAM ELSE COMPUTE FIB = F1 + F2 COMPUTE F1 = F2 COMPUTE F2 = FIB SUBTRACT 1 FROM N CALL 'FIBONACCI' END-IF. ● COBOL 60 - 1960. ● COBOL 61 - 1961. ● COBOL 65 - 1965. ● COBOL 68 - 1968 ● COBOL 74 - 1974 ● COBOL 85 - 1985 ● COBOL 2002 - 2002 ● COBOL 2014 - 2014 Recursivity
  • 25. Scheme - 1975 (define (fibonacci n) (fibonacci-iter n 0 1)) (define (fibonacci-iter n a b) (do ((i n (- i 1)) (x a b) (y b (+ a b))) ((= i 0) x) (set! a x) (set! b y))) (define (fibonacci n) (if (or (= n 0) (= n 1)) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) (display (fibonacci 100)) ● Scheme 75: 1975 ● Scheme 84: 1984 ● Several follow up releases until 2013 (define (fibonacci n) (define (fib-helper n a b) (if (= n 0) a (fib-helper (- n 1) b (+ a b)))) (fib-helper n 0 1)) (display (fibonacci 100))
  • 27. Standard Meta Language - 1983/84 ● Moby: Moby - 1980’s ● SML/NJ - 1983/1984 ● MLton - 1999 ● SML '90 - 1990 ● SML '97 - 1997 ● SML 2007 - 2007 ● SML 2022 - 2022 fun fibonacci n = if n < 2 then n else fibonacci (n - 1) + fibonacci (n - 2); structure IntInf = IntInf fun fibonacci n = let fun fibIter n a b = if n = 0 then a else fibIter (n - 1) b (IntInf.+(a, b)) in fibIter n 0 1 end;
  • 29. Erlang - 1986 ● Erlang 1986 - First proprietary release ● Erlang/OTP R1 (1996) - First commercial release ● Erlang/OTP 24 - Erlang until 2021 -module(fibonacci_recursive). -export([fib/1]). fib(0) -> 0; fib(1) -> 1; fib(N) when N > 1 -> fib(N - 1) + fib(N - 2). -module(fibonacci_recursive_tco). -export([fib/1]). fib(N) when N < 2 -> N; fib(N) -> fib_iter(N, 0, 1). fib_iter(0, A, _) -> A; fib_iter(N, A, B) -> fib_iter(N - 1, B, A + B).
  • 31. Haskell - 1990 ● First draft - 1987 ● Haskell 1.0 - 1990 ● Haskell 1.1 - 1991 ● Haskell 1.2 - 1992 ● Haskell 1.3 - 1996 ● Haskell 1.4 - 1997 ● Haskell 98 - 1998 ● Haskell 2010 - 2010 ● Haskell 2022 - 2022 fibonacci :: Integer -> Integer fibonacci 0 = 0 fibonacci 1 = 1 fibonacci n = fibonacci (n - 1) + fibonacci (n - 2) main :: IO () main = do let result = fibonacci 1000 putStrLn $ "Fibonacci of the order of 1000: " ++ show result fibonacciTailRec :: Integer -> Integer fibonacciTailRec n = fibonacciHelper n 0 1 where fibonacciHelper 0 a _ = a fibonacciHelper 1 _ b = b fibonacciHelper n a b = fibonacciHelper (n - 1) b (a + b) main :: IO () main = do let result = fibonacciTailRec 1000 putStrLn $ "Fibonacci of the order of 1000: " ++ show result
  • 33. About Java - 1995 Java deliberately doesn’t support Tail Call Optimization because: ● Backward compatibility ● It might not go well with the JVM architecture because of overhead and potential side-effects. ● Performance and complexity ● The iterative alternative is always possible ● Not very clear if TCO is the best idea for Java But this didn’t stop JVM alternative languages to explore TCO possibilities...
  • 35. Scala - 2003 ● Scala 1.0 - 2003 ● Scala 2.0 - 2006 ● Scala 2.7 - 2009 ● Scala 2.8 - 2010 ● Scala 2.9 - 2011 ● Scala 2.10 - 2012 ● Scala 2.11 - 2014 ● Scala 2.12 - 2016 ● Scala 2.13 - 2019 ● Scala 3 (previously known as Dotty) - 2020 def fibonacciIterative(n: Double): Double = { var a = 0f var b = 1f var i = 0f while (i < n) { val temp = b b = a + b a = temp i += 1 } a } def fibonacciRecursive(n: Double): Double = { if (n <= 1f) { n } else { fibonacciRecursive(n - 1f) + fibonacciRecursive(n - 2f) } } def fibonacciTailRec(n: Double): Double = { def fibHelper(n: Double, a: Double, b: Double): Double = { if (n == 0.0) a else fibHelper(n - 1.0, b, a + b) } fibHelper(n, 0.0, 1.0) }
  • 36. Scala - 2003 ● Scala 1.0 - 2003 ● Scala 2.0 - 2006 ● Scala 2.7 - 2009 ● Scala 2.8 - 2010 ● Scala 2.9 - 2011 ● Scala 2.10 - 2012 ● Scala 2.11 - 2014 ● Scala 2.12 - 2016 ● Scala 2.13 - 2019 ● Scala 3 (previously known as Dotty) - 2020 def fibonacciTailRecTCO(n: Double): Double = { @annotation.tailrec def fibHelper(n: Double, a: Double, b: Double): Double = { if (n == 0f) a else fibHelper(n - 1f, b, a + b) } fibHelper(n, 0f, 1f) } def fibonacciTailRecManualTCO(n: Double): Double = { def fibHelper(n: Double, a: Double, b: Double): Double = { var a = 0f var b = 1f var i = 0f while (i < n) { val temp = b b = a + b a = temp i += 1 } a if (n == 0.0) a else fibHelper(n - 1.0, b, a + b) } fibHelper(n, 0.0, 1.0) }
  • 37. Scala - 2003 def fibonacciTailRecTCO(n: Double): Double = { @annotation.tailrec def fibHelper(n: Double, a: Double, b: Double): Double = { if (n == 0f) a else fibHelper(n - 1f, b, a + b) } fibHelper(n, 0f, 1f) } def factorialUnMarked(n: Double): Double = { def factorialHelper(n: Double): Double = { if (n <= 1f) 1f else n * factorialHelper(n - 1f) } factorialHelper(n) } public static double factorialUnMarked(double var0) { return Fibonacci$.MODULE$.factorialUnMarked(var0); } public double factorialUnMarked(final double n) { return this.factorialHelper$1(n); } private final double factorialHelper$1(final double n) { return n <= 1.0 ? 1.0 : n * this.factorialHelper$1(n - 1.0); } public static double fibonacciTailRecTCO(double var0) { return Fibonacci$.MODULE$.fibonacciTailRecTCO(var0); } public double fibonacciTailRecTCO(final double n) { return this.fibHelper$3(n, 0.0, 1.0); } private final double fibHelper$3(final double n, final double a, final double b) { while(n != 0.0) { double var7 = n - 1.0; double var11 = a + b; n = var7; a = b; b = var11; } return a; }
  • 39. Clojure - 2007 (defn fibonacci-iterative [n] (if (<= n 1) n (loop [a 0 b 1 i 1] (if (= i n) (+ a b) (recur b (+ a b) (inc i)))))) (defn fibonacci-recursive [n] (let [n (if (instance? String n) (Double/parseDouble n) n)] (if (<= n 1.0) n (+ (fibonacci-recursive (- n 1.0)) (fibonacci-recursive (- n 2.0)))))) (defn fibonacci-tail-rec [n] (let [n (if (instance? String n) (Double/parseDouble n) n)] (letfn [(fib-tail [n a b] (if (zero? n) a (fib-tail (dec n) b (+ a b))))] (fib-tail n 0.0 1.0)))) ● First version - 2007 ● Clojure 1.0 - 2009 ● Clojure until 1.11.1 in 2022
  • 40. Clojure - 2007 ● First version - 2007 ● Clojure 1.0 - 2009 ● Clojure until 1.11.1 in 2022 (defn fibonacci-tail-rec-tco [n] (let [n (if (instance? String n) (Double/parseDouble n) n)] (letfn [(fib [n a b] (if (zero? n) a (recur (dec n) b (+ a b))))] (fib n 0.0 1.0))))
  • 42. Kotlin - 2016 ● Kotlin 1.0 - 2016 ● Kotlin 1.1 - 2017 ● Kotlin 1.2 - 2017 ● Kotlin 1.3 - 2018 ● Kotlin 1.4 - 2020 ● Kotlin 1.5 - 2021 ● Kotlin 1.6 - 2021 ● Kotlin 1.7 - 2022 ● Kotlin 1.8 - 2023 ● Kotlin 1.9 - 2023 private fun fibonacciIterative(n: Int): Double { if (n <= 1) { return n.toDouble() } var a = 0.0 var b = 1.0 for (i in 2..n) { val temp = a + b a = b b = temp } return b } fun fibonacciRecursive(n: Int): Double = if (n <= 1) n.toDouble() else fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2) private fun fibonacciTailRecursive( n: Int, a: Double = 0.0, b: Double = 1.0 ): Double = if (n == 0) a else fibonacciTailRecursive(n - 1, b, a + b)
  • 43. Kotlin - 2016 private tailrec fun fibonacciTailRecursiveTCO( n: Int, a: Double = 0.0, b: Double = 1.0 ): Double = if (n == 0) a else fibonacciTailRecursiveTCO(n - 1, b, a + b) ● Kotlin 1.0 - 2016 ● Kotlin 1.1 - 2017 ● Kotlin 1.2 - 2017 ● Kotlin 1.3 - 2018 ● Kotlin 1.4 - 2020 ● Kotlin 1.5 - 2021 ● Kotlin 1.6 - 2021 ● Kotlin 1.7 - 2022 ● Kotlin 1.8 - 2023 ● Kotlin 1.9 - 2023
  • 44. Kotlin - 2016 private tailrec fun fibonacciTailRecursiveTCO( n: Int, a: Double = 0.0, b: Double = 1.0 ): Double = if (n == 0) a else fibonacciTailRecursiveTCO(n - 1, b, a + b) private fun fibonacciTailRecursive( n: Int, a: Double = 0.0, b: Double = 1.0 ): Double = if (n == 0) a else fibonacciTailRecursive(n - 1, b, a + b) private final double fibonacciTailRecursive(int n, double a, double b) { return n == 0 ? a : ((Companion)this).fibonacciTailRecursive(n - 1, b, a + b); } // $FF: synthetic method static double fibonacciTailRecursive$default(Companion var0, int var1, double var2, double var4, int var6, Object var7) { if ((var6 & 2) != 0) { var2 = 0.0; } if ((var6 & 4) != 0) { var4 = 1.0; } return var0.fibonacciTailRecursive(var1, var2, var4); } private final double fibonacciTailRecursiveTCO(int n, double a, double b) { while(n != 0) { Companion var10000 = (Companion)this; int var10001 = n - 1; double var10002 = b; b += a; a = var10002; n = var10001; } return a; } // $FF: synthetic method static double fibonacciTailRecursiveTCO$default(Companion var0, int var1, double var2, double var4, int var6, Object var7) { if ((var6 & 2) != 0) { var2 = 0.0; } if ((var6 & 4) != 0) { var4 = 1.0; } return var0.fibonacciTailRecursiveTCO(var1, var2, var4); }
  • 46. Conclusions ● Which direction is this all taking? ● Is programming still a challenge? ● Why do we do software development? ● Are we being forced into thinking recursively? ● Is Mutability something to be completely removed from a programming language? ● Productivity vs The Joy of Coding ● What happens when we keep thinking only recursively when implementing algorithms? ● Can we blindly rely on the TCO algorithms in the way that we already trust Garbage Collection? ● Do we trust Garbage Collection? ● Can we manually implement a better algorithm with better performance than TCO? ● Would we still be able to do it, if we don’t practice? ● Can we still produce without challenges in the long run?
  • 48. Resources for this presentation Image sources ● https://commons.wikimedia.org/wiki/File:John_McCarthy_Stanford.jpg ● https://commons.wikimedia.org/wiki/File:John_Backus_2.jpg ● https://commons.wikimedia.org/wiki/File:Guy_Steele.jpg ● https://commons.wikimedia.org/wiki/File:Jerry_Sussman.jpg ● https://nl.wikipedia.org/wiki/Rij_van_Fibonacci#/media/Bestand:Fibonacci_Spiral.svg ● https://en.wikipedia.org/wiki/File:Fortran_logo.svg ● https://en.m.wikipedia.org/wiki/File:Lisp_logo.svg ● https://commons.wikimedia.org/wiki/File:IBM_keypunch_deck_for_Cobol_student_program_at_New_York_Universi ty_1979.jpg ● https://commons.wikimedia.org/wiki/File:Lambda_lc.svg ● https://commons.wikimedia.org/wiki/File:Informatics_Forum_Atrium_turned.jpg ● https://commons.wikimedia.org/wiki/File:Ericsson_logo.svg ● https://commons.wikimedia.org/wiki/File:Erlang_logo.png ● https://en.wikipedia.org/wiki/File:Haskell-Logo.svg ● https://commons.wikimedia.org/wiki/File:James_Gosling_2008.jpg ● https://commons.wikimedia.org/wiki/File:Mark_Odersky_photo_by_Linda_Poeng.jpg ● https://commons.wikimedia.org/wiki/File:Scala-full-color.svg ● https://en.m.wikipedia.org/wiki/File:Clojure_logo.svg ● https://commons.wikimedia.org/wiki/File:Kotlin_logo_2021.svg
  • 49. Resources for this presentation ● https://www.smlnj.org/sml.html ● https://en.wikibooks.org/wiki/Standard_ML_Programming/Types ● https://en.wikipedia.org/wiki/Standard_ML ● https://www.smlnj.org/ ● https://www.scala-lang.org/ ● https://kotlinlang.org/ ● https://en.wikipedia.org/wiki/COBOL ● https://fortran-lang.org/ ● https://www.java.com/en/ ● https://developer.ibm.com/languages/cobol/ ● https://www.haskell.org/ ● https://www.erlang.org/ ● https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gfortran/Code-Gen-Options.html Data sources