You are on page 1of 49

Subprograms

CSE305: Programming Languages

Lecturer: Jon Bona Lecture Notes from Stuart C. Shapiro


University at Bualo

Summer 2010

Denition

Subprogram
A piece of program Well-dened operational semantics Can be executed (called) from various places in a program

Subprograms:
1. Eliminate need to replicate code 2. Process abstraction
Programmer can make use of its operation Doesnt need to be concerned with details of how that operation is implemented

Major types

1. Procedure: executed for its side-eects 2. Function: executed for its value 3. Relational: executed for instances (Prolog) 4. Method: attached to objects More in common than not Discussion will mostly be about them all

General characteristics

Sebesta (pp. 392393) Name: A subprogram has a name Entry point: A subprogram has a single entry point Execution: One one subprogram executing at a time
Others may be active but suspended

Termination: When a subprogram terminates, execution returns to its caller


Caller: the program unit that called the subprogram

Calling subprograms

Function call
1. Function name 2. List of actual parameters Syntactically an expression Can be used wherever an expression of the functions return type is expected C-based languages allow a statement to be nothing but a function call
Its value is discarded

Calling subprograms
Prolog relational subprogram
1. Relation name 2. List of argument expressions
Could have variables in them
$ prolog | ?- [user]. | max(X,Y,Z) :X>Y, Z=X; Z=Y. | printmax(X,Y) :max(X,Y,Z), format("The max of d and d is d.n", [X,Y,Z]). | yes | ?- printmax(3,5). The max of 3 and 5 is 5. yes | ?- printmax(7,2). The max of 7 and 2 is 7. yes

Parts of a subprogram denition

Header: The subprograms protocol or signature


Name Number and order of its formal parameters Type of each of its formal parameters The return type (if function) Other attributes Not every programming language requires all of these parts

Body: The code to be executed when called Header can sometimes appear without the body
If the compiler needs header information to compile calls But programmer does not want to specify details yet Example: C function denition

Subprogram bodies

Body: A block that provides a local binding environment for


Formal parameters Local variables Locally scoped subprograms
Examples: Lisp, Python, Ruby

True for most current languages, some older PLs worked dierently

Subprogram termination

How do we specify that the subprogram is nished?


In other words, that the subprogram is complete and execution is to return to the caller

What value (if any) should the subprogram return?

Fall-through

A procedure may return when execution falls through to the bottom The body is syntactically one statement The procedure returns when that statement has been executed

Return

We may use a return statement An executable statement Terminate the procedure Return execution to calling unit return is a variety of exit that exits a procedure return <expression>
Function terminates Value of <expression> is the value of the function

Returning multiple values

Parallel assignment
We saw assignment statements with multiple variables on the LHS

Several languages allow functions to return multiple values Python example


>>> ... ... >>> >>> 3 >>> 1 def quoRem(x,y): return x/y, x%y q,r = quoRem(10,3) q r

Returning multiple values

Actually package multiple values in collections


Array in Ruby Tuple in Python (example)
>>> quoRem(10,3) (3, 1) >>> def printit(x): ... print x ... >>> printit(quoRem(10,3)) (3, 1)

No return value
Python function may return no value
>>> def nothing(): ... return ... >>> nothing() >>>

Ruby functions always return something


$ irb irb(main):001:0> def nothing() irb(main):002:1> return irb(main):003:1> end => nil irb(main):004:0> nothing() => nil

Common Lisp example

Common Lisp functions return multiple values with values


cl-user(147): (defun quoRem (x y) (values (floor (/ x y)) (mod x y))) quoRem cl-user(148): (quoRem 10 3) 3 1

Common Lisp example


May be stored using
multiple-value-bind multiple-value-call multiple-value-list multiple-value-prog1 multiple-value-setq
cl-user(147): (defun quoRem (x y) (values (floor (/ x y)) (mod x y))) quoRem cl-user(149): (multiple-value-bind (q r) (quoRem 10 3) (format t "The quotient of 10 and 3 is d and the remainder is d%" q r)) The quotient of 10 and 3 is 3 and the remainder is 1 nil

