Front page | perl.perl6.language |
Postings from January 2001
JWZ on s/Java/Perl/
From:
Michael G Schwern
Date:
January 27, 2001 15:17
Subject:
JWZ on s/Java/Perl/
Message ID:
20010127181651.E2885@blackrider.aocn.com
Tony Bowden pointed out a JWZ rant simply entitled 'java sucks'. He
makes a number of specific, solid technical points about Java which I
think have relevance to Perl.
http://www.jwz.org/doc/java.html
What follows are some of the more interesting excerpts. **These are
my comments***
Here's the quick list of things both Java and Perl are missing/doing wrong:
- Inline methods/macros/preprocessor/flet
- Poor iteration over characters in a string
- Everything should be an object to aid abstraction
- Integers should automagically degrade to bignums.
- Accessor methods should degrade to direct slot (hash) access
- Discovery of file system limitations are missing
- Too much application-level crap in the standard library.
And in his own words...
Here's things that Java and Perl are missing:
o It's far from obvious how one hints that a method should be inlined, or
otherwise go real fast. Does `final' do it? Does `private final' do it?
Given that there is no preprocessor to let you do per-function shorthand,
and no equivalent of Common Lisp's flet (or even macrolet), one ends up
either duplicating code, or allowing the code to be inefficient. Those
are both bad choices.
**constant.pm is anemic and Filter::cpp relies on an existing C
preprocessor (ie. won't work on most Windows and Mac)**
o I can't seem to manage to iterate the characters in a String without
implicitly involving half a dozen method calls per character.
**while its not quite that bad in Perl, its still harder than in
C (ie. the "string is just an array of characters" approach).
However, regexes make this technique rare.**
o This ``integers aren't objects'' nonsense really pisses me off. Why did
they do that? Is the answer as lame as, ``we wanted the `int' type to be
32 bits instead of 31''? (You only really need one bit of type on the
pointer if you don't need small conses, after all.)
The way this bit me is, I've got code that currently takes an array of
objects, and operates on them in various opaque ways (all it cares about
is equality, they're just cookies.) I was thinking of changing these
objects to be shorts instead of objects, for compactness of their
containing objects: they'd be indexes into a shared table, instead of
pointers to shared objects.
To do this, I would have to rewrite that other code to know that they're
shorts instead of objects. Because one can't assign a short to a variable
or argument that expects an Object, and consequently, one can't invoke
the equal method on a short.
Wrapping them up in Short objects would kind of defeat the purpose: then
they'd be bigger than the pointer to the original object rather than
smaller.
**I'm seeing more and more utility to the "everything is an object"
approach myself. Tying sort of addresses this, but performance
is horrid. However, without strong typing, it isn't as needed**
o After all this time, people still think that integer overflow is better
than degrading to bignums, or raising an exception?
o As far as I can see, there's no efficient way to implement `assert' or
`#ifdef DEBUG'. Java gets half a point for this by promising that if you
have a static final boolean, then conditionals that use it will get
optimized away if appropriate. This means you can do things like
if (randomGlobalObject.DEBUG) { assert(whatever, "whatever!"); }
but that's so gratuitously verbose that it makes my teeth hurt. (See
also, lack of any kind of macro system.)
**ran into this problem with Carp::Assert**
o The locking model is broken.
o First, they impose a full word of overhead on each and every object,
just in case someone somewhere sometime wants to grab a lock on that
object. What, you say that you know that nobody outside of your code
will ever get a pointer to this object, and that you do your locking
elsewhere, and you have a zillion of these objects so you'd like
them to take up as little memory as possible? Sorry. You're screwed.
o Any piece of code can assert a lock on an object and then never
un-lock it, causing deadlocks. This is a gaping security hole for
denial-of-service attacks.
o There is no way to signal without throwing: that is, there is no way to
signal an exceptional condition, and have some condition handler tell you
``go ahead and proceed anyway.'' By the time the condition handler is
run, the excepting scope has already been exited.
o The distinction between slots and methods is stupid. Doing foo.x should
be defined to be equivalent to foo.x(), with lexical magic for ``foo.x =
...'' assignment. Compilers should be trivially able to inline
zero-argument accessor methods to be inline object+offset loads. That way
programmers wouldn't break every single one of their callers when they
happen to change the internal implementation of something from something
which happened to be a ``slot'' to something with slightly more
complicated behavior.
o The file manipulation primitives are inadequate; for example, there's no
way to ask questions like ``is the file system case-insensitive?'' or,
``what is the maximum file name length?'', or ``is it required that file
extensions be exactly three characters long?'' Which could be worked
around, but for:
**File::Spec doesn't quite cover all this**
o The architecture-interrogation primitives are inadequate; there is no
robust way to ask ``am I running on Windows'' or ``am I running on
Unix.''
**We have $^O, but it requires parsing every time**
o What in the world is application-level crap like checkPrintJobAccess()
doing in the base language class library? There's all kinds of
special-case abstraction-breaking garbage like this.
Here's his gripes about Java that Perl has covered:
o It's hard to live with none of: lexically scoped local functions; a macro
system; and inlined functions.
o I really hate the lack of downward-funargs; anonymous classes are a lame
substitute. (I can live without long-lived closures, but I find lack of
function pointers a huge pain.)
o The fact that static methods aren't really class methods (they're
actually global functions: you can't override them in a subclass) is
pretty dumb.
o Two identical byte[] arrays aren't equal and don't hash the same.
o Generally, I'm dissatisfied with the overhead added by Unicode support in
those cases where I'm sure that there are no non-ASCII characters. There
ought to be two subclasses of an abstract String class, one that holds
Unicode, and one that holds 8-bit quantities. They should offer identical
APIs and be indistinguishable, except for the fact that if a string has
only 8-bit characters, it takes up half as much memory!
**umm, Perl covers this more or less**
o Interfaces seem a huge, cheesy copout for avoiding multiple inheritance;
they really seem like they were grafted on as an afterthought. Maybe
there's a good reason for them being the way they are, but I don't see
it; it looks like they were just looking for a way to multiply-inherit
methods without allowing call-next-method and without allowing instance
variables?
o And in related news, it's a total pain that one can't iterate over the
contents of an array without knowing intimate details about its contents:
you have to know whether it's byte[], or int[], or Object[]. I mean, it
is not rocket science to have a language that can transparently access
both boxed and unboxed storage.
o I sure miss multi-dispatch. (The CLOS notion of doing method lookup based
on the types of all of the arguments, rather than just on the type of the
implicit zero'th argument, this).
**We mostly have this covered**
o Relatedly, there are no ``weak pointers.'' Without weak pointers and a
working finalization system, you can't implement a decent caching
mechanism
**Hey, why isn't WeakRef in the core?**
o The notion of methods "belonging" to classes is lame. Anybody anytime
should be allowed to defined new, non-conflicting methods on any class
(without overriding existing methods.) This causes no
abstraction-breakage, since code which cares couldn't, by definition, be
calling the new, ``externally-defined'' methods.
o It comes with hash tables, but not qsort? Thanks!
o There is no way to access link() on Unix, which is the only reliable way
to implement file locking.
o There is no way to do ftruncate(), except by copying and renaming the
whole file.
o Is "%10s %03d" really too much to ask? Yeah, I know there are packages
out on the net trying to reproduce every arcane nuance of printf(), but
controlling field width and padding seems pretty darned basic to me.
--
Michael G. Schwern <schwern@pobox.com> http://www.pobox.com/~schwern/
That which stirs me, stirs everything.
-- Squonk Opera, "Spoon"
-
JWZ on s/Java/Perl/
by Michael G Schwern