Defining Macros in Scheme

Slides:



Advertisements
Similar presentations
Lisp. Versions of LISP Lisp is an old language with many variants Lisp is alive and well today Most modern versions are based on Common Lisp LispWorks.
Advertisements

Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
CSE 3341/655; Part 4 55 A functional program: Collection of functions A function just computes and returns a value No side-effects In fact: No program.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Lisp. Versions of LISP Lisp is an old language with many variants –LISP is an acronym for List Processing language Lisp is alive and well today Most modern.
CSE S. Tanimoto Macros 1 Defining Macros in Lisp Extensibility: A language is extensible if the language can be extended. New Lisp control structures.
CSE S. Tanimoto Explicit Function Application 1 Explicit Application of Functions, Functional Arguments and Explicit Evaluation Implicit and explicit.
Symbolic Expressions (S Expressions) Syntax: Opening and Closing parenthesis having elements in between. List represented in LISP: (A B2 C3 Shahid) (A.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Common Lisp Macros Read for Input Macros Macro lifetime Macro syntax
CSC3315 (Spring 2009)1 CSC 3315 Programming Paradigms Scheme Language Hamid Harroud School of Science and Engineering, Akhawayn University
ISBN Chapter 15 Functional Programming Languages.
Introduction to Scheme CS 480/680 – Comparative Languages “And now for something completely different…” – Monty Python “And now for something completely.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
Functional Programming Universitatea Politehnica Bucuresti Adina Magda Florea
CSE S. Tanimoto Lisp Defining Macros in Lisp Extensibility: A language is extensible if the language can be extended. New Lisp control structures.
18-October-2002cse Symbols © 2002 University of Washington1 Symbols CSE 413, Autumn 2002 Programming Languages
מבוא מורחב 1 Lecture #9. מבוא מורחב 2 Symbol: a primitive type constructors: (quote alpha) ==> quote is a special form. One argument: a name. selectors.
CSE S. Tanimoto Macros 1 Defining Macros in Scheme Extensibility: A language is extensible if the language can be extended. New Scheme control structures.
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
Introduction to LISP Atoms, Lists Math. LISP n LISt Processing n Function model –Program = function definition –Give arguments –Returns values n Mathematical.
1 COSC generating functions, templates, and macros Yves Lespérance Adapted from Peter Roosen-Runge.
Basic Introduction to Lisp
Macros and general code walkers in Lisp: how useful! or, how useful? Ernst van Waning
CSE 341, S. Tanimoto Lisp Explicit Application of Functions and Functional Arguments In Lisp, functions can be passed as arguments to other functions.
Forms Writing your own procedures CS 480/680 – Comparative Languages.
Clojure Macros. Homoiconicity All versions of Lisp, including Clojure, are homoiconic This means that there is no difference between the form of the data.
Artificial Intelligence and Lisp Lecture 6 LiU Course TDDC65 Autumn Semester,
Functional Programming
Functional Programming Languages
Tail Recursion.
Defining Macros in Lisp
6.001 SICP Variations on a Scheme
CSE341: Programming Languages Lecture 15 Macros
Chapter 15 – Functional Programming Languages
September 4, 1997 Programming Languages (CS 550) Lecture 6 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts.
Lists in Lisp and Scheme
Env. Model Implementation
CSE341: Programming Languages Lecture 15 Macros
6.001 SICP Data abstractions
The Metacircular Evaluator
FP Foundations, Scheme In Text: Chapter 14.
Dynamic Scoping Lazy Evaluation
The Metacircular Evaluator
CSE341: Programming Languages Lecture 15 Macros
Abstraction and Repetition
The Metacircular Evaluator (Continued)
CSE S. Tanimoto Explicit Function Application
6.001 SICP Further Variations on a Scheme
Explicit Application of Procedures, and Explicit Evaluation
Streams, Delayed Evaluation and a Normal Order Interpreter
Lecture #9 מבוא מורחב.
Lisp: Using Functions as Data
Defining Macros in Lisp
CSE341: Programming Languages Lecture 15 Macros
Clojure Macros.
Defining Functions with DEFUN
Abstraction and Repetition
CSE341: Programming Languages Lecture 15 Macros
6.001 SICP Interpretation Parts of an interpreter
Lisp: Using Functions as Data
topics interpreters meta-linguistic abstraction eval and apply
Common Lisp II.
CSE 341 Lecture 22 Macros; extending Scheme's syntax
Lisp.
More Scheme CS 331.
CSE341: Programming Languages Lecture 15 Macros
Abstraction and Repetition
CSE341: Programming Languages Lecture 15 Macros
Presentation transcript:

Defining Macros in Scheme Extensibility: A language is extensible if the language can be extended. New Scheme control structures can be created using macros. A macro form is evaluated in a special way: First the macro form is expanded by applying the macro-expansion procedure or transformer (given in the definition) to the arguments. Then the resulting expression is evaluated. CSE 341 -- S. Tanimoto Macros

Two Styles of Macros in DrScheme “Lispish” macros. Obtained using DEFINE-MACRO, which is now available in a library. They use full Scheme as the language for writing macros, rather than a specialized pattern language. They are more powerful but somewhat more dangerous than hygienic macros. “Hygienic” macros. Obtained with DEFINE-SYNTAX and SYNTAX-RULES. They have built-in help for avoiding “variable-capture” bugs, but they are less powerful. CSE 341 -- S. Tanimoto Macros

Using Lispish Macros in DrScheme (require (lib "defmacro.ss")) This makes DEFINE-MACRO available. Works in DrScheme version 201. CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Example: NULLIFY > (define x 5) 5 > x > (define-macro (nullify symbol) (list 'set! symbol ''nil) ) > (nullify x) NIL CSE 341 -- S. Tanimoto Macros

Macro Expansion for NULLIFY By defining the macro NULLIFY, we have actually defined a procedure, but it’s not named NULLIFY. It’s called the macro expansion function or transformer for NULLIFY. When the macro NULLIFY is called, its transformer is applied to the macro argument. And then that result is evaluated. We can see a representation of the intermediate result if we use the procedure MACROEXPAND (to be defined shortly). > (macroexpand '(nullify total)) (SET! TOTAL 'NIL) CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Macro Call Evaluation (nullify total) 1. The arguments (unevaluated) are passed to the macro expansion function. SYMBOL gets as its binding the symbol TOTAL. 2. The expansion procedure is applied. Any macro forms within the expansion are themselves expanded. (SET! TOTAL 'NIL) 3. The result of expansion is itself evaluated. CSE 341 -- S. Tanimoto Macros

MACROEXPAND in DrScheme (define (macroexpand expr) (syntax-object->datum (expand expr)) ) 1. EXPAND transforms the expression (presumably a macro call) by applying the macro’s transformer. Any macro calls within the expansion are also expanded. An object of type SYNTAX is returned. 2. The syntax object is converted into an S-expression by SYNTAX-OBJECT->DATUM. CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Example: IF-N-Z-P > (define-macro (if-n-z-p numexpr negform zeroform posform) (list 'cond (list (list '< (eval numexpr) 0) negform) (list (list '= (eval numexpr) 0) zeroform) (list (list '> (eval numexpr) 0) posform) (list t '(print 'error)) ) ) CSE 341 -- S. Tanimoto Macros

Macro Expansion: IF-N-Z-P > (macroexpand '(if-n-z-p (* 3 -5) -35 'zero 37)) Produces code approximately equivalent to: (IF (< -15 0) -35 (IF (= -15 0) 'ZERO (IF (> -15 0) 37 (PRINT 'ERROR)))) Note that COND, which is implemented as a macro in GCL, was expanded, too. The macro expansion process for this macro is a little inefficient, because the numerical expression is always evaluated 3 times. We could rewrite the macro to perform the expansion once, save the value in a local variable, and access it three times. But, what should we name the variable? The safe thing to do is use GENSYM to synthesize a unique symbol and use it. (An optional exercise - and fairly tricky). CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Example: PUSH > (define-macro (push element stack) (list 'if (list 'null? stack) (list 'set! stack (list 'quote (list element))) (list 'cons element stack)) ) ) CSE 341 -- S. Tanimoto Macros

Macro Expansion for PUSH > (macroexpand '(push 5 s)) (IF (NULL? S) (SET! S '(5)) (SET! S (CONS 5 S))) CSE 341 -- S. Tanimoto Macros

