CSC 533: Programming Languages Spring 2018

Slides:



Advertisements
Similar presentations
1 Copyright © 1998 by Addison Wesley Longman, Inc. Chapter 14 Functional Programming Languages - The design of the imperative languages is based directly.
Advertisements

1 Scheme and Functional Programming Aaron Bloomfield CS 415 Fall 2005.
Lists in Lisp and Scheme a. Lists are Lisp’s fundamental data structures, but there are others – Arrays, characters, strings, etc. – Common Lisp has moved.
CSE 3341/655; Part 4 55 A functional program: Collection of functions A function just computes and returns a value No side-effects In fact: No program.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
1 Programming Languages and Paradigms Lisp Programming.
Lambda Calculus and Lisp PZ03J. Lambda Calculus The lambda calculus is a model for functional programming like Turing machines are models for imperative.
Chapter 3 Functional Programming. Outline Introduction to functional programming Scheme: an untyped functional programming language.
CS 355 – PROGRAMMING LANGUAGES Dr. X. Apply-to-all A functional form that takes a single function as a parameter and yields a list of values obtained.
1 Functional programming Languages And a brief introduction to Lisp and Scheme.
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
CS 330 Programming Languages 11 / 20 / 2007 Instructor: Michael Eckmann.
Chapter 15 Functional Programming Languages. Copyright © 2007 Addison-Wesley. All rights reserved. 1–2 Introduction Design of imperative languages is.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Comp. Eng. SW Lab II: FP with Scheme 1 Computer Eng. Software Lab II , Semester 2, Who I am: Andrew Davison CoE, WiG Lab Office.
1 Lisp Functions –Built-in functions –Defining functions –Function Evaluation and Special Forms defun, if Control statements –Conditional if, cond –Repetition.
Functional Programming in Scheme
ISBN Chapter 15 Functional Programming Languages.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
CS 330 Programming Languages 11 / 21 / 2006 Instructor: Michael Eckmann.
1 CSC 533: Organization of Programming Languages Spring 2010 Functional programming  LISP & Scheme  S-expressions: atoms, lists  functional expressions,
Introduction to Scheme CS 480/680 – Comparative Languages “And now for something completely different…” – Monty Python “And now for something completely.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
ISBN Chapter 15 Functional Programming Languages.
ISBN Chapter 15 Functional Programming Languages.
LISP Data Types Functional Programming Academic Year Alessandro Cimatti
CSC 550: Introduction to Artificial Intelligence Spring 2004 Scheme programming  S-expressions: atoms, lists  functional expressions, evaluation  primitive.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
Comparative Programming Languages Functional programming with Lisp/Scheme.
Artificial Intelligence and Lisp Lecture 6 LiU Course TDDC65 Autumn Semester,
CSC 533: Programming Languages Spring 2014
CS314 – Section 5 Recitation 9
CSC 533: Programming Languages Spring 2016
CS314 – Section 5 Recitation 10
Functional Programming Languages
Functional Programming Languages
Functional Programming
History of Computing – Lisp
Types CSCE 314 Spring 2016.
Section 15.4, 15.6 plus other materials
CS 326 Programming Languages, Concepts and Implementation
Introduction to Scheme
CS 326 Programming Languages, Concepts and Implementation
CS 326 Programming Languages, Concepts and Implementation
Lists in Lisp and Scheme
CSC 533: Programming Languages Spring 2017
CSC 533: Programming Languages Spring 2015
CSC 533: Organization of Programming Languages Spring 2008
LISP A brief overview.
Introduction to Functional Programming in Racket
The Metacircular Evaluator
FP Foundations, Scheme In Text: Chapter 14.
Functional Programming Languages
Abstraction and Repetition
LISP A brief overview.
6.001 SICP Variations on a Scheme
Introduction to Functional Programming in Racket
Announcements Quiz 5 HW6 due October 23
Defining Functions with DEFUN
Abstraction and Repetition
15.2 Mathematical Functions
CSC 533: Organization of Programming Languages Spring 2007
Common Lisp II.
Chapter 15 Functional Programming 6/1/2019.
CSC 533: Organization of Programming Languages Spring 2005
Lists in Lisp and Scheme
Abstraction and Repetition
CSC 533: Programming Languages Spring 2019
Presentation transcript:

