Extra Lecture #7: Defining Syntax

Similar documents
Concepts of programming languages

CS 61A Interpreters, Tail Calls, Macros, Streams, Iterators. Spring 2019 Guerrilla Section 5: April 20, Interpreters.

INF4820. Common Lisp: Closures and Macros

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

ITERATORS AND STREAMS 9

Normal Order (Lazy) Evaluation SICP. Applicative Order vs. Normal (Lazy) Order. Applicative vs. Normal? How can we implement lazy evaluation?

CS450 - Structure of Higher Level Languages

Fall 2018 Discussion 8: October 24, 2018 Solutions. 1 Introduction. 2 Primitives

Macros & Streams Spring 2018 Discussion 9: April 11, Macros

MORE SCHEME. 1 What Would Scheme Print? COMPUTER SCIENCE MENTORS 61A. October 30 to November 3, Solution: Solutions begin on the following page.

Macros. Pat Hanrahan. CS448h Fall 2015

Delayed Expressions Fall 2017 Discussion 9: November 8, Iterables and Iterators. For Loops. Other Iterable Uses

Intro. Scheme Basics. scm> 5 5. scm>

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

Streams. CS21b: Structure and Interpretation of Computer Programs Spring Term, 2004

Computer Science 21b (Spring Term, 2015) Structure and Interpretation of Computer Programs. Lexical addressing

Scheme. Functional Programming. Lambda Calculus. CSC 4101: Programming Languages 1. Textbook, Sections , 13.7

Racket: Macros. Advanced Functional Programming. Jean-Noël Monette. November 2013

Lecture 09: Data Abstraction ++ Parsing is the process of translating a sequence of characters (a string) into an abstract syntax tree.

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

Notes on Higher Order Programming in Scheme. by Alexander Stepanov

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

INTRODUCTION TO SCHEME

Lecture #24: Programming Languages and Programs

Functional Programming. Pure Functional Programming

Symbolic Programming. Dr. Zoran Duric () Symbolic Programming 1/ 89 August 28, / 89

An Explicit Continuation Evaluator for Scheme

Lisp. Versions of LISP

CS61A Notes Disc 11: Streams Streaming Along

Organization of Programming Languages CS3200/5200N. Lecture 11

Comp 311: Sample Midterm Examination

User-defined Functions. Conditional Expressions in Scheme

SCHEME AND CALCULATOR 5b

Documentation for LISP in BASIC

Functional programming in LISP

