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

Kotlin collections
Kotlin collectionsKotlin collections
Kotlin collections
Myeongin Woo
 
10〜30分で何となく分かるGo
10〜30分で何となく分かるGo10〜30分で何となく分かるGo
10〜30分で何となく分かるGoMoriyoshi Koizumi
 
Introducción a Elixir
Introducción a ElixirIntroducción a Elixir
Introducción a Elixir
Svet Ivantchev
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101Ankur Gupta
 
Implementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CImplementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & C
Eleanor McHugh
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlin
Ahmad Arif Faizin
 
Un dsl pour ma base de données
Un dsl pour ma base de donnéesUn dsl pour ma base de données
Un dsl pour ma base de données
Romain Lecomte
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
Han Lee
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. Streams
DEVTYPE
 
Are we ready to Go?
Are we ready to Go?Are we ready to Go?
Are we ready to Go?
Adam Dudczak
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and Profit
Adil Akhter
 
2 a networkflow
2 a networkflow2 a networkflow
2 a networkflow
Aravindharamanan S
 
Python легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачиPython легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачи
Maxim Kulsha
 
Go for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionGo for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd edition
Eleanor McHugh
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
Loïc Knuchel
 
20191116 custom operators in swift
20191116 custom operators in swift20191116 custom operators in swift
20191116 custom operators in swift
Chiwon Song
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinAsync code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Fabio Collini
 
Python Yield
Python YieldPython Yield
Python Yield
yangjuven
 
Introduction to Go for Java Programmers
Introduction to Go for Java ProgrammersIntroduction to Go for Java Programmers
Introduction to Go for Java Programmers
Kalpa Pathum Welivitigoda
 

What's hot (20)

Kotlin collections
Kotlin collectionsKotlin collections
Kotlin collections
 
10〜30分で何となく分かるGo
10〜30分で何となく分かるGo10〜30分で何となく分かるGo
10〜30分で何となく分かるGo
 
Introducción a Elixir
Introducción a ElixirIntroducción a Elixir
Introducción a Elixir
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101
 
Implementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CImplementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & C
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlin
 
Un dsl pour ma base de données
Un dsl pour ma base de donnéesUn dsl pour ma base de données
Un dsl pour ma base de données
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. Streams
 
Are we ready to Go?
Are we ready to Go?Are we ready to Go?
Are we ready to Go?
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and Profit
 
2 a networkflow
2 a networkflow2 a networkflow
2 a networkflow
 
Python легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачиPython легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачи
 
Go for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionGo for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd edition
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
 
20191116 custom operators in swift
20191116 custom operators in swift20191116 custom operators in swift
20191116 custom operators in swift
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinAsync code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
 
Awt
AwtAwt
Awt
 
Python Yield
Python YieldPython Yield
Python Yield
 
Introduction to Go for Java Programmers
Introduction to Go for Java ProgrammersIntroduction to Go for Java Programmers
Introduction to Go for Java Programmers
 

Similar to An introduction to functional programming with go

going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...
going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...
going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...
Codemotion
 
Going Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoGoing Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google Go
Eleanor McHugh
 
going loopy - adventures in iteration with google go
going loopy - adventures in iteration with google gogoing loopy - adventures in iteration with google go
going loopy - adventures in iteration with google go
Eleanor McHugh
 
Going Loopy
Going LoopyGoing Loopy
Going Loopy
Eleanor McHugh
 
Hello Go
Hello GoHello Go
Hello Go
Eleanor McHugh
 
Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and C
Eleanor McHugh
 
Golang iran - tutorial go programming language - Preliminary
Golang iran - tutorial  go programming language - PreliminaryGolang iran - tutorial  go programming language - Preliminary
Golang iran - tutorial go programming language - Preliminary
go-lang
 
lets play with "c"..!!! :):)
lets play with "c"..!!! :):)lets play with "c"..!!! :):)
lets play with "c"..!!! :):)
Rupendra Choudhary
 
Generics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsGenerics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient Collections
Eleanor McHugh
 
Python-GTK
Python-GTKPython-GTK
Python-GTKYuren Ju
 
Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1
Robert Stern
 
Something about Golang
Something about GolangSomething about Golang
Something about Golang
Anton Arhipov
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
Tor Ivry
 
Torchbearersnotebook.blogspot.com program to create a list in python and valu...
Torchbearersnotebook.blogspot.com program to create a list in python and valu...Torchbearersnotebook.blogspot.com program to create a list in python and valu...
Torchbearersnotebook.blogspot.com program to create a list in python and valu...
SAKSHISINGH486
 
III MCS python lab (1).pdf
III MCS python lab (1).pdfIII MCS python lab (1).pdf
III MCS python lab (1).pdf
srxerox
 
Pnno
PnnoPnno
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in Scala
Hermann Hueck
 
CHAPTER 6
CHAPTER 6CHAPTER 6
CHAPTER 6
mohd_mizan
 
mobl: Een DSL voor mobiele applicatieontwikkeling
mobl: Een DSL voor mobiele applicatieontwikkelingmobl: Een DSL voor mobiele applicatieontwikkeling
mobl: Een DSL voor mobiele applicatieontwikkelingDevnology
 

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

going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...
going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...
going loopy - adventures in iteration with go - Eleanor McHugh - Codemotion M...
 
Going Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoGoing Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google Go
 
going loopy - adventures in iteration with google go
going loopy - adventures in iteration with google gogoing loopy - adventures in iteration with google go
going loopy - adventures in iteration with google go
 
