About documentation
John Johnson
johnatl at mac.com
Fri Aug 20 21:40:54 CEST 2004
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
The documentation for Mozart/Oz is among the best I've seen. Right up
there with the documentation for Java. A lot of people have spent a lot
of time working on it, and I appreciate it. I hope that my beginner's
mind can perhaps further the proliferation of Mozart/Oz. Please don't
take this as a flame, troll, or anything other than for what it is
intended, constructive criticism.
All examples used are meant to be typical examples, and are not meant
to pick on any particular author.
When I learn a new language, I like to 'type stuff in' and see it work.
It gives me a feel for the syntax and structure of the language, and
also teaches my fingers to type new words and sequences of letters.
This helps offload the typing to my cerebellum, so I can think on
higher levels than my typing. Most of the Mozart documentation I've
seen so far uses a structure something like this:
+---------------------------------+
| Example output |
+---------------------------------+
This show the Example Output
lots more text
which is created by this:
<High level concept>
<Another high level concept>
Lots of text here.
Here is the definition for so and so:
<High level concept>=
S = {Whatever 5}
W = {SomethingElse argument: <Definition>}
this does so and so...
a lot more text
<Definition>=
A = {SomethingHere 'test'}
T = {Whatnot 87}
and so ...
<Another high level concept>=
V = {Routine X 5}
W = {Sub Y}
- --->%-----------------------------------------
Looking at this from a beginner's perspective, it would appear, since
you've read how powerful Mozart is, that you could enter:
<High level concept>
<Another high level concept>
run it, and see the output. You quickly learn that, no, you have to
define those, so you:
<High level concept>=
S = {Whatever 5}
W = {SomethingElse argument: <Definition>}
but it won't run because the definition references another definition
which is defined later. So:
<Definition>=
A = {SomethingHere 'test'}
T = {Whatnot 87}
and it still doesn't run because you forgot that <Another high level
concept> isn't defined, so:
<Another high level concept>=
V = {Routine X 5}
W = {Sub Y}
which is better, but it still doesn't run. If you're lucky, you might
discover that adding
declare
at the very top of the file will get rid of some of the errors. Then
you realize that the definitions that say:
<Something>=
whatever
is not a definition at all, but the <Something>= just means to
substitute what follows for the reference you saw earlier. You're then
faced with the task of putting in }, ) and end's to fix the syntax.
Now it might possibly run. After all that, you're probably tired of
Mozart, and ready for lunch.
It would seem to me to be much simpler just to give a free standing
example and explain the operation afterwards. This way, the student is
quite possibly looking at the output from the example they cut and
pasted into the Mozart OPI. Comments can be added to the code, and, if
need be, a number or letter added in comments on important lines so
they can be called out in the explanatory text.
Here's a minimally commented example:
declare
% Widget Creation
Window = {New Tk.toplevel tkInit(title: 'Captialization')}
Entry = {New Tk.entry tkInit(parent: Window)}
Button = {New Tk.button tkInit(parent: Window
text: 'Change Capitalization'
% This is the action performed when the button is clicked.
action: proc {$}
String = {Entry tkReturn(get $)}
in
{Entry tk(delete 0 'end')}
{Entry tk(insert 0
% the following fun definition is mapped to each
character in the
% String, changing it's case.
{Map String fun {$ I}
case {Char.type I}
of lower then
{Char.toUpper I}
[] upper then
{Char.toLower I}
else I
end
end
}
)
}
end
)
}
% Geometry Management
{Tk.send pack(Entry Button fill:x padx:4 pady:4)}
I would like to see meaningful variable names used. As an example:
<Widget creation >=
W={New Tk.toplevel tkInit(title: 'Capitalization' )}
E={New Tk.entry tkInit(parent:W)}
B={New Tk.button tkInit(parent: W
text: 'Change Capitalization'
action: <Action definition >)}
Not only are we learning a new language and it's syntax, but we're also
dealing with cryptic variable names. Witness:
<Widget creation >=
Window = {New Tk.toplevel tkInit(title: 'Capitalization' )}
Entry = {New Tk.entry tkInit(parent:Window)}
Button = {New Tk.button tkInit(parent: Window
text: 'Change Capitalization'
action: <Action definition >)}
Now the variables represent concepts already familiar to us. Later when
we see:
{Tk.send pack(Entry Button fill:x padx:4 pady:4)}
rather than
{Tk.send pack(E B fill:x padx:4 pady:4)}
We don't have to figure out that E doesn't mean East or some other
unknown, and B doesn't mean Bottom, or another unknown.
As far as marking up the documentation for online display, the current
markup complicates cutting and pasting from the web page to Emacs. When
examples are pasted, many times there are 0xCA characters pasted
instead of spaces, and sometimes where there shouldn't be a space at
all. In Emacs, these look like rectangles, which are remarkably similar
to the [] used in case statements. Once you figure out the rectangles
shouldn't be there, you wind up deleting all the 'rectangle'
characters, which includes the empty brackets. Now the example code is
broken.
As far as formatting source, there doesn't seem to be a universal style
used by everyone. "Scrunching" seems to be pervasive. E.g.
local X in {CondSelect W key eeva X} {Browse X} end
local X in {CondSelect T key eeva X} {Browse X} end
while compact, this isn't as intelligible as:
local X in
{CondSelect W key eeva X}
{Browse X}
end
local X in
{CondSelect T key eeva X}
{Browse X}
end
Another example:
local Max X Y Z in
proc {Max X Y Z}
if X >= Y then Z = X else Z = Y end
end
X = 5
Y = 10
{Max X Y Z} {Browse Z}
end
is hard to follow due to the if...end being all on one line, and there
are also two statements on the next to the last line.
And last:
% case for pattern matching
proc {Insert Key Value TreeIn ?TreeOut}
case TreeIn
of nil then TreeOut = tree(Key Value nil nil)
[] tree(K1 V1 T1 T2) then
if Key == K1 then TreeOut = tree(Key Value T1 T2)
elseif Key < K1 then T in
TreeOut = tree(K1 V1 T T2)
{Insert Key Value T1 T}
else T in
TreeOut = tree(K1 V1 T1 T)
{Insert Key Value T2 T}
end
end
end
Is hard to follow because some statements follow then clauses on the
same line, and some begin on new lines. At first glance, it looks like
a 'wad of stuff'.
% case for pattern matching
proc {Insert Key Value TreeIn ?TreeOut}
case TreeIn
of nil then
TreeOut = tree(Key Value nil nil)
[] tree(K1 V1 T1 T2) then
if Key == K1 then
TreeOut = tree(Key Value T1 T2)
elseif Key < K1 then T in
TreeOut = tree(K1 V1 T T2)
{Insert Key Value T1 T}
else T in
TreeOut = tree(K1 V1 T1 T)
{Insert Key Value T2 T}
end
end
end
While a subtle difference, eliminates the confusion on the four lines
beginning at 'of nil...'.
There seems to be a shyness about using spaces
X=Z*Z
is perfectly legible when standing alone on the line above, but mixed
into a program, at first glance it appears to be a word beginning with
X and ending with Z. As research has proven, ylu ckn clinte tpe mhggje
lqwwkls and still read the words, since we see words as pictures,
rather than individual letters. If the line above is changed to:
X = Z * Z
it is obvious at a glance that it is not a word, but an assignment
statement. Blank lines also help break up a program into sections. I
understand that C-M-x evaluates to the previous blank line, so it would
be as nice to use a single % on a line to create the division.
And last, most of the code available isn't commented very much, if at
all. A comment before or on every line usually isn't necessary, but one
at the beginning of each function block would be very helpful,
especially to the author in coming years :-)
Thanks for hearing my out. I hope I didn't ruffle to many feathers.
Regards,
JJ
http://www.pragmaticprogrammer.com/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (Darwin)
iD8DBQFBJlPT56Q2CqQ+d1wRAmW7AJ9QdGPSg3GgRjoYyfMSjwTq3dAW8QCaAxmU
51Ic0/ZnL+uacAcNVKfsTZU=
=A769
-----END PGP SIGNATURE-----
More information about the mozart-users
mailing list