CSE341: Programming Languages Lecture 16 Macros Dan Grossman Fall 2011.

Slides:



Advertisements
Similar presentations
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists Dan Grossman Winter 2013.
Advertisements

CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Winter 2013.
CSE341: Programming Languages Lecture 12 Equivalence Dan Grossman Spring 2013.
CSE341: Programming Languages Lecture 21 Late Binding; OOP as a Racket Pattern Dan Grossman Fall 2011.
CSE341: Programming Languages Lecture 8 Lexical Scope and Function Closures Dan Grossman Fall 2011.
CSE341: Programming Languages Lecture 7 Functions Taking/Returning Functions Dan Grossman Fall 2011.
CSE341: Programming Languages Lecture 15 Mutation, Pairs, Thunks, Laziness, Streams, Memoization Dan Grossman Fall 2011.
CSE341: Programming Languages Lecture 15 Macros Dan Grossman Spring 2013.
Programming Languages Section 5. Racket
Cs1120 Fall 2009 David Evans Lecture 19: Stateful Evaluation.
CS 326 Programming Languages, Concepts and Implementation Instructor: Mircea Nicolescu Lecture 7.
Introduction to Scheme CS 480/680 – Comparative Languages “And now for something completely different…” – Monty Python “And now for something completely.
Programming LanguagesWrapup1 Programming Languages Wrap-up Xiaojuan Cai Spring 2015.
Today’s Agenda ML Development Workflow –Emacs –Using use –The REPL More ML –Shadowing Variables –Debugging Tips –Boolean Operations –Comparison Operations.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Winter 2013.
CSE 341 Lecture 21 delayed evaluation; thunks; streams slides created by Marty Stepp
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Spring 2016.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Spring 2017.
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Winter 2013.
CS170 – Week 1 Lecture 3: Foundation Ismail abumuhfouz.
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Spring 2017.
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Spring 2017.
CSE341: Programming Languages Lecture 15 Macros
Programming Languages Dan Grossman 2013
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Autumn 2017.
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Winter 2013.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Spring 2013.
Emily Leland (Not Nick) Spring 2017
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Zach Tatlock Winter 2018.
CSE341: Programming Languages Lecture 15 Macros
CSE 341: Programming Languages Section 1
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Zach Tatlock Winter 2018.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Spring 2017.
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Spring 2013.
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Autumn 2018.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Autumn 2018.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Autumn 2018.
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Spring 2016.
CSE341: Programming Languages Lecture 12 Equivalence
CSE 341 Section 7 Winter 2018 Adapted from slides by Eric Mullen, Nicholas Shahan, Dan Grossman, and Tam Dang.
CSE341: Programming Languages Lecture 15 Macros
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Autumn 2017.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Autumn 2017.
CSE341: Programming Languages Lecture 12 Equivalence
CSE341: Programming Languages Lecture 12 Equivalence
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Autumn 2018.
Winter 2018 With thanks to: Dan Grossman / Eric Mullen
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Spring 2016.
Adapted from slides by Nicholas Shahan and Dan Grossman
6.001 SICP Variations on a Scheme
Adapted from slides by Nicholas Shahan, Dan Grossman, and Tam Dang
CSE341: Programming Languages Lecture 15 Macros
Dan Grossman / Eric Mullen Autumn 2017
Nicholas Shahan Spring 2016
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Spring 2016.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Autumn 2017.
CSE341: Programming Languages Lecture 15 Macros
CSE341: Programming Languages Lecture 12 Equivalence
CSE 341 Lecture 22 Macros; extending Scheme's syntax
Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator
CSE341: Programming Languages Lecture 12 Equivalence
CSE341: Programming Languages Lecture 12 Equivalence
Brett Wortzman Summer 2019 Slides originally created by Dan Grossman
CSE341: Programming Languages Lecture 15 Macros
Brett Wortzman Summer 2019 Slides originally created by Dan Grossman
CSE341: Programming Languages Lecture 14 Thunks, Laziness, Streams, Memoization Dan Grossman Spring 2019.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Spring 2019.
CSE341: Programming Languages Lecture 21 Dynamic Dispatch Precisely, and Manually in Racket Dan Grossman Spring 2019.
CSE341: Programming Languages Lecture 15 Macros
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Spring 2019.
Presentation transcript:

CSE341: Programming Languages Lecture 16 Macros Dan Grossman Fall 2011

This lecture What are macros Why are macros difficult to use sensibly Using Racket’s macro system –Defining macros –Watching out for evaluation order and (re)-evaluation –Why hygiene makes Racket’s macros much easier to use sensibly When (not) to use macros Fall 20112CSE341: Programming Languages

What is a macro A macro describes how to transform some new syntax into different syntax in the source language A macro is one way to implement syntactic sugar –“Replace any syntax of the form e1 andalso e2 with if e1 then e2 else false ” A macro system is a language (or part of a larger language) for defining macros Macro expansion is the process of rewriting the syntax to eliminate macro uses –Before a program is run (or even compiled) Fall 20113CSE341: Programming Languages

Tokenization First question for a macro system: How does it tokenize? Macro systems generally work at the level of tokens not sequences of characters –So must know how programming language tokenizes text Example: “replace all occurrences of car with hd ” –Would not rewrite (+ cart foo) to (+ hdt foo) –Would not rewrite car-door to hd-door But would in C where car-door is subtraction Fall 20114CSE341: Programming Languages

