(* CS:3820, Fall 2018 *) (* Cesare Tinelli *) (* The University of Iowa *) (* F# examples seen in class *) (* function binding *) let next n = n + 1 next // next is bound to a function from int to int next(4) next 4 // more common syntax next next 4 // incorrect syntax: read as ((next next) 4) next (next 4) // correct syntax // input and output types can are inferred automatically let fnext n = n + 1.0 // integer version of + used in the absence of additional type info let f x = x + x f 3.4 // Type constraints can be added as needed // input is a string let double (x : string) = x + x // first argument of + evaluates to a string let double1 x = (x : string) + x // function body evaluates to a string let double2 x = (x + x) : string // function output is a string let double3 (x) : string = x + x // function output is a float let double4 x : float = x + x // function input and output are integers let double5 (x : int) : int = x + x // functions with unit return type let print_value i = printfn "The value is %i" i // this expression evaluates to () // but also has the side effect of printing // a message on the standard output stream print_value 4 (* Recursive function declarations *) let rec fac n = if n = 0 then 1 else n * fac (n - 1) fac 7 (* Mutually recursive function declarations *) let rec even n = if n = 0 then true else odd (n - 1) and odd n = if n = 0 then false else even (n - 1) (* Let binding visibility *) let a = 5 let f x = a + x f 1 let a = 2 // *new* constant with name a // new constant **shadows** old one a // however, the old one still exists and is unchanged // f was defined using the old a, not the new one f 1 // The scope of a let binder is the rest of the file // unless explicitly reduced with 'in' let q = 3 in ( q + 1 ) // ^^^^^ scope of q q // q not defined here // analogous to the following in C-like languages { int q = 4; return q + 1 } let x = 12 // outer x is 12, its scope starts with this line // and extends until the end of the file let r = (let y = x in (let x = 3 in x * y ) // inner x is 3, its scope is only this line ) x // outer x unchanged // nested declarations shadow less local ones let k = 1 in (let k = 2 in (let k = 3 in printfn "%i" k ); // within scope of each of three lets printfn "%i" k // within scope of first two lets only ); printfn "%i" k // within scope of first let only // function definitions can have local scope too let h x = x + 3 in ( h 1 // scope of identifier h ) h // error // this implies that functions can be defined locally // within other functions let f x = let l_square x = x * x in let l_double x = x + x in l_square(x) - l_double(x) f 5 l_square 3 // error