Michał “phoe” Herda

213
Michał “phoe” Herda [email protected] https://phoe.github.io 1

Transcript of Michał “phoe” Herda

Page 1: Michał “phoe” Herda

Michał “phoe” Herda

[email protected]://phoe.github.io

1

Page 2: Michał “phoe” Herda

2

Page 3: Michał “phoe” Herda

• We need means of unwinding and protecting against unwinds

3

Page 4: Michał “phoe” Herda

• We need means of unwinding and protecting against unwinds

4

Page 5: Michał “phoe” Herda

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

5

Page 6: Michał “phoe” Herda

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

6

Page 7: Michał “phoe” Herda

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

7

• This includes non-local jumps(a secret Common Lisp feature)

Page 8: Michał “phoe” Herda

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

8

• This includes non-local jumps(a secret Common Lisp feature)

• This includes loops• This includes switches• This includes error handling• This includes restart handling

Page 9: Michał “phoe” Herda

• We need means of unwinding and protecting against unwinds• We can implement all of CL-specific control flow with this!

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

9

• This includes non-local jumps(a secret Common Lisp feature)

• This includes loops• This includes switches• This includes error handling• This includes restart handling• The above four groups

are implemented in Common Lisp itself

Page 10: Michał “phoe” Herda

10

Page 11: Michał “phoe” Herda

• Software engineer at Ericsson (C/C++/Erlang)

11

Page 12: Michał “phoe” Herda

• Software engineer at Ericsson (C/C++/Erlang)

