Control Structures. Christopher Simpkins CS 3693, Fall Chris Simpkins (Georgia Tech) CS 3693 Scala / 1

Similar documents
Functions, Closures and Control Abstraction

CS 2340 Objects and Design - Scala

CISC-124. Casting. // this would fail because we can t assign a double value to an int // variable

Notes from a Short Introductory Lecture on Scala (Based on Programming in Scala, 2nd Ed.)

G Programming Languages - Fall 2012

Introduction to Object-Oriented Programming

Introduction to Object-Oriented Programming

CS 3 Introduction to Software Engineering. 3: Exceptions

G Programming Languages - Fall 2012

Scala : an LLVM-targeted Scala compiler

Functional Objects. Christopher Simpkins CS 3693, Fall Chris Simpkins (Georgia Tech) CS 3693 Scala / 1

Ruby: Introduction, Basics

Control Structures. Lecture 4 COP 3014 Fall September 18, 2017

First Programming Language in CS Education The Arguments for Scala

Variables. Substitution

Chapter 7. - FORTRAN I control statements were based directly on IBM 704 hardware

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming

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

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

Programming Languages Third Edition. Chapter 9 Control I Expressions and Statements

Chapter 7 Control I Expressions and Statements

The story so far. Elements of Programming Languages. While-programs. Mutable vs. immutable

G Programming Languages - Fall 2012

Pace University. Fundamental Concepts of CS121 1

A Second Look At ML. Chapter Seven Modern Programming Languages, 2nd ed. 1

CS 4240: Compilers and Interpreters Project Phase 1: Scanner and Parser Due Date: October 4 th 2015 (11:59 pm) (via T-square)

Ruby: Introduction, Basics

CMSC 330: Organization of Programming Languages. OCaml Expressions and Functions

CPL 2016, week 10. Clojure functional core. Oleg Batrashev. April 11, Institute of Computer Science, Tartu, Estonia

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

Introduction to Functional Programming in Haskell 1 / 56

CS558 Programming Languages

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

Control Flow. COMS W1007 Introduction to Computer Science. Christopher Conway 3 June 2003

Ruby: Introduction, Basics

Intro. Scheme Basics. scm> 5 5. scm>

CS 360 Programming Languages Interpreters

Slide 1 CS 170 Java Programming 1 The Switch Duration: 00:00:46 Advance mode: Auto

CS558 Programming Languages

CS558 Programming Languages

The PCAT Programming Language Reference Manual

CS 61B Discussion 5: Inheritance II Fall 2014

Object-oriented programming. and data-structures CS/ENGRD 2110 SUMMER 2018

CS558 Programming Languages

Control Structures in Java if-else and switch

About this exam review

The SPL Programming Language Reference Manual

Control Structures. Outline. In Text: Chapter 8. Control structures Selection. Iteration. Gotos Guarded statements. One-way Two-way Multi-way

Using Scala in CS241

Functional Programming - 2. Higher Order Functions

Chapter 4: Making Decisions

CS558 Programming Languages

Chapter 2. Flow of Control. Copyright 2016 Pearson, Inc. All rights reserved.

Ordering Within Expressions. Control Flow. Side-effects. Side-effects. Order of Evaluation. Misbehaving Floating-Point Numbers.

Control Flow COMS W4115. Prof. Stephen A. Edwards Fall 2006 Columbia University Department of Computer Science

CS558 Programming Languages

Chapter 4: Making Decisions

CS 61B Data Structures and Programming Methodology. July 7, 2008 David Sun

CS1102: Macros and Recursion

CS Programming Languages: Scala

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming

Weiss Chapter 1 terminology (parenthesized numbers are page numbers)

SCHEME AND CALCULATOR 5b

COSE212: Programming Languages. Lecture 3 Functional Programming in OCaml

6.005 Elements of Software Construction

Agenda: Discussion Week 7. May 11, 2009

CS52 - Assignment 8. Due Friday 4/15 at 5:00pm.

CS 457/557: Functional Languages

CS422 - Programming Language Design

Functional Programming. Pure Functional Languages

These are notes for the third lecture; if statements and loops.

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

CSE 413 Languages & Implementation. Hal Perkins Winter 2019 Structs, Implementing Languages (credits: Dan Grossman, CSE 341)

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Functional programming

