Cse 321 Programming Languages and Compilers Standard ML















![Cse 321, Programming Languages and Compilers Construction of lists • The Empty List [] Cse 321, Programming Languages and Compilers Construction of lists • The Empty List []](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-16.jpg)
![Cse 321, Programming Languages and Compilers Taking Lists Apart ? hd [1, 2, 3] Cse 321, Programming Languages and Compilers Taking Lists Apart ? hd [1, 2, 3]](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-17.jpg)





















![Cse 321, Programming Languages and Compilers Pattern fun | addone [] = [] addone Cse 321, Programming Languages and Compilers Pattern fun | addone [] = [] addone](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-39.jpg)








![Cse 321, Programming Languages and Compilers Pattern fun sum [] = 0 | sum Cse 321, Programming Languages and Compilers Pattern fun sum [] = 0 | sum](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-48.jpg)
![Cse 321, Programming Languages and Compilers See the pattern in use. fun sum [] Cse 321, Programming Languages and Compilers See the pattern in use. fun sum []](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-49.jpg)





- Slides: 54

Cse 321, Programming Languages and Compilers Standard ML • In this course we will use an implementation of the language Standard ML • Notes by Riccardo Pucella, about programming in ML • http: //www. cs. cornell. edu/riccardo/smlnj. html • The SML/NJ Homepage has lots of useful information: http: //www. smlnj. org// • You can get a version to install on your own machine there. I will use the version 110. 57 of SML. Earlier versions probably will work as well. I don’t foresee any problems with other versions, but if you want to use the identical version that I use in class then this is the one. 6/19/2021 1

Cse 321, Programming Languages and Compilers Characteristics of SML • Applicative style – input output description of problem. • First class functions – pass as parameters – return as value of a function – store in data-structures • Less Importantly: – Automatic memory management (G. C. no new or malloc) – Use of a strong type system which uses type inference, i. e. no declarations but still strongly typed. 6/19/2021 2

Cse 321, Programming Languages and Compilers Syntactic Elements • Identifiers start with a letter followed by digits or other letters or primes or underscores. – Valid Examples: a a 3 – Invalid Examples: 12 A a’b a. F • Identifiers can also be constructed with a sequence of operators like: !@#$%^&*+~ • Reserved words include – fun val datatype if then else – if of let in end type 6/19/2021 3

Cse 321, Programming Languages and Compilers Interacting • The normal style for interaction is to start SML, and then type definitions into the window. • Types of commands – 4 + 5; – val x = 34; – fun f x = x + 1; • Here are two commands you might find useful. val pwd = OS. File. Sys. get. Dir; val cd = OS. File. Sys. ch. Dir; • To load a file that has a sml program type Use “file. sml”; 6/19/2021 4

Cse 321, Programming Languages and Compilers The SML Read-Typecheck-Eval-Print Loop Standard ML of New Jersey v 110. 57 [built: Mon Nov 21 21: 46: 28 2005] - 3+5; val it = 8 : int Note the semicolon when - print "Hi theren"; you’re ready to evaluate. Hi there Otherwise commands can val it = () : unit spread across several lines. - val x = 22; val x = 22 : int - x+ 5; val it = 27 : int -val pwd = OS. File. Sys. get. Dir; -val pwd = fn : unit -> string - val cd = OS. File. Sys. ch. Dir; val cd = fn : string -> unit 6/19/2021 5

Cse 321, Programming Languages and Compilers Evaluation vs. Declaration evaluation - 5; val it = 5 : int - 3+4; val it = 7 : int declaration - val it = 7 : int - val tim = 5 : int evaluation - tim + 7; val it = 12 : int declaration - fun plusone x = x + 1; val plusone = fn : int -> int 6/19/2021 6

Cse 321, Programming Languages and Compilers Bindings and environments, and scope: val x = 12; fun f x = x + 2; fun g y = x + 2; • fun bindings are just like val bindings val f = (fn x => x + 2); • But NOT RECURSIVE PROGRAMS! why? fun plus x y = if x = 0 then y else 1 + (plus (x-1) y); val rec plus = fn x => fn y => if x = 0 then y else 1 + (plus (x-1) y); 6/19/2021 7

