Lab: Basic types

Assigned
Wednesday, 7 April 2021
Summary
We explore some of the basic types that many implementations of Scheme, including Racket, support. These include a variety of numeric types, characters, strings, symbols, and lists.

Useful functions and notation

In the reading, we introduced a score of new functions for processing the basic types of Racket. Think of them as an essential vocabulary for expressing basic computation in Racket, similar to the new vocabulary you might encounter when learning a foreign language. However, unlike a foreign language, there isn’t an expectation that you get a deck of flash cards and memorize these function names. Instead, the expectation is that you will eventually memorize these functions by consistently building programs that use these functions, i.e., practice.

To this end, we’ll try to provide concise references to the functions that we introduce in the reading to aid you in your task. Feel free to note the location of these sections and use them to quickly look up the appropriate functions when needed.

Numbers

Basic numeric operations: +, -, *, /, quotient, remainder, expt.

Numeric conversion: exact->inexact, inexact->exact, floor, ceiling, round, truncate.

Numeric type predicates: exact?, inexact?, integer?, real?, rational?, complex?

Characters

Constant notation: #\ch (character constants)

Character constants: #\a (lowercase a) … #\z (lowercase z); #\A (uppercase A) … #\Z (uppercase Z); #\0 (zero) … #\9 (nine); #\space (space); #\newline (newline); and #\? (question mark).

Character conversion: char->integer, integer->char, char-downcase, char-upcase

Character predicates: char?, char-alphabetic?, char-numeric?, char-lower-case?, char-upper-case?, char-whitespace?

Character comparison: char<?, char<=?, char=?, char>=?, char>?, char-ci<?, char-ci<=?, char-ci=?, char-ci>=?, and char-ci>?.

Strings

Constant notation: "string" (string constants).

String predicates: string?

String constructors: make-string, string, string-append

String extractors: string-ref, substring

String conversion: number->string, string->number, symbol->string, string->number

String analysis: string-length

String comparison: string<?, string<=?, string=?, string>=?, string>?, string-ci<?, string-ci<=?, string-ci=?, string-ci>=?, string-ci>?

Lists

Constant notation: '(val val val)

List operations: take, drop, list-ref, length

The Lab

Your team should decide who will take the A-side and B-sides of the lab. Each member should download the appropriate code:

And follow the instructions in your respective files! When you are done, combine the files, rename the result to basic-types.rkt, and upload the completed lab to Gradescope.

For those with extra time

If you find that you finish all of these problems early, try one or more of the following problems. Note that some of these problems require you to write functions which we will learn about in a day or two. For now feel free to try to write expressions for concrete values, e.g., strings, numbers, and lists that produce the effect described, and come back once we learn about functions to generalize the results with functions!

Exploring rational numbers

DrRacket’s implementation of Scheme permits you to treat any real number as a rational number, which means we can get the numerator and denominator of any real number. Let’s explore what numerator and denominator that implementation uses for a variety of values.

  1. Determine the numerator and denominator of the rational representation of the square root of 2.
  2. Determine the numerator and denominator of the rational representation of 1.5.
  3. Determine the numerator and denominator of the rational representation of 1.2.
  4. Determine the numerator and denominator of 6/5.

If you are puzzled by some of the later answers, you may want to read the notes on this problem. Note that we will not expect you to regularly figure out these strange numerators and denominators.

Rounding, revisited

You may recall that we have a number of mechanisms for rounding real numbers to integers. But what if we want to round not to an integer, but to only two digits after the decimal point? Scheme does not include a built-in operation for doing that kind of rounding. Nonetheless, it is fairly straightforward.

Suppose we have a value, val. Write instructions that give val rounded to the nearest hundredth. For example,

> (define val 22.71256)
> (your-instructions val)
22.71
> (define val 10.7561)
> (your-instructions val)
10.76

Hint: You know how to round at the decimal point. Thik about ways to shift the decimal point.

String basics

  1. Write a Scheme expression to determine whether the symbol 'plaid is a string.
  2. Write a Scheme expression to determine whether the character #\A is a string.
  3. Does the empty string (represented as "") count as a string? Write your answer to this final question in your write-up.

Notes

Notes on From reals to integers

Here are the ways we tend to think of the four functions:

(floor r) finds the largest integer less than or equal to r. Some would phrase this as “floor rounds down”.

(ceiling r) finds the smallest integer greater than or equal to r. Some would phrase this as “ceiling rounds up”.

(truncate r) removes the fractional portion of r, the portion after the decimal point.

(round r) rounds r to the nearest integer. It rounds up if the decimal portion is greater than 0.5 and it rounds down if the decimal portion is less than 0.5. If the decimal portion equals 0.5, it rounds toward the even number.

> (round 1.5)
2
> (round 2.5)
2
> (round 7.5)
8
> (round 8.5)
8
> (round -1.5)
-2
> (round -2.5)
-2

It’s pretty clear that floor and ceiling differ: If r has a fractional component, then (floor r) is one less than (ceiling r).

It’s also pretty clear that round differs from all of them, since it can round in two different directions.

We can also tell that truncate is different from ceiling, at least for positive numbers, because ceiling always rounds up, and removing the fractional portion of a positive number causes us to round down.

So, how do truncate and floor differ? As the previous paragraph implies, they differ for negative numbers. When you remove the fractional component of a negative number, you effectively round up. (After all, -2 is bigger than -2.2.) However, floor always rounds down.

Why does Scheme include so many ways to convert reals to integers? Because experience suggests that if you leave any of them out, some programmer will need that precise conversion.

Notes on Exploring rational numbers

The underlying Scheme implementation seems to represent the fractional part of many numbers as the ratio of some number and 4503599627370496, which happens to be 252. (Most computers like powers of 2.) By using a large denominator, it helps ensure that representations are as accurate as possible.

If you are energetic, you might scour the Web to find out why they use an exponent of 52.

Acknowledgements

This laboratory is based on a similar laboratory from a prior version of CSC 151. It includes a few new problems on lists and files and eliminates a few problems on numeric values. The problem on text files is taken from a library on file input from a prior version of CSC 151.