ELEANOR MCHUGH
AN
INTRODUCTION
TO
FUNCTIONAL PROGRAMMING
IN
GO
APPLIED PHYSICIST
MISAPPLIED HACKER
EMBEDDED SYSTEMS
VIRTUAL MACHINES
DIGITAL IDENTITY
RUBY
GO
C
ELEANOR M HUGH
@feyeleanor
LEANPUB://GONOTEBOOK
A GO DEVELOPER'S NOTEBOOK
▸ teaches Go by exploring code
▸ free tutorial on secure networking
▸ opinionated but not prescriptive
▸ based on a decade of experience
▸ buy once & get all future updates
▸ very irregular update cycle
▸ the only book I'll ever write on Go
LEANPUB://GONOTEBOOK
IMPERATIVE
PROGRAMMING
A SIMPLE TASK
0: 0
1: 2
2: 4
3: 6
4: 8
THE CONDITIONAL LOOP
IMPERATIVE
PROGRAMMING
THE CONDITIONAL LOOP
package main
import "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
fmt.Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
fmt.Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
fmt.Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
THE CONDITIONAL LOOP
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i := 0; i < len(s); i++ {
Printf("%v: %v\n", i, s[i])
}
}
AN EXCEPTIONAL LOOP
IMPERATIVE
PROGRAMMING
AN EXCEPTIONAL LOOP
package main
import . "fmt"
func main() {
defer func() {
recover()
}()
s := []int{0, 2, 4, 6, 8}
i := 0
for {
Printf("%v: %v\n", i, s[i])
i++
}
}
AN EXCEPTIONAL LOOP
package main
import . "fmt"
func main() {
defer func() {
recover()
}()
s := []int{0, 2, 4, 6, 8}
i := 0
for {
Printf("%v: %v\n", i, s[i])
i++
}
}
AN EXCEPTIONAL LOOP
package main
import . "fmt"
func main() {
defer func() {
recover()
}()
s := []int{0, 2, 4, 6, 8}
i := 0
for {
Printf("%v: %v\n", i, s[i])
i++
}
}
AN EXCEPTIONAL LOOP
package main
import . "fmt"
func main() {
defer func() {
recover()
}()
s := []int{0, 2, 4, 6, 8}
i := 0
for {
Printf("%v: %v\n", i, s[i])
i++
}
}
AN EXCEPTIONAL LOOP
package main
import . "fmt"
func main() {
defer func() {
recover()
}()
s := []int{0, 2, 4, 6, 8}
i := 0
for {
Printf("%v: %v\n", i, s[i])
i++
}
}
AN EXCEPTIONAL LOOP
package main
import . "fmt"
func main() {
defer func() {
recover()
}()
s := []int{0, 2, 4, 6, 8}
i := 0
for {
Printf("%v: %v\n", i, s[i])
i++
}
}
AN EXCEPTIONAL LOOP
package main
import . "fmt"
func main() {
defer func() {
recover()
}()
s := []int{0, 2, 4, 6, 8}
for i := 0; ; i++ {
Printf("%v: %v\n", i, s[i])
i++
}
}
ENUMERABLE RANGES
IMPERATIVE
PROGRAMMING
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
PROGRAMMING
WITH
FUNCTIONS
ENUMERATION BY FUNCTION
PROGRAMMING
WITH
FUNCTIONS
ENUMERATION BY FUNCTION
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s []int) {
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
ENUMERATION BY FUNCTION
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s []int) {
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
ENUMERATION BY FUNCTION
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s []int) {
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
ENUMERATION BY FUNCTION
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s []int) {
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
ENUMERATION BY FUNCTION
package main
import . "fmt"
func main() {
print_slice(0, 2, 4, 6, 8)
}
func print_slice(s ...int) {
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
TYPE ABSTRACTION
PROGRAMMING
WITH
FUNCTIONS
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
for i, v := range s.([]int) {
Printf("%v: %v\n", i, v)
}
}
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
for i, v := range s.([]int) {
Printf("%v: %v\n", i, v)
}
}
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
for i, v := range s.([]int) {
Printf("%v: %v\n", i, v)
}
}
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
if s, ok := s.([]int); ok {
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
if s, ok := s.([]int); ok {
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
if s, ok := s.([]int); ok {
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
if s, ok := s.([]int); ok {
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case []int:
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case []int:
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
ABSTRACTING TYPE
package main
import . "fmt"
func main() {
print_slice([]int{0, 2, 4, 6, 8})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case []int:
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
FUNCTIONS AS VALUES
PROGRAMMING
WITH
FUNCTIONS
FUNCTIONS AS VALUES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(s, element)
}
func element(s []int, i int) int {
return s[i]
}
func print_slice(s []int, f func([]int, int) int {
defer func() {
recover()
}()
for i := 0; ; i++ {
Printf("%v: %v\n", i, f(i))
}
}
FUNCTIONS AS VALUES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(s, element)
}
func element(s []int, i int) int {
return s[i]
}
func print_slice(s []int, f func([]int, int) int {
defer func() {
recover()
}()
for i := 0; ; i++ {
Printf("%v: %v\n", i, f(i))
}
}
FUNCTIONS AS VALUES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(s, element)
}
func element(s []int, i int) int {
return s[i]
}
func print_slice(s []int, f func([]int, int) int) {
defer func() {
recover()
}()
for i := 0; ; i++ {
Printf("%v: %v\n", i, f(s, i))
}
}
FUNCTIONS AS VALUES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(s, element)
}
func element(s []int, i int) int {
return s[i]
}
func print_slice(s []int, f func([]int, int) int) {
defer func() {
recover()
}()
for i := 0; ; i++ {
Printf("%v: %v\n", i, f(s, i))
}
}
FUNCTIONS AS VALUES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(s, element)
}
func element(s []int, i int) int {
return s[i]
}
func print_slice(s []int, f func([]int, int) int) {
defer func() {
recover()
}()
for i := 0; ; i++ {
Printf("%v: %v\n", i, f(s, i))
}
}
FUNCTIONS AS VALUES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(s, element)
}
func element(s []int, i int) int {
return s[i]
}
func print_slice(s []int, f func([]int, int) int) {
defer func() {
recover()
}()
for i := 0; ; i++ {
Printf("%v: %v\n", i, f(s, i))
}
}
FUNCTIONS AS VALUES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(s, func(s []int, i int) int {
return s[i]
})
}
func print_slice(s []int, f func([]int, int) int) {
defer func() {
recover()
}()
for i := 0; ; i++ {
Printf("%v: %v\n", i, f(s, i))
}
}
CLOSURES
PROGRAMMING
WITH
FUNCTIONS
CLOSURES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(func(i int) int {
return s[i]
})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
}
}
CLOSURES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(func(i int) int {
return s[i]
})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
}
}
CLOSURES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(func(i int) int {
return s[i]
})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
}
}
CLOSURES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(func(i int) int {
return s[i]
})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
}
}
CLOSURES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(func(i int) int {
return s[i]
})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
}
}
CLOSURES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(func(i int) int {
return s[i]
})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
}
}
CLOSURES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(func(i int) int {
return s[i]
})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
}
}
CLOSURES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_slice(func(i int) int {
return s[i]
})
}
func print_slice(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
}
}
CONCURRENCY
PROGRAMMING
WITH
FUNCTIONS
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for i := 0; i++; i < 5 {
c <- i * 2
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for i := 0; i++; i < 5 {
c <- i * 2
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int, 16)
go func() {
for i := 0; i++; i < 5 {
c <- i * 2
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for i := 0; i++; i < 5 {
c <- i * 2
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for i := 0; i++; i < 5 {
c <- i * 2
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for i := 0; i++; i < 5 {
c <- i * 2
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for i := 0; i++; i < 5 {
c <- i * 2
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for _, v := range []int{0, 2, 4, 6, 8} {
c <- v
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for _, v := range []int{0, 2, 4, 6, 8} {
c <- v
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for _, v := range []int{0, 2, 4, 6, 8} {
c <- v
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
CONCURRENCY
package main
import . "fmt"
func main() {
c := make(chan int)
go func() {
for _, v := range []int{0, 2, 4, 6, 8} {
c <- v
}
close(c)
}()
print_channel(c)
}
func print_channel(c chan int) (i int) {
for v := range c {
Printf("%v: %v\n", i, v)
i++
}
return
}
INFINITE SEQUENCES
PROGRAMMING
WITH
FUNCTIONS
INFINITE SEQUENCES
package main
import . "fmt"
func main() {
c := make(chan int)
go sequence(c)
print_channel(c)
}
func sequence(c chan int) {
for i := 0; ; i++ {
c <- i * 2
}
}
func print_channel(c chan int) {
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, <- c)
}
return
}
INFINITE SEQUENCES
package main
import . "fmt"
func main() {
c := make(chan int)
go sequence(c)
print_channel(c)
}
func sequence(c chan int) {
for i := 0; ; i++ {
c <- i * 2
}
}
func print_channel(c chan int) {
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, <- c)
}
return
}
INFINITE SEQUENCES
package main
import . "fmt"
func main() {
c := make(chan int)
go sequence(c)
print_channel(c)
}
func sequence(c chan int) {
for i := 0; ; i++ {
c <- i * 2
}
}
func print_channel(c chan int) {
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, <- c)
}
return
}
INFINITE SEQUENCES
package main
import . "fmt"
func main() {
c := make(chan int)
go sequence(c)
print_channel(c)
}
func sequence(c chan int) {
for i := 0; ; i++ {
c <- i * 2
}
}
func print_channel(c chan int) {
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, <- c)
}
return
}
INFINITE SEQUENCES
package main
import . "fmt"
func main() {
c := make(chan int)
go sequence(c)
print_channel(c)
}
func sequence(c chan int) {
for i := 0; ; i++ {
c <- i * 2
}
}
func print_channel(c chan int) {
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, <- c)
}
return
}
WORKING WITH KINDS
PROGRAMMING
WITH
FUNCTIONS
WORKING WITH KINDS
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
case []int:
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
WORKING WITH KINDS
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
case []int:
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
WORKING WITH KINDS
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
case []int:
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
WORKING WITH KINDS
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := s.(type) {
case func(int) int:
for i := 0; i < 5; i++ {
Printf("%v: %v\n", i, s(i))
}
case []int:
for i, v := range s {
Printf("%v: %v\n", i, v)
}
}
}
WORKING WITH KINDS
package main
import "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := reflect.ValueOf(s); s.Kind() {
case reflect.Func:
for i := 0; i < 5; i++ {
p := []reflect.Value{ reflect.ValueOf(i) }
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
}
case reflect.Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %v\n", i, s.Index(i).Interface())
}
}
}
WORKING WITH KINDS
package main
import "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := reflect.ValueOf(s); s.Kind() {
case reflect.Func:
for i := 0; i < 5; i++ {
p := []reflect.Value{ reflect.ValueOf(i) }
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
}
case reflect.Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %v\n", i, s.Index(i).Interface())
}
}
}
WORKING WITH KINDS
package main
import "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := reflect.ValueOf(s); s.Kind() {
case reflect.Func:
for i := 0; i < 5; i++ {
p := []reflect.Value{ reflect.ValueOf(i) }
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
}
case reflect.Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %v\n", i, s.Index(i).Interface())
}
}
}
WORKING WITH KINDS
package main
import "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := reflect.ValueOf(s); s.Kind() {
case reflect.Func:
for i := 0; i < 5; i++ {
p := []reflect.Value{ reflect.ValueOf(i) }
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
}
case reflect.Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %v\n", i, s.Index(i).Interface())
}
}
}
WORKING WITH KINDS
package main
import . "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := ValueOf(s); s.Kind() {
case Func:
for i := 0; i < 5; i++ {
p := []Value{ ValueOf(i) }
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
}
case Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %v\n", i, s.Index(i).Interface())
}
}
}
WORKING WITH KINDS
package main
import . "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := ValueOf(s); s.Kind() {
case Func:
for i := 0; i < 5; i++ {
p := []Value{ ValueOf(i) }
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
}
case Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %v\n", i, s.Index(i).Interface())
}
}
}
WORKING WITH KINDS
package main
import . "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := ValueOf(s); s.Kind() {
case Func:
for i := 0; i < 5; i++ {
p := []Value{ ValueOf(i) }
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
}
case Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %v\n", i, s.Index(i).Interface())
}
}
}
WORKING WITH KINDS
package main
import . "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
defer func() {
recover()
}
switch s := ValueOf(s); s.Kind() {
case Func:
for i := 0; ; i++ {
p := []Value{ ValueOf(i) }
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
}
case Slice:
for i := 0; ; i++ {
Printf("%v: %v\n", i, s.Index(i).Interface())
}
}
}
WORKING WITH KINDS
package main
import . "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := ValueOf(s); s.Kind() {
case Func:
for_each(func(i int) {
p := []Value{ ValueOf(i) }
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
})
case Slice:
for_each(func(i int) {
Printf("%v: %v\n", i, s.Index(i).Interface())
})
}
}
func for_each(f func(int)) (i int) {
defer func() {
recover()
}
for ; ; i++ {
f(i)
}
}
WORKING WITH KINDS
package main
import . "reflect"
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
print_values(s)
print_values(func(i int) int {
return s[i]
})
}
func print_values(s interface{}) {
switch s := ValueOf(s); s.Kind() {
case Func:
p := make([]Value, 1)
for_each(func(i int) {
p[0] = ValueOf(i)
Printf("%v: %v\n", i, s.Call(p)[0].Interface())
})
case Slice:
for_each(func(i int) {
Printf("%v: %v\n", i, s.Index(i).Interface())
})
}
}
func for_each(f func(int)) (i int) {
defer func() {
recover()
}
for ; ; i++ {
f(i)
}
}
PROGRAMMING
WITH
OBJECTS
TYPES + METHODS = OBJECTS
PROGRAMMING
WITH
OBJECTS
TYPES + METHODS = OBJECTS
package main
import . "fmt"
func main() {
s := IterableSlice{ 0, 2, 4, 6, 8 }
i := 0
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
}
type IterableSlice []int
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
TYPES + METHODS = OBJECTS
package main
import . "fmt"
func main() {
s := IterableSlice{ 0, 2, 4, 6, 8 }
i := 0
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
}
type IterableSlice []int
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
TYPES + METHODS = OBJECTS
package main
import . "fmt"
func main() {
s := IterableSlice{ 0, 2, 4, 6, 8 }
i := 0
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
}
type IterableSlice []int
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
TYPES + METHODS = OBJECTS
package main
import . "fmt"
func main() {
s := IterableSlice{ 0, 2, 4, 6, 8 }
i := 0
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
}
type IterableSlice []int
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
TYPES + METHODS = OBJECTS
package main
import . "fmt"
func main() {
s := IterableSlice{ 0, 2, 4, 6, 8 }
i := 0
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
}
type IterableSlice []int
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
INTERFACES = POLYMORPHISM
PROGRAMMING
WITH
OBJECTS
INTERFACES = POLYMORPHISM
package main
import . "fmt"
func main() {
var s Iterable = IterableSlice{ 0, 2, 4, 6, 8 }
i := 0
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
}
type Iterable interface {
Each(func(interface{}))
}
type IterableSlice []int
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
INTERFACES = POLYMORPHISM
package main
import . "fmt"
func main() {
var s Iterable = IterableSlice{ 0, 2, 4, 6, 8 }
i := 0
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
}
type Iterable interface {
Each(func(interface{}))
}
type IterableSlice []int
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
INTERFACES = POLYMORPHISM
package main
import . "fmt"
func main() {
var s Iterable = IterableSlice{ 0, 2, 4, 6, 8 }
i := 0
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
}
type Iterable interface {
Each(func(interface{}))
}
type IterableSlice []int
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
INTERFACES = POLYMORPHISM
package main
import . "fmt"
func main() {
print_values(IterableLimit(5))
print_values(IterableSlice{ 0, 2, 4, 6, 8 })
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableLimit int
type IterableSlice []int
func (i IterableLimit) Each(f func(interface{})) {
for v := IterableLimit(0); v < i; v++ {
f(v)
}
}
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
INTERFACES = POLYMORPHISM
package main
import . "fmt"
func main() {
print_values(IterableLimit(5))
print_values(IterableSlice{ 0, 2, 4, 6, 8 })
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableLimit int
type IterableSlice []int
func (i IterableLimit) Each(f func(interface{})) {
for v := IterableLimit(0); v < i; v++ {
f(v)
}
}
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
INTERFACES = POLYMORPHISM
package main
import . "fmt"
func main() {
print_values(IterableLimit(5))
print_values(IterableSlice{ 0, 2, 4, 6, 8 })
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableLimit int
type IterableSlice []int
func (i IterableLimit) Each(f func(interface{})) {
for v := IterableLimit(0); v < i; v++ {
f(v)
}
}
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
INTERFACES = POLYMORPHISM
package main
import . "fmt"
func main() {
print_values(IterableLimit(5))
print_values(IterableSlice{ 0, 2, 4, 6, 8 })
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableLimit int
type IterableSlice []int
func (i IterableLimit) Each(f func(interface{})) {
for v := IterableLimit(0); v < i; v++ {
f(v)
}
}
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
IMMUTABILITY IS A CHOICE
PROGRAMMING
WITH
OBJECTS
IMMUTABILITY IS A CHOICE
package main
import . "fmt"
func main() {
s := IterableRange{ 0, 2, 5 }
print_values(s)
print_values(s)
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableRange struct {
start int
step int
limit int
}
func (r IterableRange) Each(f func(interface{})) {
for; r.limit > 0; r.limit-- {
f(r.start)
r.start += r.step
}
}
IMMUTABILITY IS A CHOICE
package main
import . "fmt"
func main() {
s := IterableRange{ 0, 2, 5 }
print_values(s)
print_values(s)
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableRange struct {
start int
step int
limit int
}
func (r IterableRange) Each(f func(interface{})) {
for; r.limit > 0; r.limit-- {
f(r.start)
r.start += r.step
}
}
IMMUTABILITY IS A CHOICE
package main
import . "fmt"
func main() {
s := IterableRange{ 0, 2, 5 }
print_values(s)
print_values(s)
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableRange struct {
start int
step int
limit int
}
func (r IterableRange) Each(f func(interface{})) {
for; r.limit > 0; r.limit-- {
f(r.start)
r.start += r.step
}
}
IMMUTABILITY IS A CHOICE
package main
import . "fmt"
func main() {
s := IterableRange{ 0, 2, 5 }
print_values(s)
print_values(s)
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableRange struct {
start int
step int
limit int
}
func (r IterableRange) Each(f func(interface{})) {
for; r.limit > 0; r.limit-- {
f(r.start)
r.start += r.step
}
}
IMMUTABILITY IS A CHOICE
package main
import . "fmt"
func main() {
s := &IterableRange{ 0, 2, 5 }
print_values(s)
print_values(s)
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableRange struct {
start int
step int
limit int
}
func (r IterableRange) Each(f func(interface{})) {
for; r.limit > 0; r.limit-- {
f(r.start)
r.start += r.step
}
}
IMMUTABILITY IS A CHOICE
package main
import . "fmt"
func main() {
s := &IterableRange{ 0, 2, 5 }
print_values(s)
print_values(s)
}
func print_values(s Iterable) (i int) {
s.Each(func(v interface{}) {
Printf("%v: %v\n", i, v)
i++
})
return i
}
type Iterable interface {
Each(func(interface{}))
}
type IterableRange struct {
start int
step int
limit int
}
func (r *IterableRange) Each(f func(interface{})) {
for; r.limit > 0; r.limit-- {
f(r.start)
r.start += r.step
}
}
LEANPUB://GONOTEBOOK
OO makes code understandable by
encapsulating moving parts.
FP makes code understandable by
minimizing moving parts.
Michael Feathers
@mfeathers
FUNCTIONS
AS
PARADIGM
A PURE FUNCTION
FUNCTIONS
AS
PARADIGM
A PURE FUNCTION
package main
import "os"
func main() {
os.Exit(add(3, 4))
}
func add(x, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
func main() {
os.Exit(add(3, 4))
}
func add(x, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
func main() {
os.Exit(add(3, 4))
}
func add(x int, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
func main() {
os.Exit(add(3, 4))
}
func add(x int, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
func main() {
os.Exit(add(3, 4))
}
func add(x int, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
import "strconv"
func main() {
x, _ := strconv.Atoi(os.Args[1])
y, _ := strconv.Atoi(os.Args[2])
os.Exit(add(x, y))
}
func add(x, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
import "strconv"
func main() {
x, _ := strconv.Atoi(os.Args[1])
y, _ := strconv.Atoi(os.Args[2])
os.Exit(add(x, y))
}
func add(x, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
import "strconv"
func main() {
x, _ := strconv.Atoi(os.Args[1])
y, _ := strconv.Atoi(os.Args[2])
os.Exit(add(x, y))
}
func add(x, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
import "strconv"
func main() {
os.Exit(add(arg(0), arg(1)))
}
func arg(n int) (r int) {
r, _ = strconv.Atoi(os.Args[n + 1])
return
}
func add(x, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
import "strconv"
func main() {
var sum int
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
sum = add(sum, x)
}
os.Exit(sum)
}
func add(x, y int) int {
return x + y
}
A PURE FUNCTION
package main
import "os"
import "strconv"
func main() {
var sum int
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
sum = add(sum, x)
}
os.Exit(sum)
}
func add(x, y int) int {
return x + y
}
BEING IMPURE
FUNCTIONS
AS
PARADIGM
BEING IMPURE
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
accumulate(x)
}
os.Exit(y)
}
var y int
func accumulate(x int) {
y += x
}
BEING IMPURE
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
accumulate(x)
}
os.Exit(y)
}
var y int
func accumulate(x int) {
y += x
}
BEING IMPURE
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
accumulate(x)
}
os.Exit(y)
}
var y int
func accumulate(x int) {
y += x
}
BEING IMPURE
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
accumulate(x)
}
os.Exit(y)
}
var y int
func accumulate(x int) {
y += x
}
BEING IMPURE
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a.Add(x)
}
os.Exit(int(a))
}
var a Accumulator
type Accumulator int
func (a *Accumulator) Add(y int) {
*a += Accumulator(y)
}
BEING IMPURE
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a.Add(x)
}
os.Exit(int(a))
}
var a Accumulator
type Accumulator int
func (a *Accumulator) Add(y int) {
*a += Accumulator(y)
}
BEING IMPURE
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a.Add(x)
}
os.Exit(int(a))
}
var a Accumulator
type Accumulator int
func (a *Accumulator) Add(y int) {
*a += Accumulator(y)
}
BEING IMPURE
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a.Add(x)
}
os.Exit(int(a))
}
var a Accumulator
type Accumulator int
func (a Accumulator) Add(y int) {
a += Accumulator(y)
}
FUNCTIONS WITH MEMORY
FUNCTIONS
AS
PARADIGM
FUNCTIONS WITH MEMORY
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a(0))
}
var a = MakeAccumulator()
func MakeAccumulator() func(int) int {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS WITH MEMORY
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a(0))
}
var a = MakeAccumulator()
func MakeAccumulator() func(int) int {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS WITH MEMORY
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a(0))
}
var a = MakeAccumulator()
func MakeAccumulator() func(int) int {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS WITH MEMORY
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a(0))
}
var a = MakeAccumulator()
func MakeAccumulator() func(int) int {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS WITH MEMORY
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a(0))
}
var a = MakeAccumulator()
func MakeAccumulator() func(int) int {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS WITH MEMORY
package main
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a(0))
}
var a = MakeAccumulator()
type Accumulator func(int) int
func MakeAccumulator() Accumulator {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS WITH MEMORY
package main
import "os"
import "strconv"
func main() {
a := MakeAccumulator()
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a(0))
}
type Accumulator func(int) int
func MakeAccumulator() Accumulator {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS WITH MEMORY
package main
import "os"
import "strconv"
func main() {
a := MakeAccumulator()
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a(0))
}
func MakeAccumulator() func(int) int {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS AS OBJECTS
FUNCTIONS
AS
PARADIGM
FUNCTIONS AS OBJECTS
package main
import "os"
import "strconv"
func main() {
a := MakeAccumulator()
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a.Int())
}
type Accumulator func(int) int
func MakeAccumulator() Accumulator {
var y int
return func(x int) int {
y += x
return y
}
}
func (a Accumulator) Int() int {
return a(0)
}
FUNCTIONS AS OBJECTS
package main
import "os"
import "strconv"
func main() {
a := MakeAccumulator()
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a(x)
}
os.Exit(a.Int())
}
type Accumulator func(int) int
func MakeAccumulator() Accumulator {
var y int
return func(x int) int {
y += x
return y
}
}
func (a Accumulator) Int() int {
return a(0)
}
FUNCTIONS AS OBJECTS
package main func (a Accumulator) Int() int {
import "os" return a(0)
import "strconv" }
func main() { func (a Accumulator) Add(x
a := MakeAccumulator() interface{}) {
for _, v := range os.Args[1:] { switch x := x.(type) {
x, _ := strconv.Atoi(v) case int:
a.Add(x) a(x)
} case Accumulator:
os.Exit(a.Int()) a(x.Value())
} }
}
type Accumulator func(int) int
func MakeAccumulator() Accumulator {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS AS OBJECTS
package main func (a Accumulator) Int() int {
import "os" return a(0)
import "strconv" }
func main() { func (a Accumulator) Add(x
a := MakeAccumulator() interface{}) {
for _, v := range os.Args[1:] { switch x := x.(type) {
x, _ := strconv.Atoi(v) case int:
a.Add(MakeAccumulator()(x)) a(x)
} case Accumulator:
os.Exit(a.Int()) a(x.Value())
} }
}
type Accumulator func(int) int
func MakeAccumulator() Accumulator {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS AS OBJECTS
package main func (a Accumulator) Int() int {
import "os" return a(0)
import "strconv" }
func main() { func (a Accumulator) Add(x interface{}) {
a := MakeAccumulator() switch x := x.(type) {
for _, v := range os.Args[1:] { case int:
x, _ := strconv.Atoi(v) a(x)
a.Add(MakeAccumulator()(x)) case Integer:
} a(x.Int())
os.Exit(a.Int()) }
} }
type Accumulator func(int) int
type Integer interface {
Int() int
}
func MakeAccumulator() Accumulator {
var y int
return func(x int) int {
y += x
return y
}
}
FUNCTIONS
IN
MATHEMATICS
COMPUTING FACTORIALS
COMPUTING FACTORIALS
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
ITERATING FACTORIALS
FUNCTIONS
IN
MATHEMATICS
ITERATING FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = 1
for ; n > 0; n-- {
r *= n
}
}
return
}
ITERATING FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = 1
for ; n > 0; n-- {
r *= n
}
}
return
}
ITERATING FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = 1
for ; n > 0; n-- {
r *= n
}
}
return
}
ITERATING FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = 1
for ; n > 0; n-- {
r *= n
}
}
return
}
ITERATING FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = 1
for ; n > 0; n-- {
r *= n
}
}
return
}
ITERATING FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = 1
for ; n > 0; n-- {
r *= n
}
}
return
}
ITERATING FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) int {
r := 1
switch {
case n < 0:
panic(n)
case n > 0:
for ; n > 0; n-- {
r *= n
}
}
return r
}
ITERATING FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
ITERATING FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
MULTIPLE FACTORIALS
FUNCTIONS
IN
MATHEMATICS
MULTIPLE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
for _, v := range os.Args[1:] {
if x, e := strconv.Atoi(v); e != nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
MULTIPLE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
for _, v := range os.Args[1:] {
if x, e := strconv.Atoi(v); e != nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
MULTIPLE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
for _, v := range os.Args[1:] {
if x, e := strconv.Atoi(v); e == nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
MULTIPLE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
for _, v := range os.Args[1:] {
if x, e := strconv.Atoi(v); e == nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
MULTIPLE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
for _, v := range os.Args[1:] {
if x, e := strconv.Atoi(v); e == nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
MULTIPLE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
for _, v := range os.Args[1:] {
if x, e := strconv.Atoi(v); e == nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
MULTIPLE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
if x, e := strconv.Atoi(v); e == nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
HIGHER ORDER FUNCTIONS
FUNCTIONS
IN
MATHEMATICS
HIGHER ORDER FUNCTIONS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
func() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
if x, e := strconv.Atoi(v); e == nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}()
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
HIGHER ORDER FUNCTIONS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
func() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
if x, e := strconv.Atoi(v); e == nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}()
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
HIGHER ORDER FUNCTIONS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
func() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
if x, e := strconv.Atoi(v); e == nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}()
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
HIGHER ORDER FUNCTIONS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
func() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
if x, e := strconv.Atoi(v); e == nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}()
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
for _, v := range os.Args[1:] { }
SafeExecute(func(i int) { return
Printf("%v!: %v\n", i, Factorial(i)) }
})(v)
}
}
func SafeExecute(f func(int)) func(string) {
return func(v string) {
defer func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
for _, v := range os.Args[1:] { }
SafeExecute(func(i int) { return
Printf("%v!: %v\n", i, Factorial(i)) }
})(v)
}
}
func SafeExecute(f func(int)) func(string) {
return func(v string) {
defer func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
for _, v := range os.Args[1:] { }
SafeExecute(func(i int) { return
Printf("%v!: %v\n", i, Factorial(i)) }
})(v)
}
}
func SafeExecute(f func(int)) func(string) {
return func(v string) {
defer func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
for _, v := range os.Args[1:] { }
SafeExecute(func(i int) { return
Printf("%v!: %v\n", i, Factorial(i)) }
})(v)
}
}
func SafeExecute(f func(int)) func(string) {
return func(v string) {
defer func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
var errors int }
f := func(i int) { return
Printf("%v!: %v\n", i, Factorial(i)) }
}
for _, v := range os.Args[1:] {
if !SafeExecute(f)(v) {
errors++
}
}
os.Exit(errors)
}
func SafeExecute(f func(int)) func(string) bool {
return func(v string) (r bool) {
defer func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
r = true
} else {
panic(v)
}
return
}
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
var errors int }
f := func(i int) { return
Printf("%v!: %v\n", i, Factorial(i)) }
}
for _, v := range os.Args[1:] {
if !SafeExecute(f)(v) {
errors++
}
}
os.Exit(errors)
}
func SafeExecute(f func(int)) func(string) bool {
return func(v string) (r bool) {
defer func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
r = true
} else {
panic(v)
}
return
}
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
var errors int }
f := func(i int) { return
Printf("%v!: %v\n", i, Factorial(i)) }
}
for _, v := range os.Args[1:] {
if !SafeExecute(f)(v) {
errors++
}
}
os.Exit(errors)
}
func SafeExecute(f func(int)) func(string) bool {
return func(v string) (r bool) {
defer func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
r = true
} else {
panic(v)
}
return
}
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
var errors int }
f := func(i int) { return
Printf("%v!: %v\n", i, Factorial(i)) }
}
for _, v := range os.Args[1:] {
if !SafeExecute(f)(v) {
errors++
}
}
os.Exit(errors)
}
func SafeExecute(f func(int)) func(string) bool {
return func(v string) (r bool) {
defer func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
r = true
} else {
panic(v)
}
return
}
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
var errors int }
for _, v := range os.Args[1:] { return
SafeExecute( }
func(i int) {
Printf("%v!: %v\n", i, Factorial(i))
},
func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
errors++
}
},
)(v)
}
os.Exit(errors)
}
func SafeExecute(f func(int), e func()) func(string) {
return func(v string) {
defer e()
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
HIGHER ORDER FUNCTIONS
package main func Factorial(n int) (r int) {
import . "fmt" if n < 0 {
import "os" panic(n)
import "strconv" }
for r = 1; n > 0; n-- {
func main() { r *= n
var errors int }
for _, v := range os.Args[1:] { return
SafeExecute( }
func(i int) {
Printf("%v!: %v\n", i, Factorial(i))
},
func() {
if x := recover(); x != nil {
Printf("no defined value for %v\n", x)
errors++
}
},
)(v)
}
os.Exit(errors)
}
func SafeExecute(f func(int), e func()) func(string) {
return func(v string) {
defer e()
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
CURRYING
FUNCTIONS
IN
MATHEMATICS
CURRYING
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanicFor(UseNumericParam(v, func(i int) { if n < 0 {
Printf("%v!: %v\n", i, Factorial(i)) panic(n)
}), PrintErrorMessage) }
} for r = 1; n > 0; n-- {
} r *= n
}
func UseNumericParam(v string, f func(i int)) func() { return
return func() { }
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanicFor(f, e func()) {
defer e()
f()
}
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanicFor(UseNumericParam(v, func(i int) { if n < 0 {
Printf("%v!: %v\n", i, Factorial(i)) panic(n)
}), PrintErrorMessage) }
} for r = 1; n > 0; n-- {
} r *= n
}
func UseNumericParam(v string, f func(i int)) func() { return
return func() { }
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanicFor(f, e func()) {
defer e()
f()
}
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanicFor(UseNumericParam(v, func(i int) { if n < 0 {
Printf("%v!: %v\n", i, Factorial(i)) panic(n)
}), PrintErrorMessage) }
} for r = 1; n > 0; n-- {
} r *= n
}
func UseNumericParam(v string, f func(i int)) func() { return
return func() { }
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanicFor(f, e func()) {
defer e()
f()
}
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanicFor(UseNumericParam(v, func(i int) { if n < 0 {
Printf("%v!: %v\n", i, Factorial(i)) panic(n)
}), PrintErrorMessage) }
} for r = 1; n > 0; n-- {
} r *= n
}
func UseNumericParam(v string, f func(i int)) func() { return
return func() { }
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanicFor(f, e func()) {
defer e()
f()
}
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanicFor(UseNumericParam(v, func(i int) { if n < 0 {
Printf("%v!: %v\n", i, Factorial(i)) panic(n)
}), PrintErrorMessage)() }
} for r = 1; n > 0; n-- {
} r *= n
}
func UseNumericParam(v string, f func(i int)) func() { return
return func() { }
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanicFor(f, e func()) func() {
return func() {
defer e()
f()
}
}
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanicFor(UseNumericParam(v, func(i int) { if n < 0 {
Printf("%v!: %v\n", i, Factorial(i)) panic(n)
}), PrintErrorMessage)() }
} for r = 1; n > 0; n-- {
} r *= n
}
func UseNumericParam(v string, f func(i int)) func() { return
return func() { }
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanicFor(f, e func()) func() {
return func() {
defer e()
f()
}
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanic(PrintErrorMessage)( if n < 0 {
UseNumericParam(v, func(i int) { panic(n)
Printf("%v!: %v\n", i, Factorial(i)) }
})) for r = 1; n > 0; n-- {
} r *= n
} }
return
func UseNumericParam(v string, f func(i int)) func() { }
return func() {
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanic(PrintErrorMessage)( if n < 0 {
UseNumericParam(v, func(i int) { panic(n)
Printf("%v!: %v\n", i, Factorial(i)) }
})) for r = 1; n > 0; n-- {
} r *= n
} }
return
func UseNumericParam(v string, f func(i int)) func() { }
return func() {
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanic(PrintErrorMessage)( if n < 0 {
UseNumericParam(v, func(i int) { panic(n)
Printf("%v!: %v\n", i, Factorial(i)) }
})) for r = 1; n > 0; n-- {
} r *= n
} }
return
func UseNumericParam(v string, f func(i int)) func() { }
return func() {
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
CURRYING
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
p := OnPanic(PrintErrorMessage) func Factorial(n int) (r int) {
for _, v := range os.Args[1:] { if n < 0 {
p(UseNumericParam(v, func(i int) { panic(n)
Printf("%v!: %v\n", i, Factorial(i)) }
})) for r = 1; n > 0; n-- {
} r *= n
} }
return
func UseNumericParam(v string, f func(i int)) func() { }
return func() {
if x, e := strconv.Atoi(v); e == nil {
f(x)
} else {
panic(v)
}
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
RECURSION
FUNCTIONS
IN
MATHEMATICS
RECURSION
package main
func main() {
main()
}
RECURSION
package main
func main() {
main()
}
RECURSION
package main
func main() {
main()
}
RECURSION
package main
func main() {
defer func() {
recover()
}
main()
}
RECURSION
package main
import "os"
import"strconv"
var limit int
func init() {
if x, e := strconv.Atoi(os.Args[1]); e == nil {
limit = x
}
}
func main() {
limit--
if limit > 0 {
main()
}
}
RECURSION
package main
import "os"
import"strconv"
var limit int
func init() {
if x, e := strconv.Atoi(os.Args[1]); e == nil {
limit = x
}
}
func main() {
limit--
if limit > 0 {
main()
}
}
RECURSION
package main
import "os"
import"strconv"
var limit int
func init() {
if x, e := strconv.Atoi(os.Args[1]); e == nil {
limit = x
}
}
func main() {
limit--
if limit > 0 {
main()
}
}
RECURSION
package main
import "os"
import"strconv"
var limit int
func init() {
if x, e := strconv.Atoi(os.Args[1]); e == nil {
limit = x
}
}
func main() {
limit--
if limit > 0 {
main()
}
}
RECURSIVE FACTORIALS
FUNCTIONS
IN
MATHEMATICS
RECURSIVE FACTORIALS
RECURSIVE FACTORIALS
RECURSIVE FACTORIALS
RECURSIVE FACTORIALS
RECURSIVE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = 1
for ; n > 0; n-- {
r *= n
}
}
return
}
RECURSIVE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = 1
for ; n > 0; n-- {
r *= n
}
}
return
}
RECURSIVE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = 1
for ; n > 0; n-- {
r *= n
}
}
return
}
RECURSIVE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
x, _ := strconv.Atoi(os.Args[1])
Printf("%v!: %v\n", x, Factorial(x))
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * Factorial(n - 1)
}
return
}
RECURSIVE FACTORIALS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
defer func() {
if x := recover(); x != nil {
Println("no factorial")
}
}()
for _, v := range os.Args[1:] {
if x, e := strconv.Atoi(v); e != nil {
Printf("%v!: %v\n", x, Factorial(x))
} else {
panic(v)
}
}
}
func Factorial(n int) (r int) {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * Factorial(n - 1)
}
return
}
RECURSIVE FACTORIALS
package main func PrintErrorMessage() {
import . "fmt" if x := recover(); x != nil {
import "os" Printf("no defined value for %v\n", x)
import "strconv" }
}
func main() {
for _, v := range os.Args[1:] { func Factorial(n int) (r int) {
OnPanic(PrintErrorMessage)( switch {
UseNumericParam(v, func(i int) { case n < 0:
Printf("%v!: %v\n", i, Factorial(i)) panic(n)
})) case n == 0:
} r = 1
} default:
r = n * Factorial(n - 1)
func UseNumericParam(v string, f func(i int)) func() { }
return func() { return
if x, e := strconv.Atoi(v); e == nil { }
f(x)
} else {
panic(v)
}
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
RECURSIVE FACTORIALS
package main func Each(s []string, f func(string)) {
import . "fmt" for _, v := range s {
import "os" f(v)
import "strconv" }
}
func main() {
Each(os.Args[1:], func(v string) { func PrintErrorMessage() {
OnPanic(PrintErrorMessage)( if x := recover(); x != nil {
UseNumericParam(v, func(i int) { Printf("no defined value for %v\n", x)
Printf("%v!: %v\n", i, Factorial(i)) }
})) }
})
} func Factorial(n int) (r int) {
switch {
func UseNumericParam(v string, f func(i int)) func() { case n < 0:
return func() { panic(n)
if x, e := strconv.Atoi(v); e == nil { case n == 0:
f(x) r = 1
} else { default:
panic(v) r = n * Factorial(n - 1)
} }
} return
} }
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
RECURSIVE FACTORIALS
package main func Each(s []string, f func(string)) {
import . "fmt" for _, v := range s {
import "os" f(v)
import "strconv" }
}
func main() {
Each(os.Args[1:], func(v string) { func PrintErrorMessage() {
OnPanic(PrintErrorMessage)( if x := recover(); x != nil {
UseNumericParam(v, func(i int) { Printf("no defined value for %v\n", x)
Printf("%v!: %v\n", i, Factorial(i)) }
})) }
})
} func Factorial(n int) (r int) {
switch {
func UseNumericParam(v string, f func(i int)) func() { case n < 0:
return func() { panic(n)
if x, e := strconv.Atoi(v); e == nil { case n == 0:
f(x) r = 1
} else { default:
panic(v) r = n * Factorial(n - 1)
} }
} return
} }
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
RECURSIVE FACTORIALS
package main func Each(s []string, f func(string)) {
import . "fmt" for _, v := range s {
import "os" f(v)
import "strconv" }
}
func main() {
Each(os.Args[1:], func(v string) { func PrintErrorMessage() {
OnPanic(PrintErrorMessage)( if x := recover(); x != nil {
UseNumericParam(v, func(i int) { Printf("no defined value for %v\n", x)
Printf("%v!: %v\n", i, Factorial(i)) }
})) }
})
} func Factorial(n int) (r int) {
switch {
func UseNumericParam(v string, f func(i int)) func() { case n < 0:
return func() { panic(n)
if x, e := strconv.Atoi(v); e == nil { case n == 0:
f(x) r = 1
} else { default:
panic(v) r = n * Factorial(n - 1)
} }
} return
} }
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
RECURSIVE FACTORIALS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)( func PrintErrorMessage() {
UseNumericParam(v, func(i int) { if x := recover(); x != nil {
Printf("%v!: %v\n", i, Factorial(i)) Printf("no defined value for %v\n", x)
})) }
}) }
}
func Factorial(n int) (r int) {
func UseNumericParam(v string, f func(i int)) func() { switch {
return func() { case n < 0:
if x, e := strconv.Atoi(v); e == nil { panic(n)
f(x) case n == 0:
} else { r = 1
panic(v) default:
} r = n * Factorial(n - 1)
} }
} return
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
RECURSIVE FACTORIALS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)( func PrintErrorMessage() {
UseNumericParam(v, func(i int) { if x := recover(); x != nil {
Printf("%v!: %v\n", i, Factorial(i)) Printf("no defined value for %v\n", x)
})) }
}) }
}
func Factorial(n int) (r int) {
func UseNumericParam(v string, f func(i int)) func() { switch {
return func() { case n < 0:
if x, e := strconv.Atoi(v); e == nil { panic(n)
f(x) case n == 0:
} else { r = 1
panic(v) default:
} r = n * Factorial(n - 1)
} }
} return
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
RECURSIVE FACTORIALS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)( func PrintErrorMessage() {
UseNumericParam(v, func(i int) { if x := recover(); x != nil {
Printf("%v!: %v\n", i, Factorial(i)) Printf("no defined value for %v\n", x)
})) }
}) }
}
func Factorial(n int) (r int) {
func UseNumericParam(v string, f func(i int)) func() { switch {
return func() { case n < 0:
if x, e := strconv.Atoi(v); e == nil { panic(n)
f(x) case n == 0:
} else { r = 1
panic(v) default:
} r = n * Factorial(n - 1)
} }
} return
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
RECURSIVE FACTORIALS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)( func PrintErrorMessage() {
UseNumericParam(v, func(i int) { if x := recover(); x != nil {
Printf("%v!: %v\n", i, Factorial(i)) Printf("no defined value for %v\n", x)
})) }
}) }
}
func Factorial(n int) (r int) {
func UseNumericParam(v string, f func(i int)) func() { switch {
return func() { case n < 0:
if x, e := strconv.Atoi(v); e == nil { panic(n)
f(x) case n == 0:
} else { r = 1
panic(v) default:
} r = n * Factorial(n - 1)
} }
} return
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
CACHING RESULTS
FUNCTIONS
IN
MATHEMATICS
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)( func OnPanic(e func()) func(func()) {
UseNumericParam(v, func(i int) { return func(f func()) {
Printf("%v!: %v\n", i, Factorial(i)) defer e()
})) f()
}) }
} }
func PrintErrorMessage() { var cache map[int] int = make(map[int] int)
if x := recover(); x != nil {
Printf("no defined value for %v\n", x) func Factorial(n int) (r int) {
} if r = cache[n]; r == 0 {
} switch {
case n < 0:
func UseNumericParam(v string, f func(i int)) func() { panic(n)
return func() { case n == 0:
if x, e := strconv.Atoi(v); e == nil { r = 1
f(x) default:
} else { r = n * Factorial(n - 1)
panic(v) }
} cache[n] = r
} }
} return
}
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)( func OnPanic(e func()) func(func()) {
UseNumericParam(v, func(i int) { return func(f func()) {
Printf("%v!: %v\n", i, Factorial(i)) defer e()
})) f()
}) }
} }
func PrintErrorMessage() { var cache map[int] int = make(map[int] int)
if x := recover(); x != nil {
Printf("no defined value for %v\n", x) func Factorial(n int) (r int) {
} if r = cache[n]; r == 0 {
} switch {
case n < 0:
func UseNumericParam(v string, f func(i int)) func() { panic(n)
return func() { case n == 0:
if x, e := strconv.Atoi(v); e == nil { r = 1
f(x) default:
} else { r = n * Factorial(n - 1)
panic(v) }
} cache[n] = r
} }
} return
}
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)( func OnPanic(e func()) func(func()) {
UseNumericParam(v, func(i int) { return func(f func()) {
Printf("%v!: %v\n", i, Factorial(i)) defer e()
})) f()
}) }
} }
func PrintErrorMessage() { var cache map[int] int = make(map[int] int)
if x := recover(); x != nil {
Printf("no defined value for %v\n", x) func Factorial(n int) (r int) {
} if r = cache[n]; r == 0 {
} switch {
case n < 0:
func UseNumericParam(v string, f func(i int)) func() { panic(n)
return func() { case n == 0:
if x, e := strconv.Atoi(v); e == nil { r = 1
f(x) default:
} else { r = n * Factorial(n - 1)
panic(v) }
} cache[n] = r
} }
} return
}
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)( func OnPanic(e func()) func(func()) {
UseNumericParam(v, func(i int) { return func(f func()) {
Printf("%v!: %v\n", i, Factorial(i)) defer e()
})) f()
}) }
} }
func PrintErrorMessage() { var cache map[int] int = make(map[int] int)
if x := recover(); x != nil {
Printf("no defined value for %v\n", x) func Factorial(n int) (r int) {
} if r = cache[n]; r == 0 {
} switch {
case n < 0:
func UseNumericParam(v string, f func(i int)) func() { panic(n)
return func() { case n == 0:
if x, e := strconv.Atoi(v); e == nil { r = 1
f(x) default:
} else { r = n * Factorial(n - 1)
panic(v) }
} cache[n] = r
} }
} return
}
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)( func OnPanic(e func()) func(func()) {
UseNumericParam(v, func(i int) { return func(f func()) {
Printf("%v!: %v\n", i, Factorial(i)) defer e()
})) f()
}) }
} }
func PrintErrorMessage() { var cache map[int] int = make(map[int] int)
if x := recover(); x != nil {
Printf("no defined value for %v\n", x) func Factorial(n int) (r int) {
} if r = cache[n]; r == 0 {
} switch {
case n < 0:
func UseNumericParam(v string, f func(i int)) func() { panic(n)
return func() { case n == 0:
if x, e := strconv.Atoi(v); e == nil { r = 1
f(x) default:
} else { r = n * Factorial(n - 1)
panic(v) }
} cache[n] = r
} }
} return
}
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
c := make(Cache)
Each(os.Args[1:], func(v string) { func OnPanic(e func()) func(func()) {
OnPanic(PrintErrorMessage)( return func(f func()) {
UseNumericParam(v, func(i int) { defer e()
Printf("%v!: %v\n", i, c.Factorial(i)) f()
})) }
}) }
}
type Cache map[int] int
func PrintErrorMessage() {
if x := recover(); x != nil { func (c Cache) Factorial(n int) (r int) {
Printf("no defined value for %v\n", x) if r = c[n]; r == 0 {
} switch {
} case n < 0:
panic(n)
func UseNumericParam(v string, f func(i int)) func() { case n == 0:
return func() { r = 1
if x, e := strconv.Atoi(v); e == nil { default:
f(x) r = n * c.Factorial(n - 1)
} else { }
panic(v) c[n] = r
} }
} return
} }
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
c := make(Cache)
Each(os.Args[1:], func(v string) { func OnPanic(e func()) func(func()) {
OnPanic(PrintErrorMessage)( return func(f func()) {
UseNumericParam(v, func(i int) { defer e()
Printf("%v!: %v\n", i, c.Factorial(i)) f()
})) }
}) }
}
type Cache map[int] int
func PrintErrorMessage() {
if x := recover(); x != nil { func (c Cache) Factorial(n int) (r int) {
Printf("no defined value for %v\n", x) if r = c[n]; r == 0 {
} switch {
} case n < 0:
panic(n)
func UseNumericParam(v string, f func(i int)) func() { case n == 0:
return func() { r = 1
if x, e := strconv.Atoi(v); e == nil { default:
f(x) r = n * c.Factorial(n - 1)
} else { }
panic(v) c[n] = r
} }
} return
} }
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
f := MakeFactorial()
Each(os.Args[1:], func(v string) { func OnPanic(e func()) func(func()) {
OnPanic(PrintErrorMessage)( return func(f func()) {
UseNumericParam(v, func(i int) { defer e()
Printf("%v!: %v\n", i, f(i)) f()
})) }
}) }
}
func MakeFactorial() (f func(int) int) {
func PrintErrorMessage() { c := make(map[int] int)
if x := recover(); x != nil { return func(n int) (r int) {
Printf("no defined value for %v\n", x) if r = c[n]; r == 0 {
} switch {
} case n < 0:
panic(n)
func UseNumericParam(v string, f func(i int)) func() { case n == 0:
return func() { r = 1
if x, e := strconv.Atoi(v); e == nil { default:
f(x) r = n * f(n - 1)
} else { }
panic(v) c[n] = r
} }
} return
} }
}
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
f := MakeFactorial()
Each(os.Args[1:], func(v string) { func OnPanic(e func()) func(func()) {
OnPanic(PrintErrorMessage)( return func(f func()) {
UseNumericParam(v, func(i int) { defer e()
Printf("%v!: %v\n", i, f(i)) f()
})) }
}) }
}
func MakeFactorial() (f func(int) int) {
func PrintErrorMessage() { c := make(map[int] int)
if x := recover(); x != nil { return func(n int) (r int) {
Printf("no defined value for %v\n", x) if r = c[n]; r == 0 {
} switch {
} case n < 0:
panic(n)
func UseNumericParam(v string, f func(i int)) func() { case n == 0:
return func() { r = 1
if x, e := strconv.Atoi(v); e == nil { default:
f(x) r = n * f(n - 1)
} else { }
panic(v) c[n] = r
} }
} return
} }
}
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
f := MakeFactorial()
Each(os.Args[1:], func(v string) { func OnPanic(e func()) func(func()) {
OnPanic(PrintErrorMessage)( return func(f func()) {
UseNumericParam(v, func(i int) { defer e()
Printf("%v!: %v\n", i, f(i)) f()
})) }
}) }
}
func MakeFactorial() (f func(int) int) {
func PrintErrorMessage() { c := make(map[int] int)
if x := recover(); x != nil { return func(n int) (r int) {
Printf("no defined value for %v\n", x) if r = c[n]; r == 0 {
} switch {
} case n < 0:
panic(n)
func UseNumericParam(v string, f func(i int)) func() { case n == 0:
return func() { r = 1
if x, e := strconv.Atoi(v); e == nil { default:
f(x) r = n * f(n - 1)
} else { }
panic(v) c[n] = r
} }
} return
} }
}
CACHING RESULTS
package main func Each(s []string, f func(string)) {
import . "fmt" if len(s) > 0 {
import "os" f(s[0])
import "strconv" Each(s[1:], f)
}
func main() { }
f := MakeFactorial()
Each(os.Args[1:], func(v string) { func OnPanic(e func()) func(func()) {
OnPanic(PrintErrorMessage)( return func(f func()) {
UseNumericParam(v, func(i int) { defer e()
Printf("%v!: %v\n", i, f(i)) f()
})) }
}) }
}
func MakeFactorial() (f func(int) int) {
func PrintErrorMessage() { c := make(map[int] int)
if x := recover(); x != nil { return func(n int) (r int) {
Printf("no defined value for %v\n", x) if r = c[n]; r == 0 {
} switch {
} case n < 0:
panic(n)
func UseNumericParam(v string, f func(i int)) func() { case n == 0:
return func() { r = 1
if x, e := strconv.Atoi(v); e == nil { default:
f(x) r = n * f(n - 1)
} else { }
panic(v) c[n] = r
} }
} return
} }
}