• Common Lisp enthusiast (#lisp, Lisp Discord, Reddit)

12

Page 13: Michał “phoe” Herda

• Software engineer at Ericsson (C/C++/Erlang)

• Common Lisp enthusiast (#lisp, Lisp Discord, Reddit)• Author of The Common Lisp Condition System (Apress, 2020)

13

Page 14: Michał “phoe” Herda

• Software engineer at Ericsson (C/C++/Erlang)

• Common Lisp enthusiast (#lisp, Lisp Discord, Reddit)• Author of The Common Lisp Condition System (Apress, 2020)

• Somewhat capable of writing other programming languages

14

Page 15: Michał “phoe” Herda

• Software engineer at Ericsson (C/C++/Erlang)

• Common Lisp enthusiast (#lisp, Lisp Discord, Reddit)• Author of The Common Lisp Condition System (Apress, 2020)

• Somewhat capable of writing other programming languages

• I kinda like the topic of control flow

15

Page 16: Michał “phoe” Herda

• I kinda like the topic of control flow

16

Page 17: Michał “phoe” Herda

• I kinda like the topic of control flow

17

Page 18: Michał “phoe” Herda

18

Page 19: Michał “phoe” Herda

19

Page 20: Michał “phoe” Herda

20

Page 21: Michał “phoe” Herda

21

Page 22: Michał “phoe” Herda

22

Page 23: Michał “phoe” Herda

23

Page 24: Michał “phoe” Herda

24

foo()

bar()

baz()

Page 25: Michał “phoe” Herda

25

foo()

bar()

baz()

1/0

Page 26: Michał “phoe” Herda

26

foo()

bar()

baz()

1/0

ArithmeticException

Page 27: Michał “phoe” Herda

27

foo()

bar()

baz()

1/0

ArithmeticException

Page 28: Michał “phoe” Herda

28

foo()

bar()

baz()

1/0

ArithmeticException

Page 29: Michał “phoe” Herda

29

foo()

bar()

baz()

1/0

ArithmeticException

Page 30: Michał “phoe” Herda

30

foo()

bar()

baz()

1/0

catch

ArithmeticException

Page 31: Michał “phoe” Herda

31

foo()

bar()

baz()

1/0

catch

Page 32: Michał “phoe” Herda

32

foo()

bar()

Page 33: Michał “phoe” Herda

33

foo()

bar()

... // execution continues

Page 34: Michał “phoe” Herda

34

Page 35: Michał “phoe” Herda

35

Page 36: Michał “phoe” Herda

36

Page 37: Michał “phoe” Herda

37

Page 38: Michał “phoe” Herda

38

(foo)

(bar)

(baz)

Page 39: Michał “phoe” Herda

39

(foo)

(bar)

(baz)

(/ 1 0)

Page 40: Michał “phoe” Herda

40

(foo)

(bar)

(baz)

(/ 1 0)division-by-zero

Page 41: Michał “phoe” Herda

41

(foo)

(bar)

(baz)

(/ 1 0)division-by-zero

Page 42: Michał “phoe” Herda

42

(foo)

(bar)

(baz)

(/ 1 0)division-by-zero

Page 43: Michał “phoe” Herda

43

(foo)

(bar)

(baz)

(/ 1 0)division-by-zero

Page 44: Michał “phoe” Herda

44

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

Page 45: Michał “phoe” Herda

45

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

Page 46: Michał “phoe” Herda

46

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

Page 47: Michał “phoe” Herda

47

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

handler-1

Page 48: Michał “phoe” Herda

48

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

handler-2

Page 49: Michał “phoe” Herda

49

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

handler-3

Page 50: Michał “phoe” Herda

50

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(signal ...)

handler-3

handler-2

handler-1

Page 51: Michał “phoe” Herda

51

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

Page 52: Michał “phoe” Herda

52

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

Page 53: Michał “phoe” Herda

53

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

Page 54: Michał “phoe” Herda

54

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

Page 55: Michał “phoe” Herda

55

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

Page 56: Michał “phoe” Herda

56

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

Page 57: Michał “phoe” Herda

57

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

non-local jump

Page 58: Michał “phoe” Herda

58

(foo)

Page 59: Michał “phoe” Herda

59

(foo)

... // execution continues

Page 60: Michał “phoe” Herda

60

(foo)

... // execution continues

Page 61: Michał “phoe” Herda

61

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

Page 62: Michał “phoe” Herda

62

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

restart-1restart-2

restart-4

restart-3

Page 63: Michał “phoe” Herda

63

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

“Return 42 instead.”“Query the user for new numbers.”

“Abort and return to toplevel.”

“Try opening another file.”

Page 64: Michał “phoe” Herda

64

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

(invoke-debugger ...)

“Return 42 instead.”“Query the user for new numbers.”

“Abort and return to toplevel.”

“Try opening another file.”

Page 65: Michał “phoe” Herda

?

?

??

?

65

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

(invoke-debugger ...)

“Return 42 instead.”“Query the user for new numbers.”

“Abort and return to toplevel.”

“Try opening another file.”

division-by-zero

Page 66: Michał “phoe” Herda

66

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

division-by-zero

Page 67: Michał “phoe” Herda

67

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

Page 68: Michał “phoe” Herda

68

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

“Try opening another file.”

Page 69: Michał “phoe” Herda

69

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

“Try opening another file.”

restart-fn

Page 70: Michał “phoe” Herda

70

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

handler-3

handler-2

handler-1

division-by-zero

“Try opening another file.”

restart-fn

non-localjump

Page 71: Michał “phoe” Herda

71

(foo)

(bar)

Page 72: Michał “phoe” Herda

72

(foo)

(bar)

... // execution continues

Page 73: Michał “phoe” Herda

73

Page 74: Michał “phoe” Herda

74

(foo)

(bar)

(baz)

(quux)

Page 75: Michał “phoe” Herda

75

(foo)

(bar)

(baz)

(quux)some-condition

Page 76: Michał “phoe” Herda

76

(foo)

(bar)

(baz)

(quux)some-condition

(signal ...)

Page 77: Michał “phoe” Herda

77

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

Page 78: Michał “phoe” Herda

78

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

handler-1

Page 79: Michał “phoe” Herda

79

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

handler-2

Page 80: Michał “phoe” Herda

80

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

handler-3

Page 81: Michał “phoe” Herda

81

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

(signal ...)

Page 82: Michał “phoe” Herda

82

(foo)

(bar)

(baz)

(quux)some-condition

handler-3

handler-2

handler-1

¯\_(ツ)_/¯

Page 83: Michał “phoe” Herda

83

(foo)

(bar)

(baz)

(quux)

Page 84: Michał “phoe” Herda

84

(foo)

(bar)

(baz)

(quux)

... // execution continues

Page 85: Michał “phoe” Herda

85

Page 86: Michał “phoe” Herda

• Construct the exception object

86

Page 87: Michał “phoe” Herda

• Construct the exception object• Unwind the stack immediately

• Stop unwinding when something catches the exception

87

Page 88: Michał “phoe” Herda

• Construct the exception object• Unwind the stack immediately

• Stop unwinding when something catches the exception• Continue execution from that point

88

Page 89: Michał “phoe” Herda

89

Page 90: Michał “phoe” Herda

• Construct the condition object

90

Page 91: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?

91

Page 92: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?

92

Page 93: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code

93

Page 94: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart

94

Page 95: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return

95

Page 96: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point

96

Page 97: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers

97

Page 98: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it

98

Page 99: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

99

Page 100: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

100

Page 101: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

101

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

Page 102: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

102

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

Page 103: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

103

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

Page 104: Michał “phoe” Herda

104

Page 105: Michał “phoe” Herda

105

Page 106: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

106

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

Page 107: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

107

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

Page 108: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

108

• signaling = a dynamically scoped hooking mechanism

• progress bars• message passing• calling asynchronous code• etc..

• restarts = a dynamically scoped mechanism of choices

• context-dependent actionsfor interactive programming

• context-dependent meansof automated error recovery(e.g. when parsing incomplete source code)

• etc..

Page 109: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

109

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

Page 110: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

110

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

Page 111: Michał “phoe” Herda

• Construct the condition object• Call handlers from the stack in order

• What do the handlers do?• Maybe execute some code• Maybe invoke a restart• Maybe do nothing and return• Maybe unwind the stack to a predefined point• Maybe there are no handlers• Maybe she’s born with it• Maybe it’s Maybelline™

• If there was no transfer of control, return• ...and maybe enter the debugger to halt the program

111

(foo)

(bar)

(baz)

(/ 1 0)

(error ...)

handler-2

Page 112: Michał “phoe” Herda

112

Page 113: Michał “phoe” Herda

• if

(if (foo) (bar) (baz))

113

Page 114: Michał “phoe” Herda

• if• tagbody/go

(tagbody 10 (print “hello”) 20 (go 10))

114

Page 115: Michał “phoe” Herda

(block my-block (...) (... (return-from my-block 42)) (...))

115

• if• tagbody/go• block/return-from

Page 116: Michał “phoe” Herda

(catch ‘quux (...) (... (foo)) (...)))

(defun foo () (throw ‘quux 42))

116

• if• tagbody/go• block/return-from• catch/throw

Page 117: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect

(let ((thing (make-thing))) (unwind-protect (frob thing) (cleanup thing)))

117

Page 118: Michał “phoe” Herda

(let ((fn (lambda ...)) (args ...)) (apply fn 1 2 3 args))

118

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

Page 119: Michał “phoe” Herda

(let ((fn (lambda ...)) (args ...)) (apply fn 1 2 3 args))

(let ((fn (lambda ...))) (funcall fn 1 2 3))

119

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply ; and funcall

Page 120: Michał “phoe” Herda

120

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

Page 121: Michał “phoe” Herda

121

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

Page 122: Michał “phoe” Herda

122

Page 123: Michał “phoe” Herda

(let ((x 42)) (lambda () x))

123

Page 124: Michał “phoe” Herda

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

124

Page 125: Michał “phoe” Herda

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

(funcall *) ; (funcall #<FUNCTION (LAMBDA ())>)

125

Page 126: Michał “phoe” Herda

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

(funcall *) ; (funcall #<FUNCTION (LAMBDA ())>);; => 42

126

Page 127: Michał “phoe” Herda

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

(funcall *) ; (funcall #<FUNCTION (LAMBDA ())>);; => 42

;; but we can close over more;; than just lexical variables!

127

Page 128: Michał “phoe” Herda

128

(let ((x 42)) (lambda () x));; #<FUNCTION (LAMBDA ())>

(funcall *) ; (funcall #<FUNCTION (LAMBDA ())>);; => 42

;; but we can close over more;; than just lexical variables!

Page 129: Michał “phoe” Herda

129

Page 130: Michał “phoe” Herda

(defun foo (x) (funcall x))

130

Page 131: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () ; block bar ...)

131

Page 132: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) ...))

132

Page 133: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

133

Page 134: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)

134

Page 135: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

135

Page 136: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

(foo)

136

Page 137: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

(foo)

(lambda () ...)

137

Page 138: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

(foo)

(lambda () ...)

138

Page 139: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar)(bar)

(foo)

(lambda () ...)

139

Page 140: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar);; => 42

