Monday, September 13, 2010

Daily, 2010/09/13: define-type, type-case, and our first "programming language"

Announcement items:
  • Tutorial registration resolution: 3 add'l seats in each tutorial
  • Reminder: A#1 due FRIDAY; started?
  • Is the blog required? No, but tell me if I put something critical there.
  • Can I get access to ACM papers like the one linked from the blog?  SHOULD be possible from any campus connection, including right here.
High-level comment:

We built our first interpreter and learned a couple more key Racket (actually, PLAI) forms.  My scattered whiteboard use (I grab whatever space is available and write on it) and teaching-with-code style may have made it hard to keep up, and may also have masked some of the big picture ideas in the course.  I hope not!  Have to see what I can do to ameliorate this.


Details:



I love teaching by writing code for the same reason I love programs: because what we create can be executed; it has a life of its own.  However, I also find it hard to convey the excitement of the big picture while digging through code.

What happened today may have seemed small, but it's big.  We wrote a programming language!

OK, it's not quite a real language.  (Not "Turing-Complete".)  But that's still pretty huge to do in less than 50 minutes in class!  (By the way, why Racket?  This isn't the only reason, but.. try implementing the same programming language (or a more "Java-like" language) in Java!  Sure, we and Racket "cheat" to make this work so well by choosing a concrete syntax that Racket is incredibly good at handling, but why not "cheat" this way?!)

We won a Turing Award.

OK, we didn't win it, but Jon Backus did, in large part for his development of Backus-Naur Form.  This notation is incredibly convenient and very powerful.  It models the structure of languages in a concise, readable form.  That's cool!

Take a minute to appreciate that.

Hopefully, the value of teaching-with-code will become clear on roughly Friday/Monday, when we start making tiny changes to the code of our interpreter that result in profound changes to the semantics of our language.  We'll see!

Meanwhile, I hope that the pace and handling of questions worked for you.  If not, talk to me, e-mail me, or comment here.  We are definitely going to go a bit fast, but hopefully a combination of factors will help with that: (1) We will closely follow the book; so, readings and class (either lecture or tutorial) will support each other. (2) Assignments will also closely relate to class work and readings.  (3) Exams, when we get to them, will also tie in tightly with class and readings.

Finally, a few random notes:

  1. I mentioned that read in Racket will get us data from text but didn't show how to use read.  Here you go:

    > (interp (parse (read)))
    {+ 1 {- 2 3}}
    0

    Or, if you have a file with program.ae with the code above in it:

    > (interp (parse (call-with-input-file "program.ae" read)))
    0

    That said, we'll mostly just use quoted expressions rather than read from user input, like:
    (parse '{+ 1 {- 2 3}})
  2. I waived off a request to debug errors in student code in class.  I'm sorry, and I'm happy to chat errors in office hours or after class.  Unfortunately, discovering that, e.g., "you typed exp where I type sexp" doesn't contribute to the lecture as a whole; so, I can't do it during class, unless I fortuitously make errors myself :^)

    Similarly, I will ask to take other questions that seem off-topic for the lecture as a whole "off-line" (out of class).  Please do get back to me if I ask you to take a question off-line! 

    (By the way, for debugging, explore that "debug" button in DrRacket.)
  3. Tutorials should now have extra space available.  Register soon!
  4. I also wanted to mention the name of the types we create with define-type.  They're called algebraic data types.  They can be very handy, especially when you're doing structural recursion.
Cheers,
Steve

P.S. Want more strange mumbo-jumbo in failed-tests? How about one of:


; This takes advantage of Racket's "contract" library, the same stuff we
; CAN use to enforce the contracts we write on procedures.  It also feels
; like a combination of the matching capabilities and function composition
; capabilities that Haskell gives you.
;
; (define (failed-tests)
;   (reverse (filter (cons/c (not/c 'good) any/c) plai-all-test-results)))
;
; I won't go into explanations on this one, but ask me in person if you'd like.
;
; Here's a version that instead uses Racket's function composition
; capabilities. 
;
; (define (failed-tests)
;   (reverse (filter (compose not (curry symbol=? 'good) first) plai-all-test-results)))
;
; Explanations:
; (compose x y z) is roughly equivalent to (lambda (arg) (x (y (z arg))))
; In other words, it's a way to chain together many functions (in exactly the sense
; of function composition from CPSC 121, if you saw it there).
;
; (curry x arg1) is roughly equivalent to (lambda (arg2) (x arg1 arg2))
; In other words, curry lets us "partially apply" a function, giving it some
; of its arguments and leaving it waiting for the rest.
;
; Here's a version that instead uses Racket's match capabilities:
;
; (define (failed-tests)
;   (reverse (filter (match-lambda [(cons 'good _) #f] [_ #t]) plai-all-test-results)))
;
; Again, I won't go into explanations, except to say that match-lambda makes a function
; of one argument that: for any list starting with 'good gives back false and
; for anything else gives back true.  Feel free to ask in person.
 

2 comments:

  1. [EDIT with correct link]

    Speaking of Turing machines, check this beauty out!

    http://www.youtube.com/watch?v=E3keLeMwfHY

    ReplyDelete
  2. I find Turing machines to be much more interesting when made out of plastic blocks: http://www.youtube.com/watch?v=cYw2ewoO6c4

    ReplyDelete