CourseCourse ContentsContents

 Introdutction  Syntax and semantics  Regular expression CSC324H Principle of Programming  BNF  CFG Languages (Week 3) • (in Scheme) • Logic programming (in Prolog)

Yilan Gu TodayToday [email protected]  Scheme http://www.cs.toronto.edu/~yilan/324f09  Introduction  Basic data types  Properties of Pure Functional Languages  Basic functions and recursion

FunctionalFunctional Programming:Programming: IntroductionIntroduction • LISP – "LISt Processor" – A functional language developed by John McCarthy in the late 1950s for use in AI. IntroductionIntroduction – Semantics (meaning) based on λ-calculus. • The λ-calculus is a theoretical model of computation – Functions operate on lists or atomic symbols. • Programs consist of "S-expressions" • Five basic functions: cons, car, cdr, equal, atom • one conditional construct: cond – Programs and data are both S-expressions.

IntroductionIntroduction (Cont.)(Cont.) TheThe SchemeScheme We'llWe'll UseUse • Common LISP – LISP implementations began to stray • There are many flavours of Scheme, with quite a bit of variation – Semantics were redefined in Common LISP. among them. – Common LISP is now the standard version of LISP. – But not as much variation as among the LISPs. • Designed by committee in 1980s. – Simple syntax, but a large language. • DrScheme is an IDE that works with PLT Scheme. • Scheme – Use the command "drscheme" on CDF. – Created in 1975 by Gerald Sussman and Guy Steele. – Make sure the selected language is Module . – A dialect of LISP – PLT Scheme ( including DrScheme) can be downloaded from http://download.plt-scheme.org/ – Simple syntax, small language – Your assignments must run using DrScheme on CDF. – Close to the initial semantics of LISP – Allows functions to be first-class object

SchemeScheme ReferencesReferences AA SchemeScheme ProgramProgram

• A program consists of • Mitchell, Chapter 3, 4.2 - 4.5 – a set of function definitions • Sebesta, Section 15.5. – an expression to be evaluated • Dybvig, The Scheme Programming Language, 2003. – This textbook can be read online at: • A simple example that defines function abs-val and then calls this http://www.scheme.com/tspl3/ function (note that ">" is the interpreter's prompt): > (define (abs-val x) (if (>= x 0) x (- x))) > (abs-val (- 3 5)) 2

S-expressionsS-expressions TheThe BasicBasic StructureStructure • So far we've seen S-expressions that are lists (that is, enclosed in brackets). • Atoms are also S-expressions. • A program consists of S-expressions ("symbolic expressions") written in parenthesized prefix form. • An atom is anything that is not a non-empty list. Atoms include: – Prefix form – Numbers, strings, symbols, the empty list, booleans. – The general form of an S-expression in prefix-form is: • Examples of some s-expressions ( ) #t ; true #f ; false • Examples of S-expressions in prefix-form: () ; the empty list (+ 3 4) (+ 4 5) ; A simple example. (a (b c) ) ; a nested list

(+ (* 3 4 5) (- 5 3)) • Observe that lists can be nested.

BasicBasic DataData TypesTypes

• Number: 5, -7, 3.14, 1+2i Including integers, rationals, reals, and complex numbers: these types are not disjoint – Type predicates: number?, integer?, real?, complex? – Other predicates: positive?, negative?, zero?, even?, odd? ... BasicBasic DataData TypeType – Arithmatic operations: +, -, *, /, floor, remainder, ... – Comparison predicates: =, <, >, <=, >= • Symbol: a, ABC, foo – (quote ABC) or 'ABC – Type predicate: symbol? • Boolean: #t, #f – Useful predicates: boolean?, boolean=?, not, and, or

BasicBasic DataData TypesTypes BasicBasic DataData TypesTypes