140

Page 141: Michał “phoe” Herda

(defun foo (x) (funcall x))

(defun bar () (let ((fn (lambda () (return-from bar 42)))) (foo fn)))

(bar);; => 42

141

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

Page 142: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

142

Page 143: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

143

Page 144: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

144

Page 145: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

145

Page 146: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

1

!

146

Page 147: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

147

Page 148: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)1

?

?

?

148

Page 149: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)1

?

?

?

149

Page 150: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)1

2?

?

?

!

150

Page 151: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

151

Page 152: Michał “phoe” Herda

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

152

Page 153: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

153

Page 154: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

154

Page 155: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives

155

Page 156: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)

156

Page 157: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)

157

Page 158: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)

158

Page 159: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)• restarts (restart-case, ...)

159

Page 160: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)• restarts (restart-case, ...)

• This list includes use cases that are not related to exception handling

160

Page 161: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)• restarts (restart-case, ...)

• This list includes use cases that are not related to exception handling

161

• Control flow ≠ exception handling

Page 162: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• All other CL control flow operators are derivatives of those primitives• loops (do, dolist, loop, ...)• switches (cond, case, typecase, ...)• error handling (handler-case, ...)• restarts (restart-case, ...)

• This list includes use cases that are not related to exception handling

162

• Control flow ≠ exception handling

