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 Functional Programming, 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 Memoization 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 Lazy evaluation 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^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 Scope 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 function 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 macro 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
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