You ve encountered other ways of signalling errors. For example, if you lookup an unbound key in a hashtable, Java (and Scala) produce nulls:

Similar documents
The fringe of a binary tree are the values in left-to-right order. For example, the fringe of the following tree:

Finally, all fields are public by default, so you can easily write simple functions, such as this one, without writing getters:

Lecture 2. 1 Immutability. 2 Case Classes

CSC Java Programming, Fall Java Data Types and Control Constructs

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

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

Lists. Michael P. Fourman. February 2, 2010

Excerpt from "Art of Problem Solving Volume 1: the Basics" 2014 AoPS Inc.

Unit E Step-by-Step: Programming with Python

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

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

Introduction to Typed Racket. The plan: Racket Crash Course Typed Racket and PL Racket Differences with the text Some PL Racket Examples

Programming Languages and Techniques (CIS120)

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

Exercise 1: Graph coloring (10 points)

Topic 6: Exceptions. Exceptions are a Java mechanism for dealing with errors & unusual situations

An Introduction to Python

TUPLES AND RECURSIVE LISTS 5

CS 360: Programming Languages Lecture 10: Introduction to Haskell

Full file at

SCHEME INTERPRETER GUIDE 4

Warm-up and Memoization

CS1 Lecture 3 Jan. 22, 2018

Lab 7: OCaml 12:00 PM, Oct 22, 2017

Divisibility Rules and Their Explanations

Unit 4: Client View of a Component Methods

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

Finding and Fixing Bugs

Implementing an Algorithm for Boomerang Fraction Sequences in Python

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

CMPSCI 187 / Spring 2015 Postfix Expression Evaluator

CompSci 220. Programming Methodology 16: Understanding FP Error Handling Part 2

These notes are intended exclusively for the personal usage of the students of CS352 at Cal Poly Pomona. Any other usage is prohibited without

CS112 Lecture: Exceptions and Assertions

4. Java Project Design, Input Methods

CS558 Programming Languages

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

CS1 Lecture 3 Jan. 18, 2019

MA 1128: Lecture 02 1/22/2018

About This Lecture. Outline. Handling Unusual Situations. Reacting to errors. Exceptions

When we reach the line "z = x / y" the program crashes with the message:

Statistics Case Study 2000 M. J. Clancy and M. C. Linn

Arithmetic expressions can be typed into Maple using the regular operators:

SCHEME AND CALCULATOR 5b

CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Sections p.

Programming Languages and Techniques (CIS120)

Ch. 12: Operator Overloading

STATS 507 Data Analysis in Python. Lecture 2: Functions, Conditionals, Recursion and Iteration

Project 6 Due 11:59:59pm Thu, Dec 10, 2015

CSE 374 Programming Concepts & Tools. Brandon Myers Winter 2015 Lecture 4 Shell Variables, More Shell Scripts (Thanks to Hal Perkins)

Lecture Transcript While and Do While Statements in C++

Australian researchers develop typeface they say can boost memory, that could help students cramming for exams.

Implementing Coroutines with call/cc. Producer/Consumer using Coroutines

UNIVERSITY OF TORONTO Faculty of Arts and Science. Midterm Sample Solutions CSC324H1 Duration: 50 minutes Instructor(s): David Liu.

Object-Oriented Design Lecture 11 CS 3500 Spring 2010 (Pucella) Tuesday, Feb 16, 2010

CSCI 204 Introduction to Computer Science II. Lab 6: Stack ADT

CS 1110: Introduction to Computing Using Python Loop Invariants

OCaml Data CMSC 330: Organization of Programming Languages. User Defined Types. Variation: Shapes in Java

Topics. Introduction to Repetition Structures Often have to write code that performs the same task multiple times. Controlled Loop

Language Basics. /* The NUMBER GAME - User tries to guess a number between 1 and 10 */ /* Generate a random number between 1 and 10 */

Announcements. Lab Friday, 1-2:30 and 3-4:30 in Boot your laptop and start Forte, if you brought your laptop

Typed Racket: Racket with Static Types

Modern Programming Languages. Lecture LISP Programming Language An Introduction

