Principles of Programming Languages

Similar documents
Principles of Programming Languages

Functional Programming. Pure Functional Programming

Procedural abstraction SICP Data abstractions. The universe of procedures forsqrt. Procedural abstraction example: sqrt

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

Principles of Programming Languages

An introduction to Scheme

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

Principles of Programming Languages

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

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

Introduction to Scheme

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

Functional Programming. Pure Functional Languages

6.037 Lecture 4. Interpretation. What is an interpreter? Why do we need an interpreter? Stages of an interpreter. Role of each part of the interpreter

SCHEME AND CALCULATOR 5b

Organization of Programming Languages CS3200/5200N. Lecture 11

CS61A Discussion Notes: Week 11: The Metacircular Evaluator By Greg Krimer, with slight modifications by Phoebus Chen (using notes from Todd Segal)

CS 314 Principles of Programming Languages

Principles of Programming Languages

Functional Programming. Pure Functional Languages

Introduction to Typed Racket. The plan: Racket Crash Course Typed Racket and PL Racket Differences with the text Some PL Racket Examples

Chapter 1. Fundamentals of Higher Order Programming

Administrivia. Simple data types

User-defined Functions. Conditional Expressions in Scheme

Principles of Programming Languages

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

Fall Semester, The Metacircular Evaluator. Today we shift perspective from that of a user of computer langugaes to that of a designer of

CSCC24 Functional Programming Scheme Part 2

Typed Scheme: Scheme with Static Types

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

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

Chapter 15 Functional Programming Languages

Typed Racket: Racket with Static Types

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

CS558 Programming Languages

Denotational Semantics. Domain Theory

6.001 Notes: Section 6.1

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

LECTURE 16. Functional Programming

Introduction to Functional Programming

Turtles All The Way Down

CSc 520 Principles of Programming Languages

Comp 411 Principles of Programming Languages Lecture 7 Meta-interpreters. Corky Cartwright January 26, 2018

Fundamentals of Artificial Intelligence COMP221: Functional Programming in Scheme (and LISP)

6.001: Structure and Interpretation of Computer Programs

A Brief Introduction to Scheme (II)

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

Scheme Quick Reference

Functional Programming. Big Picture. Design of Programming Languages

Principles of Programming Languages

Why do we need an interpreter? SICP Interpretation part 1. Role of each part of the interpreter. 1. Arithmetic calculator.

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

A Small Interpreted Language

Basic Scheme February 8, Compound expressions Rules of evaluation Creating procedures by capturing common patterns

CS 360 Programming Languages Interpreters

Project 2: Scheme Interpreter

Principles of Programming Languages

Functional Programming Languages (FPL)

Modern Programming Languages. Lecture LISP Programming Language An Introduction

Scheme Quick Reference

Programming Languages: Application and Interpretation

Syntactic Sugar: Using the Metacircular Evaluator to Implement the Language You Want

Documentation for LISP in BASIC

6.001 Notes: Section 8.1

An Introduction to Scheme

Principles of Programming Languages

Discussion 12 The MCE (solutions)

Functional Programming

Building a system for symbolic differentiation

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

Lambda Calculus and Lambda notation in Lisp II. Based on Prof. Gotshalks notes on Lambda Calculus and Chapter 9 in Wilensky.

Announcements. The current topic: Scheme. Review: BST functions. Review: Representing trees in Scheme. Reminder: Lab 2 is due on Monday at 10:30 am.

Functional programming with Common Lisp

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

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

CS 314 Principles of Programming Languages

FP Foundations, Scheme

Recap: Functions as first-class values

TAIL RECURSION, SCOPE, AND PROJECT 4 11

CS558 Programming Languages

CMSC 330: Organization of Programming Languages. Formal Semantics of a Prog. Lang. Specifying Syntax, Semantics

CS 314 Principles of Programming Languages

Lexical Considerations

Building a system for symbolic differentiation

Lexical Considerations

An Explicit Continuation Evaluator for Scheme

COP4020 Programming Assignment 1 - Spring 2011

CSE413: Programming Languages and Implementation Racket structs Implementing languages with interpreters Implementing closures

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

CS 342 Lecture 8 Data Abstraction By: Hridesh Rajan

The PCAT Programming Language Reference Manual

CPS 506 Comparative Programming Languages. Programming Language Paradigm

1 Lexical Considerations

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

The Typed Racket Guide

Homework 3 COSE212, Fall 2018