CSC 533: Programming Languages Spring 2018 Functional programming LISP & Scheme S-expressions: atoms, lists functional expressions, evaluation, define primitive functions: arithmetic, predicate, symbolic, equality, higher-order special forms: if, cond recursion: tail vs. full

Functional programming imperative languages are modeled on the von Neumann architecture in mid 50's, AI researchers (Newell, Shaw & Simon) noted that could define a language closer to human reasoning symbolic (dynamic) list-oriented transparent memory management in late 50's, McCarthy developed LISP (List Processing Language) instantly popular as the language for AI separation from the underlying architecture tended to make it less efficient (and usually interpreted)

LISP LISP is very simple and orthogonal only 2 kinds of data objects atoms (identifiers, strings, numbers, …) lists (of atoms and sublists) unlike arrays, lists do not have to store items of same type/size do not have to be stored contiguously do not have to provide random access all computation is performed by applying functions to arguments in pure LISP: no variables, no assignments, no iteration functions and function calls are also represented as lists no distinction between program and data

Scheme Scheme was developed at MIT in the mid 70's clean, simple subset of LISP static scoping first-class functions efficient tail-recursion function calls appear as lists: (FUNC ARG1 ARG2 … ARGn) (+ 3 2) 5 (+ 3 (* 2 5)) 13 (car '(foo bar biz baz)) foo (cdr '(foo bar biz baz)) (bar biz baz) quote symbol denotes data - not evaluated by the interpreter - numbers are implicitly quoted car : returns first element of list cdr : returns rest of list

Scheme functions Scheme functions are also defined as lists (MORE DETAILS LATER) (define (FUNC ARG1 ARG2 . . . ARGn) RETURN_EXPRESSION) (define (square x) (define (last arblist) (* x x)) (car (reverse arblist))) (square 3)  (last '(a b c)) 9 c (square 1.5)  (last '(foo)) 2.25 foo

Obtaining a Scheme interpreter many free Scheme interpreters/environments exist Dr. Racket is a development environment developed at Rice University contains an integrated editor, syntax checker, debugger, interpreter Windows, Mac, and UNIX versions exist can download a personal copy from https://download.racket-lang.org/ Racket is a new, educational language built on Scheme to select classic Scheme: Language > Choose Language > Pretty Big PLAY TIME! Details to follow…

S-expressions in LISP/Scheme, data & programs are all of the same form: S-expressions (short for Symbolic-expressions) an S-expression is either an atom or a list atoms numbers 4 3.14 1/2 #xA2 #b1001 characters #\a #\Q #\space #\tab strings "foo" "Dave Reed" "@%!?#" Booleans #t #f symbols Dave num123 miles->km !_^_! symbols are sequences of letters, digits, and "extended alphabetic characters" + - . * / < > = ! ? : $ % + & ~ ^ can't start with a digit, case insensitive by default (but can set preferences in Dr. Scheme)

S-expressions (cont.) lists for example: () is a list (L1 L2 . . . Ln) is a list, where each Li is either an atom or a list for example: () (a) (a b c d) ((a b) c (d e)) (((((a))))) note the recursive definition of a list – GET USED TO IT! also, get used to parentheses (LISP = Lots of Inane, Silly Parentheses)

Functional expressions computation in a functional language is via function calls (FUNC ARG1 ARG2 . . . ARGn) (car '(a b c)) (+ 3 (* 4 2)) note: functional expressions are S-expressions evaluating a functional expression: function/operator name & arguments are evaluated in unspecified order note: if argument is a functional expression, evaluate recursively the resulting function is applied to the resulting values (car '(a b c)) so, primitive car function is called with argument (a b c) evaluates to list (a b c) : ' terminates recursive evaluation evaluates to primitive function

Arithmetic primitives predefined functions: + - * / quotient remainder modulo max min abs gcd lcm floor ceiling truncate round = < > <= >= many of these take a variable number of inputs (+ 3 6 8 4)  21 (max 3 6 8 4)  8 (= 1 (-3 2) (* 1 1))  #t (< 1 2 3 4)  #t functions that return a true/false value are called predicate functions zero? positive? negative? odd? even? (odd? 5)  #t (positive? (- 4 5))  #f

Data types in LISP/Scheme similar to JavaScript, LISP/Scheme is dynamically typed types are associated with values rather than variables, bound dynamically numbers can be described as a hierarchy of types number complex real MORE GENERAL rational integer integers and rationals are exact values, others can be inexact arithmetic operators preserve exactness, can explicitly convert (+ 3 1/2)  7/2 (+ 3 0.5)  3.5 (inexact->exact 4.5)  9/2 (exact->inexact 9/2)  4.5

Symbolic primitives predefined functions: car cdr cons list list-ref length member reverse append (list 'a 'b 'c)  (a b c) (list-ref '(a b c) 1)  b (member 'b '(a b c))  (b c) (member 'd '(a b c))  #f car and cdr can be combined for brevity (cadr '(a b c))  (car (cdr '(a b c)))  b cadr returns 2nd item in list caddr returns 3rd item in list cadddr returns 4th item in list (can only go 4 levels deep)

Equality primitives equal? compares 2 inputs, returns #t if equivalent, else #f (equal? 'a 'a)  #t (equal? '(a b) '(a b))  #t (equal? (cons 'a '(b)) '(a b))  #t other (more restrictive) equivalence functions exist eq? compares 2 symbols (efficient, simply compares pointers) eqv? compares 2 atomics (symbols, numbers, chars, strings, bools) -- less efficient, strings & numbers can't be compared in constant time (eq? 'a 'a)  #t (eqv? 'a 'a)  #t (eq? '(a b) '(a b))  #f (eqv? '(a b) '(a b))  #f (eq? 2 2)  unspecified (eqv? 2 2)  #t equal? uses eqv?, applied recursively to lists

Defining functions can define a new function using define a function is a mapping from some number of inputs to a single output (define (NAME IN1 IN2 … INn) OUTPUT_VALUE) (define (square x) (define (next-to-last arblist) (* x x)) (cadr (reverse arblist))) basically, parameter passing is by-value since each argument is evaluated before calling the function – but no copying (instead, structure sharing)

In-class exercise define a function that converts from Fahrenheit to Celsius note: celsius = 5/9 * (fahr – 32) (define (fahr->celsius temp) ??? ) similarly, define a function that does the opposite conversion (define (celsius->fahrtemp)

Conditional evaluation can select alternative expressions to evaluate (if TEST TRUE_EXPRESSION FALSE_EXPRESSION) (define (my-abs num) (if (negative? num) (- 0 num) num)) (define (singleton? arblist) (if (and (list? arblist) (= (length arblist) 1)) #t #f)) and, or, not are standard boolean connectives evaluated from left-to-right, short-circuit evaluation

Conditional evaluation (cont.) predicates exist for selecting various types symbol? char? boolean? string? list? null? number? complex? real? rational? integer? exact? inexact? note: an if-expression is a special form is not considered a functional expression, doesn’t follow standard evaluation rules (if (list? x) (car x) (list x)) anything but #f is considered "true" (if (member 'foo '(biz foo foo bar)) 'yes 'no) test expression is evaluated if value is anything but #f, first expression is evaluated & returned if value is #f, second expression is evaluated & returned

Multi-way conditional when there are more than two alternatives, can nest if-expressions (i.e., cascading if's) use the cond special form (i.e., a switch) (cond (TEST1 EXPRESSION1) (TEST2 EXPRESSION2) . . . (else EXPRESSIONn)) (define (compare num1 num2) (define (my-member item lst) (cond ((= num1 num2) 'equal) (cond ((null? lst) #f) ((> num1 num2) 'greater) ((equal? item (car lst)) lst) (else 'less))) (else (my-member item (cdr lst))))) evaluate tests in order when reach one that evaluates to "true", evaluate corresponding expression & return

In-class exercise define functions related to leap year a year is a leap year if divisible by 4, except when divisible by 100 but not 400 (define (leap-year? year) ??? ) (define (days-in-year year) (leap-year? 2016)  #t (leap-year? 2100)  #f (days-in-year 2016)  366 (days-in-year 2100)  365

Repetition via recursion pure LISP/Scheme does not have loops repetition is performed via recursive functions (define (sum-up-to N) (if (< N 1) (+ N (sum-up-to (- N 1))))) (define (my-length lst) (if (null? lst) (+ 1 (my-length (cdr lst))))) (define (my-member item lst) (cond ((null? lst) #f) ((equal? item (car lst)) lst) (else (my-member item (cdr lst)))))

Tail-recursion vs. full-recursion a tail-recursive function is one in which the recursive call occurs last (define (my-member item lst) (cond ((null? lst) #f) ((equal? item (car lst)) lst) (else (my-member item (cdr lst))))) a full-recursive function is one in which further evaluation is required (define (sum-up-to N) (if (< N 1) (+ N (sum-up-to (- N 1))))) each full-recursive call requires a new activation record on the run-time stack with tail-recursion, don't need to retain current activation record when make call can discard the current activation record, push record for new recursive call thus, no limit on recursion depth (each recursive call reuses the same memory) Scheme interpreters are required to perform this tail-recursion optimization

Tail-recursion vs. full-recursion (cont.) any full-recursive function can be rewritten using tail-recursion often accomplished using a help function with an accumulator (define (factorial N) (if (zero? N) 1 (* N (factorial (- N 1))))) (factorial-help N 1)) (define (factorial-help N value-so-far) value-so-far (factorial-help (- N 1) (* N value-so-far))))) value is computed "on the way up" (factorial 2)  (* 2 (factorial 1)) (* 1 (factorial 0)) 1 value is computed "on the way down" (factorial-help 2 1)  (factorial-help 1 (* 2 1)) (factorial-help 0 (* 1 2)) 2

In-class exercise define function to count the number of days in a range of years (define (days-in-range startYear endYear) ??? ) (days-in-range 2015 2016)  731 (days-in-range 2015 2020)  2192

Scoping in Scheme unlike early LISPs, Scheme is statically scoped can nest functions and hide details (define (factorial N) (define (factorial-help N value-so-far) (if (zero? N) value-so-far (factorial-help (- N 1) (* N value-so-far)))) (factorial-help N 1)) since factorial-help is defined inside of factorial, hidden to outside since statically scoped, arguments in enclosing function are visible to enclosed functions (i.e., non-local variables)

When tail-recursion? (define (sum-up-to N) (define (sum-help N sum-so-far) (if (< N 1) sum-so-far (sum-help (- N 1) (+ N sum-so-far)))) (sum-help N 0)) (define (my-length lst) IN-CLASS EXERCISE (length-help lst 0)) usually, a full-recursive solution is simpler, more natural for a small number of repetitions, full-recursion is sufficient for a potentially large number of repetitions, need tail-recursion

Higher-order primitives (apply FUNCTION LIST) applies the function with the list elements as inputs (apply + '(1 2 3))  (+ 1 2 3)  6 (apply min '(5 2 8 6))  (min 5 2 8 6)  2 (map FUNCTION LIST) applies the function to each list element (map sqrt '(9 25 81))  (list (sqrt 9) (sqrt 25) (sqrt 81))  (3 5 9) (map car '((a b) (c d) (e)))  (list (car '(a b)) (car '(c d)) (car '(e)))  (a c e)