Cse 321, Programming Languages and Compilers Functions • Functions are usually defined in Files and loaded into to SML. Example: – use “lect 01. sml” • Functions on numbers – Type of numbers: Int and Real – Conversion functions: floor, ceiling, trunc, round • Functions on Booleans – Relational operators < > <= >= – Combinators andalso orelse == != • Examples 6/19/2021 - 5 > 7 false - 1==4 false 8

Cse 321, Programming Languages and Compilers Finding type of functions - length val it = - op @; val it = - rev; val it = - op +; val it = 6/19/2021 fn : 'a list -> int fn : 'a list * 'a list -> 'a list fn : int * int -> int 9

Cse 321, Programming Languages and Compilers Functions • Defined by writing equations (sometimes more than 1) • By Declaration: fun plusone x = x+1; • By Lambda expression: fn x => x + 1 – These are anonymous functions, and are probably new to you. Don’t let them scare you. • Application by juxtaposition (no parenthesis needed) • plusone 8 • (fn x => x + 1) 8 • Functions of more than 1 argument: • tuples • currying 6/19/2021 10

Cse 321, Programming Languages and Compilers Multi Argument functions: Tuples • fun evenprod (x, y) = even(x * y); • Conditional Expressions: If • fun minpair (x, y) = if x < y then x else y; 6/19/2021 11

Cse 321, Programming Languages and Compilers Multi Argument functions: By Currying fun f a b c = a + b + c + 1; • has type val f = fn : int -> int • READ AS: int -> (int -> int)) • Be sure you understand the difference between the two styles. • fun evenprod (x, y) = even(x * y); – (int * int) -> bool • fun evenprod’ x y = even(x * y); – int -> bool 6/19/2021 12

Cse 321, Programming Languages and Compilers Pattern Matching Definitions: fun | | | and and true false = false true = false; Note that “and” has more than 1 equation. • (ORDER MATTERS) • Variables in Patterns: fun and true = true | and x y = false 6/19/2021 13

Cse 321, Programming Languages and Compilers Rules for patterns: • Patterns has only Constructors, (true, false, : : ) variables (x, y, z) , and constants (3, “red”). • All the patterns (on the left) should have compatible types • The cases should be exhaustive • There should be no ambiguity as to which case applies. (Ordering fixes ambiguity if there is any) 6/19/2021 14

Cse 321, Programming Languages and Compilers Lists in ML • Constant lists • [3, 6, 8] • ["red", "yellow", ""] • [] 6/19/2021 15
![Cse 321 Programming Languages and Compilers Construction of lists The Empty List Cse 321, Programming Languages and Compilers Construction of lists • The Empty List []](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-16.jpg)
Cse 321, Programming Languages and Compilers Construction of lists • The Empty List [] • The "Cons" (op : : ) Constructor 4: : [3, 7]; val it = [4, 3, 7] : int list • Concatenation [3, 4] @ [6, 7, 8] val it = [3, 4, 6, 7, 8] : int list 6/19/2021 16
![Cse 321 Programming Languages and Compilers Taking Lists Apart hd 1 2 3 Cse 321, Programming Languages and Compilers Taking Lists Apart ? hd [1, 2, 3]](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-17.jpg)
Cse 321, Programming Languages and Compilers Taking Lists Apart ? hd [1, 2, 3] 1 ? tl [1, 2, 3] [2, 3] ? List. take (2, [1, 2, 3]) [1, 2] ? List. drop (2, [1, 2, 3]) [3] 6/19/2021 17

Cse 321, Programming Languages and Compilers Libraries • There are lots of predefined types and functions in SML when it starts up. • You can find out about them at: http: //www. smlnj. org//basis/pages/top-level-chapter. html • Many more can be found in the other libraries. – http: //www. standardml. org/Basis/manpages. html • Libraries are encapsulated in Structures which are classified by Signatures (a list of what is in the structure). 6/19/2021 18

Cse 321, Programming Languages and Compilers Peeking inside a Structure • To see what is inside a Structure you can open it. • This is somewhat of a hack, but it is useful. Standard ML of New Jersey v 110. 57 [built: Mon Nov 21 21: 46: 28 2005] - signature S = INTEGER; signature INTEGER = sig eqtype int val precision : Int 31. int option val min. Int : int option val max. Int : int option val ~ : int -> int val + : int * int -> int val - : int * int -> int val * : int * int -> int val div : int * int -> int val mod : int * int -> int val quot : int * int -> int val rem : int * int -> int. . . end 6/19/2021 19

