Function Calls - Carleton College
Download
Report
Transcript Function Calls - Carleton College
Announcements
See web page for talk schedule
Dire consequences if I don’t hear from
you by Monday
Schedule next week:
• Monday – class as usual
• Wednesday – class as usual
• immediately after class – I go to Chicago for
data mining conference, return Sunday (will be
checking email)
• Friday – class as usual: Les LaCroix from
ITS will talk about scripting languages
Scheme Lists
Lists are a special form of SExpressions
() represents the empty list
(A) represents list contains A
• (A) is really (A . ())
(A B) is really (A . (B . () ) )
• (picture on blackboard)
Function Calls
Function calls represented as lists
• (A B C) means
• evaluate A to a function, evaluate B and C as parameters
Use the value returned by the call as the
"meaning" of (A B C)
Why does (car (1 2)) fail?
• (1 2) looks like a function call, but 1 isn't a
function. quote function says "don't evaluate"
• (car (quote (1 2)))
• shorthand: (car '(1 2))
User-defined functions
The list
(lambda (args) (body))
creates an anonymous function
(lambda (x y) (+ x y))
((lambda (x y) (+ x y)) 5 6)
=> 11
User-defined functions
The scheme command define binds
values and functions to symbols
• (define pi 3.14159265)
• (define add-two-nums
(lambda (x y) (+ x y)))
Abbreviated as
(define add-two-nums (x y)
(+ x y))
Functions in Scheme are first-class
objects – treated just like any other data
type
Recursion
Breaks a problem down into simpler or
smaller problems
Mentality:
If trivial case then
supply answer
else
supply part of answer
combined with solution of
smaller problem
Example: nth function
Example: nth function
(define (nth input n)
(if (= n 0) (car input)
(nth (cdr input) (- n 1))))
Example: copy-list
Example: copy-list
(define (copy-list input)
(cond ((= (length input) 0) ())
((= (length input) 1)
(list (car input)))
(else (cons (car input)
(copy-list (cdr input))))))
Let and side effects
let is used to create local variables
• example in DrScheme
let is good for preventing functions from
affecting the outside world
A side effect is when a function changes
either one if its parameters or a global
variable
Scheme uses the ! as a convention to
indicate that a function changes an
argument
Subsets
How can we define a Scheme function
to create a subset?
(subsets ‘(1 2 3)) =>
( () (1) (2) (3) (1 2)
(1 3) (2 3) (1 2 3))
Number of subsets of n+1 values is
twice as many as subsets of n values
If we have subsets of (1 2), get subsets
of (1 2 3) by duplicating all subsets of
(1 2) and adding 3
Subsets
Define distrib function to add a new
element to a list of lists
(distrib ‘(() (1) (2) (1 2)) 3) =>
( (3) (3 1) (3 2) (3 1 2))
(define (distrib L E)
(if (null? L) ()
(cons (cons E (car L))
(distrib (cdr L) E))))
Then define an extend function to attach
these two together:
Subsets
(define (extend L E)
(append L (distrib L E)))
Then defining the subsets code is easy:
(define (subsets L)
(if (null? L)
(list ())
(extend (subsets (cdr L))
(car L))))
Accessing elements of a list
(list-tail L k)
• returns tail of a list after removing first k
elements
(list-ref L k)
• pulls off the k-th element
Both of these can be slow since lists are
linked lists
Still have not heard from a
handful of people
No language or date, but paired
•
Language but no date:
•
Kevin DeRonne
Shaun Reynolds
Ryan Wakeham
Chris Ghere
Steve Fritzdixon
Looking for partner
•
Scott O’Reilly / Thorin Tatge
No contact at all
•
•
•
•
•
Robin Smogor / Jenny Cooper
Paired? Language? Date?
•
Mark Peralta / Chris Middleton
Akira Matoba
If you have not contacted me at all by the end of the day today (via
email), drop a letter grade on the talk
If you do not have a language and date scheduled before class on
Wednesday, same penalty
Vectors
Better to use vectors if accessing
multiple elements of a list:
• (define x #(1 2.0 “three”))
• (vector-ref x 2)
vector->list and list->vector convert
back and forth
“->” is Scheme convention for a
conversion function
Lookup tables
Scheme function assoc does lookup in
a list
• (define my-list
‘( (a 10) (b 20) (c 30))
(assoc ‘b my-list)
Can do it with non-atomic keys too
• (define price-list
‘( ( (subaru forester) 21000)
( (toyota rav4) 23000)
( (honda cr-v) 21200) ))
(assoc ‘(toyota rav4) price-list)
Nasty Scheme functions
set-car!
set-cdr!
examples
Scoping
Scheme has lexical scoping. Any
variables which are non-local are bound
to containing lambda parameters, let
values, or globally defined values.
Example:
(define (f x)
(lambda (y) (+ x y)))
f takes one parameter, x. It returns a
function of y.
(f 10) => (lambda (y) (+ 10 y))
Scoping
Unbound symbols are assumed to be
globals
Let is a good way to encapsulate
internal variables
(define cnt
(let ( (I 0) )
(lambda ()
(set! I (+ I 1))
I)))
Try it by executing the function (cnt)
repeatedly
Let bindings can be subtle
Notice the difference in behavior
between these two programs:
(define cnt
(let ( (I 0) )
(lambda ()
(set! I (+ I 1))
I)))
(define cnt
(lambda ()
(let ( (I 0) )
(set! I (+ I 1))
I)))
Sharing vs. Copying
If there were no side effects, would
never need to copy an object – just
copy pointers
If there are side effects, sometimes
need to copy entire objects
(define A ‘(1 2))
(define B (cons A A))
B = ( (1 2) 1 2)
show picture
(set-car! (car B) 10)
Copying Scheme objects
(define (copy obj)
(if (pair? obj)
(cons (copy (car obj))
(copy (cdr obj)))
obj))
Shallow & Deep Copying
Shallow copy – just copies a reference
Deep copy – copies the entire object
In Java (similar to C++):
• Object O1 = new Object();
• Object O2;
• O2 = O1; // shallow copy
Java has a clone operation:
• O2 = O1.clone();
... but anything referenced by the object is
shallow copied (unless you overload clone)
Equality Checking
Pointer equivalence – do the two
operands point to the same address?
Structural equivalence – do the two
operands point to identical structures,
even if in different locations?
Pointer equivalence is faster but may
not be what you want
• eqv? and eq? are pointer equivalence
• equal? is structural equivalence
equal? is usually what you want (but
slower)
Loops
Look like recursion
(let loop ((x 1) (sum 0))
if (<= x 10)
(loop (+ x 1) (+ sum x))
sum))
Sums the values from 1 to 10 and
displays it
Similar to
for (x=1; x <= 10; sum += x, x++){};
cout << sum;
Control Flow in Scheme
Scheme’s control flow is normally simple and
recursive:
• First argument is evaluated to get a function
• Remaining arguments are evaluated to get actual
parameters
• Actual parameters are bound to function’s formal
parameters
• Function body is evaluated to obtain function call
value
Leads to deeply nested expression
evaluation.
Example: Multiply a list of
integers
(define (mult-list L)
(if (null? L)
1
(* (car L) (mult-list (cdr L)))))
The call
(mult-list ‘(1 2 3 4 5))
expands to
(* 1 (* 2 (* 3 (* 4 (* 5 1)))))
Get clever: if a 0 appears anywhere in
the list, the product must be 0.
Improved multiply
(define (mult-list L)
(cond
((null? L) 1)
((= 0 (car L)) 0)
(else
(* (car L) (mult-list (cdr L)))))))
Better than above: but still do lots of
unnecessary multiplications (until you
hit zero)
Can we escape from a sequence of
nested calls once we know they’re
unnecessary?
Exceptions
C++ handles this problem with
exceptions
struct Node {
int val;
Node *next;
}
C++ Exceptions
int mult (Node *L) {
try {
return multNode(L);
} catch (int returnCode) {
return returnCode;
}
int multNode(Node *L) {
if (L == NULL)
return 1;
else if (L->val == 0)
throw 0;
else
return L->val * multNode(L->next);
}
Scheme Continuations
A continuation is a Scheme mechanism
for storing what you should do with a
return value.
Two different styles
• Implement your own
• Built in Scheme mechanisms
Scheme continuations
http://www.cs.utexas.edu/users/wilson/schintro/
schintro_127.html#SEC171
http://www.cs.utexas.edu/users/wilson/schintro/
schintro_141.html#SEC264
In most languages, calling a function
creates a stack frame that holds return
address for call and variable bindings
In Scheme, everything is stored in
garbage collected heap
Whenever you call a function, you get a
pointer to the calling function: partial
continuation (draw picture)
Scheme continuations
Scheme actually lets you manipulate
these continuations. This is weird!
Scheme function:
• call-with-current-continuation
• can be abbreviated as call/cc
Call/cc is used to call another function,
but it passes along the current
continuation as an argument.
Continuations example
(define (resumable-fun)
(display 1)
(display (call/cc abortable-fun))
(display 2))
(define (abortable-fun escape-fun)
(display ‘a)
(if (bad-thing-happens)
(escape-fun 0))
(display ‘b))
(resumable-fun)
Continuations with multiply
Problem: how to use call/cc with an
argument?
(define (mult-list L)
(call/cc mult-list-main L))
;; this is bad code – can’t take
;; a list
Trick: have call/cc call an anonymous
function
(define (mult-list L)
(call/cc (lambda (escape)
(mult-list L escape)))
Multiply with continuations
(define (mult-list-main L escape)
(cond
((null? L) 1)
((=0 (car L)) escape 0)
(else (* (car L)
(mult-list-main
(cdr L) escape))))
(define (mult-list L)
(call/cc
(lambda (escape)
(mult-list-main L escape)))
Implement your own
continuation
;; con has “to be done” multiplications
(define (mult-list L con)
(cond
((null? L) (con 1))
((= 0 (car L) 0)
(else (mult-list (cdr L)
(lambda (n)
(* n (con (car L)))))))
To actually call the function:
(define (id x) x)
(mult-list ‘(1 2 3) id)