Imperative programming in F#

Similar documents
Option Values, Arrays, Sequences, and Lazy Evaluation

Functional Programming and Parallel Computing

List Functions, and Higher-Order Functions

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Scope, Functions, and Storage Management

Mutable References. Chapter 1

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Reactive Programming, and WinForms in F#

CITS 3242 Programming Paradigms Part II. Topic 10: Imperative Programming

Functional Programming. Pure Functional Programming

Mutable Data Types. Prof. Clarkson Fall A New Despair Mutability Strikes Back Return of Imperative Programming

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Winter 2013

Mutation. COS 326 David Walker Princeton University

CSCI 2041: Functions, Mutation, and Arrays

CS 11 Ocaml track: lecture 3

CSE341: Programming Languages Lecture 11 Type Inference. Dan Grossman Spring 2016

Introduction to OCaml

Mutation. COS 326 Andrew W. Appel Princeton University. slides copyright David Walker and Andrew W. Appel

Announcements. Scope, Function Calls and Storage Management. Block Structured Languages. Topics. Examples. Simplified Machine Model.

Storage class in C. Automatic variables External variables Static variables Register variables Scopes and longevity of above types of variables.

Chapter 7 Functions. Now consider a more advanced example:

Implementing Recursion

G Programming Languages - Fall 2012

9/21/17. Outline. Expression Evaluation and Control Flow. Arithmetic Expressions. Operators. Operators. Notation & Placement

Object-Oriented Programming for Scientific Computing

JVM ByteCode Interpreter

CS4215 Programming Language Implementation. Martin Henz

Datatype declarations

Index. Cambridge University Press Functional Programming Using F# Michael R. Hansen and Hans Rischel. Index.

G Programming Languages - Fall 2012

Introduction to Concepts in Functional Programming. CS16: Introduction to Data Structures & Algorithms Spring 2017

Programming for Engineers Iteration

News. CSE 130: Programming Languages. Environments & Closures. Functions are first-class values. Recap: Functions as first-class values

NOTE: Answer ANY FOUR of the following 6 sections:

Recap: Functions as first-class values

Chapter 13: Reference. Why reference Typing Evaluation Store Typings Safety Notes

F28PL1 Programming Languages. Lecture 12: Standard ML 2

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

Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Slide 5-1

Module 10: Imperative Programming, Modularization, and The Future

Programming language seminar The F# language. Peter Sestoft Wednesday Course plan

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Fall 2011

Introduction to Computers and C++ Programming p. 1 Computer Systems p. 2 Hardware p. 2 Software p. 7 High-Level Languages p. 8 Compilers p.

Types, Type Inference and Unification

Functions BCA-105. Few Facts About Functions:

Lectures 24 and 25: Scheduling; Introduction to Effects

Abram Hindle Kitchener Waterloo Perl Monger October 19, 2006

Problem Solving with C++

CMSC 330: Organization of Programming Languages. Objects and Abstract Data Types

CSc 520 Principles of Programming Languages. 26 : Control Structures Introduction

Products and Records

Critical Analysis of Computer Science Methodology: Theory

Delhi Noida Bhopal Hyderabad Jaipur Lucknow Indore Pune Bhubaneswar Kolkata Patna Web: Ph:

THE CONCEPTION AND APPLICATION OF PFL : A PROCESS FUNCTIONAL PROGRAMMING LANGUAGE

Problem Solving, Programming, and Calculation

15 FUNCTIONS IN C 15.1 INTRODUCTION

Part VI. Imperative Functional Programming

Goals of this Lecture

Functional Languages. CSE 307 Principles of Programming Languages Stony Brook University

Some Advanced ML Features

Names and Functions. Chapter 2

CS131 Typed Lambda Calculus Worksheet Due Thursday, April 19th

02157 Functional Programming. Michael R. Ha. Lecture 2: Functions, Types and Lists. Michael R. Hansen

Programming Languages. Function-Closure Idioms. Adapted from Dan Grossman's PL class, U. of Washington

Programming Languages and Techniques (CIS120)

CS4215 Programming Language Implementation. Martin Henz

5.1. Chapter 5: The Increment and Decrement Operators. The Increment and Decrement Operators. Looping. ++ is the increment operator.

*Starting Out with C++: From Control Structures through Objects, 7/E* by *Tony Gaddis* COMPUTER PROGRAMMING LECTURE 05 LOOPS IMRAN IHSAN

Manual Allocation. CS 1622: Garbage Collection. Example 1. Memory Leaks. Example 3. Example 2 11/26/2012. Jonathan Misurda