Cse 321, Programming Languages and Compilers In Class Exercise 1 • • Define prefix and lastone in terms of head tail and reverse. First make a file “S 01 code. sml” fun lastone x = hd (rev x) Start sml fun prefix x = rev (tl (rev x)) Change directory to where the file resides • Load the file ( use “S 01 code. sml” ) • Test the function Standard ML of New Jersey v 110. 57 - K; - val cd = OS. File. Sys. ch. Dir; val cd = fn : string -> unit - cd "D: /work/sheard/courses/Psu. Cs 321/web/notes"; - use "S 01 code. sml"; [opening S 01 code. sml] val lastone = fn : 'a list -> 'a val prefix = fn : 'a list -> 'a list val it = () : unit - lastone [1, 2, 3, 4]; val it = 4 : int 6/19/2021 20

Cse 321, Programming Languages and Compilers In Class Exercise 2 • define map and filter functions – mymap f [1, 2, 3] = [f 1, f 2, f 3] – filter even [1, 2, 3, 4, 5] = [2, 4] fun mymap f [] = [] | mymap f (x: : xs) = (f x): : (mymap f xs); fun filter p [] = [] | filter p (x: : xs) = if (p x) then x: : (filter p xs) else (filter p xs); • Sample Session - mymap plusone [2, 3, 4] [3, 4, 5] - myfilter even [1, 2, 3, 4, 5, 6] [2, 4, 6] 6/19/2021 21

Cse 321, Programming Languages and Compilers Case expressions Keyword of val ex 1 = case [1, 2, 3] of Clauses can Clauses span multiple separated lines [] => 0 by “|” | (1: : xs) => if null xs then 1 else 2 | (x: : xs) => 3; 6/19/2021 The semicolon ends the “val ex 1 = ” declaration not the case exp. 22

Cse 321, Programming Languages and Compilers Using case in fun definition • The case expression uses patterns fun length(y) = case y of [] => 0 | (x : : xs) => 1 + (length xs) • In the pattern: (x : : xs) – x, stands for the hd(y) – xs, stands for the tl(y) 6/19/2021 23

Cse 321, Programming Languages and Compilers More about patterns • Patterns can be nested • Patterns can have wild-cards fun double y = case y of (a : : (b : : [])) => true | _ => false These features can be used in “fun” declarations with multiple clauses as well as in “case” expressions! • Special syntax for list Patterns fun exactlytwo x = Case x of [] => false | [x, y] => true | (x: xs) => false; 6/19/2021 24

Cse 321, Programming Languages and Compilers Let expressions • Let expressions allow programmers to make local declaration for both values and functions. Multiple declarations allowed, both “val” and “fun”, no separators necessary val ex 2 = let val x = 34 fun f x = x - 3 in f x - 4 end; The scope of the new declarations is the expression between the key words “in” and “end” 6/19/2021 25

Cse 321, Programming Languages and Compilers Exceptions exception Error of string; A new exception is declared, it carries a string as error information. Exceptions can carry any kind of data. fun error s = raise (Error s); Exceptions can be raised, to short-circuit normal evaluation. fun ex 3 b = (if b then error "true branch" else "false branch") handle Error message => message Keyword | other => raise other; handle A handler, like a “case” has multiple clauses, each can handle a different kind of error. Note “|” separating clauses. 6/19/2021 Main computation returns a string Handler also returns a string 26

Cse 321, Programming Languages and Compilers Syntax of “case” vs “handle” • “case” is before the computation being analyzed case (revonto (g x) 4) of [] => true | (x: xs) => false • “handle” is after the computation that might fail (compute (g y) (length zs)) handle Error s => g s | Bad. Level n => n+1 | other => raise other 6/19/2021 27

Cse 321, Programming Languages and Compilers Review • Case, let, and exceptions are rich constructs in ML. • Case allows pattern matching without defining a new function. • Let allows us to introduce local bindings. It allows us to introduce more than 1 binding. • Exceptions allow non-standard control. The key operations on exceptions are “raise” and “handle” – Handle is like a “case” in that it can have several clause, separated by “|”, the first that matches “wins” 6/19/2021 28

