[edit]
# calc.rkt

## Overview

## The 'READ' function

## Calc: How Does it Work?

## Calc: Number Inputs

## Calc: One Operator

**Test Your Understanding**

The calc-eval code has be reproduced for you below:
## Calc-Apply

## Calc: Nested Operators

**Test Your Understanding**

Let's test our calculator program by calling a more complex expression. The calc-eval code has be reproduced for you below:
## Compound Expressions

**Test Your Understanding**

Which of the following is NOT a possible call in calc?
## Takeaways

In this subsection, we are going to play around with a calculator program that is written in Racket.

Our calculator program will do arithmetic operations in the same syntax as Racket. Why are we doing this? We want to increase our understanding on how Racket evaluates things. In the next lab, we will add more features to it but for now, all it does is arithmetic operations.

You can download the file from here. You can also copy it to your class account by typing the following into a terminal:

`cp ~cs61as/lib/calc.rkt .`

Note the '.' at the end. This will copy the .rkt file to your current directory.

Before we dive in to the calculator, there is one function we should know: the
`read`

function. When you call `(read)`

, it will prompt you for some input.

```
> (read)
123
123
```

In the example above, we entered `123`

into the interpreter. The next `123`

shown by the interpreter is the value returned by `read`

. So what is it used for? Try this:

```
> (define a (read))
123
a
> a
123
```

Here, we are assigning `a`

to the value of your input. Thus, when we type
`123`

again, we store that value in the variable `a`

. Try the next one for
something more interesting:

```
> (define a (read))
(+ 1 2)
a
> a
(+ 1 2)
> (equal? a '(+ 1 2))
#t
```

This time, when the interpreter asked us what value we want to put into `a`

, we
typed `'(+ 1 2)'`

. `a`

ended up with the value `'(+ 1 2)'`

and NOT 3. The next
line tests whether `a`

is equal to the quoted list `'(+ 1 2)'`

. What can we
learn from this? `(read)`

accepts user inputs as symbols; they are not
evaluated.

With that covered, let's go to the Calculator program!

Let's run the program and walk through what is actually happening. Load
`calc.rkt`

in your Racket interpreter (by typing `(enter! "calc.rkt")`

), then call the function `(calc)`

:

```
> (calc)
calc:
```

Notice that our usual prompt ">" is replaced with "calc:". This is an easy way
to know that the expressions you enter which will be evaluated by `calc.rkt`

.
Now, try typing some arithmetic operation like `(+ 10 20)`

, or some number like `300`

, and play around with it!

How does it know how to evaluate math operations? Let's look at what the
`calc`

function does. Its definition is reproduced below:

```
(define (calc)
(display "calc: ")
(flush)
(print (calc-eval (read)))
(calc))
```

The first line says `(display "calc: ")`

, which tells the interpreter to show
"calc: " to the 'screen'/output.

`flush`

tells the interpreter to show whatever we type on the 'screen' output (you can ignore this for now).

The next line, `(print (calc-eval (read)))`

tells the interpreter to call `calc-eval`

with the user input and print the result.

The last line is a recursive call to `calc`

, which loops us back to the beginning. This is the **read-eval-print-loop (REPL)**: it asks for some user-input, evaluates it, prints the result, and loops.

This is all that `calc`

does. The calculator magic happens in `calc-eval`

.

So what does `calc-eval`

do? Consider a situation where we type a number in
`calc`

as follows:

```
calc: 42
42
```

That wasn't a very exciting result, but under the hood, a lot of things are
interacting. Because the user input is 42, the `calc-eval`

will be called as
`(print (calc-eval '42))`

. (Remember that `(read)`

returns a quoted symbol.)
Let's see how `calc-eval`

handles this. Its code is reproduced below.

```
(define (calc-eval exp)
(cond ((number? exp) exp)
((list? exp)
(calc-apply (car exp)
(map calc-eval (cdr exp))))
(else (error "Calc: bad expression:" exp))))
```

`calc-eval`

's body is a `cond`

, and because the formal parameter `exp`

is
called with 42, the first condition `(number? exp)`

will be fulfilled and
`calc-eval`

will return `exp`

, which is 42. All numbers are treated the same way. A subtle point here is that this is the base-case. For any arithmetic calculation, the simplest argument that can be passed around are numbers.

The next expression we are going to try is a single operator function call,
like `(+ 1 1)`

, `(* 2 3 10)`

, or `(- 100 50 20 10)`

.

```
calc: (* 2 3 10)
```

This will call `calc-eval`

as `(print (calc-eval '(* 2 3 10)))`

. (Again,
remember that `read`

treats user input as symbols.) How does `calc-eval`

handle this?

The calc-eval code has be reproduced for you below:

```
(define (calc-eval exp)
(cond ((number? exp) exp)
((list? exp)
(calc-apply (car exp)
(map calc-eval (cdr exp))))
(else (error "Calc: bad expression:" exp))))
```

What happens when we call the following expression:
```
(calc-eval '(* 2 3 10))
```

Our simple expression (* 2 3 10) to `calc`

gets passed in to `calc-apply`

as
`(calc-apply '* '(2 3 10))`

. What does it do next? Here is the code for calc-
apply:

```
(define (calc-apply fn args)
(cond ((eq? fn '+) (accumulate + 0 args))
((eq? fn '-) (cond ((null? args) (error "Calc: no args to -"))
((= (length args) 1) (- (car args)))
(else (- (car args) (accumulate + 0 (cdr args))))))
((eq? fn '*) (accumulate * 1 args))
((eq? fn '/) (cond ((null? args) (error "Calc: no args to /"))
((= (length args) 1) (/ (car args)))
(else (/ (car args) (accumulate * 1 (cdr args))))))
(else (error "Calc: bad operator:" fn))))
```

Notice that the formal argument `fn`

in `calc-apply`

only accepts 4 values:
`'+`

, `'-`

, `'*`

, or `'/`

. Everything else results in an error. `Calc-apply`

can be described as "find what function it is and do the right thing". In this case,
because `fn`

is `'*`

, `calc-apply`

will call `accumulate`

on `args`

, which is `'(2 3 10)`

, and return `60`

.

Convince yourself that for any of the 4 acceptable arguments for `fn`

, and any
list of numbers `args`

, `calc-apply`

will do the right computation.

Let's test our calculator program by calling a more complex expression. The calc-eval code has be reproduced for you below:

```
(define (calc-eval exp)
(cond ((number? exp) exp)
((list? exp)
(calc-apply (car exp)
(map calc-eval (cdr exp))))
(else (error "Calc: bad expression:" exp))))
```

What happens when we call the following expression:
```
(calc-eval '(+ 4 5 (* 10 2) 7))
```

So how does our calculator program evaluate compound expressions? It calls
`calc-eval`

on simpler expressions, and recursively repeats this until the
expressions are simple enough (just numbers) to simply return the expression. We know that `calc-eval`

and `calc-apply`

works for numbers and expressions with one operator. Everything else is just a combination. Trust the recursion!

Which of the following is NOT a possible call in calc?

In this subsection, you learned about `calc.rkt`

, which accepts an arithmetic expression (operation) as a symbol and evaluates it like a simplified scientific calculator.