0% found this document useful (0 votes)
4 views153 pages

Programming Principles

Chapter 1 discusses the importance of studying programming languages, highlighting reasons such as improved expression and language selection. It covers programming domains, evaluation criteria for languages, influences on language design, and implementation methods. The chapter emphasizes the trade-offs in language design and the significance of understanding these concepts for effective programming.

Uploaded by

yeslittlekid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views153 pages

Programming Principles

Chapter 1 discusses the importance of studying programming languages, highlighting reasons such as improved expression and language selection. It covers programming domains, evaluation criteria for languages, influences on language design, and implementation methods. The chapter emphasizes the trade-offs in language design and the significance of understanding these concepts for effective programming.

Uploaded by

yeslittlekid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 153

Chapter 1

Preliminaries

ISBN 0-321-49362-1
Chapter 1 Topics

• Reasons for Studying Concepts of


Programming Languages
• Programming Domains
• Language Evaluation Criteria
• Influences on Language Design
• Language Categories
• Language Design Trade-Offs
• Implementation Methods
• Programming Environments
Copyright © 2018 Pearson. All rights reserved. 1-2
Reasons for Studying Concepts of
Programming Languages

• Increased ability to express ideas


• Improved background for choosing
appropriate languages
• Increased ability to learn new languages
• Better understanding of significance of
implementation
• Better use of languages that are already
known
• Overall advancement of computing

Copyright © 2018 Pearson. All rights reserved. 1-3


Programming Domains
• Scientific applications
– Large numbers of floating point computations; use of arrays
– Fortran
• Business applications
– Produce reports, use decimal numbers and characters
– COBOL
• Artificial intelligence
– Symbols rather than numbers manipulated; use of linked lists
– LISP
• Systems programming
– Need efficiency because of continuous use
– C
• Web Software
– Eclectic collection of languages: markup (e.g., HTML),
scripting (e.g., PHP), general-purpose (e.g., Java)

Copyright © 2018 Pearson. All rights reserved. 1-4


Language Evaluation Criteria

• Readability: the ease with which


programs can be read and understood
• Writability: the ease with which a
language can be used to create programs
• Reliability: conformance to specifications
(i.e., performs to its specifications)
• Cost: the ultimate total cost

Copyright © 2018 Pearson. All rights reserved. 1-5


Evaluation Criteria: Readability
• Overall simplicity
– A manageable set of features and constructs
– Minimal feature multiplicity
– Minimal operator overloading
• Orthogonality
– A relatively small set of primitive constructs can be combined in a
relatively small number of ways
– Every possible combination is legal
• Data types
– Adequate predefined data types
• Syntax considerations
– Identifier forms: flexible composition
– Special words and methods of forming compound statements
– Form and meaning: self-descriptive constructs, meaningful keywords

Copyright © 2018 Pearson. All rights reserved. 1-6


Evaluation Criteria: Writability
• Simplicity and orthogonality
– Few constructs, a small number of primitives, a small set of
rules for combining them

• Support for abstraction


– The ability to define and use complex structures or
operations in ways that allow details to be ignored

• Expressivity
– A set of relatively convenient ways of specifying operations
– Strength and number of operators and predefined functions

Copyright © 2018 Pearson. All rights reserved. 1-7


Evaluation Criteria: Reliability

• Type checking
– Testing for type errors
• Exception handling
– Intercept run-time errors and take corrective measures
• Aliasing
– Presence of two or more distinct referencing methods for the
same memory location
• Readability and writability
– A language that does not support “natural” ways of expressing
an algorithm will require the use of “unnatural” approaches, and
hence reduced reliability

Copyright © 2018 Pearson. All rights reserved. 1-8


Evaluation Criteria: Cost
• Training programmers to use the
language
• Writing programs (closeness to particular
applications)
• Executing programs
• Reliability: poor reliability leads to high
costs
• Maintaining programs

Copyright © 2018 Pearson. All rights reserved. 1-9


Evaluation Criteria: Others

• Portability
– The ease with which programs can be moved
from one implementation to another
• Generality
– The applicability to a wide range of applications
• Well-definedness
– The completeness and precision of the
language’s official definition

Copyright © 2018 Pearson. All rights reserved. 1-10


Influences on Language Design

• Computer Architecture
– Languages are developed around the prevalent
computer architecture, known as the von
Neumann architecture
• Program Design Methodologies
– New software development methodologies (e.g.,
object-oriented software development) led to
new programming paradigms and by extension,
new programming languages

Copyright © 2018 Pearson. All rights reserved. 1-11


Computer Architecture Influence

• Well-known computer architecture: Von Neumann


• Imperative languages, most dominant, because of
von Neumann computers
– Data and programs stored in memory
– Memory is separate from CPU
– Instructions and data are piped from memory to CPU
– Basis for imperative languages
• Variables model memory cells
• Assignment statements model piping
• Iteration is efficient

Copyright © 2018 Pearson. All rights reserved. 1-12


The von Neumann Architecture

Copyright © 2018 Pearson. All rights reserved. 1-13


The von Neumann Architecture

• Fetch-execute-cycle (on a von Neumann


architecture computer)

initialize the program counter


repeat forever
fetch the instruction pointed by the counter
increment the counter
decode the instruction
execute the instruction
end repeat

Copyright © 2018 Pearson. All rights reserved. 1-14


Programming Methodologies Influences

• 1950s and early 1960s: Simple applications; worry


about machine efficiency
• Late 1960s: People efficiency became important;
readability, better control structures
– structured programming
– top-down design and step-wise refinement
• Late 1970s: Process-oriented to data-oriented
– data abstraction
• Middle 1980s: Object-oriented programming
– Data abstraction + inheritance + polymorphism

Copyright © 2018 Pearson. All rights reserved. 1-15


Language Categories
• Imperative
– Central features are variables, assignment statements, and
iteration
– Include languages that support object-oriented programming
– Include scripting languages
– Include the visual languages
– Examples: C, Java, Perl, JavaScript, Visual BASIC .NET, C++
• Functional
– Main means of making computations is by applying functions to
given parameters
– Examples: LISP, Scheme, ML, F#
• Logic
– Rule-based (rules are specified in no particular order)
– Example: Prolog
• Markup/programming hybrid
– Markup languages extended to support some programming
– Examples: JSTL, XSLT

Copyright © 2018 Pearson. All rights reserved. 1-16


Language Design Trade-Offs

• Reliability vs. cost of execution


– Example: Java demands all references to array elements
be checked for proper indexing, which leads to increased
execution costs

• Readability vs. writability


Example: APL provides many powerful operators (and a large
number of new symbols), allowing complex computations
to be written in a compact program but at the cost of
poor readability

• Writability (flexibility) vs. reliability


– Example: C++ pointers are powerful and very flexible but
are unreliable

