[erlang-questions] Erlang/YAWS vs Free Pascal/Xitami
Richard A. O'Keefe
ok@REDACTED
Fri Mar 28 05:32:33 CET 2008
>
> This is a "toy" example, but in Perl I made this mistake (again)
> just yesterday:
>
> my $thing = get_somestuff(...);
>
> And of course it really needed to be my ($thing) or my @thing or my
> (@thing). "Difficult to track" is relative, but by the time this all
> bubbled up into a failure it took a silly amount of time to identify
> (a half hour or an hour).
>
Perl is very much a special case.
In comparison, I've been keeping a log of the changes I've made in a
Smalltalk project.
Grand Total
addition 71
clarity 8
comment 7
delegation 2
deletion 10
efficiency 16
encapsulation 1
equality 1
equality-fix 2
extra-override 1
generality-fix 1
incomplete-edit 4
missed-override 7
missing-C 2
missing-call 1
missing-equal 1
missing-guard 3
missing-hash 6
missing-method 37
missing-parens 1
no-result 1
not-updated 1
off-by-one 4
output-format 3
promoted 1
rename 3
scope 1
scoping 7
shared-state 1
style 14
support 6
syntax 1
type-check 6
unset-variable 2
update-self 2
wrong-call 7
wrong-case 7
wrong-file 1
wrong-override 6
wrong-sign 1
TOTAL: 257
A lot of these obviously aren't errors as such ("additions" means adding
new features). "type-check" refers to adding code to do more explicit
run-time type checking (typically at object initialisation time).
Let's say there are about 150 real errors there. My estimate is that
only 5 of them would have been found by a type checker and not by
other compiler checks.
Some of the nastier ones would certainly NOT be found a by type checker.
'update-self' refers to a method like
"flexible collections">>removeAllFoundIn: aCollection
which should remove every element that is also found in aCollection.
The problem occurs when the receiver and the argument are the same
collection, which is type legal, but results in modifying a collection
that you are iterating over.
Of course, this doesn't mean that there aren't errors that a type
checker
would find that I haven't noticed yet. But 2% of changes being ones
that
a type checker would have been the right tool to find is still a small
number.
I've sometimes wondered why this result is so low.
I suspect that Smalltalk syntax is the answer.
As a simple example, let's take
java.util.Arrays.binarySearch(a, k)
java.util.Arrays.binarySearch(a, i, j, k)
(This really really ought to be a.binarySearch(k), a.binarySearch(i,
j, k),
and if Java's type system weren't so thoroughly messed up, it would
be.)
It's a pretty fair bet that in the two-argument versions the array comes
first and the key you are looking for comes second. The Smalltalk
version
would be
a binarySearchFor: k
and you would be in no doubt.
The most consistent interface for the four argument version would have
corresponding arguments in corresponding positions, so the second
argument
would still be the key. It isn't. As long as the key you are looking
for
is not some kind of integer, type checking will save you. But in
Smalltalk you would have
a from: i to: j binarySearchFor: k
and you would not be in the slightest doubt which argument was which.
Out of 24 possible argument orders, Java type checking eliminates all
but
2 if the key isn't an integer, or 6 if it is, but it still won't help
you
remember the order of the range arguments, or whether the upper bound is
inclusive or exclusive.
Since "to" is always used for inclusive bounds in Smalltalk, the
Smalltalk
method name leaves you in no doubt about any of the arguments.
Now let's look at Erlang.
digraph:add_edge(G, V1, V2, Label)
would be very hard to get wrong if it were
add_edge_to(G) from(V1) to(V2) labelled(Label)
or perhaps even
extend(G) with_edge_from(V1) to(V2) labelled(Label)
I first heard of "split procedure names" back in, oh, 1976,
from a fellow student at Auckland University called Paul Lyons
who had, I believe, invented it for himself. It was certainly
well before Smalltalk 80 came out. He might possibly have been
influenced by PL/I.
It's now about 10 years since I proposed
<name>[(<args>)] ... <name>[(<args>)]
as Erlang syntax, with the idea that
(1) you sort the packets after the first stably by <name>
(2) you concatenate the <names> with "_" separators
(3) you concatenate the argument lists
so something like
extend(G) with_edge labelled(L) to(T) from(F)
becomes
extend(G) from(F) labelled(L) to(T) with_edge
becomes
extend_from_labelled_to_with_edge(G, F, L, T)
Contrast
del_path(G,V1,V2) ->
case get_path(G,V1,V2) of
false -> true;
Path ->
rm_edges([V1|Path], G),
del_path(G, V1, V2)
end.
with
contract(G) removing paths from(V1) to(V2) ->
case find path in(G) from(V1) to(V2)
of false -> true
; Path -> contract(G) removing edges([V1|Path]),
contract(G) removing paths from(V1) to(V2)
end.
Wordy? Yes. Much chance of a type error? Not much.
Much chance of swapping two arguments of the *same* type? Not much.
This is, to my mind, a syntactically simpler approach than keyword
arguments. It is completely decoupled from the names of the function
parameters, which is particularly important for Erlang because Erlang
function arguments as such don't *have* names. But it serves the same
ends as keyword arguments, and leaves little work for a type checker.
> -j
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions
--
Te Reo Engarihi is a taonga of Te Iwi Pakeha,
ergo we should keep it pure, sans mélange, ruat caelum.
More information about the erlang-questions
mailing list