Macros “How can you get anything done in [other languages], I think, without macros?” - Paul Graham, 2003.

Slides:



Advertisements
Similar presentations
09 Examples Functional Programming. Tower of Hanoi AB C.
Advertisements

CS 63 LISP Philip Greenspun's Tenth* Rule of Programming:
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.
Some non-recursive tricks. The Lambda expression. More on Let, Let*, apply and funcall.
Macros and Function Generators CS 480/680 – Comparative Languages.
A problem with functions: arguments must always have values that can be worked out Whenever we call a function we give it arguments. Lisp then works out.
Lisp Recitation (cse471/598 Fall 2007 ) Aravind Kalavagattu.
CSE 341, S. Tanimoto Pattern Matching - 1 Pattern Matching in Lisp Lists can be used to represent sentences, relations, tree structures, etc. (this list.
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.
CMSC 471 LISP. Why Lisp? Because it’s the most widely used AI programming language Because it’s good for writing production software (Graham article)
CSE S. Tanimoto Explicit Function Application 1 Explicit Application of Functions, Functional Arguments and Explicit Evaluation Implicit and explicit.
PRACTICAL COMMON LISP Peter Seibel 1.
Recursion. Definitions I A recursive definition is a definition in which the thing being defined occurs as part of its own definition Example: A list.
Functional Programming COMP2003 A course on functional programming using Common Lisp Dr Eleni Mangina
LISP 1.5 and beyond A very quick tour. Data Atoms (symbols) including numbers – All types of numbers including Roman! (well, in the early days) – Syntactically.
TUTORIAL 2 CSCI3230 ( First Term) By Paco WONG 1.
Yu-Tzu Lin ( 林育慈 )
Input/Output Chapters 7 & 9. Output n Print produces output > (print 100) n It also returns the value it printed –that’s where the second 100 came.
Error Handling Common Lisp has the throw/catch statements so that you can simulate exception handling as seen in languages like Java But CL goes far beyond.
Using Harlequin LispWorks. Using LispWorks On BURKS 5, the file is lwper410.exe Start up LispWorks; you get two windows –Listener 1 –LispWorks Personal.
Basic Lisp CIS 479/579 Bruce R. Maxim UM-Dearborn.
Common Lisp Macros Read for Input Macros Macro lifetime Macro syntax
1 Lisp Functions –Built-in functions –Defining functions –Function Evaluation and Special Forms defun, if Control statements –Conditional if, cond –Repetition.
Lecture 2-1CS250: Intro to AI/Lisp Intelligent Agents Lecture 3-2 October 14 th, 1999 CS250.
CS 355 – PROGRAMMING LANGUAGES Dr. X. Common LISP A combination of many of the features of the popular dialects of LISP around in the early 1980s A large.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
04 Control. Control-Blocks Common Lisp has 3 basic operators for creating blocks of code progn block tagbody If ordinary function calls are the leaves.
06 INPUT AND OUTPUT Functional Programming. Streams Two kinds of streams  Character streams  Binary streams Character streams are Lisp objects representing.
Lecture 1-2CS251: Intro to AI/Lisp II “And now for something completely different…”
Lecture 6-2CS250: Intro to AI/Lisp Programming in Your Favorite Language Lecture 5-2 February 11 th, 1999 CS250.
Alok Mehta - Programming in Lisp - Macros Programming in Lisp Arrays, Macros, Expert Systems, Misc.
Macros You might recall from earlier that some of the statements we use are not actually functions but macros –In CL, a function evaluates all of its parameters.
CSE S. Tanimoto Lisp Defining Macros in Lisp Extensibility: A language is extensible if the language can be extended. New Lisp control structures.
Lisp Files, Arrays, and Macros CIS 479/579 Bruce R. Maxim UM-Dearborn.
Lisp Functional Language or Applicative Language –Achieves its effect by applying functions, either recursively or through composition Powerful, expressive,
Introduction to LISP. Lisp Extensible: It lets you define new operators yourself Lisp programs are expressed as lisp data structures –You can write programs.
UMBC CMSC Common Lisp II. UMBC CMSC Input and Output Print is the most primitive output function > (print (list 'foo 'bar)) (FOO BAR) The.
CSE S. Tanimoto Macros 1 Defining Macros in Scheme Extensibility: A language is extensible if the language can be extended. New Scheme control structures.
You can access the members of a list with the functions car (or first) and cdr (or rest): (setf list '(a b c)) (car list) ⇒ a (first list) ⇒ a (cdr list)
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
1 Variable Declarations Global and special variables – (defvar …) – (defparameter …) – (defconstant …) – (setq var2 (list 4 5)) – (setf …) Local variables.
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
Control Structures CSC 358/ Outline Midterm Lab #3 Homework #4 Sequential structures Conditional structures Unconditional branching Iteration.
Macros and general code walkers in Lisp: how useful! or, how useful? Ernst van Waning
PRACTICAL COMMON LISP Peter Seibel 1.
CSE 341, S. Tanimoto Lisp Explicit Application of Functions and Functional Arguments In Lisp, functions can be passed as arguments to other functions.
PRACTICAL COMMON LISP Peter Seibel 1.
Input Streams “A program designed for inputs from people is usually stressed beyond the breaking point by computer-generated inputs.” Dennis Ritchie, Bell.
Macros CSC 358/ Outline  Homework #6  Macro Intro  Backquote  Macros  Modify macros  Read Macros.
Clojure Macros. Homoiconicity All versions of Lisp, including Clojure, are homoiconic This means that there is no difference between the form of the data.
Macros Forms that the compiler expands into code ● Decide if the macro is really necessary ● Write down the syntax of the macro ● Figure out what the macro.
Feb 17, 2015 Clojure 4. Macros Code is data We have heard this before. It is what makes Lisp so amenable to the use of macros. Examples from Mastering.
Koen Lindström Claessen
Defining Macros in Lisp
Modern Programming Languages Lecture 20 Fakhar Lodhi
Getting Started with Lisp
Functions and Macros.
Modern Programming Languages Lecture 20 Fakhar Lodhi
CSE S. Tanimoto Explicit Function Application
Lisp: Using Functions as Data
Defining Macros in Lisp
Clojure Macros.
Abstraction and Repetition
Lisp: Using Functions as Data
Common Lisp II.
Lisp.
Defining Macros in Scheme
Presentation transcript:

Macros “How can you get anything done in [other languages], I think, without macros?” - Paul Graham, 2003

Writing Programs… … that write programs! Macros work via transformation – Macros translate a given LISP expression into another expression Allows for efficient execution

Two Similar Functions (defun print-file (file) (with-open-file (str file) (do ((line (read-line str nil nil) (read-line str nil nil))) ((null line) nil) (format t "~A~%" line) ))) (defun find-first-comment (file) (with-open-file (str file) (do ((line (read-line str nil nil) (read-line str nil nil))) ((null line) nil) (when (eql (char line 0) #\;) (return line)) )))

Desire to Generalize If this pattern reoccurs often, we would like to do something simpler like (defun print-file (file) (dofile line file (format t "~A~%" line) )) (defun find-first-comment (file) (dofile line file (when (eql (char line 0) #\;) (return line)) )) But how would you do this with a function? line is being passed as a variable name…

Solution is Macros What a function does – 1. Evaluate each argument – 2. Evaluate the body of the function What a macro does – 1. Evaluate body of macro – 2. Evaluate resulting body of expanded macro

Defining Macros Similar to defun (defmacro macro-name (argument*) S-expr*) (defmacro dofile (var file &rest body) (list 'with-open-file (list 'str file) (list* 'do (list (list var (list 'read-line 'str 'nil 'nil) (list 'read-line 'str 'nil 'nil))) (list (list 'null var) 'nil) body))) But this is impossibly ugly

Backquote The backquote ( ` ), like single quote ( ' ), can be used to inhibit evaluation >`(a b c d) (A B C D) >`(setf x (* 3 7)) (SETF X (* 3 7)) Unlike single quote, can specify partial evaluation by using a comma (, ) >`(setf x,(* 3 7)) (SETF X 21)

Simplified Macro with Backquote We can make our macro definition more readable with the backquote (defmacro dofile (var file &rest body) `(with-open-file (str,file),(list* 'do `((,var (read-line str nil nil) (read-line str nil nil))) `((null,var) nil) body))) Still kind of ugly. Problem is that body can be a list of commands, so we need list*

Splice The splicing operator ) allows the outer parentheses of an expression to be removed '(2 4 6))) (+ 4 6) Now we can fix our macro (defmacro dofile (var file &rest body) `(with-open-file (str,file) (do ((,var (read-line str nil nil) (read-line str nil nil))) ((null,var) ))

Macroexpand A tool for debugging macros, it expands a macro and suppresses second evaluation, returning the expanded expression >(defmacro front (some-list) (list 'car some-list)) FRONT >(macroexpand '(front '(1 2 3))) (CAR '(1 2 3)) T If your macro definition contains macros in it, then they will also be expanded, which may result in code you don’t recognize

Specializing the Input Currently we call our macro using (dofile var file body*) But we can group our arguments like so (dofile (var file) body*) If we parenthesize them in the macro definition Also, in macros, &body is preferred in place of &rest, for formatting reasons. So now we have: (defmacro dofile ((var file) &body body) `(with-open-file (str,file) (do ((,var (read-line str nil nil) (read-line str nil nil))) ((null,var) ))

Problems (1) This code works: (defun copy (source out) (with-open-file (outstr out :direction :output) (dofile (line source) (format outstr "~A~%" line)))) But this almost identical code doesn’t (defun copy (source out) (with-open-file (str out :direction :output) (dofile (line source) (format str "~A~%" line))))

Problems (2) If we expand the macro definition, we see why (defun copy (source out) (with-open-file (str out :direction :output) (with-open-file (str source) (do ((line (read-line str nil nil) (read-line str nil nil))) ((null line) nil) (format str "~A~%" line))) )) There are name collisions between the variables in the macro and those in the function definition. The only way to avoid this is by knowing the internals of the macro, which is unacceptable. We need to fix the macro again

Gensym gensym generates a new symbol name that is guaranteed to be unique We use it to get unique variable names for our macro (changes in red) (defmacro dofile ((var file) &body body) (let ((str (gensym))) `(with-open-file (,str,file) (do ((,var (read-line,str nil nil) (read-line,str nil nil))) ((null,var) )))

Macroexpand After Gensym >(macroexpand '(dofile (line "file.txt") nil)) (LET ((#:G1478 (OPEN "file.txt"))) (UNWIND-PROTECT (PROGN (BLOCK () (LET ((LINE (READ-LINE #:G1478 NIL NIL))) (TAGBODY #:G1479 (IF (NULL LINE) (RETURN (PROGN NIL))) (TAGBODY NIL) (PSETQ LINE (READ-LINE #:G1478 NIL NIL)) (GO #:G1479))))) (IF #:G1478 (CLOSE #:G1478))))