Copyright © 2018 Pearson. All rights reserved. 1-17


Implementation Methods
• Compilation
– Programs are translated into machine language; includes
JIT systems
– Use: Large commercial applications

• Pure Interpretation
– Programs are interpreted by another program known as
an interpreter
– Use: Small programs or when efficiency is not an issue

• Hybrid Implementation Systems


– A compromise between compilers and pure interpreters
– Use: Small and medium systems when efficiency is not the
first concern
Copyright © 2018 Pearson. All rights reserved. 1-18
Layered View of Computer
The operating system
and language
implementation are
layered over
machine interface of a
computer

Copyright © 2018 Pearson. All rights reserved. 1-19


Compilation

• Translate high-level program (source language)


into machine code (machine language)
• Slow translation, fast execution
• Compilation process has several phases:
– lexical analysis: converts characters in the source program
into lexical units
– syntax analysis: transforms lexical units into parse trees
which represent the syntactic structure of program
– Semantics analysis: generate intermediate code
– code generation: machine code is generated

Copyright © 2018 Pearson. All rights reserved. 1-20


The Compilation Process

Copyright © 2018 Pearson. All rights reserved. 1-21


Additional Compilation Terminologies

• Load module (executable image): the user


and system code together
• Linking and loading: the process of
collecting system program units and linking
them to a user program

Copyright © 2018 Pearson. All rights reserved. 1-22


Von Neumann Bottleneck

• Connection speed between a computer’s


memory and its processor determines the
speed of a computer
• Program instructions often can be executed
much faster than the speed of the
connection; the connection speed thus
results in a bottleneck
• Known as the von Neumann bottleneck; it is
the primary limiting factor in the speed of
computers
Copyright © 2018 Pearson. All rights reserved. 1-23
Pure Interpretation

• No translation
• Easier implementation of programs (run-time
errors can easily and immediately be displayed)
• Slower execution (10 to 100 times slower than
compiled programs)
• Often requires more space
• Now rare for traditional high-level languages
• Significant comeback with some Web scripting
languages (e.g., JavaScript, PHP)

Copyright © 2018 Pearson. All rights reserved. 1-24


Pure Interpretation Process

Copyright © 2018 Pearson. All rights reserved. 1-25


Hybrid Implementation Systems

• A compromise between compilers and pure


interpreters
• A high-level language program is
translated to an intermediate language that
allows easy interpretation
• Faster than pure interpretation
• Examples
– Perl programs are partially compiled to detect errors
before interpretation
– Initial implementations of Java were hybrid; the
intermediate form, byte code, provides portability to any
machine that has a byte code interpreter and a run-time
system (together, these are called Java Virtual Machine)
Copyright © 2018 Pearson. All rights reserved. 1-26
Hybrid Implementation Process

Copyright © 2018 Pearson. All rights reserved. 1-27


Just-in-Time Implementation Systems

• Initially translate programs to an intermediate


language
• Then compile the intermediate language of the
subprograms into machine code when they are
called
• Machine code version is kept for subsequent calls
• JIT systems are widely used for Java programs
• .NET languages are implemented with a JIT system
• In essence, JIT systems are delayed compilers

Copyright © 2018 Pearson. All rights reserved. 1-28


Preprocessors

• Preprocessor macros (instructions) are


commonly used to specify that code from
another file is to be included
• A preprocessor processes a program
immediately before the program is
compiled to expand embedded
preprocessor macros
• A well-known example: C preprocessor
– expands #include, #define, and similar
macros

Copyright © 2018 Pearson. All rights reserved. 1-29


Programming Environments
• A collection of tools used in software development
• UNIX
– An older operating system and tool collection
– Nowadays often used through a GUI (e.g., CDE, KDE, or
GNOME) that runs on top of UNIX
• Microsoft Visual Studio.NET
– A large, complex visual environment
• Used to build Web applications and non-Web applications in
any .NET language
• NetBeans
– Related to Visual Studio .NET, except for applications in
Java

Copyright © 2018 Pearson. All rights reserved. 1-30


Summary

• The study of programming languages is valuable for


a number of reasons:
– Increase our capacity to use different constructs
– Enable us to choose languages more intelligently
– Makes learning new languages easier
• Most important criteria for evaluating programming
languages include:
– Readability, writability, reliability, cost
• Major influences on language design have been
machine architecture and software development
methodologies
• The major methods of implementing programming
languages are: compilation, pure interpretation, and
hybrid implementation

Copyright © 2018 Pearson. All rights reserved. 1-31


Chapter 5

Names, Bindings,
and Scopes

ISBN 0-321-49362-1
Chapter 5 Topics

• Introduction
• Names
• Variables
• The Concept of Binding
• Scope
• Scope and Lifetime
• Referencing Environments
• Named Constants

Copyright © 2018 Pearson. All rights reserved. 1-2


Introduction

• Imperative languages are abstractions of


von Neumann architecture
– Memory
– Processor
• Variables are characterized by attributes
– To design a type, must consider scope, lifetime,
type checking, initialization, and type
compatibility

Copyright © 2018 Pearson. All rights reserved. 1-3


Names

• Design issues for names:


– Are names case sensitive?
– Are special words reserved words or keywords?

– If, else, for, while


– Def, import

Copyright © 2018 Pearson. All rights reserved. 1-4


Names (continued)

• Length
– If too short, they cannot be connotative
– Language examples:
• C99: no limit but only the first 63 are significant;
also, external names are limited to a maximum of
31
• C# and Java: no limit, and all are significant
• C++: no limit, but implementers often impose one

Copyright © 2018 Pearson. All rights reserved. 1-5


Names (continued)

• Special characters
– PHP: all variable names must begin with dollar
signs ($age, $name, $total)
– Perl: all variable names begin with special
characters, which specify the variable’s type
– @name, $name, %name
– Ruby: variable names that begin with @ are
instance variables; those that begin with @@ are
class variables

Copyright © 2018 Pearson. All rights reserved. 1-6


Names (continued)

• Case sensitivity
– Disadvantage: readability (names that look alike
are different)
• Names in the C-based languages are case sensitive
• Names in others are not
• Worse in C++, Java, and C# because predefined
names are mixed case (e.g.
IndexOutOfBoundsException)

Copyright © 2018 Pearson. All rights reserved. 1-7


Names (continued)

• Special words
– An aid to readability; used to delimit or separate
statement clauses
- A keyword is a word that is special only in
certain contexts
– A reserved word is a special word that cannot be
used as a user-defined name
– Potential problem with reserved words: If there
are too many, many collisions occur (e.g.,
COBOL has 300 reserved words!)

Copyright © 2018 Pearson. All rights reserved. 1-8


Variables

• A variable is an abstraction of a memory