CS558 Programming Languages

Functional abstraction. What is abstraction? Eating apples. Readings: HtDP, sections Language level: Intermediate Student With Lambda

Functional abstraction

Discussion 1H Notes (Week 3, April 14) TA: Brian Choi Section Webpage:

Designing Robust Classes

Honu. Version November 6, 2010

Project 2 Due 11:59:59pm Wed, Mar 7, 2012

Problem One: A Quick Algebra Review

CS558 Programming Languages

Compilers and computer architecture: Semantic analysis

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

CS112 Lecture: Exceptions. Objectives: 1. Introduce the concepts of program robustness and reliability 2. Introduce exceptions

CS 115 Data Types and Arithmetic; Testing. Taken from notes by Dr. Neil Moore

Fundamentals of Programming Session 4

CSCI 1226 A Test #1. Wednesday, 10 October, 2018 Name: Student #: General Instructions Read and follow all directions carefully.

Exception Handling. Sometimes when the computer tries to execute a statement something goes wrong:

Basics of Computational Geometry

CS 11 python track: lecture 3. n Today: Useful coding idioms

LECTURE NOTES ON PROGRAMMING FUNDAMENTAL USING C++ LANGUAGE

Lab 03 - x86-64: atoi

Exception Handling. Run-time Errors. Methods Failure. Sometimes when the computer tries to execute a statement something goes wrong:

(Refer Slide Time: 00:02:02)

Stateful Objects. can I withdraw 100 CHF? may vary over the course of the lifetime of the account.

Defining Functions. CSc 372. Comparative Programming Languages. 5 : Haskell Function Definitions. Department of Computer Science University of Arizona

Lecture 1. 1 Introduction

// Body of shortestlists starts here y flatmap { case Nil => Nil case x :: xs => findshortest(list(x), xs)

Using Scala in CS241

CS3110 Spring 2016 Lecture 6: Modules

The Typed Racket Guide

Haskell: Lists. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Friday, February 24, Glenn G.

CS153: Compilers Lecture 15: Local Optimization

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

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

Lecture 14: Exceptions 10:00 AM, Feb 26, 2018

A LISP Interpreter in ML

CS 3512, Spring Instructor: Doug Dunham. Textbook: James L. Hein, Discrete Structures, Logic, and Computability, 3rd Ed. Jones and Barlett, 2010

Introduction to Scientific Computing Lecture 1

Transcription:

