Referential Transparency is Overrated Didier Verna

Introduction Referential Transparency is Overrated Scoping But let’s keep this between us. . . Syntax Extension

Symbol Macros Didier Verna Macros

Conclusion [email protected] http://www.lrde.epita.fr/˜didier http://www.facebook.com/didierverna @didierverna

ACCU 2015 – Thursday, April 23rd

1/54 Table of contents

Referential Transparency is Overrated 1 Introduction Didier Verna

Introduction 2 Scoping Scoping

Syntax Extension 3 Syntax Extension (RTMP) Symbol Macros Macros 4 Symbol Macros / Generalized Variables Conclusion

5 Macros (CTMP)

6 Conclusion

2/54 Natural Languages (Analytical Philosophy) Origins

Referential Transparency is Overrated Quine Didier Verna reference ≈ meaning Introduction replacing an expression by another one which refers to Views Confusion the same thing doesn’t alter the meaning Benefits

Scoping Syntax Example: “Wallace’s dog” ≡ “Gromit” Extension

Symbol  Tomorrow, I’ll go feed Wallace’s dog. Macros  Gromit isn’t Wallace’s dog anymore. Macros

Conclusion

4/54 Programming Languages (Semantics) Inspired from Quine

Referential Transparency is Overrated Strachey1 Didier Verna If we wish to find the value of an expression which Introduction contains a sub-expression, the only thing we need Views Confusion to know about the sub-expression is its value. Benefits

Scoping

Syntax 2 Extension Reade Symbol Macros Only the meaning of immediate sub-expressions is

Macros significant in determining the meaning of a

Conclusion compound expression. Since expressions are equal if and only if they have the same meaning, [it] means that substitutivity of equality holds.

1 Fundamental Concept of Programming Languages, 1967 2 5/54 Elements of , 1989 Purely Functional Languages A more extremist view

Referential Transparency is Overrated Take your pick Didier Verna An expression which can be replaced with its value Introduction without changing the behavior of a program. Views Confusion Benefits Evaluation of the expression simply changes the Scoping form of the expression but never its value. Syntax Extension Symbol All references to a value are equivalent to the value Macros itself. Macros

Conclusion There are no other effects in any procedure for obtaining the value.

6/54 The original points Quine and Strachey agreed

Referential Transparency is Overrated Quine’s point Didier Verna Natural languages are complicated because they need to Introduction be practical. Views Confusion Benefits

Scoping Strachey’s point Syntax The same! And BTW, he was talking about imperative Extension languages. Symbol Macros

Macros A sound denotational semantics would render even Conclusion imperative languages referentially transparent (by telling you when two expressions are equal).

7/54 Purity vs. Referential Transparency Are we talking about the same thing ?

Referential Transparency is Overrated What purely functional programmers talk about Didier Verna values instead of meaning Introduction Views evaluation process becomes relevant Confusion Benefits side effects (or lack thereof) Scoping

Syntax Extension

Symbol Macros

Macros

Conclusion

8/54 The Typical PFP’s argument Which is refutable

Referential Transparency is Overrated This is referentially transparent Didier Verna i n t plus_one (x) { return x + 1; } /∗ plus_one (1) is always2 ∗/

Introduction Views Confusion Benefits This is not Scoping i n t foo = 10; Syntax i n t plus_foo (x) { return x + foo ; } /∗ plus_foo (1) depends on foo ∗/ Extension

Symbol Macros Macros Really? What about this? Conclusion foo : : I n t foo = 10

plus_foo : : I n t −> I n t plus_foo x = x + foo −− plus_foo1 is always 11...

l e t foo = 20 in l e t plus_foo x = x + foo in plus_foo 1 −− 21. Woops!

14/54 One final definition Gotta stop somewhere

Referential Transparency is Overrated Gelernter & Jagannathan Didier Verna A language is referentially transparent if (a) Introduction every subexpression can be replaced by any other Views Confusion that’s equal to it in value and (b) all occurrences of Benefits an expression within a given context yield the Scoping

Syntax same value. Extension

Symbol Macros Applies to languages, not expressions Macros Mostly rules mutation out Conclusion