cell
• Variables can be characterized as a
sextuple of attributes:
– Name int x = 10; // Declares an integer variable named x
and initializes it to 10
– Address
float y; // Declares a floating-point variable named
– Value y

– Type y = 3.14; // Assigns the value 3.14 to the variable y


– Lifetime int z = x + y; // Adds the values of x and y and
– Scope stores the result in z

Copyright © 2018 Pearson. All rights reserved. 1-9


Variables Attributes

• Name - not all variables have them


• Address - the memory address with which it is
associated
– A variable may have different addresses at different times
during execution
– A variable may have different addresses at different
places in a program
– If two variable names can be used to access the same
memory location, they are called aliases
– Aliases are created via pointers, reference variables, C and
C++ unions
– Aliases are harmful to readability (program
readers must remember all of them)

Copyright © 2018 Pearson. All rights reserved. 1-10


Variables Attributes (continued)

• Type - determines the range of values of variables


and the set of operations that are defined for
values of that type; in the case of floating point,
type also determines the precision
• Value - the contents of the location with which the
variable is associated
- The l-value of a variable is its address
- The r-value of a variable is its value
• Abstract memory cell - the physical cell or
collection of cells associated with a variable

Copyright © 2018 Pearson. All rights reserved. 1-11


The Concept of Binding

A binding is an association between an


entity and an attribute, such as between a
variable and its type or value, or between
an operation and a symbol
• Binding time is the time at which a binding
takes place.

Copyright © 2018 Pearson. All rights reserved. 1-12


Possible Binding Times

• Language design time -- bind operator


symbols to operations
• Language implementation time-- bind
floating point type to a representation
• Compile time -- bind a variable to a type
in C or Java
• Load time -- bind a C or C++ static
variable to a memory cell)
• Runtime -- bind a nonstatic local variable
to a memory cell
Copyright © 2018 Pearson. All rights reserved. 1-13
Static and Dynamic Binding

• A binding is static if it first occurs before


run time and remains unchanged
throughout program execution.
• A binding is dynamic if it first occurs during
execution or can change during execution
of the program

Copyright © 2018 Pearson. All rights reserved. 1-14


Type Binding

• How is a type specified?


• When does the binding take place?
• If static, the type may be specified by either
an explicit or an implicit declaration

Copyright © 2018 Pearson. All rights reserved. 1-15


Explicit/Implicit Declaration
• An explicit declaration is a program
statement used for declaring the types of
variables
• An implicit declaration is a default
mechanism for specifying types of variables
through default conventions, rather than
declaration statements
• Basic, Perl, Ruby, JavaScript, and PHP
provide implicit declarations
– Advantage: writability (a minor convenience)
– Disadvantage: reliability (less trouble with Perl)

Copyright © 2018 Pearson. All rights reserved. 1-16


Explicit/Implicit Declaration (continued)

• Some languages use type inferencing to


determine types of variables (context)
– C# - a variable can be declared with var and an
initial value. The initial value sets the type

– Visual Basic 9.0+, ML, Haskell, and F# use type


inferencing. The context of the appearance of a
variable determines its type

Copyright © 2018 Pearson. All rights reserved. 1-17


