CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G....

30
Scheme: Macros CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science University of Alaska Fairbanks [email protected] © 2017 Glenn G. Chappell

Transcript of CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G....

Page 1: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: Macros

CS F331 Programming Languages

CSCE A331 Programming Language Concepts

Lecture Slides

Friday, April 7, 2017

Glenn G. Chappell

Department of Computer Science

University of Alaska Fairbanks

[email protected]

© 2017 Glenn G. Chappell

Page 2: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: Data — Data Format [1/5]

The dot notation originally used in S-expressions is also valid in Scheme.

> '(1 . 2)

(1 . 2)

A list is really shorthand for the equivalent dot notation, again, just as in the original S-expression syntax.

> '(1 . (2 . (3 . (4 . ()))))

(1 2 3 4)

Dot (.) is not a function. It is simply another way of typing S-

expressions. If you want a normal function that puts things together the way dot does, use cons.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 2

Page 3: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: Data — Data Format [2/5]

The main building block for constructing data structures in Scheme is the pair. This is a node with two pointers.

We get the item referenced by the left pointer using car; similarly use cdr for the right pointer.

> (car '(1 . 2))

1

> (cdr '(1 . 2))

2

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

1 2

(1 . 2)

3

Page 4: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: Data — Data Format [3/5]

Lists are constructed from pairs and null.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

(1 2 3) = (1 . (2 . (3 . ())))1

2

3 NULL

4

Page 5: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: Data — Data Format [4/5]

The full story on the dot syntax is that the dot may optionally be added just before the last item of a list.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

(1 2 3)

= (1 . (2 . (3 . ())))

1

2

3 NULL

(1 2 . 3)

= (1 . (2 . 3))

1

2 3

5

Page 6: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: Data — Data Format [5/5]

We can create arbitrary binary trees—with the restriction that only leaves have data.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

(((() . 8) . 1) . (5 . 1))

5 11

8NULL

6

Page 7: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: Strings — Basics, Numeric Conversions

String literals in Scheme are surrounded by double quotes.

"This is a string."

Convert a number to a string using number->string. Reverse: string->number. Returns the number, or #f if none. So the return value is usable in an if.

> (number->string 42)

"42"

> (string->number "42")

42

> (string->number "Hello!")

#f

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 7

Page 8: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: Strings — Characters

Character literals have the form #\CHAR, with some exceptions.

#\A ; The 'A' character

#\newline #\space

Convert a character to its numeric version (ASCII value/Unicode codepoint) with char->integer. Reverse: integer->char.

> (char->integer #\A)

65

> (integer->char 65)

#\A

Convert between strings and lists of characters with string->listand list->string.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 8

Page 9: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: Strings — Comparisons [1/2]

The Scheme numeric comparison operators can only be used with numbers: = < <= > >=.

Many Scheme types have their own equality functions, along with the other comparisons, if appropriate.

> (string=? "abc" "def")

#f

> (string=? "42" 42)

ERROR

> (string<? "abc" "def")

#t

Also: string<=? string>? string>=? char=? char<? char<=? char>? char>=?

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 9

Page 10: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: Strings — Comparisons [2/2]

A general-purpose equality check is equal?. But this returns #f for

parameters of different types, so it is not so great for numbers.

> (= 0 0.0)

#t

> (equal? 0 0.0)

#t

Rule of Thumb

Use = for numeric equality.

Use equal? for most other kinds of equality.

If you want the code to indicate what type you are comparing, and flag type errors for other types, then use a type-specific equality function (e.g., string=?, char=?).

Use other equality functions only if you know what you are doing.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 10

Page 11: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: I/O — Console Output [1/2]

Print a any value with display. String conversion is automatic. No trailing newline is printed. Print a newline with newline. Both of

these return void, which does not print in the REPL.

> (display "Howdy thar!")

Howdy thar!

> (newline)

> (display #\A)

A

> (display '(42 #t (300)))

(42 #t (300))

> (display +)

#<procedure:+>

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

For code, see io.scm.

11

Page 12: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: I/O — Console Output [2/2]

To do multiple I/O calls in a single expression, use begin. This

takes any number of parameters, evaluates them all, in order, and returns the value of the last one.

> (begin

(display "dog")

(display "food")

(display "love")

)

dogfoodlove

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 12

Page 13: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: I/O — Console Input

Read a line from the console with read-line. This takes no

parameters. It returns the typed-in line with no trailing newline.

How can we set a variable equal to the return value of read-line

in a procedure? We want a local binding, not a global one. One way is to define inside the procedure. Another is to use let.

(let ; Locally bind vars to values in the expression

(

(VARIABLE1 VALUE1)

(VARIABLEn VALUEn)

)

( EXPRESSION )

)

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

Scheme’s let is much like Haskell’s where, except

that the definitions comebefore, instead of after.

Punchline: Haskell has letalso, but I prefer where.

13

Page 14: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: I/O — Files: Output [1/2]

Procedure call-with-output-file takes two parameters:

The filename (string).

A 1-parameter procedure that takes an output port.

Notes

On failure, call-with-output-file raises an exception, which will

crash if no error handling is done.

On success it calls the given procedure, passing the port.

The given procedure is responsible for closing the file, by passing the port to close-output-port.

A variation, call-with-output-file*, closes the file automatically

when the given procedure terminates.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 14

Page 15: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: I/O — Files: Output [2/2]

Do file output by passing the port as a second argument to display or newline.

Example use of call-with-output-file*:

(define (do-output outport)

(begin

(display "Here is some file content." outport)

(newline outport)

)

)

(call-with-output-file* "myfile.txt" do-output)

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 15

Page 16: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: I/O — Files: Lambdas [1/2]

We can do it all with a single procedure using a lambda. As in Haskell, this refers to an unnamed function (procedure).

This:

(define (f a b) (* a b))

… is the same as this:

(define f (lambda (a b) (* a b)))

Scheme has first-class functions, so we can use a lambda without giving it a name.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 16

Page 17: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: I/O — Files: Lambdas [2/2]

Here is our file output as a single expression.

(call-with-output-file*

"myfile.txt"

(lambda (outport)

(begin

(display "Here is some file content." outport)

(newline outport)

)

)

)

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 17

Page 18: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: I/O — Files: Input [1/2]

Similarly, we can use call-with-input-file to do file input.

This takes a filename and a procedure that takes an input port.

The given procedure is responsible for closing the file, by passing the port to close-input-port. Or we can use call-with-input-file*, which closes automatically.

Read a line from a file by passing the port to read-line.

As before, this normally returns the line as a string with no trailing newline.

However, on end of file, read-line returns an EOF object. Check for this by passing the return value to the predicate eof-object?.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 18

Page 19: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

ReviewScheme: I/O — Files: Input [2/2]

Suppose we are reading a file, line by line. How do we repeat?

The let procedure has a useful extension: we can give it a name:

(let NAME

(

(VARIABLE1 VALUE1)

(VARIABLEn VALUEn)

)

( EXPRESSION )

)

Within EXPRESSION, we can use NAME as a procedure taking narguments. These become the values of VARIABLE1 through VARIABLEn in that invocation of the procedure.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 19

Page 20: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosIntroduction [1/3]

We have noted that Scheme (and other Lisp-family PLs) offer excellent support for reflection: the ability of a program to examine and modify its own code.

We have also seen simple examples of this: building and evaluating expressions on the fly.

> (define a (list '+ 1 'x))

> (define b (list '+ 2 'x))

> (define c (list '* a b))

> c

(* (+ 1 x) (+ 2 x))

> (define x 10)

> (eval c)

132

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

This is an interactive DrRacket session. But

building expressions and evaluating them can also

be done within a program.

20

Page 21: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosIntroduction [2/3]

In practice, the most common way that reflection is done in Scheme is through the use of a macro: a procedure-like entity that takes its arguments unevaluated.

Because the arguments of a macro are not evaluated before the macro sees them, the macro has access not only to their values, but also to their structure. It can do anything it wants with that structure, transforming the code in arbitrary ways.

After the macro has transformed the code, it may evaluate it, or it may return the transformed code unevaluated.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 21

Page 22: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosIntroduction [3/3]

When we define a macro in Scheme, we say we are creating new syntax.

This is easy to disagree with, since, no matter what we do, Scheme code consists of space-delimited lists surrounded by parentheses.Regardless, “syntax” is the term that is used.

Existing syntax constructions include quote and define, each of

which is able to take arguments without evaluating them.

> (quote (+ 1 x))

(+ 1 x)

Scheme’s macro support is quite extensive and would take some time to cover thoroughly. We will look briefly at a couple of of the simpler macro facilities.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 22

Page 23: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosSingle-Pattern Macros [1/5]

Suppose we wish to define our own version of quote, called myquote.

Can we do it like this?

> (define myquote quote)

ERROR

No. quote is not actually a procedure. Rather, it is a syntax

construction that the compiler recognizes. But we can still define myquote as a macro.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 23

Page 24: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosSingle-Pattern Macros [2/5]

The easiest kind of Scheme macro is the pattern-based macro. We give a pattern that code can match. Any matching code is transformed in a manner that we specify. The resulting code is evaluated. (To avoid this last step, we can quote the transformed code).

Define a single-pattern macro using define-syntax-rule:

(define-syntax-rule (PATTERN) TEMPLATE)

Above, TEMPLATE is the transformed code.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 24

Page 25: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosSingle-Pattern Macros [3/5]

Here is myquote:

(define-syntax-rule (myquote x)

'x

)

(myquote x) is a pattern. The rule is that the first word matches

only itself, while other words match anything. So any 2-item list beginning with myquote matches the pattern. For the purposes of the transformation, x means the second item of this list.

> (myquote (+ a b))

(+ a b)

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 25

Page 26: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosSingle-Pattern Macros [4/5]

define-syntax-rule accepts the dot syntax, just like define.

Here is a quoting macro that goes inside the list it quotes. This is like the procedure list, except that it does not evaluate its

arguments.

(define-syntax-rule (qlist . args)

'args

)

Try it:

> (qlist (+ 1 3) (* 3 8)) ; Arguments NOT evaluated

((+ 1 3) (* 3 8)

> (list (+ 1 3) (* 3 8)) ; Arguments evaluated

(4 24)

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 26

Page 27: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosSingle-Pattern Macros [5/5]

TO DO

Write some pattern-based macros.

If time permits, write a pattern-based macro that implements a for loop with a specified index variable, start and end values, and loop body.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

Done. See macro.scm.

27

Page 28: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosMultiple-Pattern Macros [1/3]

All the macros we have written so far involve a single pattern. We can also write pattern-based macros that allow for multiple patterns.

Recall the general form of define-syntax-rule:

(define-syntax-rule (PATTERN) TEMPLATE)

This is actually shorthand for the following:

(define-syntax IDENTIFIER

(syntax-rules ()

[(PATTERN) TEMPLATE]

)

)

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

PATTERN must start with IDENTIFIER.

28

Page 29: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosMultiple-Pattern Macros [2/3]

(define-syntax IDENTIFIER

(syntax-rules ()

[(PATTERN) TEMPLATE]

)

)

Here is our qlist written in this expanded form.

(define-syntax qlist

(syntax-rules ()

[(qlist . args) 'args]

)

)

7 Apr 2017 CS F331 / CSCE A331 Spring 2017 29

Page 30: CS F331 / CSCE A331 Spring 2017 · 2017. 4. 7. · Lecture Slides Friday, April 7, 2017 Glenn G. Chappell Department of Computer Science ... see io.scm. 11. Review Scheme: I/O —Console

Scheme: MacrosMultiple-Pattern Macros [3/3]

syntax-rules allows for multiple patterns. The first matching

pattern is used.

(define-syntax IDENTIFIER

(syntax-rules ()

[(PATTERN1) TEMPLATE1]

[(PATTERNn) TEMPLATEn]

)

)

TO DO

Write some multiple-pattern macros.

7 Apr 2017 CS F331 / CSCE A331 Spring 2017

Done. See macro.scm.

30