Re: GoTo in Java
- From: mwojcik@xxxxxxxxxxx (Michael Wojcik)
- Date: 27 Jan 2006 22:12:03 GMT
In article <1138322336.610097.254790@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>, "Richard" <riplin@xxxxxxxxxxxx> writes:
> [I wrote:]
> > Yes, but I'm afraid I don't see the relevance of that to my point. I
> > mentioned the proliferation of X11 APIs for C only as an example of
> > the proliferation of reinvention.
>
> And why isn't the proliferation of sets of C++ GUI classes an example
> of proliferation of reinvention ?
It is. I'll see your antistrephon and raise you a concessio: GUI
libraries were a poor example. Container libraries are better, since
C++ does provide those as part of the language, and C does not.
Hence my point: C's popularity does not depend on the availability of
software components for use in new applications.
> In actual fact "Xlib, Xtk, Xaw, Motif..." is more an example of
> building on existing code. Xtk is built on top of Xlib, Xaw is a set of
> widget, Motif is a full GUI that relies on Xlib and Xtk.
By "Motif" I meant specifically the Motif widget set, not mwm and
the rest of CDE. If I were going to continue this line of argument
I might instead contrast the Xtk basic widget set with Xaw, Xm, the
Motif set, and (most tellingly) one-off sets like the one used in
xrn; but I'm not.
> > Swing was invented by Sun as a successor to AWT. wx4j is a port of a
> > preexisting API to Java. BambooKit isn't an API; it's an XML-based
> > GUI scripting language. None of them represent reinvention as such.
>
> Why is Swing not a 'reinvention' of AWT, or SWT not a reinvention of
> Swing ?
Swing isn't a reinvention of AWT because it was developed specifically
as a successor to AWT. Nothing makes Xaw particularly better than Xm
or vice versa; neither was developed as an improvement on the other;
they were just developed because someone felt like writing them.
> > Of those, only Ruby and Python even approach OCaml's expressiveness.
>
> Can you give an example showing OCaml to be more expressive.
(Obviously it's no more expressive in terms of Kolmogorov
complexity; I hope that goes without saying.)
Neither Ruby nor Python really support pure functional (non-destructive)
programming in any convenient fashion; at least that's the conclusion
I've seen from people who have spent more time investigating the
question than I have.
Ruby doesn't quite have first-class functions, because it doesn't
have functions. It has methods, which are always encapsulated in
objects; and blocks, which are anonymous closures; and Procs, which
are blocks bound to some state. The result is that higher-order
functions in Ruby are a bit awkward; there's a syntactic leap from
method definition, which is what Ruby programmers typically use for
defining code, to creating function-type objects for HOFs.
Here's an example I found online for a curried function in Ruby:
f = lambda { |x, y| x + y }
curry = lambda { |f, n| lambda { |x| f.call(n, x) } }
g = curry.call(f, 2)
g.call(3) #=> 5
Here's the same thing in OCaml:
let f(x,y) = x + y;;
let g(x) = f(2, x);;
g(3);; [displays "- : int = 5"]
OCaml has first-class functions as its basic function form, so
there's no special syntax required for them. Nor does it require the
special "curry" class to curry a function; f takes two parameters,
so if only one is supplied, the result is a function taking the
remaining parameter.
On the other hand, Ruby does make *every* method and closure a HOF,
in effect, by always allowing a block to be attached to it (and
invoked via the yield operator or processed in fancier ways by
treating it as a named Proc). That's quite clever, and I suppose
it'd be fair to say that Ruby is really quite close to the expres-
siveness of OCaml. The yield operator also is a nifty way of
implementing a sort of coroutine, though you need to use Ruby's
continuations for general coroutines.
In Python, functional programming is given even less attention. It's
not unworkable, because objects can capture state, which makes it
possible (and even reasonable) to build closures and continuations
from them, and HOFs in turn from that, but functional programming was
not a major goal for van Rossum, as far as I can tell.
There's that koan-style bit someone wrote about objects being the
poor man's closure and closures being the poor man's object, and it's
true that one will substitute for t'other. But OCaml fully supports
both, as part of its basic syntax, which is what makes it a genuinely
multiparadigm language.
(On the other hand, the syntax of the ML family isn't exactly lovely,
and I do like Ruby very much, and Python's not bad. If I had a fast,
portable native-code compiler for Ruby, I might make it my target
rather than OCaml. The yield operation is very nice for pipelined
data flow, which is great for a lot of comms applications.)
Perhaps the ML family's most famous bit of expressive power, though,
is its pattern-matching function bodies, which are a very basic
language feature (they're typically one of the first things students
are introduced to) and very powerful. What's more, the language
imposes some rather strong constraints on the implementation of
pattern-matching that make it very practical. (The implementation
checks during interpretation or compilation that cases are exhaustive
and unambiguous, for example, and there are optimization requirements
as well.)
OCaml's pattern matching includes parallel patterns, partial variable
binding, and guarded patterns (patterns that match only when an
expression is true). And they're particularly well-suited for the
kind of recursive function that's popular in functional programming
(and is practical in OCaml because, like Scheme, it features tail-call
optimization).
Here's an example of simple pattern matching with recursion, in a
function to sum a list:
let rec sum list = match list with
| [] -> 0
| head::rest -> head + sum rest;;
(You'd invoke this in the interpreter with eg "sum [1; 2; 3];;",
which would display "- : int = 6".)
That says "sum" is a function that takes a list and matches it against
two possibilities. If the list is empty, it returns 0; if it's not
empty, it assigns the first value to "head" and the rest of the list
to "rest", then returns head plus the sum of rest.
It's just syntactic sugar, but it's a very handy construct in practice.
You can see its use in some of the programs on Jon Harrop's site.[1]
So the real answer to your question is a combination of multiparadigm
elements with equal support for (pure and impure) functional and OO
programming, some unusual syntactic sugar, and a syntax which is
terse without being quite the line noise that's typical of, say, Perl
or APL (much as I enjoy the latter).
On the whole, I'd call Python more expressive than Javascript, Ruby
more than Python, and OCaml more than Ruby. But they're all in a
class above older procedural languages, and even older functional
ones like Scheme or LISP (at least without its OO bolt-on).
Anyway, that's how I see it. Of course you or others might make a
different case. Also, I'm by no means an expert on any of those
languages, and I may be missing out on equally compeling points in
favor of some of the others.
1. http://www.ffconsultancy.com/free/index.html
--
Michael Wojcik michael.wojcik@xxxxxxxxxxxxxx
Pogo: The dogs *scarcely* ever catches the rabbit.
Bun: "Scarcely" got a very unpleasant ring of frequency to it.
-- Walt Kelly
.
- References:
- GoTo in Java
- From: Howard Brazee
- Re: GoTo in Java
- From: Richard
- GoTo in Java
- Prev by Date: Re: GoTo in Java
- Next by Date: Re: GoTo in Java
- Previous by thread: Re: GoTo in Java
- Next by thread: Re: GoTo in Java
- Index(es):
Relevant Pages
|