Going Loopy
Going LoopyGoing Loopy
Going Loopy
 
Hello Go
Hello GoHello Go
Hello Go
 
Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and C
 
Golang iran - tutorial go programming language - Preliminary
Golang iran - tutorial  go programming language - PreliminaryGolang iran - tutorial  go programming language - Preliminary
Golang iran - tutorial go programming language - Preliminary
 
lets play with "c"..!!! :):)
lets play with "c"..!!! :):)lets play with "c"..!!! :):)
lets play with "c"..!!! :):)
 
Generics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsGenerics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient Collections
 
Python-GTK
Python-GTKPython-GTK
Python-GTK
 
Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1
 
Something about Golang
Something about GolangSomething about Golang
Something about Golang
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
 
Torchbearersnotebook.blogspot.com program to create a list in python and valu...
Torchbearersnotebook.blogspot.com program to create a list in python and valu...Torchbearersnotebook.blogspot.com program to create a list in python and valu...
Torchbearersnotebook.blogspot.com program to create a list in python and valu...
 
III MCS python lab (1).pdf
III MCS python lab (1).pdfIII MCS python lab (1).pdf
III MCS python lab (1).pdf
 
Pnno
PnnoPnno
Pnno
 
goatwork2014
goatwork2014goatwork2014
goatwork2014
 
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in Scala
 
CHAPTER 6
CHAPTER 6CHAPTER 6
CHAPTER 6
 
mobl: Een DSL voor mobiele applicatieontwikkeling
mobl: Een DSL voor mobiele applicatieontwikkelingmobl: Een DSL voor mobiele applicatieontwikkeling
mobl: Een DSL voor mobiele applicatieontwikkeling
 

More from Eleanor McHugh

[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf
Eleanor McHugh
 
The Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityThe Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data Integrity
Eleanor McHugh
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
Eleanor McHugh
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's Perspective
Eleanor McHugh
 
Go for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionGo for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd edition
Eleanor McHugh
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]
Eleanor McHugh
 
Identity & trust in Monitored Spaces
Identity & trust in Monitored SpacesIdentity & trust in Monitored Spaces
Identity & trust in Monitored Spaces
Eleanor McHugh
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignDon't Ask, Don't Tell - The Virtues of Privacy By Design
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
Don't ask, don't tell   the virtues of privacy by designDon't ask, don't tell   the virtues of privacy by design
Don't ask, don't tell the virtues of privacy by design
Eleanor McHugh
 
Anonymity, identity, trust
Anonymity, identity, trustAnonymity, identity, trust
Anonymity, identity, trust
Eleanor McHugh
 
Distributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleDistributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at Scale
Eleanor McHugh
 
Finding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goFinding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in go
Eleanor McHugh
 
Anonymity, trust, accountability
Anonymity, trust, accountabilityAnonymity, trust, accountability
Anonymity, trust, accountability
Eleanor McHugh
 
Implementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & CImplementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & C
Eleanor McHugh
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and Go
Eleanor McHugh
 
Encrypt all transports
Encrypt all transportsEncrypt all transports
Encrypt all transports
Eleanor McHugh
 
Whispered secrets
Whispered secretsWhispered secrets
Whispered secrets
Eleanor McHugh
 
Whispered secrets
Whispered secretsWhispered secrets
Whispered secrets
Eleanor McHugh
 
Privacy is always a requirement
Privacy is always a requirementPrivacy is always a requirement
Privacy is always a requirement
Eleanor McHugh
 
Hybrid Cryptography with examples in Ruby and Go
Hybrid Cryptography with examples in Ruby and GoHybrid Cryptography with examples in Ruby and Go
Hybrid Cryptography with examples in Ruby and Go
Eleanor McHugh
 

More from Eleanor McHugh (20)

[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf
 
The Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityThe Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data Integrity
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's Perspective
 
Go for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionGo for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd edition
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]
 
Identity & trust in Monitored Spaces
Identity & trust in Monitored SpacesIdentity & trust in Monitored Spaces
Identity & trust in Monitored Spaces
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignDon't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By Design
 
Don't ask, don't tell the virtues of privacy by design
Don't ask, don't tell   the virtues of privacy by designDon't ask, don't tell   the virtues of privacy by design
Don't ask, don't tell the virtues of privacy by design
 
Anonymity, identity, trust
Anonymity, identity, trustAnonymity, identity, trust
Anonymity, identity, trust
 
Distributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleDistributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at Scale
 
Finding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goFinding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in go
 
Anonymity, trust, accountability
Anonymity, trust, accountabilityAnonymity, trust, accountability
Anonymity, trust, accountability
 
Implementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & CImplementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & C
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and Go
 
Encrypt all transports
Encrypt all transportsEncrypt all transports
Encrypt all transports
 
Whispered secrets
Whispered secretsWhispered secrets
Whispered secrets
 
Whispered secrets
Whispered secretsWhispered secrets
Whispered secrets
 
Privacy is always a requirement
Privacy is always a requirementPrivacy is always a requirement
Privacy is always a requirement
 
Hybrid Cryptography with examples in Ruby and Go
Hybrid Cryptography with examples in Ruby and GoHybrid Cryptography with examples in Ruby and Go
Hybrid Cryptography with examples in Ruby and Go
 

Recently uploaded

Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
Tendenci - The Open Source AMS (Association Management Software)
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 

Recently uploaded (20)

Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 

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 } }