Dynamic Type Binding
• Dynamic Type Binding (JavaScript, Python,
Ruby, PHP, and C# (limited))
• Specified through an assignment statement
e.g., JavaScript
list = [2, 4.33, 6, 8];
list = 17.3;
– Advantage: flexibility (generic program units)
– Disadvantages:
• High cost (dynamic type checking and
interpretation)
• Type error detection by the compiler is difficult

Copyright © 2018 Pearson. All rights reserved. 1-18


Variable Attributes (continued)

• Storage Bindings & Lifetime


– Allocation - getting a cell from some pool of
available cells
– Deallocation - putting a cell back into the pool
• The lifetime of a variable is the time during
which it is bound to a particular memory
cell

Copyright © 2018 Pearson. All rights reserved. 1-19


Categories of Variables by Lifetimes

• Static--bound to memory cells before


execution begins and remains bound to the
same memory cell throughout execution,
e.g., C and C++ static variables in
functions
– Advantages: efficiency (direct addressing),
history-sensitive subprogram support
– Disadvantage: lack of flexibility (no recursion)

Copyright © 2018 Pearson. All rights reserved. 1-20


Categories of Variables by Lifetimes
• Stack-dynamic--Storage bindings are created for
variables when their declaration statements are
elaborated.
(A declaration is elaborated when the executable
code associated with it is executed)
• If scalar, all attributes except address are statically
bound
– local variables in C subprograms (not declared static)
and Java methods
• Advantage: allows recursion; conserves storage
• Disadvantages:
– Overhead of allocation and deallocation
– Subprograms cannot be history sensitive
– Inefficient references (indirect addressing)
Copyright © 2018 Pearson. All rights reserved. 1-21
Categories of Variables by Lifetimes
• Explicit heap-dynamic -- Allocated and
deallocated by explicit directives, specified by the
programmer, which take effect during execution
• Referenced only through pointers or references,
e.g. dynamic objects in C++ (via new and delete),
all objects in Java
• Advantage: provides for dynamic storage
management
• Disadvantage: inefficient and unreliable

Copyright © 2018 Pearson. All rights reserved. 1-22


Categories of Variables by Lifetimes

• Implicit heap-dynamic--Allocation and


deallocation caused by assignment
statements
– all variables in APL; all strings and arrays in Perl,
JavaScript, and PHP
• Advantage: flexibility (generic code)
• Disadvantages:
– Inefficient, because all attributes are dynamic
– Loss of error detection

Copyright © 2018 Pearson. All rights reserved. 1-23


Variable Attributes: Scope

• The scope of a variable is the range of statements


over which it is visible
• The local variables of a program unit are those that
are declared in that unit
• The nonlocal variables of a program unit are those
that are visible in the unit but not declared there
• Global variables are a special category of nonlocal
variables
• The scope rules of a language determine how
references to names are associated with variables

Copyright © 2018 Pearson. All rights reserved. 1-24


Static Scope

• Based on program text


• To connect a name reference to a variable, you (or
the compiler) must find the declaration
• Search process: search declarations, first locally,
then in increasingly larger enclosing scopes, until
one is found for the given name
• Enclosing static scopes (to a specific scope) are
called its static ancestors; the nearest static
ancestor is called a static parent
• Some languages allow nested subprogram
definitions, which create nested static scopes (e.g.,
Ada, JavaScript, Common Lisp, Scheme, Fortran
2003+, F#, and Python)

Copyright © 2018 Pearson. All rights reserved. 1-25


Scope (continued)

• Variables can be hidden from a unit by


having a "closer" variable with the same
name

Copyright © 2018 Pearson. All rights reserved. 1-26


Blocks

– A method of creating static scopes inside program


units--from ALGOL 60
– Example in C:
void sub() {
int count;
while (...) {
int count;
count++;
...
}

}

- Note: legal in C and C++, but not in Java


and C# - too error-prone

Copyright © 2018 Pearson. All rights reserved. 1-27


The LET Construct

• Most functional languages include some


form of let construct
• A let construct has two parts
– The first part binds names to values
– The second part uses the names defined in the first part
• In Scheme:
(LET (
(name1 expression1)

(namen expressionn)
)

Copyright © 2018 Pearson. All rights reserved. 1-28


The LET Construct (continued)

• In ML:
let
val name1 = expression1

val namen = expressionn
in
expression
end;

• In F#:
– First part: let left_side = expression
– (left_side is either a name or a tuple pattern)
– All that follows is the second part
Copyright © 2018 Pearson. All rights reserved. 1-29
Declaration Order

• C99, C++, Java, and C# allow variable


declarations to appear anywhere a
statement can appear
– In C99, C++, and Java, the scope of all local
variables is from the declaration to the end of
the block
– In the official documentation of C#, the scope of
any variable declared in a block is the whole
block, regardless of the position of the
declaration in the block
• However, that is misleading, because a variable still
must be declared before it can be used

Copyright © 2018 Pearson. All rights reserved. 1-30


Declaration Order (continued)

• In C++, Java, and C#, variables can be


declared in for statements
– The scope of such variables is restricted to the
for construct

Copyright © 2018 Pearson. All rights reserved. 1-31


Global Scope

• C, C++, PHP, and Python support a


program structure that consists of a
sequence of function definitions in a file
– These languages allow variable declarations to
appear outside function definitions

• C and C++have both declarations (just


attributes) and definitions (attributes and
storage)
– A declaration outside a function definition
specifies that it is defined in another file
Copyright © 2018 Pearson. All rights reserved. 1-32
Global Scope (continued)

• PHP
– Programs are embedded in HTML markup
documents, in any number of fragments, some
statements and some function definitions
– The scope of a variable (implicitly) declared in a
function is local to the function
– The scope of a variable implicitly declared
outside functions is from the declaration to the
end of the program, but skips over any
intervening functions
• Global variables can be accessed in a function
through the $GLOBALS array or by declaring it global
Copyright © 2018 Pearson. All rights reserved. 1-33
Global Scope (continued)

• Python
– A global variable can be referenced in functions,
but can be assigned in a function only if it has
been declared to be global in the function

Copyright © 2018 Pearson. All rights reserved. 1-34


Evaluation of Static Scoping

• Works well in many situations


• Problems:
– In most cases, too much access is possible
– As a program evolves, the initial structure is
destroyed and local variables often become
global; subprograms also gravitate toward
become global, rather than nested

Copyright © 2018 Pearson. All rights reserved. 1-35


Dynamic Scope

• Based on calling sequences of program


units, not their textual layout (temporal
versus spatial)
• References to variables are connected to
declarations by searching back through the
chain of subprogram calls that forced
execution to this point

Copyright © 2018 Pearson. All rights reserved. 1-36


Scope Example
function big() { big calls sub1
function sub1() sub1 calls sub2
var x = 7; sub2 uses x
function sub2() {
var y = x;
}
var x = 3;
}

– Static scoping
• Reference to x in sub2 is to big's x
– Dynamic scoping
• Reference to x in sub2 is to sub1's x

Copyright © 2018 Pearson. All rights reserved. 1-37


Scope Example

• Evaluation of Dynamic Scoping:


– Advantage: convenience
– Disadvantages:
1. While a subprogram is executing, its variables are
visible to all subprograms it calls
2. Impossible to statically type check
3. Poor readability- it is not possible to statically
determine the type of a variable

Copyright © 2018 Pearson. All rights reserved. 1-38


Scope and Lifetime

• Scope and lifetime are sometimes closely


related, but are different concepts
• Consider a static variable in a C or C++
function

Copyright © 2018 Pearson. All rights reserved. 1-39


Referencing Environments

• The referencing environment of a statement is the


collection of all names that are visible in the
statement
• In a static-scoped language, it is the local variables
plus all of the visible variables in all of the
enclosing scopes
• A subprogram is active if its execution has begun
but has not yet terminated
• In a dynamic-scoped language, the referencing
environment is the local variables plus all visible
variables in all active subprograms

Copyright © 2018 Pearson. All rights reserved. 1-40


Named Constants

• A named constant is a variable that is bound to a


value only when it is bound to storage
• Advantages: readability and modifiability
• Used to parameterize programs
• The binding of values to named constants can be
either static (called manifest constants) or dynamic
• Languages:
– C++ and Java: expressions of any kind, dynamically
bound
– C# has two kinds, readonly and const
- the values of const named constants are bound at
compile time
- The values of readonly named constants are
dynamically bound

Copyright © 2018 Pearson. All rights reserved. 1-41


Summary

• Case sensitivity and the relationship of names to


special words represent design issues of names
• Variables are characterized by the sextuples:
name, address, value, type, lifetime, scope
• Binding is the association of attributes with
program entities
• Scalar variables are categorized as: static, stack
dynamic, explicit heap dynamic, implicit heap
dynamic
• Strong typing means detecting all type errors

Copyright © 2018 Pearson. All rights reserved. 1-42


Chapter 7

Expressions and
Assignment
Statements

ISBN 0-321-49362-1
Chapter 7 Topics

• Introduction
• Arithmetic Expressions
• Overloaded Operators
• Type Conversions
• Relational and Boolean Expressions
• Short-Circuit Evaluation
• Assignment Statements
• Mixed-Mode Assignment

Copyright © 2018 Pearson. All rights reserved. 1-2


Introduction

• Expressions are the fundamental means of


specifying computations in a programming
language
• To understand expression evaluation, need
to be familiar with the orders of operator
and operand evaluation
• Essence of imperative languages is
dominant role of assignment statements

Copyright © 2018 Pearson. All rights reserved. 1-3


Arithmetic Expressions

• Arithmetic evaluation was one of the motivations


for the development of the first programming
languages
• Arithmetic expressions consist of operators,
operands, parentheses, and function calls
• In most languages, binary operators are infix,
except in Scheme and LISP, in which they are
prefix; Perl also has some prefix binary operators
• Most unary operators are prefix, but the ++ and –-
operators in C-based languages can be either
prefix or postfix

Copyright © 2018 Pearson. All rights reserved. 1-4


Arithmetic Expressions: Design Issues

• Design issues for arithmetic expressions


– Operator precedence rules?
– Operator associativity rules?
– Order of operand evaluation?
– Operand evaluation side effects?
– Operator overloading?
– Type mixing in expressions?

Copyright © 2018 Pearson. All rights reserved. 1-5


Arithmetic Expressions: Operators

• A unary operator has one operand


• A binary operator has two operands
• A ternary operator has three operands

Copyright © 2018 Pearson. All rights reserved. 1-6


Arithmetic Expressions: Operator
Precedence Rules
• The operator precedence rules for
expression evaluation define the order in
which “adjacent” operators of different
precedence levels are evaluated
• Typical precedence levels
– parentheses
– unary operators
– ** (if the language supports it)
– *, /
– +, -

Copyright © 2018 Pearson. All rights reserved. 1-7


Arithmetic Expressions: Operator
Associativity Rule
• The operator associativity rules for expression
evaluation define the order in which adjacent
operators with the same precedence level are
evaluated
• Typical associativity rules
– Left to right, except **, which is right to left
– Sometimes unary operators associate right to left (e.g., in
FORTRAN)
• APL is different; all operators have equal
precedence and all operators associate right to left
• Precedence and associativity rules can be overriden
with parentheses

Copyright © 2018 Pearson. All rights reserved. 1-8


Expressions in Ruby and Scheme
• Ruby
– All arithmetic, relational, and assignment
operators, as well as array indexing, shifts, and
bit-wise logic operators, are implemented as
methods
- One result of this is that these operators can all
be overriden by application programs
• Scheme (and Common Lisp)
- All arithmetic and logic operations are by
explicitly called subprograms
- a + b * c is coded as (+ a (* b c))

Copyright © 2018 Pearson. All rights reserved. 1-9


Arithmetic Expressions: Conditional
Expressions

• Conditional Expressions
– C-based languages (e.g., C, C++)
– An example:
average = (count == 0)? 0 : sum / count

– Evaluates as if written as follows:


if (count == 0)
average = 0
else
average = sum /count

Copyright © 2018 Pearson. All rights reserved. 1-10


Arithmetic Expressions: Operand
Evaluation Order

• Operand evaluation order


1. Variables: fetch the value from memory
2. Constants: sometimes a fetch from memory;
sometimes the constant is in the machine
language instruction
3. Parenthesized expressions: evaluate all
operands and operators first
4. The most interesting case is when an operand
is a function call

Copyright © 2018 Pearson. All rights reserved. 1-11


Arithmetic Expressions: Potentials for
Side Effects

• Functional side effects: when a function changes a


two-way parameter or a non-local variable
• Problem with functional side effects:
– When a function referenced in an expression alters
another operand of the expression; e.g., for a parameter
change:
a = 10;
/* assume that fun changes its parameter */
b = a + fun(&a);

Copyright © 2018 Pearson. All rights reserved. 1-12


Functional Side Effects

• Two possible solutions to the problem


1. Write the language definition to disallow functional side
effects
• No two-way parameters in functions
• No non-local references in functions
• Advantage: it works!
• Disadvantage: inflexibility of one-way parameters and
lack of non-local references
2. Write the language definition to demand that operand
evaluation order be fixed
• Disadvantage: limits some compiler optimizations
• Java requires that operands appear to be evaluated in
left-to-right order

Copyright © 2018 Pearson. All rights reserved. 1-13


Referential Transparency

• A program has the property of referential


transparency if any two expressions in the
program that have the same value can be
substituted for one another anywhere in the
program, without affecting the action of the
program
result1 = (fun(a) + b) / (fun(a) – c);
temp = fun(a);
result2 = (temp + b) / (temp – c);
If fun has no side effects, result1 = result2
Otherwise, not, and referential transparency is violated

Copyright © 2018 Pearson. All rights reserved. 1-14


Referential Transparency (continued)

• Advantage of referential transparency


– Semantics of a program is much easier to
understand if it has referential transparency
• Because they do not have variables,
programs in pure functional languages are
referentially transparent
– Functions cannot have state, which would be
stored in local variables
– If a function uses an outside value, it must be a
constant (there are no variables). So, the value
of a function depends only on its parameters
Copyright © 2018 Pearson. All rights reserved. 1-15
Overloaded Operators

• Use of an operator for more than one


purpose is called operator overloading
• Some are common (e.g., + for int and
float)
• Some are potential trouble (e.g., * in C and
C++)
– Loss of compiler error detection (omission of an
operand should be a detectable error)
– Some loss of readability

Copyright © 2018 Pearson. All rights reserved. 1-16


Overloaded Operators (continued)

• C++, C#, and F# allow user-defined


overloaded operators
– When sensibly used, such operators can be an
aid to readability (avoid method calls,
expressions appear natural)
– Potential problems:
• Users can define nonsense operations
• Readability may suffer, even when the operators
make sense

Copyright © 2018 Pearson. All rights reserved. 1-17


Type Conversions

• A narrowing conversion is one that converts


an object to a type that cannot include all
of the values of the original type e.g., float
to int
• A widening conversion is one in which an
object is converted to a type that can
include at least approximations to all of the
values of the original type
e.g., int to float

Copyright © 2018 Pearson. All rights reserved. 1-18


Type Conversions: Mixed Mode
• A mixed-mode expression is one that has
operands of different types
• A coercion is an implicit type conversion
• Disadvantage of coercions:
– They decrease in the type error detection ability of the
compiler
• In most languages, all numeric types are coerced
in expressions, using widening conversions
• In ML and F#, there are no coercions in
expressions

Copyright © 2018 Pearson. All rights reserved. 1-19


Explicit Type Conversions

• Called casting in C-based languages


• Examples
– C: (int)angle
– F#: float(sum)

Note that F#’s syntax is similar to that of


function calls

Copyright © 2018 Pearson. All rights reserved. 1-20


Errors in Expressions

• Causes
– Inherent limitations of arithmetic
e.g., division by zero
– Limitations of computer arithmetic
e.g. overflow
• Often ignored by the run-time system

Copyright © 2018 Pearson. All rights reserved. 1-21


Relational and Boolean Expressions
• Relational Expressions
– Use relational operators and operands of
various types
– Evaluate to some Boolean representation
– Operator symbols used vary somewhat among
languages (!=, /=, ~=, .NE., <>, #)
• JavaScript and PHP have two additional
relational operator, === and !==
- Similar to their cousins, == and !=, except that
they do not coerce their operands
– Ruby uses == for equality relation operator that
uses coercions and eql? for those that do not
Copyright © 2018 Pearson. All rights reserved. 1-22
Relational and Boolean Expressions

• Boolean Expressions
– Operands are Boolean and the result is Boolean
– Example operators
• C89 has no Boolean type--it uses int type
with 0 for false and nonzero for true
• One odd characteristic of C’s expressions:
a < b < c is a legal expression, but the
result is not what you might expect:
– Left operator is evaluated, producing 0 or 1
– The evaluation result is then compared with the
third operand (i.e., c)
Copyright © 2018 Pearson. All rights reserved. 1-23
Short Circuit Evaluation

• An expression in which the result is


determined without evaluating all of the
operands and/or operators
• Example: (13 * a) * (b / 13 – 1)
If a is zero, there is no need to evaluate (b /13
- 1)
• Problem with non-short-circuit evaluation
index = 0;
while (index <= length) && (LIST[index] != value)
index++;
– When index=length, LIST[index] will cause an
indexing problem (assuming LIST is length - 1 long)

Copyright © 2018 Pearson. All rights reserved. 1-24


Short Circuit Evaluation (continued)

• C, C++, and Java: use short-circuit evaluation for


the usual Boolean operators (&& and ||), but also
provide bitwise Boolean operators that are not
short circuit (& and |)
• All logic operators in Ruby, Perl, ML, F#, and
Python are short-circuit evaluated
• Short-circuit evaluation exposes the potential
problem of side effects in expressions
e.g. (a > b) || (b++ / 3)

Copyright © 2018 Pearson. All rights reserved. 1-25


Assignment Statements

• The general syntax


<target_var> <assign_operator> <expression>
• The assignment operator
= Fortran, BASIC, the C-based languages
:= Ada
• = can be bad when it is overloaded for the
relational operator for equality (that’s why
the C-based languages use == as the
relational operator)

Copyright © 2018 Pearson. All rights reserved. 1-26


Assignment Statements: Conditional
Targets
• Conditional targets (Perl)
($flag ? $total : $subtotal) = 0

Which is equivalent to

if ($flag){
$total = 0
} else {
$subtotal = 0
}

Copyright © 2018 Pearson. All rights reserved. 1-27


Assignment Statements: Compound
Assignment Operators
• A shorthand method of specifying a
commonly needed form of assignment
• Introduced in ALGOL; adopted by C and the
C-based languaes
– Example

a = a + b

can be written as

a += b

Copyright © 2018 Pearson. All rights reserved. 1-28


Assignment Statements: Unary
Assignment Operators
• Unary assignment operators in C-based
languages combine increment and
decrement operations with assignment
• Examples
sum = ++count (count incremented, then assigned
to sum)
sum = count++ (count assigned to sum, then
incremented
count++ (count incremented)
-count++ (count incremented then negated)

Copyright © 2018 Pearson. All rights reserved. 1-29


Assignment as an Expression
• In the C-based languages, Perl, and
JavaScript, the assignment statement
produces a result and can be used as an
operand
while ((ch = getchar())!= EOF){…}

ch = getchar() is carried out; the result


(assigned to ch) is used as a conditional
value for the while statement
• Disadvantage: another kind of expression
side effect

Copyright © 2018 Pearson. All rights reserved. 1-30


Multiple Assignments

• Perl and Ruby allow multiple-target


multiple-source assignments
($first, $second, $third) = (20, 30, 40);

Also, the following is legal and performs an interchange:


($first, $second) = ($second, $first);

Copyright © 2018 Pearson. All rights reserved. 1-31


Assignment in Functional Languages

• Identifiers in functional languages are only


names of values
• ML
– Names are bound to values with val
val fruit = apples + oranges;
- If another val for fruit follows, it is a new and
different name
• F#
– F#’s let is like ML’s val, except let also creates
a new scope

Copyright © 2018 Pearson. All rights reserved. 1-32


Mixed-Mode Assignment
• Assignment statements can also be
mixed-mode
• In Fortran, C, Perl, and C++, any numeric
type value can be assigned to any
numeric type variable
• In Java and C#, only widening assignment
coercions are done
• In Ada, there is no assignment coercion

Copyright © 2018 Pearson. All rights reserved. 1-33


Summary

• Expressions
• Operator precedence and associativity
• Operator overloading
• Mixed-type expressions
• Various forms of assignment

Copyright © 2018 Pearson. All rights reserved. 1-34


Chapter 8

Statement-Level
Control Structures

ISBN 0-321-49362-1
Chapter 8 Topics

• Introduction
• Selection Statements
• Iterative Statements
• Unconditional Branching
• Guarded Commands
• Conclusions

Copyright © 2018 Pearson. All rights reserved. 1-2


Levels of Control Flow

– Within expressions (Chapter 7)


– Among program units (Chapter 9)
– Among program statements (this chapter)

Copyright © 2018 Pearson. All rights reserved. 1-3


Control Statements: Evolution

• FORTRAN I control statements were based


directly on IBM 704 hardware
• Much research and argument in the 1960s
about the issue
– One important result: It was proven that all
algorithms represented by flowcharts can be
coded with only two-way selection and pretest
logical loops

Copyright © 2018 Pearson. All rights reserved. 1-4


Control Structure

• A control structure is a control statement


and the statements whose execution it
controls
• Design question
– Should a control structure have multiple entries?

Copyright © 2018 Pearson. All rights reserved. 1-5


Selection Statements

• A selection statement provides the means


of choosing between two or more paths of
execution
• Two general categories:
– Two-way selectors
– Multiple-way selectors

Copyright © 2018 Pearson. All rights reserved. 1-6


Two-Way Selection Statements

• General form: C++


if (x > 10) {
if control_expression cout << "x is greater than 10";
then clause } else {
else clause cout << "x is less than or equal to 10";
}
• Design Issues:
– What is the form and type of the control
expression?
– How are the then and else clauses specified?
– How should the meaning of nested selectors be
specified?

Copyright © 2018 Pearson. All rights reserved. 1-7


The Control Expression

• If the then reserved word or some other


syntactic marker is not used to introduce
the then clause, the control expression is
placed in parentheses
• In C89, C99, Python, and C++, the control
expression can be arithmetic
• In most other languages, the control
expression must be Boolean

Copyright © 2018 Pearson. All rights reserved. 1-8


Clause Form

• In many contemporary languages, the then and


else clauses can be single statements or compound
statements
• In Perl, all clauses must be delimited by braces
(they must be compound)
• In Python and Ruby, clauses are statement
sequences
• Python uses indentation to define clauses
if x > y :
x = y
print " x was greater than y"

Copyright © 2018 Pearson. All rights reserved. 1-9


Nesting Selectors

• Java example int x = 10;

if (sum == 0) if (x > 5) {
if (count == 0) System.out.println("x is greater
result = 0; than 5");
}
else result = 1;
• Which if gets the else?
• Java's static semantics rule: else matches
with the nearest previous if

Copyright © 2018 Pearson. All rights reserved. 1-10


Nesting Selectors (continued)

• To force an alternative semantics,


compound statements may be used:
if (sum == 0) { if (sum == 0) {
if (count == 0) if (count == 0) {
result = 0;
result = 0; }
} } else {
else result = 1; result = 1;
}

• The above solution is used in C, C++, and C#

Copyright © 2018 Pearson. All rights reserved. 1-11


Nesting Selectors (continued)

• Statement sequences as clauses: Ruby


if sum == 0 then
if count == 0 then
result = 0
else
result = 1
end
end

Copyright © 2018 Pearson. All rights reserved. 1-12


Nesting Selectors (continued)

• Python
if sum == 0:
if sum == 0 : if count == 0:
result = 0
if count == 0 : elif count > 0:
result = 1
result = 0
else:
else : # Code to execute if sum is not 0

result = 1

Copyright © 2018 Pearson. All rights reserved. 1-13


Selector Expressions

• In ML, F#, and Lisp, the selector is an


expression; in F#:
let y =
if x > 0 then x
else 2 * x

- If the if expression returns a value, there must


be an else clause (the expression could produce
a unit type, which has no value). The types of
the values returned by then and else clauses
must be the same.

Copyright © 2018 Pearson. All rights reserved. 1-14


Multiple-Way Selection Statements

• Allow the selection of one of any number of


statements or statement groups
• Design Issues:
1. What is the form and type of the control expression?
2. How are the selectable segments specified?
3. Is execution flow through the structure restricted to
include just a single selectable segment?
4. How are case values specified?
5. What is done about unrepresented expression values?

Copyright © 2018 Pearson. All rights reserved. 1-15


Multiple-Way Selection: Examples

• C, C++, Java, and JavaScript


switch (expression) {
case const_expr1: stmt1;
ay");

case const_exprn: stmtn;
ay"); [default: stmtn+1]
}
esday");

d day");

Copyright © 2018 Pearson. All rights reserved. 1-16


Multiple-Way Selection: Examples

• Design choices for C’s switch statement


1. Control expression can be only an integer type
2. Selectable segments can be statement sequences,
blocks, or compound statements
3. Any number of segments can be executed in one
execution of the construct (there is no implicit
branch at the end of selectable segments)
4. default clause is for unrepresented values (if
there is no default, the whole statement does
nothing)

Copyright © 2018 Pearson. All rights reserved. 1-17


Multiple-Way Selection: Examples

• C#
– Differs from C in that it has a static semantics
rule that disallows the implicit execution of
more than one segment

– Each selectable segment must end with an


unconditional branch (goto or break)

– Also, in C# the control expression and the case


constants can be strings

Copyright © 2018 Pearson. All rights reserved. 1-18


Multiple-Way Selection: Examples

• Ruby has two forms of case statements-we’ll cover


only one
leap = case
when year % 400 == 0 then true
when year % 100 == 0 then false
else year % 4 == 0
end

Copyright © 2018 Pearson. All rights reserved. 1-19


Implementing Multiple Selectors

• Approaches:
– Multiple conditional branches
– Store case values in a table and use a linear
search of the table
– When there are more than ten cases, a hash
table of case values can be used
– If the number of cases is small and more than
half of the whole range of case values are
represented, an array whose indices are the case
values and whose values are the case labels can
be used

Copyright © 2018 Pearson. All rights reserved. 1-20


Multiple-Way Selection Using if
• Multiple Selectors can appear as direct
extensions to two-way selectors, using
else-if clauses, for example in Python:
if count < 10 :
bag1 = True
elif count < 100 :
bag2 = True
elif count < 1000 :
bag3 = True

Copyright © 2018 Pearson. All rights reserved. 1-21


Multiple-Way Selection Using if

• The Python example can be written as a


Ruby case
case
when count < 10 then bag1 = true
when count < 100 then bag2 = true
when count < 1000 then bag3 = true
end

Copyright © 2018 Pearson. All rights reserved. 1-22


Scheme’s Multiple Selector
• General form of a call to COND:

(COND (define x 5)
(predicate1 expression1)
… (cond
((= x 10) "x is 10")
(predicaten expressionn) ((> x 5) "x is greater than 5")
[(ELSE expressionn+1)] (else "x is less than or equal to 5"))
)
- The ELSE clause is optional; ELSE is a synonym
for true
- Each predicate-expression pair is a parameter
- Semantics: The value of the evaluation of COND is
the value of the expression associated with the
first predicate expression that is true
Copyright © 2018 Pearson. All rights reserved. 1-23
Iterative Statements

op) • The repeated execution of a statement or


compound statement is accomplished
either by iteration or recursion
er

• General design issues for iteration control


statements:
1. How is iteration controlled?
2. Where is the control mechanism in the loop?

Copyright © 2018 Pearson. All rights reserved. 1-24


Counter-Controlled Loops
• A counting iterative statement has a loop
variable, and a means of specifying the
initial and terminal, and stepsize values
• Design Issues:
1. What are the type and scope of the loop variable?
2. Should it be legal for the loop variable or loop
parameters to be changed in the loop body, and if so,
does the change affect loop control?
3. Should the loop parameters be evaluated only once, or
once for every iteration?
4. What is the value of the loop variable after loop
termination?

Copyright © 2018 Pearson. All rights reserved. 1-25


Counter-Controlled Loops: Examples

• C-based languages
for ([expr_1] ; [expr_2] ; [expr_3]) statement
- The expressions can be whole statements, or even
statement sequences, with the statements separated by
commas
– The value of a multiple-statement expression is the value of the
last statement in the expression
– If the second expression is absent, it is an infinite loop
• Design choices:
- There is no explicit loop variable
- Everything can be changed in the loop
- The first expression is evaluated once, but the other two
are evaluated with each iteration
- It is legal to branch into the body of a for loop in C

Copyright © 2018 Pearson. All rights reserved. 1-26


Counter-Controlled Loops: Examples

• C++ differs from C in two ways:


1. The control expression can also be Boolean
2. The initial expression can include variable
definitions (scope is from the definition to the
end of the loop body)
• Java and C#
– Differs from C++ in that the control
expression must be Boolean

Copyright © 2018 Pearson. All rights reserved. 1-27


Counter-Controlled Loops: Examples
• Python
for loop_variable in object:
- loop body
[else:
- else clause]

– The object is often a range, which is either a list of values in


brackets ([2, 4, 6]), or a call to the range function, as in
range(5), which returns 0, 1, 2, 3, 4

– The loop variable takes on the values specified in the given


range, one for each iteration

– At loop termination, the loop variable has the last value that was
assigned to it

– The else clause, which is optional, is executed if the loop


terminates normally

Copyright © 2018 Pearson. All rights reserved. 1-28


Counter-Controlled Loops: Examples

• F#
– Because counters require variables, and functional
languages do not have variables, counter-controlled
loops must be simulated with recursive functions
let rec forLoop loopBody reps =
if reps <= 0 then ()
else
loopBody()
forLoop loopBody, (reps – 1)
- This defines the recursive function forLoop with the
parameters loopBody (a function that defines the
loop’s body) and the number of repetitions
- () means do nothing and return nothing
Copyright © 2018 Pearson. All rights reserved. 1-29
Logically-Controlled Loops

• Repetition control is based on a Boolean


expression
• Design issues:
– Pretest or posttest?
– Should the logically controlled loop be a
special case of the counting loop statement or
a separate statement?

Copyright © 2018 Pearson. All rights reserved. 1-30


Logically-Controlled Loops: Examples

• C and C++ have both pretest and posttest forms, in


which the control expression can be arithmetic:
while (control_expr) do
loop body loop body
while (control_expr)
- In both C and C++ it is legal to branch into the body
of a logically-controlled loop

• Java is like C and C++, except the control


expression must be Boolean (and the body can only
be entered at the beginning -- Java has no goto

Copyright © 2018 Pearson. All rights reserved. 1-31


Logically-Controlled Loops: Examples

• F#
– As with counter-controlled loops, logically-
controlled loops can be simulated with recursive
functions
let rec whileLoop test body =
if test() then
body()
whileLoop test body
else ()

- This defines the recursive function whileLoop


with parameters test and body, both functions.
test defines the control expression
Copyright © 2018 Pearson. All rights reserved. 1-32
User-Located Loop Control Mechanisms

• Sometimes it is convenient for the


programmers to decide a location for loop
control (other than top or bottom of the
loop)
• Simple design for single loops (e.g., break)
• Design issues for nested loops
1. Should the conditional be part of the exit?
2. Should control be transferable out of more
than one loop?

Copyright © 2018 Pearson. All rights reserved. 1-33


User-Located Loop Control Mechanisms

• C , C++, Python, Ruby, and C# have


unconditional unlabeled exits (break)
• Java and Perl have unconditional labeled
exits (break in Java, last in Perl)
• C, C++, and Python have an unlabeled
control statement, continue, that skips the
remainder of the current iteration, but does
not exit the loop
• Java and Perl have labeled versions of
continue

Copyright © 2018 Pearson. All rights reserved. 1-34


Iteration Based on Data Structures

• The number of elements in a data structure


controls loop iteration
• Control mechanism is a call to an iterator
function that returns the next element in
some chosen order, if there is one; else
loop is terminate
• C's for can be used to build a user-defined
iterator:
for (p=root; p==NULL; traverse(p)){
...
}

Copyright © 2018 Pearson. All rights reserved. 1-35


Iteration Based on Data Structures (continued)

• PHP
- current points at one element of the array
- next moves current to the next element
- reset moves current to the first element

• Java 5.0 (uses for, although it is called


foreach)
For arrays and any other class that implements the
Iterable interface, e.g., ArrayList

for (String myElement : myList) { … }

Copyright © 2018 Pearson. All rights reserved. 1-36


Iteration Based on Data Structures (continued)

• C# and F# (and the other .NET languages) have


generic library classes, like Java 5.0 (for arrays,
lists, stacks, and queues). Can iterate over
these with the foreach statement. User-defined
collections can implement the IEnumerator
interface and also use foreach.
List<String> names = new List<String>();
names.Add("Bob");
names.Add("Carol");
names.Add("Ted");
foreach (Strings name in names)
Console.WriteLine ("Name: {0}", name);

Copyright © 2018 Pearson. All rights reserved. 1-37


Iteration Based on Data Structures (continued)

• Ruby blocks are sequences of code, delimited by


either braces or do and end
– Blocks can be used with methods to create iterators
– Predefined iterator methods (times, each, upto):
3.times {puts ″Hey!″}
list.each {|value| puts value}
(list is an array; value is a block parameter)
1.upto(5) {|x| print x, ″ ″}
Iterators are implemented with blocks, which can
also be defined by applications

Copyright © 2018 Pearson. All rights reserved. 1-38


Iteration Based on Data Structures (continued)

• Ruby blocks are attached methods calls; they can have


parameters (in vertical bars); they are executed when the
method executes a yield statement
def fibonacci(last)
first, second = 1, 1
while first <= last
yield first
first, second = second, first + second
end
end
puts "Fibonacci numbers less than 100 are:"
fibonacci(100) {|num| print num, " "}
puts

- Ruby has a for statement, but Ruby converts them to upto


method calls

Copyright © 2018 Pearson. All rights reserved. 1-39


Python’s yield statement

Suppose we have a function, traverse, that produces the


nodes of a data structure

def traverse(self):
yield nod

- Every time traverse is called, it returns the next node of


the structure on which it is called - yield is like a return

- The presence of the yield statement in the traverse


function completely changes its semantics – it is run in its
own thread of control. In all but the first call, the call is
actually like a resume – it starts in the state it was in at the
end of its last execution. It is history sensitive.

Copyright © 2018 Pearson. All rights reserved. 1-40


Unconditional Branching

• Transfers execution control to a specified place in


the program
• Represented one of the most heated debates in
1960’s and 1970’s
• Major concern: Readability
• Some languages do not support goto statement
(e.g., Java)
• C# offers goto statement (can be used in switch
statements)
• Loop exit statements are restricted and somewhat
camouflaged goto’s

Copyright © 2018 Pearson. All rights reserved. 1-41


Guarded Commands

• Designed by Dijkstra
• Purpose: to support a new programming
methodology that supported verification
(correctness) during development
• Basis for two linguistic mechanisms for
concurrent programming (in CSP)
• Basic Idea: if the order of evaluation is not
important, the program should not specify
one

Copyright © 2018 Pearson. All rights reserved. 1-42


Selection Guarded Command

• Form
if <Boolean expr> -> <statement>
[] <Boolean expr> -> <statement>
...
[] <Boolean expr> -> <statement>
fi
• Semantics: when construct is reached,
– Evaluate all Boolean expressions
– If more than one are true, choose one non-
deterministically
– If none are true, it is a runtime error

Copyright © 2018 Pearson. All rights reserved. 1-43


Loop Guarded Command

• Form
do <Boolean> -> <statement>
[] <Boolean> -> <statement>
...
[] <Boolean> -> <statement>
od
• Semantics: for each iteration
– Evaluate all Boolean expressions
– If more than one are true, choose one non-
deterministically; then start loop again
– If none are true, exit loop

Copyright © 2018 Pearson. All rights reserved. 1-44


Guarded Commands: Rationale

• Connection between control statements


and program verification is intimate
• Verification is impossible with goto
statements
• Verification is possible with only selection
and logical pretest loops
• Verification is relatively simple with only
guarded commands

Copyright © 2018 Pearson. All rights reserved. 1-45


Conclusions

• Variety of statement-level structures


• Choice of control statements beyond
selection and logical pretest loops is a
trade-off between language size and
writability
• Functional and logic programming
languages use quite different control
structures

Copyright © 2018 Pearson. All rights reserved. 1-46

You might also like