CS 315 Programming Languages Subprograms

Similar documents
Examples for Programming Language Features

Chapter 9 Subprograms

Chapter 9. Subprograms

COP4020 Programming Languages. Subroutines and Parameter Passing Prof. Robert van Engelen

Organization of Programming Languages CS 3200/5200N. Lecture 09

Design Issues. Subroutines and Control Abstraction. Subroutines and Control Abstraction. CSC 4101: Programming Languages 1. Textbook, Chapter 8

CMSC 4023 Chapter 9. Fundamentals of Subprograms Introduction

Agenda. The main body and cout. Fundamental data types. Declarations and definitions. Control structures

Principles of Programming Languages

Subprogram Concept. COMP3220 Principle of Programming Languages. Zhitao Gong Spring

Names, Bindings, Scopes

Chapter 9. Subprograms

Subprograms. Copyright 2015 Pearson. All rights reserved. 1-1

G Programming Languages - Fall 2012

Lab Instructor : Jean Lai

Short Notes of CS201

Objects Managing a Resource

COEN244: Class & function templates

CS201 - Introduction to Programming Glossary By

IA010: Principles of Programming Languages

Subroutines. Subroutine. Subroutine design. Control abstraction. If a subroutine does not fit on the screen, it is too long

Chapter 8 ( ) Control Abstraction. Subprograms Issues related to subprograms How is control transferred to & from the subprogram?

Weeks 6&7: Procedures and Parameter Passing

G Programming Languages Spring 2010 Lecture 4. Robert Grimm, New York University

UNIT V Sub u P b ro r g o r g a r m a s

Subprograms. Bilkent University. CS315 Programming Languages Pinar Duygulu

calling a function - function-name(argument list); y = square ( z ); include parentheses even if parameter list is empty!

CS 31 Discussion 1A, Week 4. Zengwen Yuan (zyuan [at] cs.ucla.edu) Humanities A65, Friday 10:00 11:50 a.m.

1 Lexical Considerations

Lecture 3: C Programm

Chapter 5. Names, Bindings, and Scopes

CHAPTER 4 FUNCTIONS. 4.1 Introduction

Principles of Programming Languages Topic: Scope and Memory Professor Louis Steinberg Fall 2004

Object-Oriented Programming for Scientific Computing

10. Functions (Part 2)

PROCEDURES, METHODS AND FUNCTIONS

CS201 Some Important Definitions

Lecture 4 Memory Management

CS558 Programming Languages Winter 2018 Lecture 4a. Andrew Tolmach Portland State University

Ruby: Introduction, Basics

Scope, Functions, and Storage Management

CS558 Programming Languages

Programming Languages: Lecture 11

Lexical Considerations

Binding and Variables

Chapter 9 Subprograms

Chapter 10. Implementing Subprograms

COMP322 - Introduction to C++ Lecture 02 - Basics of C++

Introducing C++ to Java Programmers

CS558 Programming Languages

Lexical Considerations

Functions and Recursion

Type Aliases. Examples: using newtype = existingtype; // C++11 typedef existingtype newtype; // equivalent, still works

Lecture 2: C Programm

Module 27 Switch-case statements and Run-time storage management

C The new standard

Execution order. main()

Note 12/1/ Review of Inheritance Practice: Please write down 10 most important facts you know about inheritance...

CS3157: Advanced Programming. Outline

Separate Compilation Model

1. Describe History of C++? 2. What is Dev. C++? 3. Why Use Dev. C++ instead of C++ DOS IDE?

Functions - Lecture 7. Nested functions. Another example. A Nested Function. Josef Svenningsson

Bruce Merry. IOI Training Dec 2013

Ruby: Introduction, Basics

CS240: Programming in C

Lecture 9: Parameter Passing, Generics and Polymorphism, Exceptions

Lecture 5: Methods CS2301

CS558 Programming Languages

Chapter 9. Def: The subprogram call and return operations of a language are together called its subprogram linkage

CS1622. Semantic Analysis. The Compiler So Far. Lecture 15 Semantic Analysis. How to build symbol tables How to use them to find

CS 330 Lecture 18. Symbol table. C scope rules. Declarations. Chapter 5 Louden Outline

Problem Solving with C++