Multiple values in Common Lisp


Common Lisp does not package multiple value in a collection If used in a context that expects only one value
All but the rst are ignored
cl-user(150): (print (quoRem 10 3)) 3 3 cl-user(151):

Like Python, a Common Lisp function may return no value


cl-user(151): (defun nothing () (values)) nothing cl-user(152): (nothing) cl-user(153):

Recall hashmaps in Common Lisp


Retrieval from a hashmap returns multiple values First value is the value found, or nil if the key wasnt stored This nil could be nothing found or nil found Second value is true value or false value
True if lookup was successful False otherwise
cl-user(2): (setf ages (make-hash-table)) #<eql hash-table with 0 entries @ #x2067d712> cl-user(3): (setf (gethash mike ages) 30 (gethash alice ages) nil) nil cl-user(4): (gethash mike ages) 30 t cl-user(5): (gethash alice ages) nil t cl-user(6): (gethash bob ages) nil nil

Header: Name

Most subprograms have names It is possible to create a nameless function Python example
>>> (lambda x: 4 x+1)(3)

Name, when exists, follows syntactic rules for an identier In statically scoped languages
Scope is enclosing block

Header: Type

Function subprograms have a type Type of the returned value Procedures dont return a value
So usually dont have a type

In C-based languages
A procedure is a function whose type is void

Header: Formal parameters

Matching actual to formal parameters


Line up actual to formal parameters Bind formal parameters to values (discussed later) 1. 2. 3. 4. Positional parameters Optional parameters Keyword parameters Default values

Positional parameters

Usual method for matching actual to formal parameters nth actual parameter is matched with nth formal parameter

Optional parameters

In some languages it is possible to have optional parameters # of actual parameters < # of formal parameters Extra formal parameters are treated like local variables
Initialized to default value, if any

Common Lisp uses &optional to declare


cl-user(6): (defun reverse (list &optional end) (if (endp list) end (reverse (rest list) (cons (first list) end)))) reverse cl-user(7): (reverse (a b c d e)) (e d c b a)

Optional parameters in Common Lisp

Sequence of optional arguments gathered into a list &rest


cl-user(5): (defun union* (set &rest sets) (loop with result = set for next in sets do (setf result (union next result)) finally (return result))) union* cl-user(6): (union* (a b c) (c d e) (e f g) (h i j)) (j i h g f e d a b c)

&optional and &rest parameters initialized to nil


If not matched with actual parameters See discussion of default values

