Kawa has the usual syntax for decimal integers.
Addition, subtraction, and multiplication
are written using the usual +
,
-
, and *
,
but these are all prefix functions that take a variable number of arguments:
(+ 1 2 3) ⇒ 6 (- 10 3 4) ⇒ (- (- 10 3) 4) ⇒ 3 (* 2 -6) ⇒ -12
Kawa has arbitrary-precision integers.
Let us implement the factorial function. Type in the following (we’ll look at the syntax shortly):
#|kawa:1|#(define (factorial x)
#|(---:2|#(if (< x 1) 1
#|(---:3|#(* x (factorial (- x 1)))))
(The prompt changes to indicate a continuation line.)
This binds the name factorial
to a new function, with formal parameter x
.
This new function is immediately compiled to Java bytecodes,
and later a JIT compiler may compile it to native code.
A few tests:
#|kawa:4|#(list (factorial 3) (factorial 4))
(6 24) #|kawa:5|#(factorial 30)
265252859812191058636308480000000
Given what was said above about being able to add, subtract and multiply integers, the following may be unexpected:
#|kawa:1|#(/ 2 3)
2/3 #|kawa:2|#(+ (/ 1 3) (/ 2 3))
1
In many languages, dividing two integers, as 2/3, would result in 0. At best, the result would be a floating point number, similar to 0.666667. Instead, Kawa has a rational number type, which holds the results of divisions exactly, as a proper fraction. Hence, adding one third to two thirds will always result in exactly one.
Floating-point real numbers are known in Kawa as inexact numbers, as they cannot be stored exactly. Consider:
#|kawa:3|#(exact? 2/3)
#t #|kawa:4|#(exact? 0.33333333)
#f #|kawa:5|#(exact->inexact 2/3)
0.6666666666666666
The first two examples check numbers for being exact?
; there is a
corresponding inexact?
test. The last shows how an exact number can be
converted to an inexact form.
Numbers are converted between exact and inexact versions when required within operations or procedures:
#|kawa:6|#(+ 0.33333333 2/3)
0.9999999966666666 #|kawa:7|#(inexact? (+ 0.33333333 2/3))
#t #|kawa:8|#(sin 2/3)
0.618369803069737
A complex number is made from two parts: a real part and an
imaginary part. They are written 2+3i
. A complex number can
be manipulated just like other numbers:
#|kawa:9|#(+ 2+3i 5+2i)
7+5i #|kawa:10|#(* 2+3i 4-3i)
17+6i #|kawa:11|#(integer? (+ 2+3i -3i))
#t
Notice how in the last example the result is an integer, which Kawa recognises.
Kawa also includes quaternion numbers.
In many applications, numbers have a unit. For example, 5 might be a number of dollar bills, a weight on a scale, or a speed. Kawa enables us to represent numbers as quantities: numbers along with their unit. For example, with weight, we might measure weight in pounds and ounces, where an ounce is 1/16 of a pound.
Using Kawa, we can define units for our weight measurements, and specify the units along with numbers:
#|kawa:12|#(define-base-unit pound "Weight")
#|kawa:13|#(define-unit ounce 0.0625pound)
#|kawa:14|#3pound
3.0pound #|kawa:15|#(+ 1pound 5ounce)
1.3125pound
In this example we define a base unit, the pound, and a unit based on it, the ounce, which is valued at 0.0625 pounds (one sixteenth). Numbers can then be written along with their unit (making them quantities). Arithmetic is possible with quantities, as shown in the last line, and Kawa will do the smart thing when combining units. In this case, 1 pound and 5 ounces is combined to make 1.3125 pounds.