SlideShare a Scribd company logo
AN
INTRODUCTION
TO
FUNCTIONAL PROGRAMMING
IN
GO
ELEANOR MCHUGH
ELEANOR MCHUGH
@feyeleanor
APPLIED PHYSICIST
MISAPPLIED HACKER
EMBEDDED SYSTEMS
VIRTUAL MACHINES
DIGITAL IDENTITY
RUBY
GO
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
IMPERATIVE
PROGRAMMING
THE CONDITIONAL LOOP
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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", i, s[i])
}
}
IMPERATIVE
PROGRAMMING
AN EXCEPTIONAL LOOP
AN EXCEPTIONAL LOOP
package main
import . "fmt"
func main() {
defer func() {
recover()
}()
s := []int{0, 2, 4, 6, 8}
i := 0
for {
Printf("%v: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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 i := 0; ; i++ {
Printf("%v: %vn", i, s[i])
i++
}
}
IMPERATIVE
PROGRAMMING
ENUMERABLE RANGES
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %vn", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %vn", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %vn", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %vn", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %vn", i, v)
}
}
ENUMERABLE RANGES
package main
import . "fmt"
func main() {
s := []int{0, 2, 4, 6, 8}
for i, v := range s {
Printf("%v: %vn", i, v)
}
}
PROGRAMMINGWITH
FUNCTIONS
PROGRAMMINGWITH
FUNCTIONS
ENUMERATION BY FUNCTION
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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", i, v)
}
}
PROGRAMMINGWITH
FUNCTIONS
TYPE ABSTRACTION
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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", i, v)
}
}
}
PROGRAMMINGWITH
FUNCTIONS
FUNCTIONS AS VALUES
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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", i, f(s, i))
}
}
PROGRAMMINGWITH
FUNCTIONS
CLOSURES
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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", i, s(i))
}
}
}
PROGRAMMINGWITH
FUNCTIONS
CONCURRENCY
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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", i, v)
i++
}
return
}
PROGRAMMINGWITH
FUNCTIONS
INFINITE SEQUENCES
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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", i, <- c)
}
return
}
PROGRAMMINGWITH
FUNCTIONS
WORKING WITH KINDS
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: %vn", i, s(i))
}
case []int:
for i, v := range s {
Printf("%v: %vn", 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: %vn", i, s(i))
}
case []int:
for i, v := range s {
Printf("%v: %vn", 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: %vn", i, s(i))
}
case []int:
for i, v := range s {
Printf("%v: %vn", 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: %vn", i, s(i))
}
case []int:
for i, v := range s {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
}
case reflect.Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
}
case reflect.Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
}
case reflect.Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
}
case reflect.Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
}
case Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
}
case Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
}
case Slice:
for i := 0; i < s.Len(); i++ {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
}
case Slice:
for i := 0; ; i++ {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
})
case Slice:
for_each(func(i int) {
Printf("%v: %vn", 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: %vn", i, s.Call(p)[0].Interface())
})
case Slice:
for_each(func(i int) {
Printf("%v: %vn", i, s.Index(i).Interface())
})
}
}
func for_each(f func(int)) (i int) {
defer func() {
recover()
}
for ; ; i++ {
f(i)
}
}
PROGRAMMINGWITH
OBJECTS
PROGRAMMINGWITH
OBJECTS
TYPES + METHODS = 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", i, v)
i++
})
}
type IterableSlice []int
func (i IterableSlice) Each(f func(interface{})) {
for _, v := range i {
f(v)
}
}
PROGRAMMINGWITH
OBJECTS
INTERFACES = POLYMORPHISM
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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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)
}
}
PROGRAMMINGWITH
OBJECTS
IMMUTABILITY IS A CHOICE
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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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: %vn", 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
}
}
OO makes code understandable by
encapsulating moving parts.
FP makes code understandable by
minimizing moving parts.
Michael Feathers
@mfeathers
LEANPUB://GONOTEBOOK
FUNCTIONSAS
PARADIGM
FUNCTIONSAS
PARADIGM
A PURE FUNCTION
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
}
FUNCTIONSAS
PARADIGM
BEING IMPURE
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)
}
FUNCTIONSAS
PARADIGM
FUNCTIONS WITH MEMORY
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
}
}
FUNCTIONSAS
PARADIGM
FUNCTIONS AS OBJECTS
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
import "os"
import "strconv"
func main() {
a := MakeAccumulator()
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a.Add(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)
}
func (a Accumulator) Add(x
interface{}) {
switch x := x.(type) {
case int:
a(x)
case Accumulator:
a(x.Value())
}
}
FUNCTIONS AS OBJECTS
package main
import "os"
import "strconv"
func main() {
a := MakeAccumulator()
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a.Add(MakeAccumulator()(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)
}
func (a Accumulator) Add(x
interface{}) {
switch x := x.(type) {
case int:
a(x)
case Accumulator:
a(x.Value())
}
}
FUNCTIONS AS OBJECTS
package main
import "os"
import "strconv"
func main() {
a := MakeAccumulator()
for _, v := range os.Args[1:] {
x, _ := strconv.Atoi(v)
a.Add(MakeAccumulator()(x))
}
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
}
}
func (a Accumulator) Int() int {
return a(0)
}
func (a Accumulator) Add(x interface{}) {
switch x := x.(type) {
case int:
a(x)
case Integer:
a(x.Int())
}
}
FUNCTIONSIN
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
FUNCTIONSIN
MATHEMATICS
ITERATING FACTORIALS
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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", x, Factorial(x))
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
FUNCTIONSIN
MATHEMATICS
MULTIPLE FACTORIALS
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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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
}
FUNCTIONSIN
MATHEMATICS
HIGHER ORDER FUNCTIONS
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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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:] {
SafeExecute(func(i int) {
Printf("%v!: %vn", 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 %vn", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(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:] {
SafeExecute(func(i int) {
Printf("%v!: %vn", 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 %vn", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(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:] {
SafeExecute(func(i int) {
Printf("%v!: %vn", 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 %vn", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(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:] {
SafeExecute(func(i int) {
Printf("%v!: %vn", 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 %vn", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(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() {
var errors int
f := func(i int) {
Printf("%v!: %vn", 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 %vn", x)
s}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
r = true
} else {
panic(v)
}
return
}
}
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() {
var errors int
f := func(i int) {
Printf("%v!: %vn", 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 %vn", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
r = true
} else {
panic(v)
}
return
}
}
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() {
var errors int
f := func(i int) {
Printf("%v!: %vn", 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 %vn", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
r = true
} else {
panic(v)
}
return
}
}
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() {
var errors int
f := func(i int) {
Printf("%v!: %vn", 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 %vn", x)
}
}()
if x, e := strconv.Atoi(v); e == nil {
f(x)
r = true
} else {
panic(v)
}
return
}
}
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() {
var errors int
for _, v := range os.Args[1:] {
SafeExecute(
func(i int) {
Printf("%v!: %vn", i, Factorial(i))
},
func() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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)
}
}
}
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() {
var errors int
for _, v := range os.Args[1:] {
SafeExecute(
func(i int) {
Printf("%v!: %vn", i, Factorial(i))
},
func() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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)
}
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
FUNCTIONSIN
MATHEMATICS
CURRYING
CURRYING
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanicFor(UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}), PrintErrorMessage)
}
}
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 OnPanicFor(f, e func()) {
defer e()
f()
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanicFor(UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}), PrintErrorMessage)
}
}
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 OnPanicFor(f, e func()) {
defer e()
f()
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanicFor(UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}), PrintErrorMessage)
}
}
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 OnPanicFor(f, e func()) {
defer e()
f()
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanicFor(UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}), PrintErrorMessage)
}
}
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 OnPanicFor(f, e func()) {
defer e()
f()
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanicFor(UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}), PrintErrorMessage)()
}
}
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 OnPanicFor(f, e func()) func() {
return func() {
defer e()
f()
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanicFor(UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}), PrintErrorMessage)()
}
}
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 OnPanicFor(f, e func()) func() {
return func() {
defer e()
f()
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
}
}
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()
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
}
}
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()
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
}
}
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()
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
CURRYING
package main
import . "fmt"
import "os"
import "strconv"
func main() {
p := OnPanic(PrintErrorMessage)
for _, v := range os.Args[1:] {
p(UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
}
}
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()
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
func Factorial(n int) (r int) {
if n < 0 {
panic(n)
}
for r = 1; n > 0; n-- {
r *= n
}
return
}
FUNCTIONSIN
MATHEMATICS
RECURSION
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()
}
}
FUNCTIONSIN
MATHEMATICS
RECURSIVE FACTORIALS
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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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!: %vn", 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
import . "fmt"
import "os"
import "strconv"
func main() {
for _, v := range os.Args[1:] {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
}
}
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()
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
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()
}
}
func Each(s []string, f func(string)) {
for _, v := range s {
f(v)
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
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()
}
}
func Each(s []string, f func(string)) {
for _, v := range s {
f(v)
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
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()
}
}
func Each(s []string, f func(string)) {
for _, v := range s {
f(v)
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
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()
}
}
func Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
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()
}
}
func Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
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()
}
}
func Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
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()
}
}
func Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", 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
}
FUNCTIONSIN
MATHEMATICS
CACHING RESULTS
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
var cache map[int] int = make(map[int] int)
func Factorial(n int) (r int) {
if r = cache[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * Factorial(n - 1)
}
cache[n] = r
}
return
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
var cache map[int] int = make(map[int] int)
func Factorial(n int) (r int) {
if r = cache[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * Factorial(n - 1)
}
cache[n] = r
}
return
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
var cache map[int] int = make(map[int] int)
func Factorial(n int) (r int) {
if r = cache[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * Factorial(n - 1)
}
cache[n] = r
}
return
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
var cache map[int] int = make(map[int] int)
func Factorial(n int) (r int) {
if r = cache[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * Factorial(n - 1)
}
cache[n] = r
}
return
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, Factorial(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
var cache map[int] int = make(map[int] int)
func Factorial(n int) (r int) {
if r = cache[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * Factorial(n - 1)
}
cache[n] = r
}
return
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
c := make(Cache)
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, c.Factorial(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
type Cache map[int] int
func (c Cache) Factorial(n int) (r int) {
if r = c[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * c.Factorial(n - 1)
}
c[n] = r
}
return
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
c := make(Cache)
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, c.Factorial(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
type Cache map[int] int
func (c Cache) Factorial(n int) (r int) {
if r = c[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * c.Factorial(n - 1)
}
c[n] = r
}
return
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
f := MakeFactorial()
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, f(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
func MakeFactorial() (f func(int) int) {
c := make(map[int] int)
return func(n int) (r int) {
if r = c[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * f(n - 1)
}
c[n] = r
}
return
}
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
f := MakeFactorial()
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, f(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
func MakeFactorial() (f func(int) int) {
c := make(map[int] int)
return func(n int) (r int) {
if r = c[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * f(n - 1)
}
c[n] = r
}
return
}
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
f := MakeFactorial()
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, f(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
func MakeFactorial() (f func(int) int) {
c := make(map[int] int)
return func(n int) (r int) {
if r = c[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * f(n - 1)
}
c[n] = r
}
return
}
}
CACHING RESULTS
package main
import . "fmt"
import "os"
import "strconv"
func main() {
f := MakeFactorial()
Each(os.Args[1:], func(v string) {
OnPanic(PrintErrorMessage)(
UseNumericParam(v, func(i int) {
Printf("%v!: %vn", i, f(i))
}))
})
}
func PrintErrorMessage() {
if x := recover(); x != nil {
Printf("no defined value for %vn", x)
}
}
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 Each(s []string, f func(string)) {
if len(s) > 0 {
f(s[0])
Each(s[1:], f)
}
}
func OnPanic(e func()) func(func()) {
return func(f func()) {
defer e()
f()
}
}
func MakeFactorial() (f func(int) int) {
c := make(map[int] int)
return func(n int) (r int) {
if r = c[n]; r == 0 {
switch {
case n < 0:
panic(n)
case n == 0:
r = 1
default:
r = n * f(n - 1)
}
c[n] = r
}
return
}
}
An introduction to functional programming with go

More Related Content

What's hot (20)

PPTX
Kotlin collections
Myeongin Woo
 
PDF
10〜30ćˆ†ă§äœ•ăšăȘく戆かるGo
Moriyoshi Koizumi
 
PDF
IntroducciĂłn a Elixir
Svet Ivantchev
 
PDF
Python Performance 101
Ankur Gupta
 
PDF
Implementing Virtual Machines in Go & C
Eleanor McHugh
 
PPTX
Dts x dicoding #2 memulai pemrograman kotlin
Ahmad Arif Faizin
 
PDF
Un dsl pour ma base de données
Romain Lecomte
 
PDF
Imugi: Compiler made with Python
Han Lee
 
PDF
6. Generics. Collections. Streams
DEVTYPE
 
PDF
Are we ready to Go?
Adam Dudczak
 
PDF
FS2 for Fun and Profit
Adil Akhter
 
DOCX
2 a networkflow
Aravindharamanan S
 
PPT
Python лДгĐșĐŸ Đž ĐżŃ€ĐŸŃŃ‚ĐŸ. КрасоĐČĐŸ Ń€Đ”ŃˆĐ°Đ”ĐŒ ĐżĐŸĐČŃĐ”ĐŽĐœĐ”ĐČĐœŃ‹Đ” заЎачО
Maxim Kulsha
 
PDF
Go for the paranoid network programmer, 2nd edition
Eleanor McHugh
 
PDF
Programmation fonctionnelle en JavaScript
LoĂŻc Knuchel
 
PDF
20191116 custom operators in swift
Chiwon Song
 
PDF
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Fabio Collini
 
DOC
Awt
Swarup Saha
 
KEY
Python Yield
yangjuven
 
PDF
Introduction to Go for Java Programmers
Kalpa Pathum Welivitigoda
 
Kotlin collections
Myeongin Woo
 
10〜30ćˆ†ă§äœ•ăšăȘく戆かるGo
Moriyoshi Koizumi
 
IntroducciĂłn a Elixir
Svet Ivantchev
 
Python Performance 101
Ankur Gupta
 
Implementing Virtual Machines in Go & C
Eleanor McHugh
 
Dts x dicoding #2 memulai pemrograman kotlin
Ahmad Arif Faizin
 
Un dsl pour ma base de données
Romain Lecomte
 
Imugi: Compiler made with Python
Han Lee
 
6. Generics. Collections. Streams
DEVTYPE
 
Are we ready to Go?
Adam Dudczak
 
FS2 for Fun and Profit
Adil Akhter
 
2 a networkflow
Aravindharamanan S
 
Python лДгĐșĐŸ Đž ĐżŃ€ĐŸŃŃ‚ĐŸ. КрасоĐČĐŸ Ń€Đ”ŃˆĐ°Đ”ĐŒ ĐżĐŸĐČŃĐ”ĐŽĐœĐ”ĐČĐœŃ‹Đ” заЎачО
Maxim Kulsha
 
Go for the paranoid network programmer, 2nd edition
Eleanor McHugh
 
Programmation fonctionnelle en JavaScript
LoĂŻc Knuchel
 
20191116 custom operators in swift
Chiwon Song
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Fabio Collini
 
Python Yield
yangjuven
 
Introduction to Go for Java Programmers
Kalpa Pathum Welivitigoda
 

Similar to An introduction to functional programming with go (20)

PDF
going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...
Codemotion
 
PDF
Going Loopy - Adventures in Iteration with Google Go
Eleanor McHugh
 
PDF
going loopy - adventures in iteration with google go
Eleanor McHugh
 
KEY
Going Loopy
Eleanor McHugh
 
PDF
Hello Go
Eleanor McHugh
 
PDF
[2024] An Introduction to Functional Programming with Go [Y Combinator Remix]...
Eleanor McHugh
 
PDF
Implementing Software Machines in Go and C
Eleanor McHugh
 
PPTX
Golang iran - tutorial go programming language - Preliminary
go-lang
 
PPT
lets play with "c"..!!! :):)
Rupendra Choudhary
 
PDF
Y - Recursion The Hard Way GopherCon EU 2025
Eleanor McHugh
 
PDF
Generics, Reflection, and Efficient Collections
Eleanor McHugh
 
PDF
Python-GTK
Yuren Ju
 
PPTX
Golang basics for Java developers - Part 1
Robert Stern
 
PDF
Something about Golang
Anton Arhipov
 
DOCX
Basic python laboratoty_ PSPP Manual .docx
Kirubaburi R
 
PDF
Go ahead, make my day
Tor Ivry
 
PDF
Torchbearersnotebook.blogspot.com program to create a list in python and valu...
SAKSHISINGH486
 
PDF
III MCS python lab (1).pdf
srxerox
 
PDF
goatwork2014
Bryan Liles
 
going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...
Codemotion
 
Going Loopy - Adventures in Iteration with Google Go
Eleanor McHugh
 
going loopy - adventures in iteration with google go
Eleanor McHugh
 
Going Loopy
Eleanor McHugh
 
Hello Go
Eleanor McHugh
 
[2024] An Introduction to Functional Programming with Go [Y Combinator Remix]...
Eleanor McHugh
 
Implementing Software Machines in Go and C
Eleanor McHugh
 
Golang iran - tutorial go programming language - Preliminary
go-lang
 
lets play with "c"..!!! :):)
Rupendra Choudhary
 
Y - Recursion The Hard Way GopherCon EU 2025
Eleanor McHugh
 
Generics, Reflection, and Efficient Collections
Eleanor McHugh
 
Python-GTK
Yuren Ju
 
Golang basics for Java developers - Part 1
Robert Stern
 
Something about Golang
Anton Arhipov
 
Basic python laboratoty_ PSPP Manual .docx
Kirubaburi R
 
Go ahead, make my day
Tor Ivry
 
Torchbearersnotebook.blogspot.com program to create a list in python and valu...
SAKSHISINGH486
 
III MCS python lab (1).pdf
srxerox
 
goatwork2014
Bryan Liles
 
Ad

More from Eleanor McHugh (20)

PDF
Never Say, Never Say Die! - the art of low-level Ruby and other Macabre Tales
Eleanor McHugh
 
PDF
[2023] Putting the R! in R&D.pdf
Eleanor McHugh
 
PDF
The Relevance of Liveness - Biometrics and Data Integrity
Eleanor McHugh
 
PDF
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
Eleanor McHugh
 
PDF
The Browser Environment - A Systems Programmer's Perspective
Eleanor McHugh
 
PDF
Go for the paranoid network programmer, 3rd edition
Eleanor McHugh
 
PDF
An introduction to functional programming with Go [redux]
Eleanor McHugh
 
PDF
Identity & trust in Monitored Spaces
Eleanor McHugh
 
PDF
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Eleanor McHugh
 
PDF
Don't ask, don't tell the virtues of privacy by design
Eleanor McHugh
 
PDF
Anonymity, identity, trust
Eleanor McHugh
 
PDF
Distributed Ledgers: Anonymity & Immutability at Scale
Eleanor McHugh
 
PDF
Finding a useful outlet for my many Adventures in go
Eleanor McHugh
 
PDF
Anonymity, trust, accountability
Eleanor McHugh
 
PDF
Implementing Virtual Machines in Ruby & C
Eleanor McHugh
 
PDF
Implementing Software Machines in C and Go
Eleanor McHugh
 
PDF
Encrypt all transports
Eleanor McHugh
 
PDF
Whispered secrets
Eleanor McHugh
 
PDF
Whispered secrets
Eleanor McHugh
 
PDF
Privacy is always a requirement
Eleanor McHugh
 
Never Say, Never Say Die! - the art of low-level Ruby and other Macabre Tales
Eleanor McHugh
 
[2023] Putting the R! in R&D.pdf
Eleanor McHugh
 
The Relevance of Liveness - Biometrics and Data Integrity
Eleanor McHugh
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
Eleanor McHugh
 
The Browser Environment - A Systems Programmer's Perspective
Eleanor McHugh
 
Go for the paranoid network programmer, 3rd edition
Eleanor McHugh
 
An introduction to functional programming with Go [redux]
Eleanor McHugh
 
Identity & trust in Monitored Spaces
Eleanor McHugh
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Eleanor McHugh
 
Don't ask, don't tell the virtues of privacy by design
Eleanor McHugh
 
Anonymity, identity, trust
Eleanor McHugh
 
Distributed Ledgers: Anonymity & Immutability at Scale
Eleanor McHugh
 
Finding a useful outlet for my many Adventures in go
Eleanor McHugh
 
Anonymity, trust, accountability
Eleanor McHugh
 
Implementing Virtual Machines in Ruby & C
Eleanor McHugh
 
Implementing Software Machines in C and Go
Eleanor McHugh
 
Encrypt all transports
Eleanor McHugh
 
Whispered secrets
Eleanor McHugh
 
Whispered secrets
Eleanor McHugh
 
Privacy is always a requirement
Eleanor McHugh
 
Ad

Recently uploaded (20)

PDF
Capcut Pro Crack For PC Latest Version {Fully Unlocked} 2025
hashhshs786
 
PDF
Letasoft Sound Booster 1.12.0.538 Crack Download+ Product Key [Latest]
HyperPc soft
 
PDF
Executive Business Intelligence Dashboards
vandeslie24
 
PDF
Continouous failure - Why do we make our lives hard?
Papp KrisztiĂĄn
 
PPTX
Fundamentals_of_Microservices_Architecture.pptx
MuhammadUzair504018
 
PPTX
Equipment Management Software BIS Safety UK.pptx
BIS Safety Software
 
PPTX
Tally software_Introduction_Presentation
AditiBansal54083
 
PPTX
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
PDF
Revenue streams of the Wazirx clone script.pdf
aaronjeffray
 
PPTX
A Complete Guide to Salesforce SMS Integrations Build Scalable Messaging With...
360 SMS APP
 
PPTX
Platform for Enterprise Solution - Java EE5
abhishekoza1981
 
PDF
GridView,Recycler view, API, SQLITE& NetworkRequest.pdf
Nabin Dhakal
 
PPTX
Revolutionizing Code Modernization with AI
KrzysztofKkol1
 
PPTX
Writing Better Code - Helping Developers make Decisions.pptx
Lorraine Steyn
 
PPTX
MiniTool Power Data Recovery Full Crack Latest 2025
muhammadgurbazkhan
 
PPTX
How Apagen Empowered an EPC Company with Engineering ERP Software
SatishKumar2651
 
PDF
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
PPTX
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
PDF
Salesforce CRM Services.VALiNTRY360
VALiNTRY360
 
PDF
Unlock Efficiency with Insurance Policy Administration Systems
Insurance Tech Services
 
Capcut Pro Crack For PC Latest Version {Fully Unlocked} 2025
hashhshs786
 
Letasoft Sound Booster 1.12.0.538 Crack Download+ Product Key [Latest]
HyperPc soft
 
Executive Business Intelligence Dashboards
vandeslie24
 
Continouous failure - Why do we make our lives hard?
Papp KrisztiĂĄn
 
Fundamentals_of_Microservices_Architecture.pptx
MuhammadUzair504018
 
Equipment Management Software BIS Safety UK.pptx
BIS Safety Software
 
Tally software_Introduction_Presentation
AditiBansal54083
 
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
Revenue streams of the Wazirx clone script.pdf
aaronjeffray
 
A Complete Guide to Salesforce SMS Integrations Build Scalable Messaging With...
360 SMS APP
 
Platform for Enterprise Solution - Java EE5
abhishekoza1981
 
GridView,Recycler view, API, SQLITE& NetworkRequest.pdf
Nabin Dhakal
 
Revolutionizing Code Modernization with AI
KrzysztofKkol1
 
Writing Better Code - Helping Developers make Decisions.pptx
Lorraine Steyn
 
MiniTool Power Data Recovery Full Crack Latest 2025
muhammadgurbazkhan
 
How Apagen Empowered an EPC Company with Engineering ERP Software
SatishKumar2651
 
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
Salesforce CRM Services.VALiNTRY360
VALiNTRY360
 
Unlock Efficiency with Insurance Policy Administration Systems
Insurance Tech Services
 

An introduction to functional programming with go

  • 2. ELEANOR MCHUGH @feyeleanor APPLIED PHYSICIST MISAPPLIED HACKER EMBEDDED SYSTEMS VIRTUAL MACHINES DIGITAL IDENTITY RUBY GO
  • 3. 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
  • 6. A SIMPLE TASK 0: 0 1: 2 2: 4 3: 6 4: 8
  • 8. 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: %vn", i, s[i]) } }
  • 9. 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: %vn", i, s[i]) } }
  • 10. 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: %vn", i, s[i]) } }
  • 11. 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: %vn", i, s[i]) } }
  • 12. 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: %vn", i, s[i]) } }
  • 13. 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: %vn", i, s[i]) } }
  • 14. 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: %vn", i, s[i]) } }
  • 15. 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: %vn", i, s[i]) } }
  • 16. 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: %vn", i, s[i]) } }
  • 17. 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: %vn", i, s[i]) } }
  • 18. 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: %vn", i, s[i]) } }
  • 19. 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: %vn", i, s[i]) } }
  • 20. 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: %vn", i, s[i]) } }
  • 21. 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: %vn", i, s[i]) } }
  • 22. 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: %vn", i, s[i]) } }
  • 23. 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: %vn", i, s[i]) } }
  • 24. 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: %vn", i, s[i]) } }
  • 26. AN EXCEPTIONAL LOOP package main import . "fmt" func main() { defer func() { recover() }() s := []int{0, 2, 4, 6, 8} i := 0 for { Printf("%v: %vn", i, s[i]) i++ } }
  • 27. AN EXCEPTIONAL LOOP package main import . "fmt" func main() { defer func() { recover() }() s := []int{0, 2, 4, 6, 8} i := 0 for { Printf("%v: %vn", i, s[i]) i++ } }
  • 28. AN EXCEPTIONAL LOOP package main import . "fmt" func main() { defer func() { recover() }() s := []int{0, 2, 4, 6, 8} i := 0 for { Printf("%v: %vn", i, s[i]) i++ } }
  • 29. AN EXCEPTIONAL LOOP package main import . "fmt" func main() { defer func() { recover() }() s := []int{0, 2, 4, 6, 8} i := 0 for { Printf("%v: %vn", i, s[i]) i++ } }
  • 30. AN EXCEPTIONAL LOOP package main import . "fmt" func main() { defer func() { recover() }() s := []int{0, 2, 4, 6, 8} i := 0 for { Printf("%v: %vn", i, s[i]) i++ } }
  • 31. AN EXCEPTIONAL LOOP package main import . "fmt" func main() { defer func() { recover() }() s := []int{0, 2, 4, 6, 8} i := 0 for { Printf("%v: %vn", i, s[i]) i++ } }
  • 32. AN EXCEPTIONAL LOOP package main import . "fmt" func main() { defer func() { recover() }() s := []int{0, 2, 4, 6, 8} i := 0 for i := 0; ; i++ { Printf("%v: %vn", i, s[i]) i++ } }
  • 34. ENUMERABLE RANGES package main import . "fmt" func main() { s := []int{0, 2, 4, 6, 8} for i, v := range s { Printf("%v: %vn", i, v) } }
  • 35. ENUMERABLE RANGES package main import . "fmt" func main() { s := []int{0, 2, 4, 6, 8} for i, v := range s { Printf("%v: %vn", i, v) } }
  • 36. ENUMERABLE RANGES package main import . "fmt" func main() { s := []int{0, 2, 4, 6, 8} for i, v := range s { Printf("%v: %vn", i, v) } }
  • 37. ENUMERABLE RANGES package main import . "fmt" func main() { s := []int{0, 2, 4, 6, 8} for i, v := range s { Printf("%v: %vn", i, v) } }
  • 38. ENUMERABLE RANGES package main import . "fmt" func main() { s := []int{0, 2, 4, 6, 8} for i, v := range s { Printf("%v: %vn", i, v) } }
  • 39. ENUMERABLE RANGES package main import . "fmt" func main() { s := []int{0, 2, 4, 6, 8} for i, v := range s { Printf("%v: %vn", i, v) } }
  • 42. 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: %vn", i, v) } }
  • 43. 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: %vn", i, v) } }
  • 44. 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: %vn", i, v) } }
  • 45. 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: %vn", i, v) } }
  • 46. 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: %vn", i, v) } }
  • 48. 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: %vn", i, v) } }
  • 49. 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: %vn", i, v) } }
  • 50. 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: %vn", i, v) } }
  • 51. 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: %vn", i, v) } } }
  • 52. 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: %vn", i, v) } } }
  • 53. 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: %vn", i, v) } } }
  • 54. 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: %vn", i, v) } } }
  • 55. 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: %vn", i, v) } } }
  • 56. 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: %vn", i, v) } } }
  • 57. 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: %vn", i, v) } } }
  • 59. 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: %vn", i, f(i)) } }
  • 60. 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: %vn", i, f(i)) } }
  • 61. 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: %vn", i, f(s, i)) } }
  • 62. 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: %vn", i, f(s, i)) } }
  • 63. 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: %vn", i, f(s, i)) } }
  • 64. 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: %vn", i, f(s, i)) } }
  • 65. 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: %vn", i, f(s, i)) } }
  • 67. 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: %vn", i, s(i)) } } }
  • 68. 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: %vn", i, s(i)) } } }
  • 69. 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: %vn", i, s(i)) } } }
  • 70. 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: %vn", i, s(i)) } } }
  • 71. 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: %vn", i, s(i)) } } }
  • 72. 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: %vn", i, s(i)) } } }
  • 73. 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: %vn", i, s(i)) } } }
  • 74. 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: %vn", i, s(i)) } } }
  • 76. 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: %vn", i, v) i++ } return }
  • 77. 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: %vn", i, v) i++ } return }
  • 78. 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: %vn", i, v) i++ } return }
  • 79. 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: %vn", i, v) i++ } return }
  • 80. 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: %vn", i, v) i++ } return }
  • 81. 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: %vn", i, v) i++ } return }
  • 82. 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: %vn", i, v) i++ } return }
  • 83. 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: %vn", i, v) i++ } return }
  • 84. 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: %vn", i, v) i++ } return }
  • 85. 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: %vn", i, v) i++ } return }
  • 86. 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: %vn", i, v) i++ } return }
  • 88. 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: %vn", i, <- c) } return }
  • 89. 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: %vn", i, <- c) } return }
  • 90. 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: %vn", i, <- c) } return }
  • 91. 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: %vn", i, <- c) } return }
  • 92. 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: %vn", i, <- c) } return }
  • 94. 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: %vn", i, s(i)) } case []int: for i, v := range s { Printf("%v: %vn", i, v) } } }
  • 95. 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: %vn", i, s(i)) } case []int: for i, v := range s { Printf("%v: %vn", i, v) } } }
  • 96. 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: %vn", i, s(i)) } case []int: for i, v := range s { Printf("%v: %vn", i, v) } } }
  • 97. 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: %vn", i, s(i)) } case []int: for i, v := range s { Printf("%v: %vn", i, v) } } }
  • 98. 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: %vn", i, s.Call(p)[0].Interface()) } case reflect.Slice: for i := 0; i < s.Len(); i++ { Printf("%v: %vn", i, s.Index(i).Interface()) } } }
  • 99. 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: %vn", i, s.Call(p)[0].Interface()) } case reflect.Slice: for i := 0; i < s.Len(); i++ { Printf("%v: %vn", i, s.Index(i).Interface()) } } }
  • 100. 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: %vn", i, s.Call(p)[0].Interface()) } case reflect.Slice: for i := 0; i < s.Len(); i++ { Printf("%v: %vn", i, s.Index(i).Interface()) } } }
  • 101. 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: %vn", i, s.Call(p)[0].Interface()) } case reflect.Slice: for i := 0; i < s.Len(); i++ { Printf("%v: %vn", i, s.Index(i).Interface()) } } }
  • 102. 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: %vn", i, s.Call(p)[0].Interface()) } case Slice: for i := 0; i < s.Len(); i++ { Printf("%v: %vn", i, s.Index(i).Interface()) } } }
  • 103. 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: %vn", i, s.Call(p)[0].Interface()) } case Slice: for i := 0; i < s.Len(); i++ { Printf("%v: %vn", i, s.Index(i).Interface()) } } }
  • 104. 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: %vn", i, s.Call(p)[0].Interface()) } case Slice: for i := 0; i < s.Len(); i++ { Printf("%v: %vn", i, s.Index(i).Interface()) } } }
  • 105. 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: %vn", i, s.Call(p)[0].Interface()) } case Slice: for i := 0; ; i++ { Printf("%v: %vn", i, s.Index(i).Interface()) } } }
  • 106. 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: %vn", i, s.Call(p)[0].Interface()) }) case Slice: for_each(func(i int) { Printf("%v: %vn", i, s.Index(i).Interface()) }) } } func for_each(f func(int)) (i int) { defer func() { recover() } for ; ; i++ { f(i) } }
  • 107. 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: %vn", i, s.Call(p)[0].Interface()) }) case Slice: for_each(func(i int) { Printf("%v: %vn", i, s.Index(i).Interface()) }) } } func for_each(f func(int)) (i int) { defer func() { recover() } for ; ; i++ { f(i) } }
  • 110. 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: %vn", i, v) i++ }) } type IterableSlice []int func (i IterableSlice) Each(f func(interface{})) { for _, v := range i { f(v) } }
  • 111. 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: %vn", i, v) i++ }) } type IterableSlice []int func (i IterableSlice) Each(f func(interface{})) { for _, v := range i { f(v) } }
  • 112. 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: %vn", i, v) i++ }) } type IterableSlice []int func (i IterableSlice) Each(f func(interface{})) { for _, v := range i { f(v) } }
  • 113. 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: %vn", i, v) i++ }) } type IterableSlice []int func (i IterableSlice) Each(f func(interface{})) { for _, v := range i { f(v) } }
  • 114. 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: %vn", i, v) i++ }) } type IterableSlice []int func (i IterableSlice) Each(f func(interface{})) { for _, v := range i { f(v) } }
  • 116. 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: %vn", 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) } }
  • 117. 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: %vn", 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) } }
  • 118. 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: %vn", 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) } }
  • 119. 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: %vn", 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) } }
  • 120. 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: %vn", 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) } }
  • 121. 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: %vn", 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) } }
  • 122. 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: %vn", 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) } }
  • 124. 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: %vn", 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 } }
  • 125. 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: %vn", 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 } }
  • 126. 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: %vn", 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 } }
  • 127. 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: %vn", 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 } }
  • 128. 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: %vn", 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 } }
  • 129. 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: %vn", 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 } }
  • 130. OO makes code understandable by encapsulating moving parts. FP makes code understandable by minimizing moving parts. Michael Feathers @mfeathers LEANPUB://GONOTEBOOK
  • 133. A PURE FUNCTION package main import "os" func main() { os.Exit(add(3, 4)) } func add(x, y int) int { return x + y }
  • 134. A PURE FUNCTION package main import "os" func main() { os.Exit(add(3, 4)) } func add(x, y int) int { return x + y }
  • 135. A PURE FUNCTION package main import "os" func main() { os.Exit(add(3, 4)) } func add(x int, y int) int { return x + y }
  • 136. A PURE FUNCTION package main import "os" func main() { os.Exit(add(3, 4)) } func add(x int, y int) int { return x + y }
  • 137. A PURE FUNCTION package main import "os" func main() { os.Exit(add(3, 4)) } func add(x int, y int) int { return x + y }
  • 138. 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 }
  • 139. 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 }
  • 140. 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 }
  • 141. 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 }
  • 142. 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 }
  • 143. 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 }
  • 145. 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 }
  • 146. 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 }
  • 147. 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 }
  • 148. 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 }
  • 149. 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) }
  • 150. 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) }
  • 151. 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) }
  • 152. 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) }
  • 154. 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 } }
  • 155. 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 } }
  • 156. 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 } }
  • 157. 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 } }
  • 158. 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 } }
  • 159. 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 } }
  • 160. 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 } }
  • 161. 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 } }
  • 163. 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) }
  • 164. 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) }
  • 165. FUNCTIONS AS OBJECTS package main import "os" import "strconv" func main() { a := MakeAccumulator() for _, v := range os.Args[1:] { x, _ := strconv.Atoi(v) a.Add(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) } func (a Accumulator) Add(x interface{}) { switch x := x.(type) { case int: a(x) case Accumulator: a(x.Value()) } }
  • 166. FUNCTIONS AS OBJECTS package main import "os" import "strconv" func main() { a := MakeAccumulator() for _, v := range os.Args[1:] { x, _ := strconv.Atoi(v) a.Add(MakeAccumulator()(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) } func (a Accumulator) Add(x interface{}) { switch x := x.(type) { case int: a(x) case Accumulator: a(x.Value()) } }
  • 167. FUNCTIONS AS OBJECTS package main import "os" import "strconv" func main() { a := MakeAccumulator() for _, v := range os.Args[1:] { x, _ := strconv.Atoi(v) a.Add(MakeAccumulator()(x)) } 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 } } func (a Accumulator) Int() int { return a(0) } func (a Accumulator) Add(x interface{}) { switch x := x.(type) { case int: a(x) case Integer: a(x.Int()) } }
  • 170. COMPUTING FACTORIALS 0! = 1 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 6! = 720 7! = 5040 8! = 40320 9! = 362880
  • 172. 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!: %vn", 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 }
  • 173. 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!: %vn", 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 }
  • 174. 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!: %vn", 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 }
  • 175. 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!: %vn", 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 }
  • 176. 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!: %vn", 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 }
  • 177. 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!: %vn", 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 }
  • 178. 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!: %vn", 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 }
  • 179. 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!: %vn", x, Factorial(x)) } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 180. 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!: %vn", x, Factorial(x)) } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 182. 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!: %vn", 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 }
  • 183. 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!: %vn", 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 }
  • 184. 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!: %vn", 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 }
  • 185. 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!: %vn", 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 }
  • 186. 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!: %vn", 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 }
  • 187. 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!: %vn", 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 }
  • 188. 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!: %vn", 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 }
  • 190. 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!: %vn", 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 }
  • 191. 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!: %vn", 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 }
  • 192. 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!: %vn", 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 }
  • 193. 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!: %vn", 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 }
  • 194. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { SafeExecute(func(i int) { Printf("%v!: %vn", 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 %vn", x) } }() if x, e := strconv.Atoi(v); e == nil { f(x) } else { panic(v) } } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 195. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { SafeExecute(func(i int) { Printf("%v!: %vn", 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 %vn", x) } }() if x, e := strconv.Atoi(v); e == nil { f(x) } else { panic(v) } } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 196. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { SafeExecute(func(i int) { Printf("%v!: %vn", 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 %vn", x) } }() if x, e := strconv.Atoi(v); e == nil { f(x) } else { panic(v) } } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 197. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { SafeExecute(func(i int) { Printf("%v!: %vn", 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 %vn", x) } }() if x, e := strconv.Atoi(v); e == nil { f(x) } else { panic(v) } } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 198. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { var errors int f := func(i int) { Printf("%v!: %vn", 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 %vn", x) s} }() if x, e := strconv.Atoi(v); e == nil { f(x) r = true } else { panic(v) } return } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 199. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { var errors int f := func(i int) { Printf("%v!: %vn", 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 %vn", x) } }() if x, e := strconv.Atoi(v); e == nil { f(x) r = true } else { panic(v) } return } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 200. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { var errors int f := func(i int) { Printf("%v!: %vn", 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 %vn", x) } }() if x, e := strconv.Atoi(v); e == nil { f(x) r = true } else { panic(v) } return } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 201. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { var errors int f := func(i int) { Printf("%v!: %vn", 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 %vn", x) } }() if x, e := strconv.Atoi(v); e == nil { f(x) r = true } else { panic(v) } return } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 202. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { var errors int for _, v := range os.Args[1:] { SafeExecute( func(i int) { Printf("%v!: %vn", i, Factorial(i)) }, func() { if x := recover(); x != nil { Printf("no defined value for %vn", 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) } } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 203. HIGHER ORDER FUNCTIONS package main import . "fmt" import "os" import "strconv" func main() { var errors int for _, v := range os.Args[1:] { SafeExecute( func(i int) { Printf("%v!: %vn", i, Factorial(i)) }, func() { if x := recover(); x != nil { Printf("no defined value for %vn", 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) } } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 206. CURRYING package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanicFor(UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) }), PrintErrorMessage) } } 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 OnPanicFor(f, e func()) { defer e() f() } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 207. CURRYING package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanicFor(UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) }), PrintErrorMessage) } } 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 OnPanicFor(f, e func()) { defer e() f() } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 208. CURRYING package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanicFor(UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) }), PrintErrorMessage) } } 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 OnPanicFor(f, e func()) { defer e() f() } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 209. CURRYING package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanicFor(UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) }), PrintErrorMessage) } } 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 OnPanicFor(f, e func()) { defer e() f() } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 210. CURRYING package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanicFor(UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) }), PrintErrorMessage)() } } 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 OnPanicFor(f, e func()) func() { return func() { defer e() f() } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 211. CURRYING package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanicFor(UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) }), PrintErrorMessage)() } } 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 OnPanicFor(f, e func()) func() { return func() { defer e() f() } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 212. CURRYING package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) } } 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() } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 213. CURRYING package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) } } 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() } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 214. CURRYING package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) } } 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() } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 215. CURRYING package main import . "fmt" import "os" import "strconv" func main() { p := OnPanic(PrintErrorMessage) for _, v := range os.Args[1:] { p(UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) } } 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() } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } func Factorial(n int) (r int) { if n < 0 { panic(n) } for r = 1; n > 0; n-- { r *= n } return }
  • 220. RECURSION package main func main() { defer func() { recover() } main() }
  • 221. 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() } }
  • 222. 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() } }
  • 223. 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() } }
  • 224. 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() } }
  • 230. 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!: %vn", 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 }
  • 231. 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!: %vn", 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 }
  • 232. 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!: %vn", 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 }
  • 233. 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!: %vn", 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 }
  • 234. 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!: %vn", 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 }
  • 235. RECURSIVE FACTORIALS package main import . "fmt" import "os" import "strconv" func main() { for _, v := range os.Args[1:] { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) } } 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() } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", 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 }
  • 236. RECURSIVE FACTORIALS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } 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() } } func Each(s []string, f func(string)) { for _, v := range s { f(v) } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", 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 }
  • 237. RECURSIVE FACTORIALS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } 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() } } func Each(s []string, f func(string)) { for _, v := range s { f(v) } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", 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 }
  • 238. RECURSIVE FACTORIALS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } 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() } } func Each(s []string, f func(string)) { for _, v := range s { f(v) } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", 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 }
  • 239. RECURSIVE FACTORIALS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } 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() } } func Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", 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 }
  • 240. RECURSIVE FACTORIALS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } 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() } } func Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", 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 }
  • 241. RECURSIVE FACTORIALS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } 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() } } func Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", 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 }
  • 242. RECURSIVE FACTORIALS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } 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() } } func Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", 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 }
  • 244. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } var cache map[int] int = make(map[int] int) func Factorial(n int) (r int) { if r = cache[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * Factorial(n - 1) } cache[n] = r } return }
  • 245. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } var cache map[int] int = make(map[int] int) func Factorial(n int) (r int) { if r = cache[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * Factorial(n - 1) } cache[n] = r } return }
  • 246. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } var cache map[int] int = make(map[int] int) func Factorial(n int) (r int) { if r = cache[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * Factorial(n - 1) } cache[n] = r } return }
  • 247. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } var cache map[int] int = make(map[int] int) func Factorial(n int) (r int) { if r = cache[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * Factorial(n - 1) } cache[n] = r } return }
  • 248. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, Factorial(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } var cache map[int] int = make(map[int] int) func Factorial(n int) (r int) { if r = cache[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * Factorial(n - 1) } cache[n] = r } return }
  • 249. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { c := make(Cache) Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, c.Factorial(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } type Cache map[int] int func (c Cache) Factorial(n int) (r int) { if r = c[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * c.Factorial(n - 1) } c[n] = r } return }
  • 250. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { c := make(Cache) Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, c.Factorial(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } type Cache map[int] int func (c Cache) Factorial(n int) (r int) { if r = c[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * c.Factorial(n - 1) } c[n] = r } return }
  • 251. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { f := MakeFactorial() Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, f(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } func MakeFactorial() (f func(int) int) { c := make(map[int] int) return func(n int) (r int) { if r = c[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * f(n - 1) } c[n] = r } return } }
  • 252. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { f := MakeFactorial() Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, f(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } func MakeFactorial() (f func(int) int) { c := make(map[int] int) return func(n int) (r int) { if r = c[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * f(n - 1) } c[n] = r } return } }
  • 253. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { f := MakeFactorial() Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, f(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } func MakeFactorial() (f func(int) int) { c := make(map[int] int) return func(n int) (r int) { if r = c[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * f(n - 1) } c[n] = r } return } }
  • 254. CACHING RESULTS package main import . "fmt" import "os" import "strconv" func main() { f := MakeFactorial() Each(os.Args[1:], func(v string) { OnPanic(PrintErrorMessage)( UseNumericParam(v, func(i int) { Printf("%v!: %vn", i, f(i)) })) }) } func PrintErrorMessage() { if x := recover(); x != nil { Printf("no defined value for %vn", x) } } 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 Each(s []string, f func(string)) { if len(s) > 0 { f(s[0]) Each(s[1:], f) } } func OnPanic(e func()) func(func()) { return func(f func()) { defer e() f() } } func MakeFactorial() (f func(int) int) { c := make(map[int] int) return func(n int) (r int) { if r = c[n]; r == 0 { switch { case n < 0: panic(n) case n == 0: r = 1 default: r = n * f(n - 1) } c[n] = r } return } }