15/54 Intermediate Conclusion Where to go from here

Referential Transparency is Overrated There is always some form of context dependency Didier Verna (lexical / dynamic definitions, free / bound variables,

Introduction side effects etc) Views Confusion PFPs disregard their own contexts (lexical and purity) Benefits

Scoping PFPs reduce the notion of “meaning” to that of “value” Syntax (result of a λ-calculus evaluation process) Extension

Symbol Macros Consequently, I hereby claim that the expression “referential Macros transparency” is not referentially transparent :-). Conclusion

16/54 Optimization, Safety, Expressiveness. . . Why referential transparency is profitable

Referential Transparency is Overrated Optimization:

Didier Verna I I Parallelism (Cf. Erlang) Introduction Views Safety: Confusion Benefits I Localized semantics (hence localized bugs) Scoping I Program reasoning and proof Syntax Extension Expressiveness:

Symbol I Macros

Macros

Conclusion

17/54 Safety with Program Proof Formal reasoning

Referential Transparency is Overrated Demonstrate (please) that ∀n,ssq(n) > 0 Didier Verna

Introduction Views Confusion Benefits Purely functional Imperative Scoping ssq : : I n t −> I n t i n t ssq ( i n t n ) Syntax ssq 1 = 1 { Extension ssq n = n∗n + ssq ( n−1) i n t i = 1 , a = 0;

Symbol while ( i <= n ) Macros { a += i ∗ i ; Macros True for N = 1 i += 1; } Conclusion Assuming it holds for return a ; N − 1... }

Ahem. . .

18/54 Expressiveness with Lazy Evaluation Thank you Church-Rosser

Referential Transparency is Overrated Explicit representation of infinite data structures Didier Verna

Introduction Views Confusion Benefits Haskell Lisp Scoping i n t l i s t : : I n t −> [ I n t ] ( defun i n t l i s t ( s ) Syntax intlist s = s : intlist (s + 1) ( cons s (intlist (1+ s)))) Extension −− (intlist 0)!!3 −> 3. ;;(elt(intlist 0) 3) −>^^C Symbol Macros

Macros

Conclusion

20/54 Where to Look for Bindings? Scoping

Referential Transparency is Overrated Lexical Scoping: in the defining context Didier Verna Dynamic Scoping: in the calling context Introduction

Scoping Definitions Lexical Lexical Scope Dynamic Scope Dynamic Scope Interlude ( l e t ( ( x 10)) ( l e t ( ( x 10)) Syntax ( defun foo ( ) ( defun foo ( ) Extension (declare (special x)) x ) ) x ) ) Symbol Macros ( l e t ( ( x 20)) ( l e t ( ( x 20)) ( foo ) ) ;; −> 10 ( foo ) ) ;; −> 20 Macros

Conclusion First Lisp was dynamically scoped Lexical scope since Scheme (except Emacs Lisp!) Common Lisp still offers both (Emacs Lisp now does)

22/54 Lexical Closures Brought to you by lexical scope

Referential Transparency is Overrated Definition: Didier Verna Combination of definitions and their defining

Introduction environment (free variables values at define-time) Scoping Benefits: Definitions Lexical Scope I 1st order functional (anonymous) arguments Dynamic Scope Interlude I 1st order functional (anonymous) return values

Syntax I ...(e.g. encapsulation) Extension

Symbol Lisp note: lexical state is mutable Macros

Macros

Conclusion

23/54 Why lexical closures are crucial They’re everywhere!

Referential Transparency is Overrated 1st order functional (anonymous) arguments Didier Verna ( defun l i s t + ( l s t n ) ( mapcar (lambda (x) (+ x n)) Introduction l s t ) ) Scoping Definitions Lexical Scope Dynamic Scope 1st order functional (anonymous) return values Interlude

Syntax ( defun make−adder ( n ) Extension (lambda (x) (+ x n)))

Symbol Macros

Macros Mutable lexical state

Conclusion ( l e t ( ( cnt 0 ) ) ( defun newtag ( ) ( incf cnt ) ) ( defun resettag () ( setq cnt 0 ) ) )

