[approx. Per .: previous parts [
1 ;
2 ;
3 ]
The previous parts translated
amarao , in this part the paragraph about null pointers is also translated by it]
Null pointers
Suppose you created a survey on a site that asks readers their name and age. The only problem is that for some reason, some of your readers do not want to tell their age - they stubbornly refuse to fill in the appropriate field. What makes a bad database administrator in this case?
Considering that age is an integer, there are two options for solving the problem. The most frequent (and most incorrect) is to give a special meaning as a sign of a blank field. For example, age -1 means that the data was not received, otherwise the data were obtained (even if they are incorrect). This method works fine until you decide to calculate the average age of visitors. Since you forgot to take into account your special meaning, you come to the conclusion that the average age of visitors is seven and a half years, you hire a web designer to remove all long words and rework the design using bright colors.
Another, correct method is to store the age in a field that is “integer or null”. Here is a SQL table for storing ages:
')
create table users
(
userid serial,
name text not null,
age int - may be null
);
If age data is not obtained, then a special SQL NULL value is entered into the database. SQL will automatically ignore this value if you tell it to calculate the average.
In many programming languages, there is also the concept of null, although ease of use may vary. In Perl, any scalar expression (number or string) can be
undef
(the Perl method to say “zero”). This causes a lot of warnings that are often ignored by novice programmers, despite the fact that such warnings most often indicate serious errors. In Java, any object reference can also be
null
, so using an
Integer
to store an age and using
null
in an age reference is perfectly reasonable. In C, of ​​course, the pointer may be null, but if you want a simple integer to be null, you will have to first put it in the object created by malloc on the heap.
OCaml uses an elegant solution to the null problem using a simple polymorphic variant type defined (in
Pervasives
) as follows:
type 'a option = None | Some of 'a
The "null pointer" is written as
None
. The age from the example above (an integer that may be null) is of type
int option
[Remember, it reads backwards, like
int list
and
binary_tree
].
# Some 3 ;;
-: int option = Some 3
What about the list of optional integers?
# [None; Some 3; Some 6; None] ;;
-: int option list = [None; Some 3; Some 6; None]
And what about the optional list of integers?
# Some [1; 2; 3] ;;
-: int list option = Some [1; 2; 3]
Assertions, warnings, fatal errors and output to stderr
One of the greatest features of Perl is a rich set of commands for debugging programs and handling unexpected errors, including the ability to display a stack cut, throw and catch exceptions, etc. OCaml has a not so rich set of debugging commands — better than Java, about the same as C, not as good as Perl. (We will talk about exceptions in more detail later.)
First of all,
assert
takes an expression as an argument and throws an exception. Assuming that you do not catch this exception (it is probably unwise that you will catch this exception, especially for beginners), this will stop the program and output the source code with the line number in which the error occurred. For example:
# assert (Sys.os_type = "Win32") ;;
Exception: Assert_failure ("", 0, 30).
(Running on Win32 naturally does not give an error)
You can also just cause
assert false
to stop your program, just if things are going bad, but you should probably use ...
failwith "error message"
will throw a
Failure
exception which again, if not catching, will stop the program with the output sent by the error message.
failwith
often used in conjunction with pattern matching, as in this example:
match Sys.os_type with
"Unix" | "Cygwin" -> (* code omitted *)
| "Win32" -> (* code omitted *)
| "MacOS" -> (* code omitted *)
| _ -> failwith "this system is not supported"
We point out some additional possibilities of pattern matching in the same example. The so-called "band sample" [approx. Lane: here I had problems with translation, the original “range pattern”, if someone knows a more correct translation, then unsubscribe (preferably in hp)] is used to match “Unix” or “Cygwin”, and a special sample _ which corresponds to "something else."
If you want to debug your program, but you, like me, are disgusted with all debuggers except gdb, then you probably want to display a warning through some function. For example (note the highlighted lines):
open Graphics;;
open_graph " 640x480";;
for i = 12 downto 1 do
let radius = i * 20 in
prerr_endline ("radius is " ^ (string_of_int radius));
set_color (if (i mod 2) = 0 then red else yellow);
fill_circle 320 240 radius
done;;
read_line ();;
If you prefer printf from C, then use the Printf module:
open Graphics;;
open Printf;;
open_graph " 640x480";;
for i = 12 downto 1 do
let radius = i * 20 in
eprintf "radius is %d\n" radius;
set_color (if (i mod 2) = 0 then red else yellow);
fill_circle 320 240 radius
done;;
read_line ();;
[approx. per. About the link to the original: I know that the original is on ocaml-tutorial.org, but it does not open for me [directly; via google cache; via archive.org; via Tor] so I indicated a link to the mirror]