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

An introduction to functional programming with go

  • 1.
  • 2.
    ELEANOR MCHUGH @feyeleanor APPLIED PHYSICIST MISAPPLIEDHACKER EMBEDDED SYSTEMS VIRTUAL MACHINES DIGITAL IDENTITY RUBY GO
  • 3.
    LEANPUB://GONOTEBOOK A GO DEVELOPER'SNOTEBOOK ▸ 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
  • 4.
  • 5.
  • 6.
    A SIMPLE TASK 0:0 1: 2 2: 4 3: 6 4: 8
  • 7.
  • 8.
    THE CONDITIONAL LOOP packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain import . "fmt" func main() { s := []int{0, 2, 4, 6, 8} for i := 0; i < len(s); i++ { Printf("%v: %vn", i, s[i]) } }
  • 25.
  • 26.
    AN EXCEPTIONAL LOOP packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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++ } }
  • 33.
  • 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) } }
  • 40.
  • 41.
  • 42.
    ENUMERATION BY FUNCTION packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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) } }
  • 47.
  • 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) } } }
  • 58.
  • 59.
    FUNCTIONS AS VALUES packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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)) } }
  • 66.
  • 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)) } } }
  • 75.
  • 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 }
  • 87.
  • 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 }
  • 93.
  • 94.
    WORKING WITH KINDS packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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) } }
  • 108.
  • 109.
  • 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) } }
  • 115.
  • 116.
    INTERFACES = POLYMORPHISM packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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) } }
  • 123.
  • 124.
    IMMUTABILITY IS ACHOICE 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 ACHOICE 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 ACHOICE 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 ACHOICE 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 ACHOICE 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 ACHOICE 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 codeunderstandable by encapsulating moving parts. FP makes code understandable by minimizing moving parts. Michael Feathers @mfeathers LEANPUB://GONOTEBOOK
  • 131.
  • 132.
  • 133.
    A PURE FUNCTION packagemain import "os" func main() { os.Exit(add(3, 4)) } func add(x, y int) int { return x + y }
  • 134.
    A PURE FUNCTION packagemain import "os" func main() { os.Exit(add(3, 4)) } func add(x, y int) int { return x + y }
  • 135.
    A PURE FUNCTION packagemain import "os" func main() { os.Exit(add(3, 4)) } func add(x int, y int) int { return x + y }
  • 136.
    A PURE FUNCTION packagemain import "os" func main() { os.Exit(add(3, 4)) } func add(x int, y int) int { return x + y }
  • 137.
    A PURE FUNCTION packagemain import "os" func main() { os.Exit(add(3, 4)) } func add(x int, y int) int { return x + y }
  • 138.
    A PURE FUNCTION packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 }
  • 144.
  • 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) }
  • 153.
  • 154.
    FUNCTIONS WITH MEMORY packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 } }
  • 162.
  • 163.
    FUNCTIONS AS OBJECTS packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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()) } }
  • 168.
  • 169.
  • 170.
    COMPUTING FACTORIALS 0! =1 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 6! = 720 7! = 5040 8! = 40320 9! = 362880
  • 171.
  • 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 }
  • 181.
  • 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 }
  • 189.
  • 190.
    HIGHER ORDER FUNCTIONS packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 packagemain 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 }
  • 204.
  • 205.
  • 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 }
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
    RECURSION package main func main(){ defer func() { recover() } main() }
  • 221.
    RECURSION package main import "os" import"strconv" varlimit 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" varlimit 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" varlimit 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" varlimit int func init() { if x, e := strconv.Atoi(os.Args[1]); e == nil { limit = x } } func main() { limit-- if limit > 0 { main() } }
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 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 }
  • 243.
  • 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 } }