24/54 Why is dynamic scoping dangerous ? But also useful

Referential Transparency is Overrated Problems:

Didier Verna I Name clashes on free variables I Very difficult to debug Introduction I Mc Carthy’s first example of higher order function Scoping Definitions (1958) was wrong! Lexical Scope Dynamic Scope Advantages: Interlude I Dynamic paradigms (e.g. COP) Syntax Extension I Global variables! Symbol As per defvar and defparameter Macros E.g. Emacs user options Macros

Conclusion

29/54 Mc Carthy’s bugged example Transcribed in Common Lisp

Referential Transparency is Overrated The first mapping function Didier Verna ( defmacro while (test &rest body ) ‘( do ()(( not , t e s t ) ) Introduction ,@body ) )

Scoping ( defun my−mapcar ( func l s t ) Definitions ( l e t ( e l t n ) Lexical Scope ( while ( setq e l t (pop l s t ) ) Dynamic Scope ( push ( funcall func e l t ) n ) ) Interlude ( nreverse n ) ) ) Syntax Extension ( defun l i s t + ( l s t n ) (my−mapcar ( lambda ( x ) Symbol (declare (special n)) Macros (+ x n ) ) ;; Barf!! l s t ) ) Macros

Conclusion

30/54 Intermediate Conclusion Remember when I asked you about (let ((x 10)) (foo)) ?

Referential Transparency is Overrated Duality of syntax (intentional): Didier Verna

Introduction Lexical scope Dynamic scope Scoping Definitions ( l e t ((lock nil)) ( l e t ( ( case−fold−search nil)) Lexical Scope ( defun lock () (test−and−set lock ) ) ( search−forward "^Bcc: " )) Dynamic Scope ( defun unlock ( ) ( setq lock n i l ) ) ) Interlude

Syntax Extension

Symbol Macros Going further

Macros Semantics-agnostic macros (e.g. being-true)

Conclusion

32/54 Reader Macros Hijacking the Lisp syntax

Referential Transparency is Overrated Hooking into the Lisp reader Didier Verna readtable: currently active syntax extension table Introduction character: special syntactic meaning Scoping reader macro: implements macro character behavior Syntax Extension Reader Macros Note: RTMP Applications

Symbol Macros Standard syntactic extensions Macros ’ quote Conclusion #’ function #c complex ...

34/54 Why is RTMP useful? Not only for syntactic sugar