• Pair: pair • List: (), (1), (a b), (1 2 3) (1 . 2) – the only list that is not a pair is () ((1 . 2) . 3) 1 address 2 decrement – a sequence of pairs, such that each pair's cdr is next pair, and (1 2 3 . 4) cdr of last pair is () • Constructors -- cons • Examples (cons 1 2) (cons 1 '()) (cons (cons 1 2) 3) (cons '(1) '(2 3)) 1 (cons 1 (cons 2 (cons 3 4)) (car '(1))

 (cdr '(1)) Selectors – car cdr 2 (car '(1 . 2)) (cdr '(1 2 3)) (cdr '(1 2 . 3)) 3 nil

BasicBasic DataData TypesTypes SomeSome ExercisesExercises ofof PairsPairs andand ListsLists • Pair: (1 . 2), (#t . #f), (1 . #t) • List: (), (1), (a b), (1 2 foo 3.14) '((1 . 3) (1) 2 . 3) • predicates: list?, pair?, null? • selection: liscar, cdr, cadr, caadr, cadddr, ... (car '((1 . 3) (1) 2 . 3)) • construction: cons, cons*, list, ... • more: length, append, member, ... (car (cdr '((1 . 3) (1) 2 . 3))) • higher-order: map, reduce, fold-right, fold-left, ...

(cdr (cdr '((1 . 3) (1) 2 . 3)))

(cdr (car (cdr '((1 . 3) (1) 2 . 3))))

ValuesValues andand EvaluationEvaluation READ-EVAL-PRINTREAD-EVAL-PRINT LoopLoop

Objects and their values: (REPL)(REPL) • number: it's own value • symbol: may be undefined READ : Read input from user (define x 3) EVAL : Evaluate input • (quote expr) : expr List elements are evaluated from left to right: 'expr : shortcut for (quote expr) (f arg0 arg1 ... argn) • Lists: 1. evaluate f: obtain a procedure '() has value () 2. evaluate each arg0 ... argn (f arg0 ... argn) has value f(arg0, ..., argn) 3. apply procedure to argument values PRINT : Print resulting value: the result of the procedure application

This is called applicative-order evaluation.

READ-EVAL-PRINTREAD-EVAL-PRINT LoopLoop PreceduresPrecedures ExampleExample • Procedure: (lambda (arg0 ... argN) expr) > (cons 'a (cons 'b '(c d))) > (lambda (x) (+ x 1)) ;Value 1: (a b c d) ;Value 11: #[compound-procedure 11] Read the input (cons 'a (cons 'b '(c d))) • Evaluate cons : obtain a procedure > ((lambda (x) (+ x 1)) 42) • Evaluate 'a : obtain a ;Value: 43 • Evaluate (cons 'b '(c d)) : > ((lambda (x y) • Evaluate cons : obtain a procedure (if (> x y) x y)) – Evaluate 'b : obtain b – Evaluate '(c d) : obtain (c d) 42 0) – Apply cons to b and '(c d) : obtain (b c d) ;Value: 42 • Apply the cons procedure to a and (b c d) : obtain (a b c d) • Print the result of the application: (a b c d)

TheThe SpiritSpirit ofof FunctionalFunctional PLsPLs

• Programs are viewed as collections of functions .

• Execution of programs is viewed as evaluation . PurePure FunctionalFunctional ProgrammingProgramming

PurePure FunctionalFunctional LanguagesLanguages PurePure FunctionalFunctional LanguagesLanguages

: • Manifest Interface Principle (of Programming Languages): syntactically identical expressions mean the same thing, (i.e. return the All interfaces should be apparent (manifest) in the syntax. same result when evaluated) regardless of WHERE they appear in a program. – A pure function is one that simply uses its input arguments to compute a return value, without performing any side- – In a language that only uses pure functions, any function call effects….? with instantiated arguments, e.g. (f 5 10), ALWAYS returns – Side-effects are changes to the system’s computational state the same value and hence means the same thing in the that could affect future calls to itself or other functions. context of a particular program.

PurePure FunctionalFunctional Languages:Languages: PurePure FunctionalFunctional LanguagesLanguages toto assignassign isis bad…bad… (no(no assignment)assignment) • When all functions are pure, referential transparency and the • When an assignment statement is applied to variables (i.e. memory manifest interface principle are upheld, and thus: locations) that – No side-effects, rograms are much easier to formally analyze – a) will be maintained AFTER the function call is completed, a) Once we know the local behaviors of functions, we can reason about the system in – b) will be used for their values during later function calls (to the same or terms of independent function calls, without having to worry about the (side) effects other functions), of these calls on future calls. It violates referential transparency and destroys one’s ability to b) We can identify identical functional calls as equivalent objects and simplify the statically analyze source code (both formally or intuitively). code accordingly. E.g. (+ (f 5 10) (f 5 10)) simplifies to (* 2 (f 5 10)) for any numeric function f • Example: (define g 10) ; define a global variable, g. – Programs are much easier to DEBUG!!! You can understand programs by just looking at the static source code. You need not (define (f a) ; define function f, with one argument, a. think about the underlying computational states and how they are affected by (set! g (* g g)) ; Scheme’s assignment operator, meaning g = g*g program dynamics. (+ a g)) ]=> (f 7) What you see is what you get! 107 ]=> (f 7) (Mitchell, page78 for more) 10007 ; BADDD 

PurePure FunctionalFunctional LanguagesLanguages PurePure FunctionalFunctional LanguagesLanguages

• Recursion vs. iteration: • Functions are first-class values: In pure FP, recursion is generally preferred as a matter of style to – Can be returned as the value of an expression iterative constructs like while-loops or for-loops. This makes – Can be passed as an argument programs – Can be put in a data structure as a value – easier to reason about and to prove correct – Unnamed functions exist as values – easier to conceptualize as functions: recursions, like functions, identify the structure of one or more arguments as the only values upon which the computation (and termination) depends

PurePure FunctionalFunctional LanguagesLanguages

• A higher-level language: – All storage management is implicit: we don't have to think about how program state maps to a computer's memory (or at least, not until we want to write super-efficient code). That means no assignment, no new/free calls to manage our own memory, and no pointers. – The state of a computation is much easier to think about SchemeScheme BasicBasic FunctionsFunctions

Why Lisp is successful? Motivation, simple, unambiguous execution model, theorectical What's the contributions of Lisp? Recursive functions, lists, programs as data, garbage collection (Mitchell page 39-40)

PredicatePredicate functionsfunctions PredicatePredicate FunctionsFunctions • eq? eqv? equal? • Function that return #t (true) or #f (false) – eq? tests for the same object (similar to a pointer comparison) – Note: some scheme interpreters use empty list () to indicate #f – eqv? extends eq? to look into value of numbers and characters – equal? Goes further than eqv? And looks recursively into the contents of lists, vectors, etc.. • Predefined functions: – (= … ) ; comparison for numbers • Rules: – (> … ) ; also ( < ..) – For all three tests, objects of different types are never equal. – (and …) ; also ( or …) ( not ….) – (negative? …) – Exact and inexact numbers are considered different types – (number? …) ; – (symbol? …) ; • Example: – (zero? …) ; – (string? …) ; – (boolean? …) ; – (list? …) ; – (null? …) ; – (char? …) ; – (eqv? …) ; An equivalence predicate is the computational analogue of a ; mathematical equivalence relation (it is symmetric, reflexive, and ; transitive) – (eq? …) ; the finest or most discriminating – (equal? …) ; the coarsest

IFIF ExpressionExpression ConditionalConditional ExpressionExpression

• A Conditional expression are of the form:

(cond (

) or ( cond (

)

(

) (

) • If Expression: … … – Can be used when there are a maximum of 2 cases (

) (

))

(if ) (else )) (if ) – cond is a built in primitive

– Example: – pi is a predicate (truth function) that evaluates to either #t or #f • (if (< x 0) (- x) x ) ;? – Each predicate expression is evaluated in the order it appears. As soon as one is found to be true, the corresponding expression (e ) is evaluated and • (define (zerocheck? x) ( if (= x 0) #t #f ) ) ;? i returned as the result of the cond expression. – cond is like nested if then else statements

ShortShort CircuitCircuit EvaluationEvaluation AnonymousAnonymous FunctionsFunctions • (and ...) • Anonymous functions are defined using lambda expressions: – E.g. (lambda () ) (if ( and (try-first-thing) (try-second-thing) • Examples: (try-third-thing))…) – ((lambda (symbol) (eq? 'joe symbol)) 'fed) ; ? – If the three calls all return true values #t – ((lambda (x) (* x x)) 3) ; ? – If any of them returns #f, however, none of the rest are evaluated, and #f is returned as the value of the overall expression • A lambda expression can be used to construct a procedure to be • (or ... ) used as an operator - E.g. – E.g.: (if ( or (try-first-thing) ((lambda (x y z) (+ x y z)) 1 2 3) ; ? (try-second-thing) (try-third-thing)) …) • We could use a lambda expression to construct an anonymous - Likewise, it stops when it gets a true value function and then later on, we can bind a name to that function if we want. • (not ...) (define add-3 (lambda (x y z) (+ x y z)) ) (define (add-3 x y z) (+ x y z))

RecursionRecursion Scheme:Scheme: howhow toto approachapproach recursion?recursion? • Strategy: - How to reduce the problem? • Recursion is the preferred way to do computation in functional • Header: languages. - What info needed as input and output? - Write the function header. - Use a noun phrase for the function name • Spec: - Write a method specification in terms of the parameters and return value. - Include preconditions • Base cases: 1. When is the answer so simple that we know it without recursing? 2. What is the answer in these base cases(s)? 3. Write code for the base case(s) Did the right hand draw the left hand first? • Recursive Cases: Or did the left hand draw the right hand that draws the left hand?? 1. Describe the answer in the other case(s) in terms of the answer on smaller inputs 2. Simplify if possible This famous art work by M.C. Escher is an example of recursion 3. Write code for the recursive case(s)

RecursionRecursion ExampleExample RecursionRecursion ExampleExample (cont.)(cont.) • Consider a function named Power which calculates the result of • In fact we can write the formula: raising an integer to a positive power. If X is an integer and N is a positive integer, the formula for X N is

• This definition of X N is a classic recursive definition, a definition given in terms of a smaller version of itself.

• We could also write this formula as: • When does the process stop? – When we have reached a case where we know the answer without resorting to a recursive definition. – Base case: N is 1  X 1 is X

• Or even as: • Pseudocode:

RecursionRecursion ExampleExample (cont.)(cont.) RecursionRecursion ExampleExample 22 • Consider The factorial of a number N (written N!) is N multiplied • Trace: by N-1, N-2, N-3 and so on. Hence, another way of expressing factorial is

• When does the process stop? – 0! = 1

• Pseudocode:

RecursionRecursion ExampleExample 22 (Cont.)(Cont.) • In Scheme: (define (factorial n) Simple Excercises (if (= n 0) ; base condition 1 • Define a function f(n), such that it generates (* n (factorial (- n 1 ) ) ) ) ) ; recursive case 1, 1, 2, 1, 3, 2, 5, 6, 11, 30, 41, 330, ... • Trace: • Define a funciton length(list), such that it returns the length of a plain list. E.g, (length '()) ;0 (length '(1 3 4)) ;2

Scheme:Scheme: programmingprogramming stylestyle Scheme:Scheme: programmingprogramming stylestyle -- cont’dcont’d • Use special suffix: – "?" for predicates (i.e. functions returning #t or #f , e.g. member? ) • Deeply nested cars and cdrs are often difficult to understand, – "!" for any procedure with "side effects" (i.e. changes of bindings for non- and should therefore be avoided. local variables, e.g. set! )

• Procedure definitions should be brief • Since Scheme is a dynamically typed language, the names of – Oriented towards a single, well-defined task parameters should reflect their value. – Should be split into a number of subtasks if > 1 page • Most general guidelines on programming style also apply to • Comments: Scheme programs. – ; for comments on the same line with code – ;; for comments that run from beginning of line – ;;; for comments that describe the contents of the file (usually first in file)

• Indentation: – Indent procedure definitions like this, with the body starting a new line, and indented a few characters (define foo 15)

Next time: • Different recursion types • Local binding: let, let*, letrec • High order-functions • etc.