Page 163: Michał “phoe” Herda

163

• Control flow ≠ exception handling

Page 164: Michał “phoe” Herda

• Do not conflate unwinding with throwing exceptions

164

• Control flow ≠ exception handling

Page 165: Michał “phoe” Herda

• Do not conflate unwinding with throwing exceptions• Throwing exceptions is a subset of control flow

165

• Control flow ≠ exception handling

Page 166: Michał “phoe” Herda

• Do not conflate unwinding with throwing exceptions• Throwing exceptions is a subset of control flow• Throwing exceptions is not synonymous with unwinding

166

• Control flow ≠ exception handling

Page 167: Michał “phoe” Herda

• Do not conflate unwinding with throwing exceptions• Throwing exceptions is a subset of control flow• Throwing exceptions is not synonymous with unwinding• Throwing exceptions is not a primitive operation

167

• Control flow ≠ exception handling

Page 168: Michał “phoe” Herda

• Do not conflate unwinding with throwing exceptions• Throwing exceptions is a subset of control flow• Throwing exceptions is not synonymous with unwinding• Throwing exceptions is not a primitive operation

• Proofs: Common Lisp, Dylan, Smalltalk

168

• Control flow ≠ exception handling

Page 169: Michał “phoe” Herda

169

Page 170: Michał “phoe” Herda

but wait hold on for just one moment

170

Page 171: Michał “phoe” Herda

Appendix A

Proving one-phase unwind in TAGBODY and BLOCK

171

Page 172: Michał “phoe” Herda

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

172

Page 173: Michał “phoe” Herda

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

173

Page 174: Michał “phoe” Herda

174

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

Page 175: Michał “phoe” Herda

(block foo (lambda () (return-from foo)))