Lecture #24: Programming Languages and Programs

An Explicit-Continuation Metacircular Evaluator

15 Unification and Embedded Languages in Lisp

Programming Languages

Transcription:

Principles of Programming Languages www.cs.bgu.ac.il/~ppl172 Lesson 6 - Defining a Programming Language Bottom Up Collaboration and Management - Elements of Programming Dana Fisman 1

What we accomplished so far Different programming languages encourage different programming practices (and make other difficult) o IP (imperative programming) vs. FP (functional programming) o FPs tools include: - first class citizen functions - immutability - functional abstractions 2

What we accomplished so far Two aspects in program definition: o The syntactic domain: Expressions - created inductively from atoms using combination operators o The semantic domain: Values - computed inductively when evaluating expressions o Operational semantics: give meaning to expressions by describing the evaluation process 3

What we accomplished so far Data types denotes sets of values on which operations can be preformed uniformly o Primitive types o User-defined types Data types can be related to one another using set relations (subsumed-in, disjoint, ) Data types can be created from other data types using set operations (union, intersection, product) 4

What we accomplished so far We can use a type-language to associate datatypes to expressions othe type-language is build inductively using the type-system) Some programs allow programmers to annotate variables and functions with type annotations A type checker can establish that a given program satisfies the type declaration constraints. 5

Our next mission Learn a small functional programming language with a formal definition of its syntax a formal definition of its operational semantics build an interpreter - a program computing the value of expressions following the inductive definition provided by the operational semantics Semantics: <expr> -> <value> interpreters provide 6 Interpreter: a program implementing the semantics function a clarification mechanism an Illustration mechanism

Which language? What properties should a language that is good for learning principles of programming languages have? 7

Why Scheme In one word: Minimalistic a small language - a small number of primitives, - a small number of constructs - a small number of data-types common syntax to all composite expressions common semantics to all composite expression Compare to Javascript Yet: it is expressive: Turing complete allows powerful functional abstractions which make programming productive 8

Plan Introduce syntactic constructs and their semantics in a gradual manner L0 L1 L2 L3 9 Scheme

Specifying a programming language How do we specify a programming language? What are the elements that together define a language? The key elements are: Primitives Primitive literal values (numbers, booleans) Primitive operations (arithmetic ops, comparison ops) Combination means Means to create compound values Means to create compound expressions Abstraction Expressions Means to manipulate compound objects as standalone units Two aspects Values 10

L0 - Syntax Atomic expressions 1. Number literal expression 0, 1, 2, 2. Boolean literal expression #t, #f 3. Primitive operation expression +, -, *, /, <, >, = Compound expressions 4. compound expressions (op expr 1 expr n ) 11

L0 - examples 8 (+ 1 7) 42 (- 45 3) 14 (* 2 7) 9 (/ 45 5) #f (> 2 7) 12

L0 - examples 16 (* (+ 1 1) (- 9 1)) #t (= (+ 1 5) (- 9 3)) (* (+ 1 1) (- 9 1)) 16 (= (+ 1 5) (- 9 3)) #t Why prefix notation? 10 (+ 1 2 3 4) 13

L0 - examples 4 4 #t #t + #<procedure:+> 14

L0 - Semantics Atomic expressions 1. Number literal expression 0, 1, 2, Evaluates to the corresponding numeric value 2. Boolean literal expression #t, #f Evaluates to the corresponding boolean value The atomic expressions evaluate to themselves 3. Primitive operation expression +, -, *, /, <, >, = Evaluates to the corresponding operation <procedure:op> Compound expressions 4. compound expressions (op expr 1 expr n ) 1. Let (val 0,val 1,,val n ) = (evaluate(op), evaluate(exp n ),, evaluate(exp n )) 2. Apply the procedure val 0 to the values val 1,,val n Recursive application 15

L0 - Syntax Atomic expressions 1. Number literal expression 0, 1, 2, 2. Boolean literal expression #t, #f 3. Primitive operation expression +, -, *, /, <, >, = Compound expressions 4. compound expressions (op expr 1 expr n ) What is missing from L0? (+ (- (* 2 37) 18) (* 9 (- (* 2 37) 18)))) abstraction - one of the key components! 16

Naming 17 We will add to L0 a means to name expressions. 6 (define size 6) size (* 2 size) 12 (define <name> <expr>) (define area (* size size)) area 36 size in this context is called a variable a variable as in math rather than as in IP The relation between a variable and the value it denotes is called a binding