Full Macro-form Evaluation First the form is fully expanded, and then the resulting form is evaluated. > (define mystack () ) > (push 5 mystack ) > (push '(next element) mystack ) > mystack ((NEXT ELEMENT) 5) CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Example: TWICE Takes any number of forms and evaluates them all once and then all again. > (define-macro (twice . forms) (append '(begin) forms forms) ) > (twice (display "Macros are powerful") (newline) (display "Aren’t they?") (newline) ) Macros are powerful Aren’t they? CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Example: AVERAGE Takes two numeric arguments and returns the mean. > (define-macro (average num1 num2) (list '/ (list '+ (eval num1) (eval num2)) 2) ) > (macroexpand '(average 2 (* 5 4))) (/ (+ 2 20) 2) or, in DrScheme (uses top-level env’t): (#%app (#%top . /) (#%app (#%top . +) (#%datum . 2) (#%datum . 20)) (#%datum . 2)) > (average 2 (* 5 4)) 11 Arguments to macros are not automatically evaluated, as they are in function calls. CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Example: SET-TO-ONE Takes any number of arguments, which must be symbols, and gives each the value 1. > (define-macro (set-to-one . symbols) (append '(begin) (map (lambda (s) (list 'set! s 1)) symbols))) > (macroexpand '(set-to-one x y z)) (BEGIN (SET! X 1) (SET! Y 1) (SET! Z 1)) > (define x 0) > (define y 0) > (define z 0) > (set-to-one x y z) > y 1 CSE 341 -- S. Tanimoto Macros

Backquote and Comma Syntax Allows the body of a macro to look like the expanded form. > (define-macro (push element stack) ‘(if (null? ,stack) (set! ',stack '(,element)) (set! ,stack (cons ,element ,stack)) ) ) >(macroexpand '(push 5 s)) (IF (NULL? S)(SET! 'S '(5))(SET! S (CONS 5 S))) Backquote is like QUOTE but it allows subexpressions preceded by a comma to be evaluated. CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Example: ENQUEUE Like PUSH, but puts the new element at the end of the list. > (define-macro (enqueue item lst) ‘(if (null? ,lst) (set! ',lst '(,item)) (nconc ,lst (list ,item)) ) ) > (define q '(a b c)) > (enqueue 'd q) > q (A B C D) CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Procedure NCONC Destructively concatenate two lists by creating a pointer from the CDR of the last cons in the first list to the first cons of the second list. > (define (nconc l1 l2) (cond ((null? l1) ()) ((pair? (cdr l1)) (nconc (cdr l1) l2)) (#t (set-cdr! l1 l2)) ) ) > (define lst1 '(a b c)) > (define lst2 ‘(d e f)) > (nconc lst1 lst2) > lst1 (A B C D E F) CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Example: SELECT Each clause is a list that begins with a value that might equal that of OBJECT. These value are tested in turn, and the first one that is equal to OBJECT has its remaining clause elements evaluated, and the value of the last of these is returned. > (select 5 (4 "too small") (5 "just right" "five") (6 "six") ) "five" CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Example: SELECT Note that the backquote doesn’t have to be at top-level. Also note the use of the dot (.) in the body which means that the list that follows should be spliced into the current list. (define-macro (select object . clauses) (append '(cond) (map (lambda (clause) `((equal? (car ',clause) ,object) . ,(cdr clause)) ) clauses))) CSE 341 -- S. Tanimoto Macros