Referential Transparency is Overrated Examples Didier Verna ;; Of course, the comment syntax is implemented with macro characters... (asdf:defsystem :com. dvlsoft .clon Introduction :description "The Command-Line Options Nuker." : author "Didier Verna " Scoping :maintainer "Didier Verna " "BSD" Syntax : l i c e n s e Extension :version #.(version :short) : depends−on (#+sbcl :sb−posix Reader Macros #+(and clisp com.dvlsoft.clon.termio) : cffi) Applications : s e r i a l t Symbol #|... |# ) Macros

Macros

Conclusion

35/54 Application to DSLs The embedded homogeneous kind

Referential Transparency is Overrated From a previous talk: Didier Verna ;; Going from this: { option :foreground white Introduction :face { syntax :bold t :foreground cyan } :face { usage :foreground yellow } Scoping } Syntax ;; To that: − Extension ( define face option :foreground white :face (define−face syntax :bold t :foreground cyan) Reader Macros :face (define−face usage :foreground yellow)) Applications

Symbol Macros

Macros What kind of underlying data structure would you like ?

Conclusion { :key1 val1 :key2 val2 #|... |# }

What about this?

( defun random−f f i −bridge (foo bar) { struct winsize window; /∗ ... ∗/ })

36/54 Symbol Macros A special kind of macros

Referential Transparency is Overrated Macro-expanded symbols Didier Verna ( define−symbol−macro foo expansion−form ) ;; Locally with SYMBOL −MACROLET Introduction

Scoping

Syntax Extension Expansion then subject to regular macro-expansion Symbol Macros Symbol Macros Example Generalized Variables Application ( defun compute−thing ( ) #|...|# ) ( define−symbol−macro thing (compute−thing ) ) Macros ;; Using THING is cleaner than using(COMPUTE −THING). Conclusion

38/54 Generalized Variables l-values vs. r-values

Referential Transparency is Overrated The problem Didier Verna ( setq l s t ’ ( 1 2 3 ) ) ;; −> (12 3) ( nth 1 l s t ) ;; −>2 Introduction ( defun setnth ( nth l s t newval ) Scoping "Replace the NTH element in list LST with NEWVAL." ( rplaca ( nthcdr l s t nth ) newval ) Syntax newval ) Extension

Symbol (setnth 1 lst 20) ;; −> 20 Macros l s t ;; −> (1 20 3) Symbol Macros Generalized Variables Application

Macros Different setters for every data structure ? Conclusion How boring. . .

The solution

( setf ( nth 1 l s t ) 20)

39/54 Making your own Setf expanders

Referential Transparency is Overrated 50 or so expanders in the Lisp standard Didier Verna Accessors (struct or class instances) Introduction Make your own with Scoping I (defun (setf foo) ...) Syntax I defsetf Extension I define-setf-expander Symbol Macros Symbol Macros Generalized Variables Application

Macros

Conclusion

40/54 Application Combining symbol macros and generalized variables

Referential Transparency is Overrated with-slots / with-accessors Didier Verna ( with−accessors ((origin circle − origin) (radius circle − radius)) circle ;;... Introduction ( setf origin (+ origin translation − f a c t o r ) ) ( incf radius 3) Scoping #|... |# ) Syntax Extension

Symbol Macros Symbol Macros Generalized Variables Application

Macros

Conclusion

41/54 Crash Course What are Lisp macros exactly?

Referential Transparency is Overrated Ordinary Lisp functions (almost) Didier Verna Macro arguments: chunks of code (seen as data) Introduction Non-strict: arguments not evaluated Scoping

Syntax Transform expressions into new expressions Extension

Symbol Macros

Macros Crash Course Variable Capture Variable Injection Lexical channels

Conclusion

43/54 Why are macros useful? CTMP, factoring, non-strict idioms etc

Referential Transparency is Overrated Will this work?

Didier Verna ( defun ifnot (test then else) ( i f test else then)) Introduction ;;(ifnott(error"Kaboum!")’okay) −> Kaboum! Scoping

Syntax Extension This will Symbol Macros ( defmacro ifnot (test then else) ( l i s t ( quote i f ) test else then)) Macros Crash Course ;;(ifnott(error"Kaboum!")’okay) −>(ift’okay(error"Kaboum!")) Variable Capture Variable Injection Lexical channels Conclusion Even better, and even more better

( defmacro ifnot (test then else) ( l i s t ’ i f test else then))

( defmacro ifnot (test then else) ‘( i f ,test ,else ,then))

44/54 Macro pitfalls Evaluation control, unwanted variable capture

Referential Transparency is Overrated Does this work? Didier Verna ( defmacro maybe−push (object place) ‘( when , o b j e c t ( push ,object ,place))) Introduction

Scoping

Syntax Extension And this? Symbol ( defmacro maybe−push (object place) Macros ‘( l e t ((obj ,object)) Macros (when obj ( push obj ,place)))) Crash Course Variable Capture Variable Injection Lexical channels

Conclusion At last!

( defmacro maybe−push (object place) ( l e t ( ( the−object (gensym ))) ‘( l e t ( ( , the−object ,object)) (when , the−object ( push , the−object ,place)))))

45/54 Intentional variable capture I By example

Referential Transparency is Overrated This screams for abstraction Didier Verna ( defun signs ( l i s t ) ( mapcar (lambda (x) ( i f (= −1 ( signum x ) ) ’− ’ + ) ) Introduction ( remove−if (lambda (x) ( or ( not (numberp x ) ) ( complexp x ) ) ) Scoping l i s t ))) Syntax Extension

Symbol Macros This screams a little less Macros Crash Course ( defun filter−map (term filter l i s t ) Variable Capture ( mapcar term (remove−if f i l t e r l i s t ))) Variable Injection Lexical channels ( defun signs ( l i s t ) ( filter−map (lambda (x) ( i f (= −1 ( signum x ) ) ’− ’ + ) ) Conclusion (lambda (x) ( or ( not (numberp x ) ) ( complexp x ) ) ) l i s t ))

46/54 Intentional variable capture II By example

Referential Transparency is Overrated This doesn’t scream anymore Didier Verna ( defmacro filter−map (term filter l i s t ) ‘( mapcar (lambda (x) ,term) (remove−if (lambda (x) ,filter) , l i s t ))) Introduction ( defun signs ( l i s t ) Scoping ( filter−map ( i f (= −1 ( signum x ) ) ’− ’ + ) Syntax ( or ( not (numberp x ) ) ( complexp x ) ) Extension l i s t ))

Symbol Macros

Macros Crash Course Exercise: write a Haskell-like list comprehension Variable Capture Variable Injection facility. Lexical channels

Conclusion

47/54 Side Note: Alternatives with Syntax Extension More than one way. . .

Referential Transparency is Overrated With capture Didier Verna ( defun brace−reader (stream subchar arg) (declare (ignore subchar)) Introduction ( l e t ((body (read − d e l i m i t e d − list #\} stream t))) ( push ( cond (( or ( null arg) (= 1 arg)) ’(x)) Scoping ((= 2 arg) ’(x y)) Syntax ((= 3 arg) ’(x y z)) Extension ((= 4 arg) ’(x y z t))) body ) Symbol ( push ’lambda body) Macros body ) ) ( set−dispatch−macro−character #\# #\{ #’brace−reader ) Macros Crash Course ;; (#2{( ∗ xy)}3 4) −> 12 Variable Capture Variable Injection Lexical channels Conclusion Without capture (unicode Lisp)

( set−macro−character #\λ (lambda (stream char ) ’ lambda ) )

;;(( λ (xy)( ∗ xy))3 4) −> 12

48/54 Anaphora In the grammatical sense

Referential Transparency is Overrated Graham’s classical examples Didier Verna ( defmacro aif (test then &optional else) ‘( l e t ((it ,test)) Introduction ( i f it ,then ,else)))

Scoping ;; awhen, acond, awhile, aand etc. Syntax Extension ( defmacro alambda (args &body body) ‘( labels ((self ,args ,@body)) Symbol # ’ s e l f ) ) Macros

Macros Crash Course Variable Capture Variable Injection And the all-mighty and highly controversial loop Lexical channels macro! Conclusion

49/54 Pure (Free Variable) Injection Lexical trojans

Referential Transparency is Overrated In its simplest form Didier Verna ( defmacro inject () ’x)

Introduction

Scoping

Syntax Extension

Symbol Macros

Macros Crash Course Variable Capture Variable Injection Lexical channels

Conclusion

50/54 Application: Lexical Communication Channels Under the hood. . .

Referential Transparency is Overrated Principle: Didier Verna Two or more macros communicating with each other by Introduction injecting / capturing lexical bindings (variables, macros, Scoping symbol macros etc) Syntax Extension This lexical communication channel does not even have Symbol to be visible in the source code Macros

Macros Crash Course Variable Capture Variable Injection Lexical channels

Conclusion

51/54 Examples Cf. live demo (if it works. . . )

Referential Transparency is Overrated Tracing anaphora Didier Verna ( t r a c i n g − conditionals ;;... Introduction ( i f t h i s do−this do−that ) #|...|# ) Scoping

Syntax Extension Symbol Alternate version Macros

Macros ( t r a c i n g − conditionals ... Crash Course ;;... Variable Capture ( i f this (progn do−this ...here) do−that ) Variable Injection #|...|# ) Lexical channels

Conclusion

52/54 Conclusion Bringing programming languages closer to natural ones

Referential Transparency is Overrated Referential transparency is useful Didier Verna Breaking it is also useful (readability, concision) Introduction Breaking it is dangerous (safety vs. expressiveness) Scoping

Syntax Extension

Symbol Macros

Macros

Conclusion

54/54