Evaluating the define form (define <var> <expr>) The interpreter maintains a global environment: a table recording the bindings between variables and their values The evaluation rule for (define <var> <expr>) is 1. Let val = Evaluate(<expr>) 2. Add the binding (<var> val) to the global environment 3. Return void (= has no return value) 18 global env. variable value milion 1000000 pi 3.14159 size 6 global env. : variable => value

L1 - Syntax Atomic expressions 1. Number literal expression 0, 1, 2, 2. Boolean literal expression #t, #f 3. Primitive operation expression +, -, *, /, <, >, = 4. Variable expression size, my-secret-num, Compound expressions 5. special compound expressions (define <var> <expr>) 6. Non-special compound expressions (expr 0 expr 1 expr n ) 19

L1 - examples (define size 6) (define pi 3.14) (define area (* (* size size) pi)) area 113.04 (+ area (* 2 3)) 119.04 In the evaluation of define the expr is evaluated variable value size 6 pi 3.14159 area 113.04 20

L1 - Semantics Atomic expressions 1. Number literal expression 0, 1, 2, 2. Boolean literal expression #t, #f 3. Primitive operation expression +, -, *, /, <, >, = 4. Variable expression size, secret-num, Compound expressions 5. special compound expressions (define <var> <expr>) Lookup the variable in the env. Return the corresponding value special form 6. Non-special compound expressions (expr 0 expr 1 expr n ) non-special form 21 Evaluate: variable => value Need an evaluation rule for each of our constructs

special vs. non-special forms Two types of compound expressions (expr 0 expr 1 expr n ) non-special form all expressions are evaluated (keyword ) special form not all expressions are evaluate first expr is assumed to be a procedure first expr is a keyword 22 the evaluation rule is the fixed the evaluation rule depends on the keyword

Evaluation of Non-Special Forms (expr_0 expr_1 expr_2 expr_n) 1. Evaluate all subexpressions expr_i. The value of expr_0 must be of type Procedure, otherwise the evaluation fails (run-time error). 2. Apply the procedure which is the value of expr_0, to the values of the other subexpressions. 23

Evaluation of Non-Special Forms (expr_0 expr_1 expr_2 expr_n) The evaluation rule is recursive (* 3 (+ 2 (+ 1 100))) 309 (* 3 (+ 2 101)) (* 3 103) 24

L1 - Syntax Atomic expressions 1. Number literal expression 0, 1, 2, 2. Boolean literal expression #t, #f 3. Primitive operation expression +, -, *, /, <, >, = 4. Variable expression size, my-secret-num, Compound expressions 5. special compound expressions (define <var> <expr>) 6. Non-special compound expressions (expr 0 expr 1 expr n ) 25 What is missing from L1? No conditional expressions No way to define functions (that receive parameters)

Defining procedures In Typescript they are called functions, in Scheme procedures. What defines a function? Domain Range Giving it a name or not is a different issue a function associates an element d of the domain to an element r of the range a computable function associates with an element d of the domain some transformation (computation) on d 26

Defining procedures Syntax of procedure definition (lambda <parameters> <func-body>) where the syntax for <parameters> is And the syntax for <func-body> is (<param_1> <param_2> <param_n>) <expr_1> <expr_2> <expr_n> 27

Defining procedures (lambda <parameters> <func-body>) 28 (lambda (x) (* x x)) (lambda (x y z) (+ x y z)) Such expressions result in a procedure definition Not a procedure application (lambda (x y) (+ (* x x) (* 2 x y) (* y y))) We can think of lambda as the constructor of functions

Applying procedures (<proc> <parameters>) ((lambda (x) (* x x)) 3) 9 my-proc ((lambda (x y z) (+ x y z)) 1 2 3) my-proc 6 ((lambda (x y) (+ (* x x) (* 2 x y) (* y y))) 1 2) my-proc 9 In the same way as we apply primitive procedures (+ x y) (proc x y) can be a user-defined procedure 29

Note the difference The special lambda form The non-special form (lambda (x) (* x x)) ((lambda (x) (* x x)) 3) #procedure 9 user defined procedure Declaration of an anonymous procedure (same as x => x*x in Typescript) Note the syntactic differences The common way to apply procedure on parameters 30 The result is the value procedure The result is a value

