CS54 - Fall 2022 - Class 1
Example code in this lecture
power.sml
Lecture notes
PERM list, etc.
CS51, CS54 and CS62: how it all fits together
- Who should be here?
- taken CS51
- taken AP CS
- something similar and have gotten approval from a CS faculty member
course overview
Course web page:
http://www.cs.pomona.edu/classes/cs54/
- Use Piazza (I'll have you all registered soon!)
- Mentor sessions
- Use them to get help *if* you get stuck
- These are NOT required
- Work before coming to the session
- The earlier sessions will be *much* less crowded and you'll get better support
- Course readings
- Won't be extensive reading, but do read the handouts as I suggest
- Course schedule
Administrative:
http://www.cs.pomona.edu/classes/cs54/syllabus.html
Assignment 0
- Posted and due Friday at 5pm
- Key part: getting SML working for you!
- Start ASAP on getting it installed
- Installation instructions on the course webpage
- Corey (the CS dept sysadmin) will have office hours in Edmunds 218 (upstairs): Wednesday, 1-2:30pm and 4-5pm (before and after class)
- laptops
- You have access to all of the CS labs. They have everything installed
- You may also use your laptop for this class, but you'll have to set it up with SML and a few other things installed.
Background
- Who took CS51?
- How many know python?
- Who took AP?
- How many know Java?
- How many know SML?
- Another functional language?
Two ways of interacting with SML
1) the interpreter
- Type commands and get back results
- Nice for testing things out and doing simple things
- I'll use this a lot in class
2) by editing a file and then running in the interpreter
- Much more useful when writing actual programs
- Same as if you'd typed the commands into the interpreter
To start SML you first open Terminal, which is a shell (if you're using Windows, you'll install and use cygwin)
- What can you do in the shell?
- almost everything you can do with the GUI (i.e. the windows environment)
- navigate the file system
- edit files
- run programs
- ...
- then just type sml and you'll see:
Standard ML of New Jersey v110.69 [built: Mon Jun 8 23:24:21 2009]
\-
(The dash is the statement prompt from SML, though I'll often use '>' in my notes)
Your first SML function
> fun add1 x = x + 1;
val add1 = fn : int -> int
- The syntax for declaring a function is:
fun <name_of_function> <arguments> = <function_body>;
- it looks a bit more like declaring a mathematical function
- What do you think: "val add1 = fn : int -> int" is?
- This is the response from SML saying that it has defined a new value
- The responses can always be broken down as follows:
val <variable_name> = <value> : <type>
- The name of the value is add1
- fn tells us it's a function
- int -> int is the type of the function
- This already tells us some interesting things about SML:
- functions are "first-class entities" in SML. They are treated like any other *value* in the language (ints, strings, etc.)
- they can be stored to variables
- they can be passed as arguments to other functions
- they can be returned from functions
- int -> int
- this says that the function takes an integer as a parameter and returns an integer
- How did SML know this?
- Everything in SML has a type
- this is called a "strongly-typed" language
- values have a type
- functions, therefore, also have a type
- operators (like +, -, *, etc.) have a type as well
- SML has a *very* good type inference system
- + we know is used on numbers
- therefore, x must be a number
- therefore the function both takes and returns a number
Using a function
- Once we've declared a function, we can use it
> add1 10;
val it = 11 : int
- As before, the response from SML can be broken down:
- name of the variable: it
- what do you think "it" is?
- name for the previous statement when we don't assign it to a value
- can actually use it if you'd like in the next statement
- value is 11
- type of the value is int
- get used to looking at the response and understanding it!
- Anything interesting about how we called the function?
- no parentheses!
- we could have added them, but for style reasons we won't put them in
- like Java, we will terminate all statements with a semi-colon
The power function
- We'd like to write a function called power that takes two numbers, n and k, and produces n^k
- Write this in python (or Java), recursively:
def power(n, k):
if n == 0:
return 1
else:
return n * power(n, k-1)
- in Java:
public static int power(int n, int k){
if( n == 0 ){
return 1
}else{
return n * power(n, k-1)
}
}
- look at the power function in
power.sml code
- now I'm using sublime to view the file (you can use any text editor you'd like, but I recommend something with syntax highlighting)
- like before, we use "fun" to define a new function
- what's different?
- we're not using if/else like in python/Java
- SML uses "patterns" to match different input cases
- it can do many things, like match constants (e.g. 0), but not everything (e.g. match all negative numbers)
- pattern matching starts at the top and works down. When it finds one that matches, it executes that code and only that code
- for example, the order in the power function *does* matter. If we'd put (n,k) first, the (n,0) case would never be reached
Using the function
- We can type this (or copy and paste this) into the SML window and we get the following response:
val power = fn : int * int -> int
- Anything new here?
- the input type to the function is "int * int"
- this is called a "tuple"
- a tuple is a combination of two or more values (like in python!)
- they are defined by putting comma separated values inside parentheses
> (1, 2);
val it = (1,2) : int * int
- the function only has one input
- in fact, technically, all functions in SML only have one input!
- to call it we give it a tuple:
> power (10, 2);
val it = 100 : int
loading files
- the SML interpreter is nice for doing interactive things and debugging, but we don't want to keep copying and pasting code into the SML interpreter
- use
- we can run the contents of an entire file through using "use", e.g.
> use "power_alone.sml";
val power = fn : int * int -> int
val it = () : unit
- it behaves as if you started at the top of the file and typed each of the lines one at a time
- you'll see the output from the SML for each line
- additionally, you'll see one last line at the end which is the "result" from the actual use command
- most of the time this is how you will work:
- edit your function(s) in your text editor
- *save* the file
- "use" the file
- try out some of the functions in the interpreter
- repeat
A better power function
- Any problems with the power function?
- Doesn't handle negative numbers
- How could we fix this?
Look at the power2 function in
power.sml code
- We now have three patterns in the function
1) for when k = 0
2) for when n = 0 (strictly, this could be handled by the third case)
3) the general case
- the if-then-else statement is used to handle the case where k < 0
- notice that if-then-else represents a value
- each branch has a value of the same type
- no matter what branch we go down, we obtain a value
- we'll see this type of behavior A LOT