Cse 321, Programming Languages and Compilers Introducing new kinds of data • Objects of an inductive type are allocated in the heap. • The abstract interface is to use constructor (functions) rather than malloc • This provides some level of type checking, and abstraction. • Constructor functions automatically defined. No need to define like constructors in Java • Two kinds of constructors. Constants like nil ([]), and functions like cons (: : ). 6/19/2021 29

Cse 321, Programming Languages and Compilers Constant Constructors • Constant constructors are constant • Can be allocated once at compile-time. • Like constant pointers that never change. • The nil constructor [] for lists is an example. 6/19/2021 30

Cse 321, Programming Languages and Compilers Constructor Functions • Constructor functions allocate in the heap. • Each constructor may allocate a different amount of memory • If we had to do this in C we might write list cons (void * hd, list tl) { list Block = (list) malloc (sizeof (struct list. Struct)); Block->Tag = cons. Tag; Block->Data. cons. Data. hd = hd; Block->Data. cons. Data. tl = tl; return (Block); }; • In ML this is done automatically. 6/19/2021 31

Cse 321, Programming Languages and Compilers Introducing new data and constructors datatype Tree Constant constructor, contains no data = Tip | Node of Tree * int * Tree; Constructor function. Contains 3 fields. The function Node takes a triple with 3 components. The “of” keyword is used for constructor functions val tree 1 = Node(Tip, 4, Tip) , 7 , Node(Tip, 10, Tip)); 6/19/2021 7 4 10 32

Cse 321, Programming Languages and Compilers Pattern Matching functions fun sum Tip = 0 | sum (Node(x, n, y)) = n + sum x + sum y; Two constructors, two clauses • using binary search tree invariant fun search n Tip = false | search n (Node(x, m, y)) = if n=m then true The bar “|” separates else if (n < m) then search n x clauses else search n y; 6/19/2021 33

Cse 321, Programming Languages and Compilers Searching Trees. fun search n Tip = false | search n (Node(x, m, y)) = if n=m then true else if (n < m) then search n x else search n y; • • • val ex 4 = search 3 tree 1; search 3 (Node(Tip, 4, Tip), 7, Node(Tip, 10, Tip))) search 3 (Node (Tip, 4, Tip)) search 3 Tip false • • val ex 5 = search 10 tree 1; search 10 (Node(Tip, 4, Tip), 7, Node(Tip, 10, Tip))) search 10 (Node (Tip, 10, Tip)) true 6/19/2021 34

Cse 321, Programming Languages and Compilers Expressions datatype Exp = Const of int | Add of Exp * Exp | Mult of Exp * Exp | Sub of Exp * Exp; val exp 1 = Add(Const 4, Const 3); (* 4+3 *) val exp 2 = Mult(exp 1, exp 1); (* (4+3)*(4+3) *) Mult(Add(Const 4, Const 3) , Add(Const 4, Const 3)); 6/19/2021 35

Cse 321, Programming Languages and Compilers Pattern matching functions fun Exp. Value (Const n) = n | Exp. Value (Add(x, y)) = Exp. Value x + Exp. Value y | Exp. Value (Mult(x, y)) = Exp. Value x * Exp. Value y | Exp. Value (Sub(x, y)) = Exp. Value x - Exp. Value y; 6/19/2021 36

Cse 321, Programming Languages and Compilers More SML • In SML we use library functions all the time. – Int. to. String – List. exists • The list library functions are particularly useful. – – – – These library functions often take a function as an argument List. map : ('a -> 'b) -> 'a list -> 'b list List. find : ('a -> bool) -> 'a list -> 'a option List. filter : ('a -> bool) -> 'a list List. exists : ('a -> bool) -> 'a list -> bool List. all : ('a -> bool) -> 'a list -> bool List. foldr : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b • It is worth studying these functions closely 6/19/2021 37