public class Foo { private int var; public int Method1() { // var accessible anywhere here } public int MethodN() {

An introduction to C++ template programming

Functions CHAPTER 5. FIGURE 1. Concrete syntax for the P 2 subset of Python. (In addition to that of P 1.)

Chapter 11. Abstract Data Types and Encapsulation Concepts ISBN

EECS402 Lecture 02. Functions. Function Prototype

Functions CHAPTER 5. FIGURE 1. Concrete syntax for the P 2 subset of Python. (In addition to that of P 1.)

Programming Languages Third Edition. Chapter 10 Control II Procedures and Environments

Absolute C++ Walter Savitch

\n is used in a string to indicate the newline character. An expression produces data. The simplest expression

CS558 Programming Languages

QUIZ. 1. Explain the meaning of the angle brackets in the declaration of v below:

Pointers and Arrays CS 201. This slide set covers pointers and arrays in C++. You should read Chapter 8 from your Deitel & Deitel book.

Design issues for objectoriented. languages. Objects-only "pure" language vs mixed. Are subclasses subtypes of the superclass?

ENVIRONMENT MODEL: FUNCTIONS, DATA 18

Administration CS 412/413. Advanced Language Support. First-class vs. Second-class. First-class functions. Function Types

CS 345. Functions. Vitaly Shmatikov. slide 1

G Programming Languages - Fall 2012

15 FUNCTIONS IN C 15.1 INTRODUCTION

Chapter 10. Implementing Subprograms ISBN

Names, Scopes, and Bindings. CSE 307 Principles of Programming Languages Stony Brook University

Introduction to C++ Systems Programming

A Fast Review of C Essentials Part II

C++11: 10 Features You Should be Using. Gordon R&D Runtime Engineer Codeplay Software Ltd.

CS102 Software Engineering Principles

Programming Abstractions

Chapter 2. Procedural Programming

Every language has its own scoping rules. For example, what is the scope of variable j in this Java program?

The Notion of a Class and Some Other Key Ideas (contd.) Questions:

Transcription:

CS 315 Programming Languages Subprograms Subprograms Definition header: name, parameters (formals), return type body: code E.g.: int triple (int x) return 3 * x; Call name, parameters (actuals) E.g.: triple(3) Design issues about subprograms Parameter passing semantics/syntax (already discussed) Functions as arguments/return types Nested function definitions Closures: nested functions that reference variables form the enclosing function scope Generic subprograms Co-routines Parameters Positional order matters (one-to-one mapping of actuals to formals) optional parameters appear at the end Keyword-based order does not matter when mixed, keyword-based parameters appear after positional ones Variable number of parameters E.g.: Python is very powerful in terms of parameter passing Positional def sum(x, y, z): return x + y + z u = sum(a, b, c) Positional with defaults def sum(x, y, z=3): return x + y + z u = sum(a, b) u = sum(a, b, c) Keyword-based def sum(x, y, z=3): return x + y + z

u = sum(y=a, x=b) u = sum(y=a, z=c, x=b) Variable number of args def sum(x, y, *z): s = x + y for e in z: s = s + e return s u = sum(a, b) u = sum(a, b, c, 3, 5) def sum(x, y, **z): s = x + y for k, e in z.iteritems(): s = s + e return s u = sum(a, b) u = sum(a, b, i=3, j=5, k=6) u = sum(x=a, y=b, i=3, j=5, k=6) def sum(x, y, *z, **w): s = x + y for e in z: s = s + e for k, e in w.iteritems(): s = s + e return s u = sum(a, b) u = sum(a, b, c, d, i=3, j=5, k=6) # Python also supports unpacking via * v = [3, 5, 6] u = sum(*v) # equivalent to u = sum(3, 5, 6) v = 'i': 3, 'j': 5, 'k': 6 u = sum(**v) # equivalent to u = sum(i=3, j=5, k=6) Models of parameter passing Semantics in mode actuals are copied into formals during the initiation of the call out mode formals are copied into actuals during the return of the call inout mode actuals are copied into formals during the initiation of the call and formals are copied into actuals during the return of the call Common implementations pass-by-value: in-mode pass-by-result: out-mode pass-by-value-result: in-out mode pass-by-reference: a variation of in-out mode where there is no copy, but the formal references the actual, which means they are aliases (when one changes the other does too)

E.g.: C++ void foo(int x, int * y, int & z) int a, b, c; foo (a, &b, c); // first parameter is passed by value // second parameter, which is a pointer, is also passed by value // but it can be used to implement inout semantics for b // third parameter is passed by reference void swap1(int a, int b) int tmp = a; a = b; b = tmp; swap1(c, d); // does not swap void swap3(int& a, int& b) int tmp = a; a = b; b = tmp; swap3(c, d); void swap2(int* a, int* b) int tmp = *a; *a = *b; *b = tmp; swap2(&c, &d); Q: When does pass-by-value-result and pass-by-reference give different results? Assume inout specifies pass-by-value-result and ref specifies pass-by-reference. void foo(inout int a, inout int b) a++; b++; x = 2; foo(x, x); // x is 3 void foo(ref int a, ref int b) a++; b++; x = 2; foo(x, x); // x is 4 Pass-by-reference has performance advantages as it does not need to copy data. However, it results in creation of aliases (as in the above example), which might be hard to manage sometimes.

Passing functions as parameters For dynamic languages, this is easy / no type checking at compile-time. E.g.: Python def map(op, items): res = [] for item in items: res.append(op(item)) return res def square(x): return x * x print map(square, [1, 2, 3]) # [1, 4, 9] triple = lambda x : 3*x print map(triple, [1, 2, 3]) # [3, 6, 9] For languages like C/C++ you need type checking. E.g.: C++ int square (int x) return x * x; vector<int> map(int (*op)(int a), vector<int> const & list) vector<int> res; for (int val : list) res.push_back((*op)(val)); return res; vector<int> list = 1, 2, 3, 4; vector<int> res = map(&square, list);

Closures Subprograms together with their referencing environment, including variables referenced from the enclosing scope. Example: Python: def make_adder(x): def adder(y): return x + y # here x is from make_adder return adder adder = make_adder(3) print adder(5) # 8 C++: function<int(int)> make_adder(int x) auto adder = [=] (int y) return x + y; ; return adder; auto adder = make_adder(3); cout << adder(5); // 8 Java: Function<Integer, Integer> make_adder(integer x) Function<Integer,Integer> adder = new Function<Integer,Integer>() @Override public Integer apply(integer y) return x + y; ; return adder; Function<Integer, Integer> add3 = make_adder(3); System.out.println(add3.apply(5)); // 8 It is important to note that the variables used within the closure may be from the referencing environment, in which case, such variables may be changed elsewhere, impacting the closure. def make_appender(post_list): def appender(pre_list): pre_list.extend(post_list) return appender X = [4, 5] Y = [1, 2] Z = [1, 2] appender = make_appender(x) appender(y) print Y # [1, 2, 4, 5] X.insert(0, 3) # insert 3 to front appender(z) print Z # [1, 2, 3, 4, 5] # Question: What if I replace # X.insert(0, 3) with X = [3, 4, 5] import copy def make_appender(post_list): pl_copy = copy.deepcopy(post_list) def appender(pre_list): pre_list.extend(pl_copy) return appender X = [4, 5] Y = [1, 2] Z = [1, 2] appender = make_appender(x) appender(y) print Y # [1, 2, 4, 5] X.insert(0, 3) # insert 3 to front appender(z) print Z # [1, 2, 4, 5]

# Answer: Z would be [1, 2, 4, 5] We can also modify the variable that comes from the enclosing function form within the closure. E.g.: def make_counter(): next_value = 0 def return_next_value(): value = next_value make_counter.next_value = val + 1 # Python 2.0 requires fully qualifying nonlocal variables # that are being mutated (thus the make_counter.) return value return return_next_value c1 = make_counter() c2 = make_counter() print c1() # 0 print c1() # 1 print c1() # 2 print c2() # 0 print c2() # 1 In C++, one needs to be careful about such local variables (which are on the stack and go out of the scope after the function returns): #include <functional> using namespace std; function<int (void)> make_counter() int next_value = 0; auto return_next_value = [&] () // [&] captures by reference int value = next_value; next_value++; return value; ; return return_next_value; auto c1 = make_counter(); auto c2 = make_counter(); c1(); c1(); c1(); c2(); c2(); The above program is buggy. The reason is that, next_value is stored on the stack. When the function returns, the value is gone (its lifetime is over). To fix this, we need to use heap allocation. function<int (void)> make_counter() shared_ptr<int> next_value = new int(0); auto return_next_value = [=] () // [=] captures by value // that is, pointer is copied int value = *next_value; (*next_value)++; return value; return return_next_value;

Generic sub-programs Ability to write subprograms that work with more than one type. C++ template <class T> T max(t first, T second) return first > second? first : second; What to do without templates? C has macros: #define max(a, b) (((a)>(b))?(a):(b)) Why do we have so many parentheses? Because macros use text substitution and if a and b above are expressions, they may mess up the operator precedence. Still, macros are not safe. E.g.: Consider max(x++, y), which translates into (((x++)>(y))?(x++):(y)) In some cases, this would result in incrementing x twice. Java class name <T> <T> return_type metod_name(...)... A few important differences: type parameters must be classes, not primitive types Java uses a single method/class via type erasure (ArrayList<Integer> and ArrayList<Float> are the same type at run-time (ArrayList<Object>), but in C++ these would be different types) Java supports restrictions public static <T> T max(t[] list) public static <T extens Comparable<T>> T max(t[] list) Wildcards: public void drawall(arraylist<? extends Shape> things) public <T extends Shape> void drawall(arraylist<t> things) The second alternative is more powerful (can enforce same or different types): public bool compare(list<?> a, List<?> b) public <T1, T2> bool compare(list<t1> a, List<T2> b) public <T> bool compare(list<t> a, List<T> b)

Co-routines Co-routines are multi-entry, multi-exit functions. A specialized form of co-routines that is more popular is called generators. E.g.: Python supports generators. Consider the problem of printing all 2 combinations for numbers in the range [0, n): # printing 2 combinations def print2combs(n): for i in xrange(0, n): for j in xrange(i+1, n): print (i,j) print2combs(5) print Consider a similar problem, where the goal is to iterate, rather than print. class CombIter: def init (self, n): self.n = n def next(self): self.j = self.j + 1 if (self.j==self.n): self.i = self.i + 1 self.j = self.i + 1 if (self.i==self.n-1): raise StopIteration return (self.i, self.j) def iter (self): self.i = 0 self.j = 0 return self for p in CombIter(5): print p # or do whatever you want to do with p There is a much easier way of doing this with generators: def gen2combs(n): for i in xrange(0, n): for j in xrange(i+1, n): yield (i,j) for p in gen2combs(5): print p # or do whatever you want to do with p The yield statement results in returning a value, but the next time the function is called, it continues from the exact place where it yielded.