Parenthesization Second question for a macro system: How does associativity work? C/C++ basic example: Probably not what you wanted: means not So C macro writers use lots of parentheses, which is fine: Racket won’t have this problem: –Macro use: (macro-name …) –After expansion: ( something else in same parens ) Fall 20115CSE341: Programming Languages #define ADD(x,y) x+y ADD(1,2/3)* / 3 * / 3 * 4(1 + 2 / 3) * 4 #define ADD(x,y) ((x)+(y))

Local bindings Third question for a macro system: Can variables shadow macros? Suppose macros also apply to variable bindings. Then: Would become: This is why C/C++ convention is all-caps macros and non-all-caps for everything else Racket gets this and other scope gotchas “right” Fall 20116CSE341: Programming Languages (let ([hd 0][car 1]) hd) ; 0 (let* ([hd 0][car 1]) hd) ; 0 (let ([car 0][car 1]) car) ; error (let* ([car 0][car 1]) car) ; 1

Example Racket macro definitions Two simple macros Fall 20117CSE341: Programming Languages (define-syntax my-if ; macro name (syntax-rules (then else) ; other keywords [(my-if e1 then e2 else e3) ; macro use (if e1 e2 e3)])) ; form of expansion (define-syntax comment-out ; macro name (syntax-rules () ; other keywords [(comment-out ignore instead) ; macro use instead])) ; form of expansion If the form of the use matches, do the corresponding expansion –In these examples, list of possible use forms has length 1 –Else syntax error

Example uses Fall 20118CSE341: Programming Languages (my-if x then y else z) ; (if x y z) (my-if x then y then z) ; syntax error (my-if x then (begin (print "hi") 34) then 15) (comment-out (begin (print "hi") 34) 15) (comment-out (car null) #f) It’s like we added keywords to our language –Other keywords only keywords in uses of that macro –Syntax error if keywords misused –Rewriting (“expansion”) happens before execution

Revisiting delay and force Recall our definition of promises from last lecture –Should we use a macro instead to avoid clients’ explicit thunk? Fall 20119CSE341: Programming Languages (define (my-delay th) (mcons #f th)) (define (my-force p) (if (mcar p) (mcdr p) (begin (set-mcar! p #t) (set-mcdr! p ((mcdr p))) (mcdr p)))) (define (f p) (… (my-force p) …)) (f (my-delay (lambda () e)))

A delay macro A macro can put an expression under a thunk –Delays evaluation without explicit thunk –Cannot implement this with a function Now client then should not use a thunk (that would double-thunk) –Racket’s pre-defined delay is a similar macro Fall CSE341: Programming Languages (define-syntax my-delay (syntax-rules () [(my-delay e) (mcons #f (lambda() e))])) (f (my-delay e))

What about a force macro? We could define my-force with a macro too –Good macro style would be to evaluate the argument exactly once (use x below, not multiple evaluations of e ) –Which shows it is bad style to use a macro at all here! –Don’t use macros when functions do what you want Fall CSE341: Programming Languages (define-syntax my-force (syntax-rules () [(my-force e) (let([x e]) (if (mcar x) (mcdr x) (begin (set-mcar! x #t) (set-mcdr! p ((mcdr p))) (mcdr p))))]))

Another bad macro Any function that doubles its argument is fine for clients –These are equivalent to each other So macros for doubling are bad style but instructive examples: –These are not equivalent to each other. Consider: Fall CSE341: Programming Languages (define (dbl x) (+ x x)) (define (dbl x) (* 2 x)) (define-syntax dbl (syntax-rules()[(dbl x)(+ x x)])) (define-syntax dbl (syntax-rules()[(dbl x)(* 2 x)])) (dbl (begin (print "hi") 42))

More examples Sometimes a macro should re-evaluate an argument it is passed –If not, as in dbl, then use a local binding as needed: Also good style for macros not to have surprising evaluation order –Good rule of thumb to preserve left-to-right –Bad example (fix with a local binding): Fall CSE341: Programming Languages (define-syntax dbl (syntax-rules () [(dbl x) (let ([y x]) (+ y y))])) (define-syntax take (syntax-rules (from) [(take e1 from e2) (- e2 e1)]))

Local variables in macros In C/C++, defining local variables inside macros is unwise –When needed done with hacks like __strange_name34 Here’s why with a silly example: –Macro: –Use: –Naïve expansion: –But instead Racket “gets it right,” which is part of hygiene Fall CSE341: Programming Languages (define-syntax dbl (syntax-rules () [(dbl x) (let ([one 1]) (* 2 x one))])) (let ([one 7]) (dbl one)) (let ([one 7]) (let* ([one 1]) (* 2 one one)))

The other side of hygiene This also looks like it would do the “wrong” thing –But Racket’s hygienic macros do the “right thing” –Macro: –Use: –Naïve expansion: Fall CSE341: Programming Languages (define-syntax dbl (syntax-rules () [(dbl x) (* 2 x)])) (let ([* +]) (dbl 42)) (let ([* +]) (* 2 42))

How hygienic macros work A hygienic macro system: –Secretly renames local variables in macros with fresh names –Looks up variables used in macros where the macro is defined Neither of these rules are followed by the “naïve expansion” most macro systems use –Without hygiene, macros are much more brittle (non-modular) Rarely hygiene is not what you want –Racket has somewhat complicated support for that Fall CSE341: Programming Languages

More examples See lec16.rkt for macros that: Allow 0, 1, or 2 local bindings with fewer parens than let* A for loop for executing a body a fixed number of times A re-implementation of let* in terms of let –Requires macros that take any number of arguments –Requires recursive macros Fall CSE341: Programming Languages