Cse 321, Programming Languages and Compilers List. map captures a pattern • Add one to every element of a list – fun addone [] = [] – | addone (x: : xs) = (x + 1) : : addone xs addone [2, 3, 4] val it = [3, 4, 5] : int list • Turn a list of ints into a list of strings – fun stringy [] = [] – | stringy (x: : xs) = (Int. to. String x) : : stringy xs stringy [2, 5, 9] val it = ["2", "5", "9"]: string list • Negate every element of a list – fun neg. L [] = [] – | neg. L (x: : xs) = (not x) : : neg. L xs neg. L [true, 3 > 4] val it = [false, true] : bool list 6/19/2021 38
![Cse 321 Programming Languages and Compilers Pattern fun addone addone Cse 321, Programming Languages and Compilers Pattern fun | addone [] = [] addone](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-39.jpg)
Cse 321, Programming Languages and Compilers Pattern fun | addone [] = [] addone (x: : xs) = (x + 1) : : addone xs stringy [] = [] stringy (x: : xs) = (Int. to. String x) : : stringy xs neg. L [] = [] neg. L (x: : xs) = (not x) : : neg. L xs fun map f [] = [] | map f (x: : xs) = (f x) : : (map f xs) val ex 1 = map (fn x => (x+1)) [2, 3, 4]; val ex 1 = [3, 4, 5] : int list val ex 2 = map Int. to. String [2, 5, 7]; val ex 2 = ["2", "5", "7"] : string list val ex 3 = map not [true, 3 > 4]; val ex 3 = [false, true] : bool list 6/19/2021 39

Cse 321, Programming Languages and Compilers Anonymous functions • Study: (fn x => (x+1)) – It is an anonymous function. A function without a name. – It has one parameter “x” – It adds one to its parameter, and returns the result. (fn x => (x+1)) 4; val it = 5 : int • Any non-recursive function can be written anonymously. – (fn x => x = 5) » Tests if its parameter is equal to 5 map (fn x => x=5) [1, 4, 5, 3, 5]; val it = [false, true, false, true] : bool list – (fn x => fn y => (x, y)) » Has two parameters » Returns a pair – (fn (x, y) => (not y, x+3)) » What is the type of this function? 6/19/2021 40