Using DEFINE-SYNTAX and SYNTAX-RULES in DrScheme We do not need to use (require (lib "defmacro.ss")) Instead of DEFINE-MACRO we use DEFINE-SYNTAX and SYNTAX-RULES. This creates a hygienic macro and requires that we use a pattern language. Works in DrScheme version 201. CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros WHEN (define-syntax when (syntax-rules () ((_ condition form ...) (if condition (begin form ...)) ) ) ) > (define n 2) > (when (= n 2) (display n)(newline)) 2 CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros WHEN … EXCEPT > (define-syntax when (syntax-rules (except) ((_ condition form except c) (if (and condition (not c)) (begin form)) ) ((_ condition form ...) (if condition (begin form ...)) ) ) ) > (define n 18) > (when (even? n) (display 'not-prime) except (= n 2)) NOT-PRIME > (set! n 2) (nothing) Note … must occur at the end of a list. CSE 341 -- S. Tanimoto Macros

CSE 341 -- S. Tanimoto Macros Language Extension A new control structure, such as SELECT, is a good example of extending a language. Most languages allow user-defined functions, which provide a first level of language extension. By providing a coherent set of extensions to Lisp, typically containing both macro and function definitions, you can create an embedded language (EL). If you need a domain-specific language, an EL may be the way to go, because: The EL takes advantage of its host language, Lisp, for its basic syntax, parsing, and for handling lots of generic functionality. Example domains: knowledge representation, automatic theorem proving, text-processing, combinatorics, gene sequence processing. CSE 341 -- S. Tanimoto Macros