Keyword parameters
Formal parameter is mentioned with actual parameter in call Indicates they should be matched Common Lisp example
cl-user(14): (defun testKey (&key first second third) (list first second third)) testKey cl-user(15): (testKey :second 2 :third c :first I) (I 2 c) cl-user(16): (member c (a b c d e)) (c d e) cl-user(17): (member (3 c) ((1 a) (2 b) (3 c) (4 d) (5 e))) nil cl-user(18): (member (3 c) ((1 a) (2 b) (3 c) (4 d) (5 e)) :test #equal) ((3 c) (4 d) (5 e)) cl-user(19): (member March ((January 31) (February 28) (March 31) (April 30)) :key #first) ((March 31) (April 30))

Default values
Optional or keyword formal parameters can have a default value Used if subprogram is called without a matching actual parameter Common Lisp example
cl-user(6): (defun packem (w x &optional (y 5) (z 7)) (list w x y z)) packem cl-user(7): (packem 1 3) (1 3 5 7) cl-user(8): (packem 1 3 11) (1 3 11 7)

Keyword parameters in Python


Python combines keyword parameters and default values All parameters can be keywords All parameters can have default values Example from An Introduction to Python by van Rossum & Drake
def parrot(voltage, state=a stiff, action=voom, type=Norwegian Blue): print "-- This parrot wouldnt", action, print "if you put", voltage, "volts through it." print "-- Lovely plumage, the", type print "-- Its", state, "!"

Keyword parameters in Python


Python combines keyword parameters and default values All parameters can be keywords All parameters can have default values Example from An Introduction to Python by van Rossum & Drake
def parrot(voltage, state=a stiff, action=voom, type=Norwegian Blue): print "-- This parrot wouldnt", action, print "if you put", voltage, "volts through it." print "-- Lovely plumage, the", type print "-- Its", state, "!" >>> parrot(1000) -- This parrot wouldnt voom if you put 1000 volts through it. -- Lovely plumage, the Norwegian Blue -- Its a stiff !

Keyword parameters in Python


Python combines keyword parameters and default values All parameters can be keywords All parameters can have default values Example from An Introduction to Python by van Rossum & Drake
def parrot(voltage, state=a stiff, action=voom, type=Norwegian Blue): print "-- This parrot wouldnt", action, print "if you put", voltage, "volts through it." print "-- Lovely plumage, the", type print "-- Its", state, "!" >>> parrot(action = VOOOOOM, voltage = 1000000) -- This parrot wouldnt VOOOOOM if you put 1000000 volts through it. -- Lovely plumage, the Norwegian Blue -- Its a stiff !

Keyword parameters in Python


Python combines keyword parameters and default values All parameters can be keywords All parameters can have default values Example from An Introduction to Python by van Rossum & Drake
def parrot(voltage, state=a stiff, action=voom, type=Norwegian Blue): print "-- This parrot wouldnt", action, print "if you put", voltage, "volts through it." print "-- Lovely plumage, the", type print "-- Its", state, "!" >>> parrot(a thousand, state = pushing up the daisies) -- This parrot wouldnt voom if you put a thousand volts through it. -- Lovely plumage, the Norwegian Blue -- Its pushing up the daisies !

Keyword parameters in Python


Python combines keyword parameters and default values All parameters can be keywords All parameters can have default values Example from An Introduction to Python by van Rossum & Drake
def parrot(voltage, state=a stiff, action=voom, type=Norwegian Blue): print "-- This parrot wouldnt", action, print "if you put", voltage, "volts through it." print "-- Lovely plumage, the", type print "-- Its", state, "!" >>> parrot(a million, bereft of life, jump) -- This parrot wouldnt jump if you put a million volts through it. -- Lovely plumage, the Norwegian Blue -- Its bereft of life !

Optional parameters in Ruby


Optional parameters indicated by supplying default value *arg collects extra arguments (also in Python) Keyword parameters are not supported
$ irb irb(main):001:0> def list(x,y=3) irb(main):002:1> return x,y irb(main):003:1> end => nil irb(main):004:0> list(6,7) => [6, 7] irb(main):005:0> list(2) => [2, 3] irb(main):006:0> def listmore(x,*y) irb(main):007:1> return x,y irb(main):008:1> end => nil irb(main):009:0> listmore(1,2,3,4,5,6) => [1, [2, 3, 4, 5, 6]]

Parameter passing

Semantic parameter passing modes


1. In mode
Value of actual parameter made available via formal parameter Value of actual parameter cannot be changed by subprogram Java

2. Out mode
Value of actual parameter not made available to subprogram Value can be changed/set by subprogram

3. Inout mode
Value of actual parameter made available via formal parameter Value can be changed by subprogram Prolog

Pass-by-name

Inout mode technique Actual parameter expression texturally replaces formal parameter REQUIRED: Read discussion of Common Lisp macros in Shapiros lecture notes
Work through examples on your own This material is REQUIRED This material may be on the FINAL

Pass-by-value

In mode technique Formal parameter is bound to its own memory cell at call time Value of actual parameter is copied into it Formal parameter acts like a local variable within subprogram Formal parameter deallocated at subprogram termination This is the model you are most used to from Java

Pass-by-result

Out mode technique Formal parameter acts like an uninitialized local variable At subprogram termination time its value is copied into the l -value of the actual parameter C# uses this technique
Example and discussion of C# ref and out keywords in Shapiro notes

Pass-by-value-result

Inout mode technique Acts like pass-by-value at call time Acts like pass-by-result at termination Formal parameter is bound to its own memory cell
Distinct from that of the actual parameter

Pass-by-reference

Inout mode technique Formal parameter bound to same memory cell as actual parameter Formal parameter is an alias of actual parameter C++ example

Pass-by-reference: C++ example


Listing 1: pbrTest.cpp
#include <stdio.h> void testPBR(int &x, int &y) { printf("testPBR called with x = %d y = %d\n", x, y); y = x*x; printf("testPBR about to return with x = %d y = %d\n", x, y); } int main(int argc, char **argv) { int i=3, j=5; printf("Before call, i = %d j = %d\n", i, j); testPBR(i,i); printf("After call, i = %d j = %d\n", i, j); return 0; } $ g++ -Wall -o pbrTestCPP pbrTest.cpp $ ./pbrTestCPP Before call, i = 3 j = 5 testPBR called with x = 3 y = 3 testPBR about to return with x = 9 y = 9 After call, i = 9 j = 5

Subtleties

Java
All parameter passing in Java is pass-by-value However, many variables hold references to objects So although the parameter is passed by value, the object is essentially passed by reference

C
Its sometimes said that C uses pass-by-value except for arrays, which are passed by reference Untrue C always uses pass-by-value Array-valued variables are actually pointers that point to rst element in array Similar to situation with objects in Java

Function parameters
Function as a data type Functions can be passed as parameters Common Lisp has functions that apply functions to their arguments As does Python:
Listing 2: printTable.py
def doubleit(x): return 2*x def sqr(x): return x*x def printTable(f, args): for i in args: print i, apply(f, (i,)) printTable(doubleit, [1,2,3,4,5]) print printTable(sqr, [1,2,3,4,5]) $ 1 2 3 4 5 1 2 3 4 5 python printTable.py 2 4 6 8 10 1 4 9 16 25

Function parameters in C

In C an actual parameter may be the name of a function Matching formal parameter must be a pointer to a function returning the correct type The name of a function is a constant pointer to the function. Its value is the address of the functions machine code in memory. C Pocket Reference, Prinz & Kirch-Prinz, translated by Tony Crawford, OReilly 2002.

Function parameters: C example


Listing 3: printTable.c
#include <stdio.h> int doubleit(int x) { return x + x; } int sqr(int x) { return x * x; } void printTable(int (*f)(), int a[], int length) { int i; for (i = 0; i < length; i++) { printf("%d %d\n", a[i], (*f)(a[i])); } } int main() { int a[5] = {1, 2, 3, 4, 5}; printTable(doubleit, a, 5); printf("\n"); printTable(sqr, a, 5); return 0; }

$ gcc -Wall -o printTable printTable.c $ ./printTable 1 2 2 4 3 6 4 8 5 10 1 2 3 4 5 1 4 9 16 25

Overloaded subprograms

One name associated with multiple protocols Each with its own body Dispatching is the process of choosing which body to execute
1. Compare call with various protocols associated with name 2. Decide which protocol to execute

Polymorphic subprograms

Polymorphic subprograms dispatch on type of arguments Heart of object-oriented programming Each class in a class hierarchy can dene its own version of a method Which method body to execute is dynamically decided
Based on type of principal actual argument Or on type of several actual arguments

Example: multimethods in Clojure, a JVM Lisp

Dispatch on number of parameters

Commonly used in Java for constructors Can be used to give the eect of optional parameters
Which Java doesnt have

Dispatch by pattern matching


Haskell discussion in Shapiros lecture notes Erlang example
Listing 4: factorial.erl
-module(factorial). -export([factorial/1]). factorial(0) -> 1; factorial(N) when N < 0 -> -1; factorial(N) when N > 0 -> N * factorial(N-1). $ erl Eshell V5.7.4 (abort with G) 1> c(factorial). {ok,factorial} 2> factorial:factorial(0). 1 3> factorial:factorial(4). 24 4> factorial:factorial(-1). -1 5> q(). ok

Dispatch by unication

Prolog uses unication More in Knowledge Representation course See also Shapiros notes

Further topics

Generic subprograms User-dened operator overloading Coroutines Further reading in Sebesta

You might also like