SCHEME 10 COMPUTER SCIENCE 61A. July 26, Warm Up: Conditional Expressions. 1. What does Scheme print? scm> (if (or #t (/ 1 0)) 1 (/ 1 0))

CS1102: Macros and Recursion

TAIL RECURSION, SCOPE, AND PROJECT 4 11

Introduction to Functional Programming

SCHEME The Scheme Interpreter. 2 Primitives COMPUTER SCIENCE 61A. October 29th, 2012

Functional Programming Languages (FPL)

Lecture #13: Type Inference and Unification. Typing In the Language ML. Type Inference. Doing Type Inference

An introduction to Scheme

Programming Languages. Thunks, Laziness, Streams, Memoization. Adapted from Dan Grossman s PL class, U. of Washington

CSE341 Autumn 2017, Final Examination December 12, 2017

COP4020 Programming Assignment 1 - Spring 2011

Discussion 11. Streams

Streams, Delayed Evaluation and a Normal Order Interpreter. CS 550 Programming Languages Jeremy Johnson

LECTURE 18. Control Flow

Lecture 16: Static Semantics Overview 1

A Brief Introduction to Common Lisp

Implementing Coroutines with call/cc. Producer/Consumer using Coroutines

Racket. CSE341: Programming Languages Lecture 14 Introduction to Racket. Getting started. Racket vs. Scheme. Example.

FP Foundations, Scheme

CSE341 Spring 2017, Final Examination June 8, 2017

Scheme Tutorial. Introduction. The Structure of Scheme Programs. Syntax

Sample Final Exam Questions

4.2 Variations on a Scheme -- Lazy Evaluation

CSE341: Programming Languages Winter 2018 Unit 5 Summary Zach Tatlock, University of Washington

11/6/17. Functional programming. FP Foundations, Scheme (2) LISP Data Types. LISP Data Types. LISP Data Types. Scheme. LISP: John McCarthy 1958 MIT

Homework. Reading: Chapter 17 Homework: All exercises from Chapter 17 Due: 10/27 Correction: Chapter 16 homework is due 10/25

Meet the Macro. a quick introduction to Lisp macros. Patrick Stein / TC Lisp Users Group /

Functional Programming. Pure Functional Languages

CIS4/681 { Articial Intelligence 2 > (insert-sort '( )) ( ) 2 More Complicated Recursion So far everything we have dened requires

INTERPRETATION AND SCHEME LISTS 12

CS61A Summer 2010 George Wang, Jonathan Kotker, Seshadri Mahalingam, Eric Tzeng, Steven Tang

STATS 507 Data Analysis in Python. Lecture 2: Functions, Conditionals, Recursion and Iteration

Chapter 15. Functional Programming Languages

6.945 Adventures in Advanced Symbolic Programming

FUNKCIONÁLNÍ A LOGICKÉ PROGRAMOVÁNÍ 5. LISP: MAKRA, DATOVÁ STRUKTURA ZÁZNAM

Agenda. Peer Instruction Question 1. Peer Instruction Answer 1. Peer Instruction Question 2 6/22/2011

Functional Programming

Lists in Lisp and Scheme

Functional Programming. Pure Functional Languages

A LISP Interpreter in ML

6.037 Lecture 7B. Scheme Variants Normal Order Lazy Evaluation Streams

61A LECTURE 18 SCHEME. Steven Tang and Eric Tzeng July 24, 2013

CPS 506 Comparative Programming Languages. Programming Language Paradigm

CS 480. Lisp J. Kosecka George Mason University. Lisp Slides

STREAMS 10. Basics of Streams. Practice with Streams COMPUTER SCIENCE 61AS. 1. What is a stream?

OBJECT ORIENTED PROGRAMMING USING C++

;; definition of function, fun, that adds 7 to the input (define fun (lambda (x) (+ x 7)))

Problem Set 4: Streams and Lazy Evaluation

Deferred operations. Continuations Structure and Interpretation of Computer Programs. Tail recursion in action.

Scheme: Strings Scheme: I/O

CSE341 Spring 2017, Final Examination June 8, 2017

Programming Systems in Artificial Intelligence Functional Programming

6.184 Lecture 4. Interpretation. Tweaked by Ben Vandiver Compiled by Mike Phillips Original material by Eric Grimson

CS 314 Principles of Programming Languages

hexpressioni ::= hvariablei j hself evaluating literali j (quote hdatumi) j (lambda (hvariablei*) hexpressioni + ) j (if hexpressioni hexpressioni hex

STREAMS 10. Basics of Streams. Practice with Streams COMPUTER SCIENCE 61AS. 1. What is a stream? 2. How does memoization work?

Functional Languages. CSE 307 Principles of Programming Languages Stony Brook University

An Explicit-Continuation Metacircular Evaluator

LECTURE 16. Functional Programming

CSCC24 Functional Programming Scheme Part 2

A little bit of Lisp

Project 2: Scheme Interpreter

61A LECTURE 22 TAIL CALLS, ITERATORS. Steven Tang and Eric Tzeng July 30, 2013

Lambda Calculus see notes on Lambda Calculus

Transcription:

Extra Lecture #7: Defining Syntax In effect, function and class definitions extend the Python language by adding new commands and data types. However, these are highly constrained extensions. For example, the is no way to define def swap(x, y): """Swap the values of variables X and Y."""???? because Python used call-by-value. Likewise,thereisgenerallynowaytodefineanewcontrolconstruct. Indeed, language extension can be dangerous; it s easy to get wrong and can make programs less easy to read or understand. Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 1

Macros A macro is a programming-language construct that allows one to define, in effect, a function that generates program text that is substituted for calls on the macro function. For example (making up some new Python syntax): defmacro swap(x, y): x, y = y, x A call on this macro, such as swap(a[i], a[k]) would be expanded into a[i], a[k] = a[k], a[i] which is what actually gets executed. Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 2

Simple Macro Features The (imaginary) defmacro construct is essentially the same as the macro facilities of C and C++. In those languages, the definition #define BLUE 3 simply causes 3 to be substituted for the identifier BLUE wherever it appears. And definitions such as #define dolist(var, List) \ for (LinkedList* Var = List; Var!= NULL; Var = Var->next) expands into dolist(a, mylist) for (LinkedList* A = mylist; A!= NULL; A = A->next) Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 3

C Macro Implementation These substitutions are performed in C and C++ by a preprocessor program before standard compilation takes place. The preprocessor performs substitutions and deletes all the macrodefinition statements (as well as C/C++ comments). These macros do not observe scope rules; the macro preprocessor actually knows almost nothing about C. In fact, one can use the C preprocessor as a separate program on any kind of textual input data. Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 4

Bells and Whistles Aside from simple substitution of macro parameters, C/C++ macros provide very little in the way of text processing...... aside from stringification : #define defsym(x) x = #x defsym(y) expands into y = "y"...and token concatenation: #define doarray(var, A, low, high) \ for (int var ## _index = low; var ## _index < high; \ var ## _index += 1) { \ int var = (A)[var ## _index]; #define enddo } This example allows one to write things like doarray(p, anarray, 0, N) printf("item %d is %d.\n", p_index, p); enddo Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 5

Conditional Compilation The C macro preprocessor also provides statements like this: #if defined(ndebug) #define assert(test, Message) #else #define assert(test, Message) \ if (!(Test)) { \ fprintf(stderr, "%s\n", Message); \ abort(1); \ } #endif This example says that if a macro named NDEBUG is defined, we define a macro named assert to do nothing (it expands to nothing), and otherwise it expands to a statement that tests whether an expression Test is true, and exits with an error message if it isn t. Thus, when NDEBUG is defined, all assertions in the program are turned off and consume no execution time. This facility is called conditional compilation. Everything here happens before any execution of the program. Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 6

Scheme Macros The Lisp family has its own version of macro processing, one that is far more powerful than that of C. Scheme provides a powerful (but rather tricky) way to create new special forms: define-syntax. One of the extensions of our project is a simpler, more traditional form of this: define-macro. Macros are like functions, but Do not evaluate their arguments (this is what makes them special forms). Automatically treat the returned value as a Scheme expression and execute it. Thus, macros write programs that then get executed. Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 7

First: Quasiquote Writing programs that write programs entails constructing Scheme expressions that often contain substantial constant parts (that one would like to write as ordinary Scheme lists) with pieces that are computed and differ from one expansion to another. For this purpose, it is convenient to have a minilanguage that allows one to write expressions that resemble the expressions they produce. With quasiquote, I can write (list a b (+ 2 3) d) (a b,(+ 2 3) d) ;; which produces (a b 5 d), as ;; That s a backquote in front That is, everything preceded by a comma is replaced by its value. Additionally, in place of (define values (list (+ 2 3) (- 2 1))) (append (a b) values (d)) ;; which produces (a b 5 1 d), I can write (a b,@values d) or (a b,@(list (+ 2 3) (- 2 1)) d) That is everything preceded by,@ is evaluated and its (list) value spliced in. Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 8

Macro Example We may define a new looping construct: (define-macro (while cond stmt) (begin (define ($loop$) (if,cond (begin,stmt ($loop$)))) ($loop$))) So (while (> x y) (set! x (f y))) first yields (begin (define ($loop$) (if (> x y) (begin (set! x (f y)) ($loop$)))) ($loop$)) And then this is executed. Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 9

A Macro for Streams Syntax extension allows us to define a convenient kind of stream in Scheme. As we did in Python, a stream in Scheme will consist of a head, and either a function to compute the tail or the tail itself. (define-macro (cons-stream head tail) (cons,head (lambda (),tail))) We ll need a special cdr function that calls the tail computation (if it is a function). (define (cdr-stream str) (if (procedure? (cdr str)) ; Compute and memoize tail (set-cdr! str ((cdr str)))) (cdr str)) Actually, these are built into our (fully extended) project. Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 10

Streams in Scheme ;; The stream of all 1 s (define ones (cons-stream 1 ones)) (car ones) ===> 1 (car (cdr-stream ones)) ===> 1 (define (add-streams a b) ; Infinite streams, that is (cons-stream (+ (car a) (car b)) (add-streams (cdr-stream a) (cdr-stream b)))) ;; The stream 1 2 3... (define nums?) ;; The Fibonacci sequence (define fib (cons-stream 1 (cons-stream 1?))) Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 11

Streams in Scheme ;; The stream of all 1 s (define ones (cons-stream 1 ones)) (car ones) ===> 1 (car (cdr-stream ones)) ===> 1 (define (add-streams a b) ; Infinite streams, that is (cons-stream (+ (car a) (car b)) (add-streams (cdr-stream a) (cdr-stream b)))) ;; The stream 1 2 3... (define nums (cons-stream 1 (add-streams ones nums))) ;; The Fibonacci sequence (define fib (cons-stream 1 (cons-stream 1?))) Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 12

Streams in Scheme ;; The stream of all 1 s (define ones (cons-stream 1 ones)) (car ones) ===> 1 (car (cdr-stream ones)) ===> 1 (define (add-streams a b) ; Infinite streams, that is (cons-stream (+ (car a) (car b)) (add-streams (cdr-stream a) (cdr-stream b)))) ;; The stream 1 2 3... (define nums (cons-stream 1 (add-streams ones nums))) ;; The Fibonacci sequence (define fib (cons-stream 1 (cons-stream 1 (add-streams fib (cdr-stream fib))))) Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 13

Name Clashes The unnecessary use of macros has long been discouraged, because they introduce some serious issues. Consider our loop example: (define-macro (while cond stmt) (begin (define ($loop$) (if,cond (begin,stmt ($loop$)))) ($loop$))) The identifier $loop$ is intended to be local to the macro. I gave it a funny name to make it unlikely that it will conflict with any names the programmer has used. But there s no guarantee that I ve succeeded in preventing a name clash. One solution: some Lisp dialects supply a builtin function that generates new symbols that are guaranteed to differ from all other symbols. (define-macro (while cond stmt) (define loop-sym (gensym)) (begin (define (,loop-sym) (if,cond (begin,stmt (,loop-sym)))) (,loop-sym))) Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 14

Real Scheme Approach Real Scheme allows a general syntax-definition construct that creates local variables as needed (among other things). (define-syntax while (syntax-rules () (( pred b1...) (let loop () (when pred b1... (loop)))))) Last modified: Fri Apr 7 18:15:08 2017 CS61A: Extra Lecture #7 15