Lecture 5 1 Required Reading Read Chapters 16 and 17 of Programming in Scala. 2 Partial Functions and Signalling Errors Many functions are not defined on all inputs. For example, if you re reading input from a keyboard (i.e., a string) and want to parse the string as a number, you can apply Integer.parseInt: scala > val n = Integer. parseint ("10") n: Int = 10 But, if the string is not a numeral, you get an exception: scala > val n = Integer. parseint (" ten ") java. lang. NumberFormatException : For input string : " ten " You ve encountered other ways of signalling errors. For example, if you lookup an unbound key in a hashtable, Java (and Scala) produce nulls: scala > val ht = new java. util. Hashtable [ Int, String ]() ht: java. util. Hashtable [Int, String ] = { scala > ht.put (10, " hello ") scala > val r = ht. get (20) r: String = null Finally, here is a more insidious example. The following function calculates the point where two lines, defined by y = m 1.x + b 1 and y = m2. x + b 2, intersect. The function is not defined when the two lines are parallel (i.e., when their slopes are the same, or m 1 = m 2 ): case class Point ( x: Double, y: Double ) def inter ( m1: Double, b1: Double, m2: Double, b2: Double ): Point = { val x = (b2 - b1) / (m1 - m2) Point (x, m1 * x + b1) When the slopes are the same, the denominator, m1 - m2 is 0. So, you might expect a divide-by-zero ArithmeticException. That s not: what happens: scala > 1.0 / 0.0 res0 : Double = Infinity So you can t even catch this error with an exception handler, since no exception is raised: scala > val r = inter (0, 0, 0, 0) r: Point = Point (NaN, NaN ) 55

All these mechanisms for signalling errors share similar flaws: 1. Exceptions: you have to remember to catch them, or your program will crash. You can t tell if a function will throw an exception without carefully reading its code, which may not even be possible if it is in a library. 2. Producing null: even worse than exceptions, because your program will will not crash on an error. When it does crash, you ll spend a lot of time trying to figure out what produced the null. 3. Producing other null-like values: see above. The real problem is that the types of all these functions are not useful: The type of Integer.parseInt is String =>Int, but it may throw an exception instead of producing an Int. The type of ht.get is Any => String, but it may produce a null. The type of inter is (Double, Double, Double, Double) =>Point, but it can produce Point(NaN, NaN), which is clearly not what we had in mind. A Solution Let s use inter as an example and modify the function so that its type makes it obvious that it may not always return a Point. We introduce the following sealed trait: sealed trait OptionalPoint case class SomePoint ( pt: Point ) extends OptionalPoint case class NoPoint () extends OptionalPoint And we modify inter to produce NoPoint instead of a malformed-point: def inter ( m1: Double, b1: Double, m2: Double, b2: Double ): OptionalPoint = { if (m1 - m2 == 0) { NoPoint () else { val x = (m1 - m2) / (b2 - b1) Point (x, m1 * x + b1) With this new type, any program that applies inter will be forced to check if if a point was produced: inter (10, 3, 10, 3) match { case NoPoint => println (" no intersection ") case SomePoint ( Point (x, y)) => println ( s" intersection at ( $x, $y)") Consider another example: a type that represents an alarm clock. An alarm clock needs to track the current time and the alarm time if the alarm is set: case class Time ( h: Int, m: Int, s: Int ) case class AlarmClock ( time : Time, alarm : Time, alarmon : Boolean ) But, with this representation, it is easy to make simple errors. For example, you may accidentally trigger the alarm when time == alarm, if you forget to check alarmon first. A cleaner represention is to use the same pattern we used above: 56

sealed trait OptionalAlarm case class NoAlarm () extends OPtionalAlarm case class AlarmSet ( time : Time ) extends OptionalAlarm case class AlarmClock ( time : Time, alarm : OptionalAlarm ) In both inter and AlarmClock, it is completely obvious from the type that a point is not always produced and that an alarm is not always set. Partial functions are pervasive in computing and this pattern will make your programs more robust. But, it is annoying to define a new type such as OptionalPoint and OptionalAlarm for each type. 2.1 The Option Type Scala has a builtin generic type called Option that abtracts the pattern we discussed above. For example, here is inter rewritten to use Option: def inter ( m1: Double, b1: Double, m2: Double, b2: Double ): Option [ Point ] = { if (m1 - m2 == 0) { None else { val x = (m1 - m2) / (b2 - b1) Some ( Point (x, m1 * x + b1 )) 3 Built-in List methods Scala s List type has dozens of useful methods. For example, these methods correspond to the higher-order functions we ve seen so far: We can map over a list: assert ( List (10, 20, 30). map (x => x + 1) == List (11, 21, 31)) We can filter a list: assert ( List (1, 2, 3, 4). filter ( x => x % 2 == 0) == List (2, 4)) We can fold over a list: assert ( List (10, 20, 30). foldright (0)(( x, acc ) => x + acc ) == 60) Notice that the syntax of foldright is unusual. We ll get into the details how it works later. For now, there is no need to write sums and products using folds. Scala s lists have methods that do these directly: assert ( List (10, 20, 30). sum == 60) assert ( List (10, 20, 30). product == 6000) There are several other useful methods. For example: lst.take(n) produces a list with first n elements of lst. produces a list without the first n elements of lst. Similarly, lst.drop(n) 57

val lst = List ("X", "Y", "Z", "A", "B", "C") assert ( lst. take (3) == List ("X", "Y", "Z")) assert ( lst. drop (3) == List ("A", "B", "C")) assert ( lst. take (3) ::: lst. drop (3) == lst ) In the last line, the ::: operator (pronounced append ) appends two lists. Notation We emphasize that ::: is an ordinary method, even though it is written using funny symbols and appears to be an infix operator. We could append lists using conventional method-application syntax: assert ( lst.:::( lst ) == lst ::: lst ) In fact, all operators on objects are actually ordinary methods. E.g., we could write 2.+(3.*(6)), to do arithmetic using conventional method-application syntax. However, the usual notation of 2 + (3 * 6) is typically easier to read. lst.exists(f) produces true if there exists any element in the list on which f produces true. assert ( List (1, 2, 3, 4). exists ( n => n == 2) == true ) assert ( List (1, 2, 3, 4). exists ( n => n == 5) == false ) lst.forall(f) checks that all elements in lst satisfy f: assert ( List (2, 4, 6, 8). forall ( x => x % 2 == 0) == true ) assert ( List (2, 3, 4). forall ( x => x % 2 == 0) == false ) There are several other useful functions. You should explore the List API to learn more about them. 4 Sets and Maps paragraphsets The Scala standard library also defines sets and maps, which are two other data structures that are very common. Note that these represent mathematical sets, so they don t have duplicate elements and are not ordered. i.e., the three definitions below are the same: Set (1, 2, 3) Set (1, 2, 2, 3) Set (3, 2, 1) Sets have methods for calculating set union, set intersection, set difference, testing emptiness, and so on: assert ( Set (1, 2, 3). union ( Set (2, 3, 4)) == Set (1, 2, 3, 4)) assert ( Set (1, 2, 3). intersect ( Set (2, 3, 4)) == Set (2, 3)) assert ( Set (1, 2). intersect ( Set (3, 4)). isempty == true ) We can also map and filter the elements of sets, similar to lists: assert ( Set (1, 2, 3, 4). filter ( x => x % 2 == 0) == Set (2, 4)) assert ( Set (1, 2, 3, 4, 5). map (x => x % 2) = Set (0, 1)) There are severy other useful methods in the Set API. 58

Maps The Map data-structure (which is not the same as the map function) is a finite map from keys to values. For example: val duedates = Map ( 1 -> " Jan 28", 2 -> " Feb 4", 3 -> " Feb 11") Notation X -> Y is just another notation for the tuple (X, Y), but is commonly used with maps to suggest that it maps X to Y. Therefore, we could have writen val duedates = Map ( (1, " Jan 28"), (2, " Feb 4"), (3, " Feb 11")) We can lookup a key in two ways. First, we can simply apply the map to a key, just like a function: assert ( duedates (1) == " Feb 4") However, if the key is not found, this throws an exception. An alternative is to apply the get methods, which produces Some(v) if the key is mapped to a value and None otherwise: duedates. get ( x) match { case Some ( v) => v case None => " Unknown assignment " We can augment maps using the following syntax: val moreduedates = duedates + (4 -> " Feb 18") We emphasize that this produces a new map with all the contents of duedates and the key mapping for 4. The original map is not modified. Notation The notation m + (k -> v) seems to be something new, but we know how to unpack it. We just learned the arrow notation is another way of writing tuples, we can first rewrite it as m + (k, v). We also learned that all operators on objects are actually methods, so can rewrite it again as m.+((k, v)). Therefore, we can conclude that maps have a method called + that takes one argument. This argument is a tuple where the first component is a key k and the second component is the value v. The result of applying this method is a new map where k is mapped to v. It is often get the set of keys in a map: assert ( duedates. keys == Set (1, 2, 3)) Similarly, we can get an iterator over the values. Typically, you ll want to turn the iterator into a list immediately: assert ( duedates. values. tolist == List (" Jan 28", " Feb 4", " Feb 11")) As usual, there are dozens of handy methods over maps. You should explore the Map API. 59

5 Conversions It is sometimes necssary and easy to convert lists, sets, and maps to each other. These objects have methods called tolist, toset, and tomap that do exactly what their names suggest. For example: assert ( Map ("X" -> 10, "Y" -> 20). tolist == List (("X", 10), ("Y", 20))) assert ( List (("X", 10), ("Y", 20)). tomap == Map ("X" -> 10, "Y" -> 20)) 60