175

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

Page 176: Michał “phoe” Herda

(let ((fn (block foo (lambda () (return-from foo))))) (funcall fn)); ...?

176

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

Page 177: Michał “phoe” Herda

(let ((fn (block foo (lambda () (return-from foo))))) (funcall fn)); ERROR: Condition CONTROL-ERROR; was signaled.

177

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply

Page 178: Michał “phoe” Herda

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply (let ((fn (block foo

(lambda () (return-from foo))))) (funcall fn)); ERROR: Condition CONTROL-ERROR; was signaled.

178

Page 179: Michał “phoe” Herda

• if• tagbody/go ; 1-phase unwind (no search)• block/return-from ; 1-phase unwind (no search)• catch/throw ; 2-phase unwind (search)• unwind-protect• lambda/apply (let ((fn (block foo

(lambda () (return-from foo))))) (funcall fn)); ERROR: Condition CONTROL-ERROR; was signaled.

179

? ?

Page 180: Michał “phoe” Herda

(block foo (lambda () (return-from foo)))

180

Page 181: Michał “phoe” Herda

(block foo ...)

181

Page 182: Michał “phoe” Herda

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo ...) (setf return-valid-p nil)))

182

Page 183: Michał “phoe” Herda

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo ...) ;; let’s expand the lambda! (setf return-valid-p nil)))

183

Page 184: Michał “phoe” Herda

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo (lambda () (if return-valid-p (%1-phase-unwind-to-tag foo) (error ‘control-error)))) (setf return-valid-p nil)))

184

Page 185: Michał “phoe” Herda

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo (lambda () (if return-valid-p (%1-phase-unwind-to-tag foo) (error ‘control-error)))) (setf return-valid-p nil)))

185

Page 186: Michał “phoe” Herda

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo (lambda () (if return-valid-p (%1-phase-unwind-to-tag foo) (error ‘control-error)))) (setf return-valid-p nil)))

186

Page 187: Michał “phoe” Herda

(let ((return-valid-p t)) (unwind-protect (%unwind-tag foo (lambda () (if return-valid-p (%1-phase-unwind-to-tag foo) (error ‘control-error)))) (setf return-valid-p nil)))

;; similar validation scheme applies for TAGBODY/GO

187

Page 188: Michał “phoe” Herda

Appendix B

Describing UNWIND-PROTECT

188

Page 189: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

189

Page 190: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

190

Page 191: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

191

Page 192: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

192

Page 193: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

193

Page 194: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

194

Page 195: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

195

Page 196: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

196

Page 197: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

197

Page 198: Michał “phoe” Herda

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

(foo)

(bar)

(baz)

(quux)

(frob)

198

Page 199: Michał “phoe” Herda

Appendix C

Common Lisp condition system without Common Lisp

(this is the last one I promise)199

Page 200: Michał “phoe” Herda

200

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

Page 201: Michał “phoe” Herda

201

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

Page 202: Michał “phoe” Herda

202

Page 203: Michał “phoe” Herda

203

Page 204: Michał “phoe” Herda

204

Page 205: Michał “phoe” Herda

205• Can we port the condition system to Java?

Page 206: Michał “phoe” Herda

206• Can we port CL control flow to Java?

Page 207: Michał “phoe” Herda

207• Can we port CL control flow to Java?

Page 208: Michał “phoe” Herda

208

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

Page 209: Michał “phoe” Herda

209

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

Page 210: Michał “phoe” Herda

210

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

“I suppose it is tempting, if the only tool you have is a hammer,to treat everything as if it were a nail.”

--- Abraham H. Maslow

Page 211: Michał “phoe” Herda

211

• if• tagbody/go• block/return-from• catch/throw• unwind-protect• lambda/apply

• if• tagbody/go• block/return-from• catch/throw• try/finally• new/.apply()• throw exception

https://github.com/phoe/cafe-latte

Page 212: Michał “phoe” Herda

212

Page 213: Michał “phoe” Herda

yes, it’s seriously the end this time

213