Ch. 11: References & the Copy-Constructor. - continued -

Topic 5: Examples and higher-order functions

Mobile Computing Professor Pushpendra Singh Indraprastha Institute of Information Technology Delhi Java Basics Lecture 02

Lambda Calculus and Type Inference

Types and Type Inference

Shared state model. April 3, / 29

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

Standard ML. Curried Functions. ML Curried Functions.1

CIS192 Python Programming

Repetition and Loop Statements Chapter 5

1 Lexical Considerations

Hands-On Lab. Introduction to F# Lab version: Last updated: 12/10/2010. Page 1

CSCI-GA Scripting Languages

Programming Paradigms in Python

C 101. Davide Vernizzi. April 29, 2011

CIS 120 Midterm II November 7, Name (printed): Pennkey (login id):

CS422 - Programming Language Design

CS558 Programming Languages

Lecture 7: Primitive Recursion is Turing Computable. Michael Beeson

OBJECT ORIENTED PROGRAMMING USING C++ CSCI Object Oriented Analysis and Design By Manali Torpe

Introduction to ML. Based on materials by Vitaly Shmatikov. General-purpose, non-c-like, non-oo language. Related languages: Haskell, Ocaml, F#,

CIS192 Python Programming

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

Stack. 4. In Stack all Operations such as Insertion and Deletion are permitted at only one end. Size of the Stack 6. Maximum Value of Stack Top 5

Assignment: 1. (Unit-1 Flowchart and Algorithm)

Lesson #3. Variables, Operators, and Expressions. 3. Variables, Operators and Expressions - Copyright Denis Hamelin - Ryerson University

COMP 202 Recursion. CONTENTS: Recursion. COMP Recursion 1

Name :. Roll No. :... Invigilator s Signature : INTRODUCTION TO PROGRAMMING. Time Allotted : 3 Hours Full Marks : 70

Haskell Scripts. Yan Huang

Absolute C++ Walter Savitch

We would like to find the value of the right-hand side of this equation. We know that

Transcription:

Imperative programming in F# Björn Lisper School of Innovation, Design, and Engineering Mälardalen University bjorn.lisper@mdh.se http://www.idt.mdh.se/ blr/ Imperative programming in F# (revised 2015-05-05)

F# is a Multiparadigm Programming Language So far we have used F# mainly as a functional language But F# is really a multi-paradigm language It supports both functional, imperative, and object-oriented programming Although the focus of this course is functional programming, we will spend some time on the imperative and object-oriented parts in F# Imperative programming in F# (revised 2015-05-05) 1

F# as an Imperative Language We have already seen some limited side-effects (printf, file I/O), and sequencing In addition, F# has: mutable data (that can be overwritten), imperative control structures (loops, conditionals), and iteration over sequences, lists, and arrays (similar to loops) Imperative programming in F# (revised 2015-05-05) 2

Mutable Variables F# has mutable variables (sometimes called locations) Their contents can be changed Declared with keyword mutable: > let mutable x = 5;; val mutable x : int = 5 Can be of any type: > let mutable f = fun x -> x + 1;; val mutable f : (int -> int) Imperative programming in F# (revised 2015-05-05) 3

Updating Mutable Variables Update (assignment) is done using the <- operator: > let mutable x = 5;; val mutable x : int = 5 > x <- x + 1;; val it : unit = () > x;; val it : int = 6 Imperative programming in F# (revised 2015-05-05) 4

Using the Values of Mutable Variables The current value of a mutable variable is returned by its name. Thus, x refers to the current value of x. This has some consequences. An example: > let mutable x = 5;; val mutable x : int = 5 > let y = [x;x];; val y : int list = [5; 5] > x <- x + 1;; val it : unit = () > y;; val it : int list = [5; 5] So the list y is not changed when x is updated. This is because the current value of x was used when creating y. y is an ordinary, immutable list Imperative programming in F# (revised 2015-05-05) 5

Mutable Records We have already seen (immutable) records Like variables, record fields can be declared mutable meaning that they can be updated An example: an account record, having three fields: an account holder field (string, immutable), an account number field (int, immutable), an amount field (int, mutable), and a field counting the number of transactions (ditto) (See next page) Imperative programming in F# (revised 2015-05-05) 6

type Account = { owner : string; number : int; mutable amount : int; mutable no_of_trans : int } A function to initialize an account record: let account_init own no = { owner = own; number = no; amount = 0; no_of_trans = 0 } Imperative programming in F# (revised 2015-05-05) 7

