COS 333: Chapter 9, Part 2
Summary
TLDRThis lecture delves into advanced sub-program concepts, exploring parameter parsing methods such as in, out, and in-out modes, and their implementations like pass by value and pass by reference. It discusses the efficiency and safety trade-offs in parameter passing and touches on the complexities of multi-dimensional array parameters. The lecture also addresses the design issues related to sub-programs, including type checking, indirect calls, and the referencing environment of passed sub-programs, with examples in various programming languages.
Takeaways
- π The lecture delves into Chapter 9, continuing the discussion on sub-programs, their design issues, and parameter parsing methods.
- π It differentiates between 'in', 'out', and 'in-out' modes for formal parameters, explaining how data is passed between the caller and the sub-program.
- π The lecture introduces five implementation models for parameter passing: pass by value, pass by result, pass by reference, pass by value-result, and pass by name.
- π Pass by value is demonstrated with an example in C++, highlighting how the actual parameter's value initializes the formal parameter within a sub-program.
- π Discusses the disadvantages of pass by value, such as the need for additional storage and potential high cost for large parameters due to copying.
- π§ Pass by result is explained with an ADA example, showing how the sub-program can modify the actual parameter's value through the formal parameter.
- π Pass by value-result combines both pass by value and pass by result, allowing data to be passed into and out of the sub-program.
- π‘ The advantages of pass by reference are highlighted, including efficiency in processing time and memory usage due to passing a reference instead of a copy.
- π§ The potential downsides of pass by reference are also discussed, such as slower access to formal parameters due to indirect addressing and the possibility of unwanted side effects.
- π The lecture provides insights into how different programming languages handle parameter passing, with examples from C, C++, Java, ADA, and others.
- π The concept of 'pass by name' is introduced as an older parameter parsing technique, which uses textual substitution and can lead to late binding of variables at runtime.
Q & A
What are the three modes for parameters in sub-programs?
-The three modes for parameters in sub-programs are 'in' mode, 'out' mode, and 'in-out' mode. 'In' mode formal parameters receive data from actual parameters in a subprogram call. 'Out' mode formal parameters send data to actual parameters. 'In-out' mode formal parameters both receive data from and send data to actual parameters.
What is the difference between pass by value and pass by reference?
-Pass by value involves copying the actual parameter's value into the formal parameter, creating two separate copies of the data. Pass by reference, on the other hand, involves passing the memory address of the actual parameter to the formal parameter, allowing the sub-program to access and modify the original data directly.
Why might pass by value be implemented using an access path?
-Pass by value can be implemented using an access path, typically through a pointer or reference, to avoid the overhead of copying large data structures. However, this approach is not commonly recommended due to the difficulty in enforcing write protection within the called sub-program, which could lead to unintended modifications of the actual parameter.
What are the advantages of pass by reference over pass by value?
-Pass by reference is more efficient in terms of processing time and memory usage. It avoids the need for copying large amounts of data, thus reducing processing time and memory overhead. However, it can introduce potential issues such as unwanted side effects and aliases.
How does pass by result differ from pass by value?
-Pass by result is an 'out' mode parameter parsing technique where the value of the formal parameter is used to change the corresponding actual parameter's value. Unlike pass by value, no value is transmitted to the sub-program; instead, data is only transmitted back to the caller when control is returned.
What is the concept of 'pass by name' in parameter passing?
-Pass by name involves textual substitution where all occurrences of a formal parameter are replaced by the corresponding actual parameter. The binding to a value or address only occurs when the formal parameter is used in the sub-program, allowing for late binding and flexibility in how parameters are accessed.
Why is parameter type checking important in programming languages?
-Parameter type checking is important for ensuring the reliability of a program. It verifies that the types of actual and formal parameters match, preventing type mismatches that could lead to unexpected behavior or errors at runtime.
How do programming languages handle multi-dimensional arrays as parameters?
-Languages like C and C++ require specifying the sizes of all dimensions except the first in the function parameter list. Java and C# handle multi-dimensional arrays as objects with a length property, allowing the size to be dynamically determined at runtime without needing explicit size declarations in the parameter list.
What is the difference between shallow binding and deep binding for sub-programs?
-Shallow binding uses the calling environment of the sub-program that actually performs the call, while deep binding uses the definition environment of the sub-program being called. Shallow binding is natural for dynamically scoped languages, whereas deep binding is for statically scoped languages.
What are the considerations for passing sub-programs as parameters?
-When passing sub-programs as parameters, considerations include whether parameter types are checked and determining the referencing environment for the passed sub-program, which can be influenced by shallow binding, deep binding, or ad-hoc binding.
How do function pointers in C++ allow for calling sub-programs indirectly?
-Function pointers in C++ are pointers to functions that include parameter and return types. They can be assigned to any function that matches the specified requirements, allowing for indirect calls to functions through the pointer.
What is the role of delegates in C# for calling sub-programs indirectly?
-In C#, delegates are objects that can be used to call sub-programs indirectly. They are created by defining a delegate type with a specific method signature and then instantiating delegate objects with methods that match this signature.
Outlines
π Lecture Overview on Sub-programs and Parameter Passing
The lecture delves into chapter 9, continuing the discussion on sub-programs from the previous session. It revisits fundamental concepts and terminology before exploring parameter parsing methods, including in, out, and in-out modes. The lecture also introduces various implementation models for parameter passing, such as pass by value, pass by reference, and pass by name, highlighting their use cases and implications for programming.
π In-Depth Analysis of Parameter Passing Mechanisms
This section provides a detailed examination of parameter passing mechanisms, starting with pass by value, which involves copying the actual parameter's value into the formal parameter. It discusses the implications of this method, including the need for additional storage and potential performance costs for large data structures. The explanation also covers pass by result, which changes the actual parameter's value based on the formal parameter, and its challenges, such as the order of parameter copying back to the caller.
π Exploring Pass by Value-Result and Pass by Reference
The paragraph discusses pass by value-result, which combines elements of both pass by value and pass by result, allowing data to be passed into and out of a sub-program. It also explains pass by reference, where an access path to the data is passed, leading to efficiency in memory and processing time but introducing complexities like indirect addressing and potential side effects. The potential issues with aliasing and unwanted side effects in pass by reference are also highlighted.
π Understanding Pass by Name and Its Implementation
This part of the lecture introduces pass by name, a less common method that involves textual substitution of formal parameters with actual parameters at call time. It allows for late binding, where the value accessed depends on the variable's runtime value. The explanation clarifies how pass by name works with an example, demonstrating how the output can change based on the variable's value at runtime.
π Real-World Programming Languages' Parameter Passing Techniques
The script provides insights into how various real-world programming languages implement parameter passing. It covers languages like C, C++, Java, Ada, Fortran 95, C#, PHP, Perl, Python, and Ruby, explaining their default parameter parsing methods and any special considerations, such as Java's behavior with objects and references, or Python and Ruby's pass by assignment due to their object-oriented nature.
π Parameter Type Checking and Its Impact on Programming Languages
This section discusses the importance of parameter type checking for ensuring program reliability. It contrasts older languages like Fortran 77 and early C, which lacked type checking, with modern languages that enforce it. The explanation also covers the implications of type checking on programming language design and safety, emphasizing the benefits of type-checked approaches.
π Multi-Dimensional Arrays in Sub-Program Parameters
The lecture addresses the complexities of passing multi-dimensional arrays to sub-programs, explaining the need for the compiler to know array dimensions for correct mapping. It discusses the limitations and solutions in languages like C and C++, which require specifying dimensions in the function definition, and the more flexible approaches in Java and C#, where array lengths are intrinsic properties of the array objects.
π Design Considerations for Parameter Parsing in Programming Languages
This part explores the trade-offs between efficiency and good programming practices in parameter parsing techniques. It examines the advantages of pass by reference in terms of processing time and memory usage, but also its conflict with one-way data transfer preferences. The discussion also touches on languages that support a mix of techniques, like C++, and the rationale behind their design choices.
π Indirect Sub-Program Calls and Function Pointers
The script explains the concept of indirect sub-program calls, where the exact sub-program to be called is determined at runtime, using function pointers in C and C++ and delegates in C#. It provides examples of how these mechanisms work, allowing for dynamic event handling and flexibility in programming, and also introduces the concept of multicast delegates in C#.
π Passing Sub-Programs as Parameters Across Languages
This section discusses the ability to pass sub-programs as parameters in different programming languages, highlighting support in C and Fortran 95, and the lack thereof in Ada and Java. It also introduces the concept of referencing environments for passed sub-programs, explaining shallow, deep, and ad hoc binding, and their implications for variable visibility and scoping rules.
π Referencing Environments for Passed Sub-Programs
The final part of the lecture focuses on the referencing environment for sub-programs passed as parameters, illustrating the concept with an example and explaining how different binding strategiesβshallow, deep, and ad hocβaffect which variable is referenced within the sub-program. It concludes the lecture with a look forward to the next session, which will continue the discussion on sub-programs.
Mindmap
Keywords
π‘Sub-programs
π‘Parameter Parsing
π‘Formal Parameters
π‘Actual Parameters
π‘Pass by Value
π‘Pass by Reference
π‘Indirect Calling
π‘Function Pointers
π‘Delegates
π‘Shallow Binding
π‘Deep Binding
π‘Ad-Hoc Binding
Highlights
Fundamental concepts of sub-programs and important terminology were covered, setting the stage for deeper discussion.
Design issues relevant to sub-programs, including local stack dynamic and static variables, were examined.
Parameter parsing methods were introduced, highlighting three modes: in mode, out mode, and in-out mode parameters.
Diagrams were used to illustrate the direction of data flow in in mode, out mode, and in-out mode parameters.
Two primary approaches for data transfer between caller and callee were discussed: physical copy of a value and transmission of an access path.
Five implementation models for parameter passing were presented, including pass by value, pass by result, and others.
Pass by value was explained with an example in C++, demonstrating how the actual parameter's value is copied into the formal parameter.
The disadvantages of pass by value, such as additional storage requirements and potential costly moves for large parameters, were discussed.
Pass by result was introduced as an auto mode parameter parsing technique, with an example in Ada illustrating its usage.
Potential problems associated with pass by result, including additional storage and order of parameters copying back, were highlighted.
Pass by value result, combining features of pass by value and pass by result, was explained with an example in Ada.
Pass by reference, an in-out mode parameter passing technique, was discussed with examples in C++ using pointers and references.
Efficiency of pass by reference was emphasized, noting its advantages in processing time and memory usage.
Disadvantages of pass by reference, such as slower access times and potential for unwanted side effects, were covered.
Pass by name, an in-out mode parameter parsing method using textual substitution, was introduced as an older approach.
An example was provided to illustrate the concept of pass by name, demonstrating late binding and its effects on runtime behavior.
Support for parameter parsing methods in various real-world programming languages was reviewed, comparing their approaches and limitations.
The importance of parameter type checking for reliability was discussed, contrasting older languages with modern ones.
The handling of multi-dimensional arrays as parameters, including mapping functions and dimension sizes, was explained.
Design considerations for parameter parsing, including efficiency and data transfer direction, were analyzed in terms of trade-offs.
The capability of passing sub-programs as parameters and the considerations for type checking and referencing environments was explored.
Different binding strategies for sub-programs, such as shallow, deep, and ad-hoc binding, were presented with examples.
Transcripts
welcome to the second lecture on chapter
nine of the textbook in the previous
lecture we covered primarily some
fundamental concepts related to
sub-programs and also went through some
important terminology that we'll be
using through the remainder of the
discussion on this chapter
we also looked at a number of design
issues that were relevant for sub
programs and then finished off by
looking at local stack dynamic as well
as static variables within a local
referencing environment of a sub program
in this lecture we'll be continuing with
our discussion on chapter 9.
these are the topics that we'll be
discussing in today's lecture we'll
start off by looking at a variety of
different parameter parsing methods
in the most important aspect of the work
that we'll be discussing today relates
to parameters that are sub-programs in
other words when a sub-program receives
another sub-program as a parameter
then related to parameters that are
sub-programs we'll look at how
sub-programs can be called indirectly
especially when they've been passed to
another sub-program
we'll start off by discussing semantic
models for parameter parsing
so broadly speaking there are three
modes for parameters
we firstly have in mode formal
parameters which are parameters within a
subprogram definition that receive data
from an actual parameter in a call to
the sub program so this is the standard
model for parameter parsing where we are
sending data from the call into the body
of the
sub program by means of a parameter
secondly we have out mode formal
parameters which send data to an actual
parameter
in the subprogram call
so these are essentially parameters that
are used to send back a value to the
caller
and then in the third place we have in
out formal parameters which both receive
data from and send data to
an actual parameter in a sub-program
call
here we have three diagrams that
illustrate in mode out mode and in out
mode parameters
so for in mode parameters we see that we
are sending data from the caller through
to the callee
in other words we are sending data from
the actual parameters a b and c in this
case to the formal parameters x y and z
in the definition of the sum program
out mode parameters work in the opposite
direction so we're sending data from the
callee
out to the
caller
and in this case we are then sending
data from the dummy variables in the
definition of the sub program in other
words x y and z
to the caller by means of the actual
parameters a b and c
and then in out mode parameters work in
both directions so they receive data
from the caller into the callee and then
send data back from the callee to the
caller
now that we've discussed the various
modes available for parameters we have
to consider how the actual transfer of
data takes place between the caller and
the cooli or vice versa
so there are basically two approaches
that can be used
the first is a physical copy of a value
so in this case two copies of the value
exist at the same time both in the
caller and the callee regardless of
which direction the data transfer is
happening in
then secondly we have transmission of an
access path to a value and in this case
we have only one value that exists and
we are essentially then passing through
a reference or a pointer to that value
so this gives us then five
implementation models for parameter
passing namely pass by value passed by
result passed by value result passed by
reference and pause by name and we'll be
looking at each of these separately in
the coming slides
we'll start by looking at pause by value
which is an in mode parameter parsing
technique
so with pass by value the value of the
actual parameter is used to initialize
the corresponding formal parameter
so here we have an example in c plus
plus of pass by value
and up here we can see we have a
definition of a sub program in this case
a function its name is foo and it
receives a single parameter which is an
integer and is named a
so a then is the formal parameter in
this case
here we have our main function
and in it we have a variable called b
which is an integer variable defined and
it has an initial value of 12.
now we call the foo function over here
and pass through the variable b
b being the actual parameter
so inside the body of the foo function
we take then our parameter that we have
received namely a
and we increment this by 2.
now what's important to understand here
is that in the call
the value 12
is copied from the variable b
into the formal parameter a
and then if we try to modify a inside
the body of the foo function then this
doesn't affect the variable b
so how can pause by value be implemented
well the normal approach is that it's
done by means of copying which we saw on
the previous slide so in other words we
copy a value from the caller into the
called sub program
now it is also possible for us to
achieve past by value by means of
transmitting an access path in which
case we would do it through a pointer or
a reference however this approach is
generally speaking not recommended
because it's not easy to enforce right
protection inside the called sub program
rights protection is necessary because
we don't want any modification in the
call sub program to change the actual
parameter where the call takes place so
there has to be some mechanism for right
protecting that parameters so that
modifications can't be done inside the
call sub program
now disadvantages associated with
physically copying
the value from the caller to the call
sub program is that additional storage
is required and this is because as i
previously mentioned
we have the parameters stored two times
once in the actual parameter and once in
the formal parameter
also the move can potentially be costly
and this is especially the case for very
large parameters so for example if we're
passing a struct or a class that has a
lot of fields within it each of those
fields needs to be copied from the
caller
into the formal parameter in the call
sub program and all of that copying can
take up a lot of processing time
now if we use an access path instead
then there are also disadvantages
associated with that approach so firstly
as i previously mentioned we need to
write protect
the parameter in the called sub program
also access can potentially be more
costly in terms of processing time and
this is because we are using a pointer
or a reference and therefore we have to
use indirect addressing to access the
value and this then can take up some
additional processing time
next we'll look at pass by result which
is an auto mode parameter parsing
technique
so with pass by result the value of the
formal parameter is used to change the
corresponding actual parameters value
so over here we have an example in ada
we are defining a procedure
named a test
and because it's a procedure this means
that a test does not return a result but
rather produces results through
modifications to its
parameters here we have in integer
specified which tells us that the
parameters a and b
are in mode parameters that are passed
by value as we discussed a moment ago
we also have art integer which appears
here which specifies that the c
parameter
is an out mode pass by result parameter
inside the body of our a test procedure
we have an assignment that takes place
we are assigning a plus b
to the variable c
so this is allowed because a and b are
in mode passed by value parameters so
the data just gets then sent in to the
procedure
by means of its formal parameters and
those values are then just used in this
computation over here producing a result
c can be assigned to because it is an
out mode pass by result parameter
so c is treated like an uninitialized
local variable that we simply assign to
so now let's look at the school over
here where we are calling the a test
procedure
and we pass through these parameters
over here
so 5 plus p is computed and that's seen
through as the parameter a
and 48 is passed through as the
parameter b
q is a variable which is passed through
as the third parameter the result of
this thing is that the
addition is performed inside the body of
the a test procedure
adding the first two parameters together
we then assign the result to c
which is then copied back to q
and q's value is then overwritten by the
value that has been assigned to c
now let's look at how pause by result is
implemented
so as we saw on the previous slide the
value of the formal parameter is used to
change the corresponding value of the
actual parameter
what this means is no value is
transmitted to the sub program and
instead we only transmit data out of the
subprogram to the caller
so the pass then of data happens when
control is returned to the caller
and we implement this by means of a copy
from the formal parameter in the sub
program to the actual parameter in the
call to the sub program
so what i would like you to do now is to
try to
answer
whether an access path can be
transferred instead of performing a copy
all right so i'll answer the previous
question
and the answer is that it is in fact
impossible to transfer an access path we
have to use a copy so what i would like
you to do once again is to pause the
video and try to explain why this is the
case
now there are some potential problems
that are also associated with pass by
result
firstly
we require additional storage space in
memory and also potentially an expensive
copy operation that needs to be
performed
this is exactly the same as the main
drawback associated with pass by value
and this is because we are using a copy
operation
we have some more subtle issues though
as well
so let's assume that we have a sub
program called sub and we perform this
call to sub you can see that we are
passing through p1 both as the first
parameter and as the second parameter
now let's also assume that in the
implementation for the sub sub program
we have different names for the two
formal parameters so for example we
might have sub and then the first
parameter would be called a and the
second parameter would be called b
so the question is then which value does
p1 have after the score has completed
and this depends on the order that the
parameters are copied back in
so do we copy the first parameter first
and the second parameter second
or vice versa
now this may seem like an obvious
question we might just
handle it from left to right so then it
will be the right most
parameters value that will be copied
back
but this depends on the specific
implementation sometimes due to compiler
optimizations we will copy back the
values in a different order so we need
to address this somehow by at least
making it appear consistent to the
programmer who would be using this
sub-program call
here we have another potential issue and
that may arise again illustrated by
means of a simple example here we are
calling a sub program called sub once
again and again we are assuming
different names for the two formal
parameters
but we are then passing through the list
array at subscript sub and then passing
through sub as the second parameter as
you can see over here
so the question then is what value does
list at subscript sub have
and this will be decided at either the
start of the sub program or the end of
the sub program so we may determine it
by means of the subscript value that sub
originally has before the call or we may
be determining it based on the value of
sub that is returned by means of the
parameter at the end of the subprogram
call
next we have pass by value result which
is used for in-out mode parameters
so pass by value result combines pause
by value and pause by result and it's
sometimes also called pause by copy
so in this case data is passed by means
of the pause by value result parameter
into the sub-program but we also then
transmit data from the sub-program back
to the caller
so for this to happen formal parameters
must have local storage that we can
assign to
so the drawbacks associated with pass by
value results are a combination of the
drawbacks associated with pass by result
and pass by value
now here we have
a simple example in ada which is quite
similar to the previous example that we
looked at again here we've defined a
procedure called a test
and we are sending an in-mode parameter
called a as the first parameter and an
in-out mode parameter called c
so c is a pass by value result parameter
because it is used for in-out mode
parameter parsing
so now if we look at the body of our
procedure
we see that we are computing a result by
adding c
to a this is allowed because c is an in
mode as well as an out mode parameter
we can also assign 2c in which case the
value will then be assigned to the
formal parameter and copied to the
actual parameter and this is also legal
because once again c is a combination of
an in mode and out mode parameter
so in this case then the formal
parameter c is used for two things
it passes a value into the a test
procedure but it can also be assigned to
in which case we are then copying from
the formal parameter to the actual
parameter in the subprogram call
the second last parameter passing
technique that we'll look at is called
pass by reference and you should also be
fairly familiar with this technique
pause by reference is also an in auto
mode parameter passing technique
so pass by reference passes an access
path and it can do this by means of
either a pointer or a reference pass by
reference is also sometimes called pass
by sharing
so over here we have an example of pass
by reference both by means of a pointer
and a reference in c
plus
we have a sub program in this case a
function called foo
and it receives two parameters firstly p
which is defined as an integer pointer
in other words an integer memory address
secondly we have r which is defined as
an integer reference by means of the
ampersand notation you can see over
there
so we can use then both the pointer or
the reference inside the body of the foo
function
in the case of the pointer we must
de-reference it first using the asterisk
notation and then we can assign a value
to it in this case 23. in the case of
the reference r we can simply assign to
it as though it's a normal variable and
it doesn't require any dereferencing and
here we're just assigning the value 19
to this reference
so both p and r in this example then can
be used to pass data into the foo
function whichever values the points or
the reference have from the caller in
other words derived from the actual
parameter
in the function call
and both then p and r can also be used
to send data back to the caller in other
words through the formal parameters to
the actual parameters in the function
call
now of course the big advantage
associated with pass by reference is
that it is very efficient
and this is efficiency in terms of
processing time but also in terms of
memory usage
so it is efficient in terms of memory
usage because we don't have two copies
of the data that is being passed to the
sub program that exists in memory at the
same time instead there's only one copy
of the data and we simply pass through a
reference to that data hence using less
memory
secondly it is more efficient in terms
of processing time because we don't have
to perform a copy on the data that is
being passed because once again there is
only one copy in existence and only a
reference to it is passed to the sub
program in question
now this is of course not to say that
there aren't drawbacks associated with
pass by reference and this slide lists
three such disadvantages
so firstly if we compare pass by
reference to pass by value then pass by
reference is slower in terms of accesses
to formal parameters and the reason for
this is that we are using indirect
addressing in order to retrieve a value
rather than just accessing the value
directly as we would in the case of pass
by value
secondly pause by reference introduces
potential problems associated with
unwanted side effects and we discussed
this in quite a lot of detail in chapter
15 so i won't spend time recapping this
now however please refer to chapter 15
if you need to refresh your memory about
side effects
in the third place pause by reference
introduces the possibility of unwanted
aliases and these aliases broaden access
to values and allow for potential
collisions to take place as a result
so let's look at this function over here
which is a function sub program in c
plus
the function is called fun and it has
two parameters
first and second which are both formal
parameters and they are both integer
references by virtue of the fact that
they use the ampersand notation so now
let's look at this call to the function
where we are calling the fun function
but we are passing through
two
actual parameters that are exactly the
same total in both cases over here
so what this means then is that first
and second both refer to the same actual
parameter namely total and are therefore
aliases for the value of total
so what i would like you to do at this
point is to pause the video and try to
explain what potential problems this
aliasing could result in
the last parameter parsing technique
that we'll look at is also an in-out
mode parameter parsing method named
pause by name and this is definitely the
most interesting out of the techniques
that we've discussed so far
so past by name uses textual
substitution and it's a far older
approach than the others and therefore
not very widely used in modern
programming languages now on this slide
i'll define how pause by name works but
it will become a lot clearer once we
work through an example on the next two
slides
so essentially post by name works by
taking all formal parameter occurrences
and replacing them by the appropriate
actual parameter
now the formal parameters which have
been replaced
are then bound to an access method at
call time and this axis method could
either be a copy or a reference
now the actual binding to a value or
address only occurs when the formal
parameters actually used in the sub
program and this is very important
because this allows us quite a lot of
additional flexibility because it allows
for a kind of late binding which will
illustrate by means of the next example
so let's illustrate pause by name by
means of a simple example
what we're going to do first of all is
look at this example in terms of
standard pass by value which we will
then compare on the next slide to pass
by name in order to illustrate the
difference
so in this example we have a sub program
which is a c
function named foo
and it receives two parameters where the
formal parameters are named a and b and
both of them are integer values we'll
get to the body of the free function in
a moment so now let's look at our main
function over here and our main function
has a variable named vowel which has an
initial value of zero
then we have an array named arr which
contains three values and these values
are the values 2 8 and 9.
so now we call our view function we pass
through val as our first parameter
and our array at subscript val as our
second parameter
so now if we assume normal pass by value
what this means is we'll be passing
through for our first parameter a value
of 0 and for our second parameter will
be accessing our array at subscript
vowel which is zero so in other words we
will be retrieving the first value which
is two and passing that through as the
second actual parameter
so now inside the body of our view
function we then receive a and b
which we've just seen are the values 0
and 2.
and because this is passed by value
we'll assume that these values have been
copied into the foo function
so now we set a's value to 1 and then we
print out a and b
so of course printing a out will print
out 1 because we updated a's value by
means of an assignment
and then when we print out b we will be
printing out the value 2 because that
was the value that was sent through the
actual parameter
in the call to foo in the second
parameter position over here
so let's look at our previous example
but this time assume that we are using
pass by name rather than pass by value
so what does it mean if we are using
pass by name well it means we will
perform textual substitutions where we
substitute every occurrence of a formal
parameter
with the corresponding actual parameter
so what this means is every occurrence
of a in our foo function
must be replaced with the corresponding
actual parameter which is vel and
similarly every occurrence of b
must be replaced with the corresponding
actual parameter which is the array
accessed at subscript vowel
so what does this thing mean well it
means that the body of our
foo function
will change such that we are assigning
one
to vowel rather than a
which i've noted at the bottom over here
similarly the first parameter for our
print becomes val as i've indicated at
the bottom over here
and the second parameter for our print
becomes our array access that subscript
val which i've indicated over here at
the bottom again
so what does this mean then for the
output of our example
well we are printing out firstly the
value of the vowel variable as we've
seen we've just assigned a value of 1 to
it so that means our first output will
be 1.
our second output however will differ
because we are accessing our array at
subscript val and val currently has a
value of 1 meaning that we're accessing
our array at the second position
namely the value 8 and that will then be
the second value that we will print out
to the screen
now this is a kind of a late binding and
it's a late binding in the sense that
the access to our array which we are
going to use to retrieve a value for
printing is based on a variable called
val and the value of this variable can
obviously change at runtime based on
this assignment so in other words the
value that is accessed depends on what
variable val has at runtime and is not
determined prior to runtime for example
at compile time
so therefore this is a kind of a late
binding in the sense that it is late
because it happens at run time
what's also important to understand is
that the access mechanism used for the
formal parameters can either be a copy
or a reference
now if it is a copy what this means is
that this vowel that is being assigned
to in the body of our foo function is in
fact a copy of the vowel in our main
function so what that means is that this
assignment of one two vowel will not
affect the vowel in main
alternatively if a reference is used
then the vowel that we are assigning to
is in fact an alias for the vowel in the
main which means that that variable's
value will then also be changed now this
of course doesn't affect this example
but if we were to for example have an
output of a val that occurs after the
call to foo then that would differ
depending on whether we were using a
copy or a reference
so that concludes our discussion on
various parameter parsing methods
and now we will look at some examples of
real-world programming languages and how
they provide support for a subset of the
parameter parsing methods
so in c we of course have standard pass
by value and this takes place whenever
we pass a variable
to a function by means of a parameter
and we don't use a pointer
pass by reference is achieved when we
use a pointer as a parameter
now in c plus we also have pass by value
but additionally we then also have
pointers and references which can also
be used for pass by reference parameter
passing
now java is interesting in the sense
that you might have heard that
everything in java is passed by value
except for objects which are passed by
reference now it turns out that this is
not in fact strictly speaking true
all parameters are passed by value in
java now when it comes to objects then
object parameters seem as though they
are being passed by reference but what's
actually happening is that object
references are being passed by value
now generally speaking for all intents
and purposes this doesn't have any kind
of impact and it seems that objects are
being passed by reference however it
does come into play if for instance we
try to update an object reference that
has been passed to a method and make
that point to a new object in that case
we are then assigning a new object to a
copy of a reference which will not
modify the original reference for
further details on this i refer you to
the notes on this slide where i have a
worked example that illustrates why this
concept is important to understand in
java
now ada has three transmission modes for
formal parameters it has in mode
parameters which can be referenced but
not assigned to and this is the default
mode so this is a pass by value
pass by result is handled by means of
out mode parameters and these can be
assigned to but not referenced and then
we have in out mode parameters which can
be referenced
and assigned to
and these are pause by value result
parameters
fortran 95 and newer has a similar
approach to what we see in ada where
parameters can also be in mode art mode
or in out mode parameters
now c sharp uses pass by value as its
default parameter parsing method it's
also possible to use parts by reference
and in this case both the formal
parameter and the actual parameter must
both be preceded by the special word ref
php uses a similar approach to c-sharp
so what i would like you to do now is
once again pause the video and try to
explain what effect the requirement that
riff must appear before both the formal
parameter and the actual parameter
has on the programming language
evaluation criteria we've been using
through this course
now perl is interesting in that it
differs from the previously mentioned
programming languages by implicitly
placing all of the actual parameters
from a subprogram call into a built-in
array called at underscore
now the elements of this at underscore
array are then aliases for the actual
parameters from the sub program call so
what i would like you to do at this
point is again pause the video and try
to explain which parameter parsing
method this implies
in the sense that aliases are used for
the elements in this built-in
array finally both python and ruby use
pause by assignment
so with pause by assignment the actual
parameter is assigned to the formal
parameter
now remember in both of these languages
that all data values are objects and
that assigning one object to another is
simply a reference change so because we
are assigning from the actual parameters
in the call to a sub program
and to the formal parameters in the
definition of the sub program this means
that we are essentially performing a
pass by reference parameter pass and
this is because a reference change is
used in all cases
now this can only not be the case when
assigning to immutable objects as formal
parameters so what i would like you to
do at this point is to pause the video
and try to explain what happens if we
have an immutable parameter as a formal
parameter in either python or ruby
next we get onto the design issue of
whether parameter type checking is
required in a programming language
so parameter type checking is a test to
see whether an actual and a formal
parameters types match one another this
kind of match is very important for
reliability
now in older programming languages such
as fortran 77
early
pre-1989 c
perl javascript and php we see that no
type checking was performed at all
so what i would like you to do is to
pause the video at this point and try to
explain what effect this lack of type
checking had on these programming
languages
all right so to answer this question
let's look at early versions of c as
well as c89 where it's maintained as a
possible alternative versus c
plus work in terms of type checking of
parameters
so in this initial approach on the left
over here there's no type checking that
is performed we can see
that in the header for our sub program
we've specified that the sign function
has a return type of double it receives
a single parameter called x
in the following line we specify that x
is a double value but this is not an
enforcement so essentially what we are
telling the compiler is that you should
expect a double value but there is in
fact no guarantee at all
so what this means is that a value other
than a double value could be seen
through as a parameter and what would
happen inside the body of this function
would be that on a bit level the
parameter value that had been sent
through would be interpreted as a double
value if in fact it wasn't a double
value then the value that would be
interpreted would bear no resemblance to
the original value
so this approach was used exclusively in
the older versions of c and it's still
maintained in c89 as an option however
it's generally speaking not used in
practice due to the fact that it is
unsafe
now the second approach over here is
then also supported in c89 as well as in
c
so here again we can see that we have a
sub program called sign it returns a
double value and it has a single
parameter called x but we've specified
that the type of this parameter is a
double
so what happens here now is type
checking is performed for this parameter
if we try to pass a type that doesn't
match for example a student object then
an error will be raised at that point
if we try to pass another numeric type
that is not a double then the compiler
will attempt to perform a coercion to
convert it into a double value if the
coercion can't be successfully performed
then again there will be an error that
will be raised but if the coercion can
be performed then the program will
simply continue assuming that that type
conversion has taken place
now what's important to understand is
that this type checked approach is much
safer than the original non-type checked
approach and this is because the value
will always be interpreted as a double
it won't just simply be a conversion on
a bit level
now more modern programming languages
like pascal fortran 90 java and ada
always require parameter type checking
to be performed so what i would like you
to do at this point is to pause the
video and explain what the effect of
this requirement is
now python and ruby
are interesting in that variables don't
have types but objects do
so for example if we look at this line
of code over here we have an assignment
that is taking place and we are
assigning to p
a new person object now the object that
is assigned to p has the type of person
but the variable p has no type it is
simply a reference to an object of some
generic type
so the formal parameters then are
typeless for any subprogram and what
this thing means is that formal
parameters can't be type checked because
they don't have types associated with
them
a similar kind of thing happens in java
if we were to write a method that
receives an object now we can pause to
this method any particular object it
could be a list it could be a person and
there is no way that that can be type
checked by the method what this means is
that inside the method we could perform
a cost which would then turn out to be
an invalid cost at runtime
so in that sense objects that are passed
through two methods in java also can't
be type checked exactly the same way as
objects in python and ruby can't be type
checked
next we'll take a look at how
multi-dimensional arrays can be passed
as parameters to sub-programs
so multi-dimensional arrays are
obviously arrays of two dimensions or
more
now the compiler needs to be able to map
array subscript references to values
within the multi-dimensional array and
in order to do this the compiler
constructs a mapping function
now this mapping function must know the
size of all of the dimensions except for
the first dimension which is equivalent
to the number of rows in the structure
within this multi-dimensional array
now the reasoning behind this is the
fact that arrays are stored in row major
format so each row is stored as a single
fixed length entity in memory and this
is why the dimensions making up these
rows must be known ahead of time
again in the notes for this slide i
provide a more concrete example of how
this works in practice so please refer
to that if you'd like more background
detail
now if the sub program can be separately
compiled which is the case in languages
like c and c plus plus then the array
name on its own doesn't tell the
compiler these dimension sizes that it
needs to know in order to be able to
correctly reference values in the
multi-dimensional array structure and
the compiler can only know the size of
these dimensions from the sub-program
text
so what this means then is that the
compiler needs to know the declared
dimension sizes and these sizes must be
provided within the program text itself
so let's look at what this looks like in
c and c plus in both of these languages
we must include the sizes of all of the
subscripts except for the first which
represents the number of rows in the
structure so here we have an example of
a function definition and we can see
that this function receives a
two-dimensional array called matrix it
stores integer values and we can see
that for our first subscript we haven't
provided a size but for the second
subscript we have provided a size of 10
that tin must be there in order for the
compiler to be able to correctly
reference values stored within the
matrix
now the big disadvantage associated with
this is that it reduces the flexibility
of our programming language and the
reason for this is that in this example
we can only receive a matrix that has 10
columns if we want to be able to receive
a matrix with 20 columns we need to
define a new sub program with a
different parameter in order to do that
the solution in c and c plus plus to
this problem of lack of flexibility is
of course to pass our two-dimensional
array as a pointer
so we can then pass the dimension sizes
as separate parameters as we see in this
example over here so here we've passed
through an integer pointer and this is a
pointer to our multi-dimensional array
we assume that it's a two-dimensional
array and we then pass through integer
parameters for both the number of rows
and the number of columns in our
two-dimensional structure
inside the body of our function
definition then we use pointer
arithmetic in order to access the values
that are stored within the
two-dimensional array so what i would
like you to do at this point is to pause
the video and try to think of any
disadvantages associated with this
approach and how these disadvantages
will affect the programming language
evaluation criteria
in java and c-sharp arrays are objects
and are all single dimensional
now of course arrays can be stored
within arrays allowing us to create
multi-dimensional array structures and
therefore we are using an orthogonal
approach to define our multi-dimensional
array structures
now each array in java or c-sharp has a
named constant and this named constant
represents the length of the array when
the array is created the named constant
in the case of java is length all
lowercase letters and in the case of c
sharp its length with an uppercase l
so what this means is we can then by
means of code actually query the array
to find its length and therefore no
sizes need to be specified in the formal
parameters as was the case in c and c
plus
now there are two design considerations
that come into play when we talk about
parameter parsing
the first is the relative efficiency of
the parameter parsing technique or
techniques supported by a programming
language and the second relates to
whether one-way or two-way data transfer
is supported by the parameter passing
technique or techniques supported by a
programming language now unfortunately
these two considerations are in conflict
with one another and therefore there's
usually a trade off between the two
now good programming practice suggests
that we should try to limit access to
variables and therefore one-way
parameters are generally preferable so
what this implies is that we should
rather use either pass by value or pass
by result in order to send values into
or retrieve values from a sub program
however if we look at pass by reference
we see that it is much more efficient
than pass by value it is more efficient
in terms of processing time because we
don't have to go through an expensive
copy operation each time that a
parameter is passed and it's also more
efficient in terms of memory space used
because we don't have to maintain two
copies of a past value at the same time
however past by reference usually
implies two-way parameters which is in
conflict with our good programming
practices
so generally speaking some programming
languages will choose to support only
pass by value and possibly pass by
result
whereas other programming languages will
support only pass by reference some
languages support a mix of the two
and c
plus finds a good middle ground by
allowing for references to constant
values to be passed through
two functions
what this means then is that we have the
general behavior of pass by value
because we're not working with a memory
address
but we also then don't have the issue
of two-way parameters because we are not
allowed to modify the value that the
reference refers to seeing as it is a
constant value
please refer to the notes for this slide
for a practical example of how this
approach would work in practice
the next design issue related to some
programs that we need to talk about
relates to whether sub-programs can be
passed as parameters but before we can
get to that we need to talk about
calling sub-programs indirectly
so sub-programs are called indirectly
when there are several possible
sub-programs we can call and the correct
one is not known until execution time
a good example of this in practice is
during event handling
where we have a number of different
events that can occur at run time for
example a user may click on a button or
they may press enter within a text entry
field
the exact course of action that the user
will take cannot be known at compile
time and therefore only occurs at run
time at which point the correct event
needs to be triggered and the event
would be encapsulated inside a sub
program so cnc plus plus supports
calling sub programs indirectly through
what are called function pointers
and these are pointers to functions that
include parameter and return types so
over here we have a simple example of
this in c plus
we have a function called myfunc its
return type is float and it has two
parameters firstly a float parameter and
then that's followed by an int parameter
next we define a pointer called ptr we
can see it's pointed because we use this
asterisk notation and also notice that
the pointer's name is surrounded by
parentheses
this is the function pointer we specify
that the return type for the function
pointer is a float and the parameters
are a float followed by an int
so now we can assign to this pointer any
function as long as it satisfies the
requirements that have been specified
for the pointer in other words the
return type must be a float and the
first parameter must be float while the
second parameter is an int now this of
course is the case for my func and
therefore we can assign my func to our
function pointer ptr
now what we can do is we can call ptr
and we can pass through parameter values
for that and this is then effectively
indirectly calling the myfunc function
through the pointer that we have defined
which is a function pointer
in c-sharp sub-programs are called
indirectly through method pointers which
are implemented as objects called
delegates so in order to implement a
delegate we first need to create a
delegate type which we do in this
example over here
how our delegate type is called change
and we specify that this is a public
delegate with a return type of int and a
parameter type of int as well
so now we can instantiate a delegate
object
with a method that has the appropriate
protocol that matches what has been
defined for the delegate type so over
here we have a static method called fun
one it has a return type of int and a
single parameter which is an int so
therefore matches with our delegate type
now we can create an instance of our
delegate type this instance which is the
delegate is called my change function
its type is change which is the same
type as the delegate type that we just
defined
and we can then assign to that a new
change object and pass through fun1 as a
parameter at this point my change
function is now an alias for fun one so
now much as we did with function
pointers that we looked at on the
previous slide we can call my change
function which is the delegate pass
through a parameter value of 12 and that
is then an alias
for a direct call to the fun one method
now c sharp also supports multicast
delegates and these are delegates that
store several method pointers which are
run in sequence
so we can for example add another
function to my change function we just
use the plus
equals operator and then specify a
second method this method will then be
added to the delegate and when we
execute the delegate then fund one will
be called first and then fund two
afterwards it's important to note that
fund fund2 must also return an integer
value and receive only a single integer
as a parameter
now it is sometimes convenient for us to
pass a subprogram name as a parameter
and this allows us to pass one
sub-program to another sub-program where
the second sub-program will execute the
first sub-program
this of course then requires a way to
call a sub-program indirectly which
we've just discussed
so there are two issues associated with
passing sub programs as parameters
firstly are the parameter types checked
and secondly and most importantly what
is the referencing environment for the
past sub program we'll look at each of
these in turn in the next few slides
now of course support for parameters
that are sub-programs differ from
programming language to programming
language
cnc plus allow for a function to receive
a function pointer as a parameter and
this allows for functions to be passed
to other functions
the fact that function pointers are used
allow for the parameters to be type
checked and so what i would like you to
do at this point is to pause the video
and try to explain why this is the case
now fortran 95 allows subprograms to be
passed as parameters and it also type
checks these parameters
however ada and java don't allow
parameters that are sub programs
now we come to the most important part
of this lecture which relates to the
referencing environment of past
subprograms
so recall that a referencing environment
is the set of all of the variables that
are visible to a statement so in other
words it's a set of the variables that
the statement can reference now a past
sub-program also has a referencing
environment and this becomes important
when the past sub-program refers to a
variable but this variable is defined
outside of the past sub-program and in
this case we need to be able to
disambiguate which variable is actually
being referred to
so we'll now illustrate the options
available for the referencing
environment of a past sub-program by
means of a simple example
in this example we have a sub-program
called sub-one and sub-one has defined
within it a variable called x which has
a value of 1. it also has a number of
nested sub programs defined within it
namely sub 2
sub 3 and sub 4. we then have at the
bottom of sub 1 a call to sub 3.
in sub 3 we have another variable x
defined which has a value of 3 and we
then call sub 4 but importantly we pass
through sub 2 as a parameter 2 sub 4.
sub 4 is defined over here and this
receives a sub program as a parameter
which is called sub x it also defines a
variable called x which has a value of 4
and it calls sub x
now sub 2 that has been passed through
in the call to sub 4 is defined up here
and all that this does is it prints x
out
so the question now is which value of x
is the one that is printed we can see
that x hasn't been defined locally
within sub two
so one of the three initializations of x
will be the one that will be referred to
in sub two and this depends on the
referencing environment for sub two so
there are three possible approaches that
can be used for determining the
referencing environment for step two and
these are shallow binding deep binding
and ad-hoc binding we'll be looking at
each of these in turn on the next three
slides
we'll first look at shallow binding
so with shadow binding the referencing
environment of the past sub program is
the call that enacts the past sub
program
now in our example over here we can see
that sub 3 calls sub 4 and passes
through sub 2 as a parameter but sub 4
is responsible for actually calling sub
2 by means of its parameter sub x so sub
4 is the sub program in acting the call
to the past sub program so what this
means is that the x that is referred to
in sub 2 will be the x defined in sub 4
which gives us a value of 4 that is then
printed out to the screen
now shadow binding is natural for
dynamically scoped programming languages
so what is the case in dynamically
scoped programming languages we move
backwards through the chain of called
sub-programs until we encounter the
variable that we are looking for now the
order of the chord sub programs goes
from sub 1 to sub 3 and then from sub 3
to sub 4 and then from sub 4 to sub 2.
so if the variable x is not defined in
sub 2 then we look in the
previous
subprogram call in the chain which is 4
and that gives us our variable value of
4 4x which then gets printed out so this
is why shallow binding is natural for a
dynamically scoped programming language
next we'll look at deep binding so with
deep binding the referencing environment
of the past stutter program
is the past sub-programs definition
itself
so
let's then look at our example over here
the past sub-program is of course sub 2.
so therefore we're looking at the
referencing environment for sub 2. now
of course x isn't defined within sub 2
and therefore we need to look outside of
sub 2's scope so let's assume that we
use static scoping what this means then
is that we need to look in the static
ancestor of sub 2 which is of course sub
1 because sub 2 is nested within sub 1.
so in this case then we will be
referring to the variable x defined in
sub 1 which means we will be printing
out the value of 1.
now deep binding is natural for
statically scoped programming languages
and this is because we follow static
scoping rules we look in the current
scope and if the variable is not
contained within that scope we look at
the next static ancestor and then
continue our search until eventually we
find the variable that we are looking
for
finally we have ad hoc binding and here
the referencing environment of the past
sub program is the call statement that
actually passed this other program
so let's look at our example over here
this is the call that actually passes
the sub program to sub 4. so sub 2 is
passed as a parameter to the sub 4 sub
program
so this will then be the referencing
environment for sub 2 which means that
this print for x will refer to the x
defined within sub 3 and this will then
be the value 3 that will be printed out
to the screen
ad hoc binding doesn't relate to either
static or dynamic scoping at all
all right so that concludes this lecture
in the next lecture we will be
continuing and concluding our discussion
on sub programs
5.0 / 5 (0 votes)