Evaluating procedure applications ((lambda (<params>) <expr1> <expr2> <exprn>) <act-params>) The <func-body> can be made of multiple expressions The evaluation rule evaluates all the expressions and returns the value of the last one. What is this useful for? 31

What is it useful for? 9 ((lambda (x) (+ x 100) (* x (+ x 329)) (* x x)) 3) ((lambda (x) (display x) (* x x)) 3) 39 Only the last expression affects the returned value Multiple expressions in the body are useful when side-effects are desired 32 3 9 ((lambda (x) (display x) (newline) (* x x)) 3) The expression for the returned value should always come last!

Naming procedures Every expression in Scheme can be named using the following syntax (define <name> <expr>) (define ten 10) ten 10 (define square (lambda (x) (* x x))) square name expr #<procedure:square> 16 (square 4) 33

Naming procedures 34 16 For naming functions we also have the following (syntactic sugaring) form (define (<name> <parameters>) <body-expr>) (define (square x) (* x x))) (define square square (lambda (x) (* x x))) #<procedure:square> These two forms have exactly the (square 4) same semantics! (define area (* (* size size) pi)) 113.04 Note the differences with area Had the function referred to a variable which is not local or a parameter, its current value would have been recorded as well! variable value size 6 pi 3.14159 area 113.04 square #(Closure (x) (* x x)) The closure

The if special form (if <predicate> <consequent> <alternative>) (if (< 1 100) "then-part" "else-part") "then-part" (if (< 100 1) "then-part" "else-part") "else-part" (if (< 1 100) (+ 2 2) (* 7 7)) 4 (if (< 100 1) (+ 2 2) (* 7 7)) 35 49

The if special form Is the alternative (else-part) evaluated when the condition is (evaluated to) true? (if (< 1 100) (/ 1 0) (* 7 7)) /: division by zero (if (< 1 100) (+ 2 2) (/ 1 0)) 4 36

Evaluating the if special form (if <predicate> <consequent> <alternative>) Let p = Evaluate (<predicate>) If p is #t, Evaluate(<consequent>) and return it Otherwise Evaluate(<alternative>) and return it 37 In the if special form one of the expressions is not evaluated Unlike the non-special form in which all expressions are evaluated

The cond special form -Examples (cond ((> 1 2) first" ) ((> 2 2) "second") ((> 3 2) third" )) "third" (cond ((> 1 2) first" ) ((> 2 2) "second") (else third" )) "third" (cond ((> 1 2) "first" "FIRST") ((> 2 2) "second" "SECOND") ((> 3 2) "third" "THIRD")) "THIRD" (cond ((> 1 2) (display "first") "FIRST") ((> 2 2) (display "second") "SECOND") ((> 3 2) (display "third") "THIRD")) 38 third"third"

The cold special form (cond (<pred 1 > <expr-1 1 > <expr-2 1 > <expr-n 1 >) (<pred 2 > <expr-1 2 > <expr-2 2 > <expr-k 2 >) (<pred n > <expr-1 n > <expr-2 n > <expr-m n >) (else <expr-1 e > <expr-2 e > <expr-l e >)) A syntactic sugaring of if Thus, the only expressions that are evaluated are those corresponding to the first predicate to evaluate to true Only the predicates until the first predicate to evaluate to true are evaluated 39

L2 - Example Implementing Newton's method for computing square roots Newton's method is stated as this algorithm: If g is non-zero guess for a square root of x, then (g + x/g) / 2 is a better approximation of x. This algorithm is iterative! Interestingly, we can implement it although we have no construct for iteration 40

L2 - Example Auxiliary functions 41

L2 - Example As long as the guess is not good enough, improve it improved guess 42 First guess is set to 1 Check the difference between guess*guess and x is small enough Improve the guess according to Newton s method

L2 - Syntax Atomic expressions 1. Number literal expression 0, 1, 2, 2. Boolean literal expression #t, #f 3. Primitive operation expression +, -, *, /, <, >, = 4. Variable expression size, my-secret-num, Compound expressions 5. special compound expressions I. (define <var> <expr>) II. (lambda <parameters> <func-body>) III. (if <predicate> <consequent> <alternative>) IV. (cond ) 6. Non-special compound expressions (expr 0 expr 1 expr n ) 43