A mutable field can be updated with the <- operator: account.no_of_trans <- account.no_of_trans + 1 Example: a function that adds an amount to an account: let add_amount account money = account.amount <- account.amount + money account.no_of_trans <- account.no_of_trans + 1 Imperative programming in F# (revised 2015-05-05) 8

Mutable Reference Cells They provide a third way to have mutable data in F# Main difference to mutable variables is that the reference cells themselves can be referenced, not just the values held in them Type a ref, meaning a cell that holds a value of type a. Initialized with function ref : a -> a ref: let r = ref 5 Creates a reference cell r : int ref that holds the value 5 r is the cell itself. Its contents can be accessed with the! prefix operator:!r = 5 Note the difference between r (the cell), and!r (the contents of the cell) Imperative programming in F# (revised 2015-05-05) 9

Updating Reference Cells The binary infix operator (:=) : a ref -> a -> unit is used to update the contents of a reference cell Creating/initializing, accessing, and updating a reference cell: let r = ref 5 printf "Contents of r: %d\n"!r r :=!r - 2 printf "New contents of r: %d\n"!r Resulting printout: Contents of r: 5 New contents of r: 3 Imperative programming in F# (revised 2015-05-05) 10

Defining Mutable Reference Cells Mutable reference cells can be defined in F# itself They are simply records with one mutable field contents : type ref< a> = { mutable contents: a } let (!) r = r.contents let (:=) r v = r.contents <- v let ref v = { contents = v } Imperative programming in F# (revised 2015-05-05) 11

Handling Reference Cells Reference cells can be stored in data structures, and passed around. They can be accessed using the ordinary operations on data structures: > let r = [ref 5;ref 3];; val r : int ref list = [{contents = 5;}; {contents = 3;}] >!(List.head r);; val it : int = 5 > List.head r :=!(List.head r) + 2;; val it : unit = () > r;; val it : int ref list = [{contents = 7;}; {contents = 3;}] Imperative programming in F# (revised 2015-05-05) 12

Updating Reference Cells in Data Structures Updating the contents of a reference cell will affect data structures where it is stored: > let z = ref 5;; val z : int ref = {contents = 5;}; > let r = [z;z];; val r : int ref list = [{contents = 5;}; {contents = 5;}] > z :=!z + 1;; val it : unit = () > r;; val it : int ref list = [{contents = 6;}; {contents = 6;}] Compare this with the mutable variable example! There, the value of x was stored in the list. Here, it is the cell z that is stored Imperative programming in F# (revised 2015-05-05) 13

Why Two Types of Mutable Data? Why are there both mutable variables and ref variables in F#? They are stored differently. Mutable variables are stored on the stack, ref variables on the heap This implies some restrictions on the use of mutable variables Imperative programming in F# (revised 2015-05-05) 14

An Example that does not Work A good way to use mutable data is to make them local to a function. Then the side-effects will be local, and the function is still pure. Alas, mutable variables cannot be used like this: let f(x) = let mutable y = 0 in let rec g(z) = if z = 0 then y else y <- y + 2;g(z-1) in g(x) /localhome/bjorn/unison/work/gru/f#/test/locvar.fs(5,21): error FS0407: The mutable variable y is used in an invalid way. Mutable variables cannot be captured by closures. Consider eliminating this use of mutation or using a heap-allocated mutable reference cell via ref and!. Imperative programming in F# (revised 2015-05-05) 15

Using a ref Variable Instead A ref variable works: let f(x) = let y = ref 0 in let rec g(z) = if z = 0 then!y else y :=!y + 2;g(z-1) in g(x) val f : int -> int Imperative programming in F# (revised 2015-05-05) 16

In C/C#/Java: Comparing Assignments in F# and C/C#/Java x = x + y/z - 17 In F#, with mutable variables: x <- x + y/z - 17 Very similar to C/C#/Java In F#, with reference cells: x :=!x +!y/!z - 17 The main difference is that F# makes a difference between the cell itself (x) and the value it contains (!x) Imperative programming in F# (revised 2015-05-05) 17

Arrays Arrays are mutable in F# Array elements can be updated similarly to mutable record fields: let a = [ 1; 3; 5 ] a.[1] <- 7 + a.[1] Now, a = [ 1; 10; 5 ] Imperative programming in F# (revised 2015-05-05) 18

F# has conditionals and loops Control Structures in F# The conditional statement is just the usual if-then-else: if b then s1 else s2 It first evaluates b, then s1 or s2 depending on the outcome of b If side effects are added, then this is precisely how an imperative if-then-else should work If s : unit, then if b then s is allowed, and is then equivalent to if b then s else () Imperative programming in F# (revised 2015-05-05) 19