Programming with Math and Logic

CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion. Zach Tatlock Winter 2018

Scala, Your Next Programming Language

LECTURE 18. Control Flow

CS1 Lecture 22 Mar. 6, 2019

Functional Programming. Big Picture. Design of Programming Languages

Introduce C# as Object Oriented programming language. Explain, tokens,

SCHEME The Scheme Interpreter. 2 Primitives COMPUTER SCIENCE 61A. October 29th, 2012

8 Understanding Subtyping

Dialects of ML. CMSC 330: Organization of Programming Languages. Dialects of ML (cont.) Features of ML. Functional Languages. Features of ML (cont.

Decision Making in C

So what does studying PL buy me?

CS558 Programming Languages. Winter 2013 Lecture 3

4 Flow Control, Exceptions, and Assertions

LECTURE 04 MAKING DECISIONS

Lecture #23: Conversion and Type Inference

INF 212 ANALYSIS OF PROG. LANGS FUNCTION COMPOSITION. Instructors: Crista Lopes Copyright Instructors.

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

EECS 183. Week 3 - Diana Gage. www-personal.umich.edu/ ~drgage

Chapter 8. Statement-Level Control Structures

int foo() { x += 5; return x; } int a = foo() + x + foo(); Side-effects GCC sets a=25. int x = 0; int foo() { x += 5; return x; }

Lecture 2: SML Basics

Conversion vs. Subtyping. Lecture #23: Conversion and Type Inference. Integer Conversions. Conversions: Implicit vs. Explicit. Object x = "Hello";

Relation Overriding. Syntax and Semantics. Simple Semantic Domains. Operational Semantics

14. Exception Handling

Transcription:

Control Structures Christopher Simpkins csimpkin@spsu.edu CS 3693, Fall 2011 Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 1 / 1

Control Structures Scala has only four built-in control structures: if while for try Other control structures are defined in libraries using function literals more on that next time. Another example of how Scala scales elegantly. if, for, try return values, which means they are expressions Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 2 / 1

if Expressions Scala s if works just like if in other languages, except that it returns a value. Consider a typical imperative if: var port = 9999 if (!args.isempty) { port = args(0).toint } In Scala, the extra variable initialization is unnecessary: val port = if (!args.isempty) args(0).toint else 9999 Also, with initialization and selection combined, we can use a val instead of a var... Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 3 / 1

The value of val. A Rumination on Functional Style vals are referentially transparent, a property of functional programs which means you can reason about programs algebraically (as opposed to keeping a state machine in your head while you read an imperative program) you can safely substitute equivalent expressions So you could use the port variable like this if you need to use it later: val port = if (!args.isempty) args(0).toint else 9999 val sock = new Socket( 127.0.0.1, port)... or like this if you don t need the port after your socket is initialized: val sock = new Socket( 127.0.0.1, if (!args.isempty) args(0).toint else 9999) Socket happens to have a getport method. However, better to have extra val port =... line for readability. Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 4 / 1

while Loops Only built-in control structure that s not an expression Still has a result type: Unit, whiich is a type with a single value, the unit value, written () Works just like in imperative languages while (!world.isterminal(s)) { a = chooseaction(q, s) s1 = world.act(s, a) r = rewards(s1) Q((s,a)) = Q((s,a)) + alpha * (r + (gamma*max(q,s1)) - Q((s,a))); s = s1 } There s also a do-while, which performs its test after the loop body, meaning the loop body will execute at least one time do { something() } while (you == can) Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 5 / 1

for Expressions Extremely versatile. Here s the syntax from the Scala spec: Expr1 ::= for ( ( Enumerators ) { Enumerators } ) {nl} [ yield ] Expr Enumerators ::= Generator {semi Enumerator} Enumerator ::= Generator Guard val Pattern1 = Expr Generator ::= Pattern1 <- Expr [Guard] Guard ::= if PostfixExpr Here s a simpler way to think of it using EBNF: forexpr enumerator generator guard vardef scalavarid scalaexpr ::= for ( enumerator+ ) { body } [yield] resultexpr ::= generator ([guard] [vardef])* ::= scalavarid <- scalaseq ::= if booleanexpr ::= scalavarid = scalaexpr ::= <any valid Scala variable identifier> ::= <any valid Scala expression> Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 6 / 1

Basic for Expression Iterating through a collection: scala> val xs = List(1, 2, 3, 4, 5, 6) xs: List[Int] = List(1, 2, 3, 4, 5, 6) scala> for (x <- xs) print(math.pow(x, 2)+" ") 1.0 4.0 9.0 16.0 25.0 36.0 x <- xs is the generator (no guard or vardef in this example) A new iteration variable, x, is generated for each element of xs Body is executes xs.length times, each time with x bound to a new element of xs x not visible outside for expression scala> x <console>:8: error: not found: value x x ^ Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 7 / 1

Imperative-style Iteration Could use an imperative-like index variable if you wanted: scala> for (i <- 0 to 5) print(math.pow(xs(i), 2)+" ") 1.0 4.0 9.0 16.0 25.0 36.0... but that s not funcitonal style, and it s clearer to simply generate the sequence elements directly. Why bother thinking about off-by-one errors? scala> for (i <- 1 to xs.length) print(math.pow(xs(i), 2)+" ") 4.0 9.0 16.0 25.0 36.0 java.lang.indexoutofboundsexception: 6 at scala.collection.linearseqoptimized... (Did you notice the other off-by-one error?) Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 8 / 1

Filtering for Expression If we only want even numbers, we can filter them in with a guard expression scala> xs res10: List[Int] = List(1, 2, 3, 4, 5, 6) scala> for (x <- xs if x % 2 == 0) print (x+" ") 2 4 6 if x % 2 == 0 is a guard expression Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 9 / 1

Nested Iteration Multiple generators separated by ; produce nested iterations: scala> val xs = List( a, b, c) xs: List[Symbol] = List( a, b, c) scala> val ys = List(1, 2, 3) ys: List[Int] = List(1, 2, 3) scala> for (x <- xs; y <- ys) print((x,y)+" ") ( a,1) ( a,2) ( a,3) ( b,1) ( b,2) ( b,3) ( c,1) ( c,2) ( c,3) Which is shorthand for: scala> for (x <- xs) for (y <- ys) print((x,y)+" ") If you put the enumerator expressions in { } instead of ( ), you can put each clause on a separate line without using a semicolon. Parentheses turn off semicolon inference. Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 10 / 1

Mid-stream Variable Binding We can bind variables to save computation, for example: scala> val phoenetics = Map( a -> "alpha", b -> "bravo", c -> "charlie")... scala> for (x <- xs; xspell = phoenetics(x); y <- ys) print((xspell,y)+" ") (alpha,1) (alpha,2) (alpha,3) (bravo,1) (bravo,2) (bravo,3) (charlie,1) (charlie,2) (charlie,3) which is equivalent to: scala> for (x <- xs) { val xspell = phoenetics(x) for (y <- ys) print((xspell, y)+" ") } (alpha,1) (alpha,2) (alpha,3) (bravo,1) (bravo,2) (bravo,3) (charlie,1) (charlie,2) (charlie,3) Notice we had to use { } to define the loop body of the outer for expression Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 11 / 1

Yielding a New Collection If we want a new collection we can yield it. scala> val xs = List(1, 2, 3, 4, 5, 6) xs: List[Int] = List(1, 2, 3, 4, 5, 6) scala> for (x <- xs) yield math.pow(x, 2) res26: List[Double] = List(1.0, 4.0, 9.0, 16.0, 25.0, 36.0) yielded collections match the collection type of the generator they came from yield must come after generator definitions and before loop body intermediate variables are in scope in yield expression, loop body variables are not (see previous point) scala> val ys = Array(1, 2, 3, 4, 5, 6) ys: Array[Int] = Array(1, 2, 3, 4, 5, 6) scala> for (y <- ys; dub = y*2) yield math.pow(dub, 2) res29: Array[Double] = Array(4.0, 16.0, 36.0, 64.0, 100.0, 144.0) Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 12 / 1

Throwing Exceptions You throw exceptions in Scala just like in Java val half = if (n % 2 == 0) n/2 else throw new RuntimeException("n must be even") In Scala, throw has a return type: Nothing Nothing is a bottom type, i.e., a subtype of everything So the type of half above is Int Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 13 / 1

Catching Exceptions with try-catch Expressions try { val f = new FileReader("input.txt") // Use and close file } catch { case ex: FileNotFoundException => handlemissingfile(ex.getfilename) case ex: IOException => handleioerror() } Each case is searched until a match is found Only one case is executed, i.e., no fall-through as in C-style switch statement case ex: IOException means if ex is of type IOException, but not FileNotFoundException (since the previous case didn t match), execute the code to the right of => If nothing matches, exception propagates Can match everything ( catch-all ) with case _ =>... ( _ is Scala s wildcard character). Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 14 / 1

Ensuring Clean-up with finally Clauses Use finally blocks to release resources, such as file handles, database connections, and network sockets import java.io.filereader val file = new FileReader("input.txt") try { // Use the file } finally { file.close() // Be sure to close the file } Just like Java, Scala is lexically (a.k.a. statically) scoped, so file had to be defined outside of try-finally to be visible in both try and finally blocks finally clause is always executed, whether exception is caught or propagated Next week we ll see a better way to ensure resource release with the loan pattern Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 15 / 1

Value of try-catch-finally Expressions If try block does not throw an exception, the last value in try block is value of try-catch-finally expression scala> def f() = try { 1 } catch { case ex: RuntimeException => 2 } finally { 3 } f: ()Int scala> f res32: Int = 1 Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 16 / 1

Values of try-catch-finally Expressions If try block throws an exception that matches a case in catch block, value of the case expression is value of try-catch-finally expression scala> def f() = try { throw new RuntimeException 1 } catch { case ex: RuntimeException => 2 } finally { 3 } f: ()Int scala> f res32: Int = 2 Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 17 / 1

Value of try-catch-finally Expressions finally clause is intended for side-effects; last value in finally clause is never the value of the try-catch-finally expression scala> def g(): Int = try { 1 } finally { 2 } scala> g res32: Int = 1 Beware return statements, which override normal value determination: scala> def f(): Int = try { return 1 } finally { return 2 } f: ()Int scala> f res33: Int = 2 Here we re saying regardless of the value of the try-catch-finally expression, this method will return 2. Scala style is to avoid explicit returns. Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 18 / 1

Yielding Values from try-catch-finally Expressions Summary: If try block does not throw an exception, the last value in try block is value of try-catch-finally expression If try block throws an exception that matches a case in catch block, value of the case expression is value of try-catch-finally expression finally clause is intended for side-effects; last value in finally clause is never the value of the try-catch-finally expression Avoid explicit returns! Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 19 / 1

Match Expression Basics Work like the catch clauses of try-catch expressions, except that the match variable is not implicitly defined scala> def attitude(weather: String) = weather match { case "sun" => "hello" case "rain" => "good bye" case _ => "whatever" // if no cases above match } attitude: (weather: String)java.lang.String scala> attitude("sun") res35: java.lang.string = hello scala> attitude("rain") res36: java.lang.string = good bye scala> attitude("pizza") res38: java.lang.string = whatever match expressions return values No fall-through - use case _ =>... to define default Very powerful and cool. We ll see later how case classes and pattern matching support algebraic data types Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 20 / 1

Scala Has No Built-in Break and Continue Consider this Java code that finds the first argument that ends in.scala but doesn t start with - int i = 0; // This is Java boolean foundit = false; while (i < args.length) { if (args[i].startswith("-")) { i = i + 1; continue; } if (args[i].endswith(".scala")) { foundit = true; break; } i = i + 1; } How do we eliminate the breaks and continues? Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 21 / 1

Scala Has No Built-in Break and Continue Replace continues with ifs and breaks with boolean variables. var i = 0 var foundit = false while (i < args.length &&!foundit) { if (!args(i).startswith("-")) { if (args(i).endswith(".scala")) foundit = true } i=i+1 } Better yet, write a recursive function that captures the meaning of the logic: def searchfrom(i: Int): Int = if (i >= args.length) -1 else if (args(i).startswith("-")) searchfrom(i + 1) else if (args(i).endswith(".scala")) i else searchfrom(i + 1) val i = searchfrom(0) Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 22 / 1

Closing Points Scala is lexically scoped (we ve seen examples of this) Read the chapter s section on refactoring imperative code We ll start to see the Zen of Scala and funcitonal programming next week when we define our own control structres Chris Simpkins (Georgia Tech) CS 3693 Scala 2011-08-31 23 / 1