L2 - Semantics not all expressions are evaluated Atomic expressions 1. Number literal expression 0, 1, 2, 2. Boolean literal expression #t, #f 3. Primitive operation expression +, -, *, /, <, >, = 4. Variable expression size, my-secret-num, Compound expressions 5. special compound expressions I. (define <var> <expr>) II. (lambda <parameters> <func-body>) III. (if <predicate> <consequent> <alternative>) IV. (cond ) all are 6. Non-special compound expressions (expr 0 expr 1 expr n ) 44

Review of Last Lecture L3 L2 L1 if define cond only primitive ops and types lambda recursive comb. of primitive ops. supports recursive procedures Scheme 45

What is missing from L2? Compound values! In Javascript we have: array [] map {} What are the minimal constructs that we need to add in order to obtain array and map capabilities? 46

The pair compound data type The pair compound data type combines two values into a single unit. To support this the language provides: A value constructor (called cons) Accessors to take apart a compound pair value: for the first (called car) for the second (called cdr) A type predicate to check whether a value belongs to the set of pair values (called pair?) An equality predicate for pairs (called equal?) 47 To support pairs we add 5 primitive functions: cons, car, cdr, pair?, equal?

Pair, and associated types Types of the pair constructor and accessors: cons: [T 1 *T 2 -> Pair(T 1,T 2 )] car: [Pair(T 1,T 2 ) -> T 1 ] cdr: [Pair(T 1,T 2 ) -> T 2 ] pair?: [Any -> boolean] equal?: [Any * Any -> boolean] 48

L3 - pair examples (define foo (cons 1 2)) (car foo) 1 (cdr foo) 2 (define bar (cons 1 2)) (equal? foo bar) #t (pair? foo) #t 49 (pair? 2) #f

L3 - nesting pairs (define p12 (cons 1 2)) (define p123 (cons p12 3)) (define p1234 (cons p123 4)) (define p12345 (cons p1234 5)) p12345 '((((1. 2). 3). 4). 5) (car p12345) '(((1. 2). 3). 4) 3 (cdr (car (car p12345))) (cdr p12345) 5 Syntactic sugaring 3 (cdaar p12345))) 50 Can we use this to implement lists? What about the empty list???

Lists Using literals A list is an inductive data type. The base case is the empty list The inductive case creates a non-empty list by combining an element with a list (define L1234 '(1 2 3 4))) L1234 E1234 '(1 2 3 4) '(1 2 3 4) Using the list constructor (define E1234 (list 1 2 3 4))) 51 (define Lemp '()) Lemp '() (define Eemp (list)) Eemp '() (define C1234 (cons 1 (cons 2 (cons 3 (cons 4 ())))))) C1234 '(1 2 3 4) Using the pair constructor

Lists Lists can indeed be implemented using pairs and the empty list (and in fact are implemented this way in scheme) But the language also offers special constructs to deal with lists: A list constructor : (list <el1> <eln>) A literal list : (<el1> <eln>) Accessors first, second, third, A type predicate to check whether a value belongs to the set of list values (called list?) An emptiness predicate for list (called empty?) 52

functions on list : length (define length (lambda (l) (if (empty? l) 0 (+ 1 (length (cdr l)))))) Recursive functions operating on inductive data types follow their inductive definition 53

functions on list : n-th (define nth (lambda (n l) (cond [(empty? l) '()] [(= n 0) (car l)] [else (nth (- n 1) (cdr l))]))) 54 (nth 2 '(1 2 3 4)) 3 What happened here? (nth 8 '(1 2 3 4)) '() (nth 0 '(1 2 3 4)) 1

functions on list : n-th (define nth (lambda (n l) (cond [(empty? l) '()] [(= n 0) (car l)] [else (display (list "n:" n " l:" l)) (newline) (nth (- n 1) (cdr l))]))) Recall: the debug printing must precede the last expression, which is the returned value (nth 8 '(1 2 3 4)) 55 (n: 8 l: (1 2 3 4)) (n: 7 l: (2 3 4)) (n: 6 l: (3 4)) (n: 5 l: (4)) '()

L3 - Syntax Atomic expressions 1. Number literal expression 0, 1, 2, 2. Boolean literal expression #t, #f 3. Primitive operation expression +, -, *, /, <, >, =, cons, car, cdr, pair?, list?, empty? 4. Variable expression size, my-secret-num, 5. The empty list literal expression `() Compound expressions 6. special compound expressions I. (define <var> <expr>) II. (lambda <parameters> <func-body>) III. (if <predicate> <consequent> <alternative>) IV. (cond ) 7. Non-special compound expressions (expr 0 expr 1 expr n ) 56