While Loops F# has a quite conventional while loop construct: while b do s s must have type unit, and while b do s then also has type unit An example: let x = ref 3 while!x > 0 do printf "x=%d\n"!x x :=!x - 1 Resulting printout: x=3 x=2 x=1 Imperative programming in F# (revised 2015-05-05) 20

Simple For Loops The simplest kind of for loop: for v = start to stop do s for v = start downto stop do s The first form increments v by 1, the second decrements it by 1 Note that v cannot be updated by the code inside the loop let blahonga n = for i = 1 to n do printf "Blahonga!\n" Imperative programming in F# (revised 2015-05-05) 21

Iterated For Loops These loops are iterated over the elements of a sequence (or list, or array). They have this general format: for pat in sequence do s The pattern pat is matched to each element in sequence, and s is executed for each matching in the order of the sequence Imperative programming in F# (revised 2015-05-05) 22

Simple For Loops as Iterated For Loops The simplest patterns are variables, and the simplest sequences are range expressions. With them, we can easily recreate simple for loops: for i in 1.. 10 do printf "Blahonga no. %d!\n" i for i in 10.. (-1).. 1 do printf "Blahonga no. %d!\n" i Also with non-unit stride: for i in 1.. 2.. 10 do printf "Blahonga no. %d!\n" i for i in 10.. (-3).. 1 do printf "Blahonga no. %d!\n" i Imperative programming in F# (revised 2015-05-05) 23

More General Iterated Loops More general use of patterns and sequences (lists, arrays) to iterate over: for Some x in [Some 1; None; Some 2; Some 2] do printf "%d" x Only the matching elements are selected. Printout will be 122 let squares = seq { for i in 1.. 100 -> (i,i*i) } let sum = ref 0 let sum2 = ref 0 for (i,i2) in squares do sum :=!sum + i sum2 :=!sum2 + i2 printf "Sum = %d\nsquare sum = %d\n"!sum!sum2 This example illustrates a mix of matched variables, which stand for values, and reference variables which stand for cells that contain values Imperative programming in F# (revised 2015-05-05) 24

Concluding Example: Iteration is Recursion Let s finally see how we can define our own imperative control constructs through recursion We will define a while loop construct This shows that iteration is just a special case of recursion! Since while is already a construct in F#, we define a function repeat that implements a repeat-until construct (like while, but executes the loop body once before making the test) Imperative programming in F# (revised 2015-05-05) 25

Idea: define a function repeat b s, where b is a condition (type bool), and s a loop body (executed only for the side effect) Use sequencing to make executions of arguments happen in the right order: first execute s, then test if b is true. If yes, recursively call repeat again, with the same arguments b and s If s has side effects, and b depends on these, the recursion can still terminate Imperative programming in F# (revised 2015-05-05) 26

Let s implement this idea right off: Repeat, First Attempt let rec repeat b s = s; if b then repeat b s else () repeat : bool -> unit -> unit However, this solution has a problem! Consider this: let n = ref 3 let b1 =!n > 0 let s1 = printf "n=%d\n"!n; n :=!n - 1 If we evaluate repeat b1 s1 we get the printout n=3 and then the evaluation goes into infinite recursion. Why?? Imperative programming in F# (revised 2015-05-05) 27

Why it Went Wrong repeat is a function. F# uses call by value. Therefore, the arguments get evaluated the first time repeat is called. Subsequent argument uses will not re-evaluate them, just reuse their previous value Therefore, the side effects of s will only occur once b will always return the value of the first call = infinite recursion, if true How can we fix this? Imperative programming in F# (revised 2015-05-05) 28

Repeat, Second Attempt A way to have the arguments reevaluated each time they are used is to wrap each one into a function A function body is reevaluated each time the function is called This will give us the desired effect! The functions will be given a dummy argument We can use the value () as dummy argument We obtain b : unit -> bool s : unit -> unit Imperative programming in F# (revised 2015-05-05) 29

New Solution let rec repeat b s = s (); if b () then repeat b s else () repeat : (unit -> bool) -> (unit -> unit) -> unit If we define let n = ref 3 let b1 = (fun () ->!n > 0) let s1 = (fun () -> printf "n=%d\n"!n; n :=!n - 1) And evaluate repeat b1 s1 we get (in fsi): n=3 n=2 n=1 val it : unit = () Imperative programming in F# (revised 2015-05-05) 30