Cse 321, Programming Languages and Compilers List. find • Used for searching a list. – List. find : ('a -> bool) -> 'a list -> 'a option • Uses a function as a parameter to determine if the search is successful. • E. g. Is there an even element in a list? List. find even [1, 3, 5]; val it = NONE : int option List. find even [1, 3, 4]; val it = SOME 4 : int option 6/19/2021 41

Cse 321, Programming Languages and Compilers List. find anonymous functions List. find (fn x => x = "Tim") ["Tom", "Jane"]; val it = NONE : string option List. find (fn x => even x andalso x>10) [2, 4, 5, 12]; val it = SOME 12 : int option 6/19/2021 42

Cse 321, Programming Languages and Compilers List. filter Filter keeps some elements, and throws away others. – List. filter : ('a -> bool) -> 'a list It uses a function (p) as a parameter to decide which elements to keep (p x = true), and which to throw away (p x = false) val ex 6 = List. filter even [1, 2, 3, 4, 5, 6]; val ex 6 = [2, 4, 6] : int list 6/19/2021 43

Cse 321, Programming Languages and Compilers List. filter and anonymous functions val people = [("tim", 22), ("john", 18), ("jane", 25), ("tim", 8)]; val ex 7 = filter (fn (nm, age) => nm <> "tim" orelse age>10) people; val ex 7 = [("tim", 22), ("john", 18), ("jane", 25)] : (string * int) list 6/19/2021 44

Cse 321, Programming Languages and Compilers List. exists • “exists” is like “find” in that it searches a list – but rather than the element that completes the search it is only interested in if such an element exists. – List. exists : ('a -> bool) -> 'a list -> bool • Uses a function as a parameter to determine if the search is successful. val ex 8 = List. exists even [2, 3, 5]; val ex 8 = true : bool • Note that even if only 1 element in the list causes the function to be true, exists returns true. 6/19/2021 45

Cse 321, Programming Languages and Compilers List. all • List. all tests elements in a list for a property. It returns true only if every element has that property. – List. all : ('a -> bool) -> 'a list -> bool • Uses a function as a parameter to perform the test. val ex 9 = List. all even [2, 4, 5]; val ex 9 = false : bool • List. exists and List. all are related functions. They are duals. – not(List. all p xs) = List. exists (fn x => not(p x)) xs 6/19/2021 46

Cse 321, Programming Languages and Compilers List. foldr captures a pattern • Add up every element in a list. fun sum [] = 0 | sum (x: : xs) = x + (sum xs); • Compute the maximum element in a list of natural numbers (Integers >= 0). fun maximum [] = 0 | maximum (x: : xs) = Int. max(x, maximum xs); • Compute if every element in a list of boolean is true. fun all. True [] = true | all. True (x: : xs) = x andalso (all. True xs); 6/19/2021 47
![Cse 321 Programming Languages and Compilers Pattern fun sum 0 sum Cse 321, Programming Languages and Compilers Pattern fun sum [] = 0 | sum](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-48.jpg)
Cse 321, Programming Languages and Compilers Pattern fun sum [] = 0 | sum (x: : xs) = x + (sum xs); fun maximum [] = 0 | maximum (x: : xs) = Int. max(x, maximum xs); fun all. True [] = true | all. True (x: : xs) = x andalso (all. True xs); fun foldr acc base [ ] = base | foldr acc base (x: : xs) = acc(x, foldr acc base xs); 6/19/2021 48
![Cse 321 Programming Languages and Compilers See the pattern in use fun sum Cse 321, Programming Languages and Compilers See the pattern in use. fun sum []](https://slidetodoc.com/presentation_image_h2/7d0b73819da3933c20fb77bd440ec7b7/image-49.jpg)
Cse 321, Programming Languages and Compilers See the pattern in use. fun sum [] = 0 | sum (x: : xs) = x + (sum xs); fun sum xs = foldr (op +) 0 xs; fun maximum [] = 0 | maximum (x: : xs) = Int. max(x, maximum xs); fun maximum xs = foldr Int. max 0 xs; fun all. True [] = true | all. True (x: : xs) = x andalso (all. True xs); fun all. True xs = foldr (fn (a, b) => a andalso b) true xs; 6/19/2021 49

Cse 321, Programming Languages and Compilers Take another look What does this function do? fun ok [] = false | ok xs = not(exists (fn ys => xs=ys) (!old)) andalso not(exists (fn ys => xs=ys) (!worklist)) 6/19/2021 50

Cse 321, Programming Languages and Compilers The Option Library - open Option; opening Option datatype 'a option = NONE | SOME of 'a exception Option val get. Opt : 'a option * 'a -> 'a val is. Some : 'a option -> bool val. Of : 'a option -> 'a val filter : ('a -> bool) -> 'a option val join : 'a option -> 'a option val app : ('a -> unit) -> 'a option -> unit val map : ('a -> 'b) -> 'a option -> 'b option val map. Partial : ('a -> 'b option) -> 'a option -> ‘ b option 6/19/2021 51

Cse 321, Programming Languages and Compilers Interesting functions that use Options • Int. from. String: string -> int option Int. from. String "234"; val it = SOME 234 : int option Int. from. String "abc"; val it = NONE : int option • String. extract: string * int option -> string String. extract("abcde", 1, SOME 3); val it = "bcd" : string String. extract("abcde", 1, NONE); val it = "bcde" : string 6/19/2021 52

Cse 321, Programming Languages and Compilers More option functions • List. find: ('a -> bool) -> 'a list -> 'a option List. find even [1, 3, 5]; val it = NONE : int option List. find (fn x => x="tim") ["tom", "tim", "jane"]; val it = SOME "tim" : string option • List. get. Item: 'a list -> ('a * 'a list) option – List. get. Item [1, 2, 3, 4]; – val it = SOME (1, [2, 3, 4]) – List. get. Item []; – val it = NONE 6/19/2021 53

Cse 321, Programming Languages and Compilers Using While Loops fun ident c cs = let val xs = ref cs Don’t forget to test for empty list val x = ref c val ans = ref [] in while (not(null(!xs)) andalso Char. is. Alpha (hd (!xs))) do ( ans : = !ans @ [!x] ; x : = hd(!xs) ; xs : = tl(!xs) ); (Id (String. implode (!ans @ [!x])), !xs) end 6/19/2021 54