Conversions

We've now seen all of Scheme's data types: Booleans, characters, numbers, pairs and lists (together with the empty list), procedures, strings, symbols, ports, and vectors. (In Chez Scheme, the end-of-file object is an additional type, but in some versions of Scheme it is implemented as a value of one of the previously listed types.)

Scheme keeps values of these types distinct. However, in a few cases there is a straightforward and useful correspondence between values of different types. For these cases, Scheme provides special conversion procedures which take arguments of one type and return values of the other.

We encountered one pair of conversion procedures back in the lab on characters:

> (char->integer #\L)  ;; assuming ASCII characters
76
> (integer->char 114)
#\r

A second pair of conversion procedures relates the strings that denote numbers with the numbers themselves. The string->number procedure takes as its argument a string containing any Scheme numeral and returns the number it stands for:

> (string->number "0038")
38
> (string->number (string-append "-32" "." "414"))
-32.414
> (string->number (string-append "60/1" "50"))
2/5

The number->string procedure takes any number and returns a string numeral for it -- the same numeral that would be printed by the display or write procedure:

> (number->string 60/150)
"2/5"
> (number->string (* -14/3 35.0))
"-163.33333333333334"
> (number->string #e1.5)  ;; #e is the exactness prefix
"3/2"

Exercise 1

What does string->number return if it is given a string that is not a numeral?


Exercise 2

Is there any number n such that (string->number (number->string n)) is not equal to n?


The remaining pair of standard Scheme conversion procedures relates symbols and strings. For every Scheme symbol, there is a string that contains the name of the symbol. The symbol->string procedure computes and returns this string:

> (symbol->string 'apple)
"apple"
> (symbol->string (cadr '(alpha beta gamma)))
"beta"
> (symbol->string 'SAMPLE)
"sample"

As the last example shows, each symbol is converted to the ``standard case'' of the particular Scheme implementation (in the case of Chez Scheme, lower case) before being converted to a string.

The string->symbol procedure takes any Scheme string and returns a symbol that has that string as its name:

> (string->symbol "apple")
apple
> (string->symbol (substring "amphibian" 2 5))
phi

Some strings are converted into symbols that cannot otherwise be named in Scheme. When printed, these are enclosed in vertical-bar characters to mark them as specials:

> (string->symbol "ALL CAPS")
|ALL CAPS|
> (string->symbol "5(3)")
|5(3)|
> (string->symbol "")
||
> (symbol? (string->symbol ""))
#t

Exercise 3

Write a Scheme procedure symbol-list->string that takes as argument a list ls in which every element is a symbol and returns as value a string that begins with a left parenthesis, ends with a right parenthesis, and in between contains string representations of all the symbols in ls, separated by single spaces.

> (symbol-list->string '(alpha beta gamma))
"(alpha beta gamma)"
> (symbol-list->string (list 'APPLE 'PEAR 'PEACH 'GRAPE))
"(apple pear peach grape)"
> (symbol-list->string '())
"()"

Exercise 4

Write the conversion procedure string->symbol-list that goes in the opposite direction, taking a string and returning a list of symbols. (If the argument string does not begin with a left parenthesis and end with a right parenthesis, return instead a single symbol corresponding to the entire argument string.)


Exercise 5

Challenge problem (for students familiar with non-decimal systems of numeration): Each of the procedures string->number and number->string takes an optional second argument, which must be an integer in the range from 2 to 36. If this argument is present, its value is used as a base of numeration for the string. (That is, string->number evaluates its argument as a numeral of that base and number->string constructs and returns a numeral using that base.) In bases larger than ten, the letters of the alphabet are used as single digits, with A for ten, B for eleven, and so on. For instance:

> (number->string 93 8)     ;; 93 = (1 * 8^2) + (3 * 8) + 5
"135"
> (string->number "7F" 16)  ;; 127 = (7 * 16) + 15
127

Write a Scheme procedure decimal->octal that takes as argument any string that is a base-ten numeral and returns the octal (base-eight) numeral that has the same numeric value (as a string).


This document is available on the World Wide Web as

http://www.math.grin.edu/courses/Scheme/spring-1998/conversions.html

created November 16, 1997
last revised June 21, 1998

John David Stone (stone@math.grin.edu)