Re: Is anything easier to do in java than in lisp?

RobertMaas_at_YahooGroups.Com
Date: 06/19/04


Date: Sat, 19 Jun 2004 12:04:31 -0700


> From: Pete Kirkham <pete-kirkham-2004@cafemosaic.co.uk>
> How would you see that in lisp without using the introspector running
> in an interactive environment?

If you use ordinary nested-list structures when first developing your
new program, the ordinary read-eval-print loop is all you need to see
the result of every step you key in manually. Only a poor teacher would
insist on brand new students, never programmed before, using other
kinds of structures from the very start. And any experienced lisp
programmer would know to use ordinary nested-list structures when
developing something that is really difficult to do, then switch to
other kinds of structures later if there's a really good reason to do
so. By comparison, in java generally you hardly ever use
nested-linklist structures, you use instances of classes, for which
there isn't a standard useful way to print them. So even with BeanShell
you won't have the ease of lisp. (If BeanShell provides a useful
printed representation of every class instance, somebody please correct
what I said there. By the way, does anybody have a CGI interface to
BeanShell so that I could play with it to get a feel for how nice it
is?)

> People expect more than can be delivered through an HTML form, let
> alone VT100.

Google does just fine with HTML forms, and it's pretty popular, both
regular Web search, and Google Groups.
Yahoo Groups does fine with HTML forms too, except for their live chat
service which requires something more.

> Or lambda, which is so old it's ancient Greek.

Without changing the syntax, what word would you like in place of
lambda? Maybe anonymous-function, or just anonfunc to keep it short?

> programmers are taught that a program is 'like a recipe', so how can
> a recipe take part of the cookbook as an ingredient?

Actually I like that metaphor! Lisp allows you to write programs that
not just follow recipies a human wrote, but write their own recipes and
then follow them just the same! Macros are a crude beginning to that
idea: You write a template that converts one kind of form into another
kind of form, with the latter being a recipe that the computer can
follow. So for example you could have the macro form:
  Fried eggs and toast <n>
expand into:
  Put oil and <n> eggs into frypan and turn on burner.
  Put <n> pieces of bread into toaster-oven, set to high, and press on.
  When eggs are almost done, turn over.
  After toaster oven turns off, wait a few seconds then remove toast.
  When eggs are all done, remove from pan, place on top of toast, and
    turn off burner.
So depending on the number you put for <n>, you get a different recipe.
(With cakemixes etc. where you have to measure strange amounts of
different ingredients proportionally, the parameterized recipe is much
more useful than my trivial example above. Most such recipes give the
amounts for a standard size such as to serve four, and tell you to us
proportionally larger or smaller amounts to serve other numbers of
people, which is a royal pain to do manually. So having the ability to
have the computer generate the desired recipe could be seen as an
advantage to anyone who ever cooks such recipes.) Then once the student
understands that metaphor, and has written simple programs manually,
combining the two ideas to write a macro that writes a program would be
understandable.

> too many people are taught to program rather than taught to think.

Why do you assume it's an either-or situation, not both??

> lisp/Prolog/SQL you say 'I want the first part of the rest of the list'.
> C/C++/Java/CODASYL 'I have a list, I will navigate through it until I
> have the second element, then return that element'

I disagree. In either lisp or C you can do it either way.

> Lisp syntax structures its calls starting with the result (though the
> effect is still procedural), Java syntax structures its calls starting
> with your arguments.

For static methods, that's not true at all. Package and class and
function name is first, arguments come later, making them the same as
ordinary lisp function calls where package:functionname precede
arguments.

For instance methods it's only partly true. The object reference comes
first, then the dot, then the method name interpreted within the class
that the object has at runtime, then the other arguments which are
interpreted per their compiletime declared class not their actual
runtime class in deciding which overloaded method to call.

But there seems to be a fundamental difference in the *semantics*:
http://cl-cookbook.sourceforge.net/clos-tutorial/
   ... OO systems which only allow you to
   specialize on the first argument. This argument is then given
   linguistic prominence, and the function call is given a new syntax to
   reflect that:
Hmm, sounds like java is an example of such an OO language, am I correct?
   CLOS supports multi-methods - methods that can specialize on more than
   one argument.
So that's why the same kind of syntax, one argument up front the rest
later, isn't used in lisp (specifically CLOS).

> the Java syntax fits in with the model of program-as-recipe

Ignoring the point about how Java doesn't make it easy for programs to
compose programs, whereas lisp does: I disagree. Either language can be
programmed the same way: Define a function (method) which takes
arguments, do some calculation based on them, do some more calculation
based on those calculations, etc., until it has the finished result,
then return that result. (Either can return multiple values: CL
explicitly via an efficient mechanism, Java via allocatinging a vector
and returning that, which is the old way lisp did it before
multiple-value returns were implemented. That's just an efficiency
issue.) You get some ingredients, do various mixing and cooking of
them, and at the end you have something to eat. Function/method calling
within a function/method is like a sub-recipe for making some difficult
ingredient, such as won tons which are an ingredient in won ton soup.
Again, I see no essential difference between Java and Lisp in having
recipe as a metaphor.

> > Anyway, back to lack of keywords, so every combination of what would be
> > keywords in CL becomes a totally separate functionName and/or
> > argumentList in java.
> This is more a lack of optional arguments, rather than keyword arguments.

Incorrect. Just yesterday I was working on a GUI program (AWT Applet)
in Java, and needed to find the appropriate version of a particular
method. I wanted to specify the message text, title, type of message,
and nothing else. But that particular combination wasn't available, so
I had to use a method that required additional arguments, and supply
dummy values for each of them. Optional arguments wouldn't have helped,
because the *first* argument of the method I used was one of the
arguments I didn't want to have to specify myself. Optional arguments
only let you stop supplying arguments from some point onward, they
don't let you skip early arguments and include later ones. Keyword
arguments would have allowed me to specify exactly the arguments I
wanted, and let the rest default to reasonable values. Look at this
mess:

   static String showInputDialog(Component parentComponent,
   Object message)
Doesn't let me specify title, hence useless for my need.

   static String showInputDialog(Component parentComponent,
   Object message, Object initialSelectionValue)
Doesn't let me specify title, hence useless for my need.

   static String showInputDialog(Component parentComponent,
   Object message, String title, int messageType)
What I want, except I have to supply the first argument somehow even
though it's a pain, but null seems to work (put dialog in middle of
whole screen instead of centered within current Applet if I specify
that as the parentComponent).

   static Object showInputDialog(Component parentComponent,
   Object message, String title, int messageType, Icon icon,
   Object[] selectionValues, Object initialSelectionValue)
Requires several arguments I can't supply, hence useless for my need.

   static String showInputDialog(Object message,
   Object initialSelectionValue)
Doesn't let me specify title, hence useless for my need.

Oh if you're curious why I'm using a swing JOptionPane method within an
AWT Applet: Because AWT doesn't have anything like that yet, a
deficiency of Java'a GUI API.

> IDEs also help in the other aspect that keywords do, by showing the
> programmer what the names of the arguments are.

But there are five different overloaded versions of the same-name
method, so it's impossible for the IDE to know which of the five should
have its argument names shown to programmer. By comparison with CL with
keyword arguments an IDE could do the "right thing" of clearly
indicating which arguments if any are required then what keyword
arguments may be used, perhaps by a pull-down menu hanging from the
cursor the way Visual Basic's IDE deals with a list of all the GUI
controls that might be specified for an event handler.

> > Indeed, in java working with linked lists must be an awful pain.
> > Either your list can contain only one kind of element, so you declair
> > your own class to include link-cells whose data pointer is of that
> > type, or you use the generic Object type and deal with having to write
> > code that explicitly checks the case of every element at runtime.
> You tend to use the singly polymorphic dispatch mechanism. It's not as
> elegant as generic functions, but it's not something you notice- the
> main difference is that the generic function definition has to be placed
> into an 'interface' and (if using Java version<1.5) you have to 'cast'
> (coerce) the elements in the list to the interface type.

It's a big loser: Suppose you want to have a list that can contain any
mixture of twenty different types, mostly built-in types. You *cannot*
create an interface for these twenty types, then make each of the
twenty types implement your new interface, because you are not allowed
to re-define system-supplied API classes to make them implement a new
interface they didn't before. So you'd have to extend each of the
system-supplied classes to be a version that was just like the system
version but which implemented your new interface. Then you'd have to
keep track of whether you were using your extension or the original
type throughout your program, doing downcasting explicitly as needed.
It's a waste of effort, probably easier to just use Object type which
needs explicit typecase dispatch in your code, but Java doesn't have
typecase, so daisy chain of:
  else if (obj instanceof type<n>) { ... }
no big deal. Or better, have a single static method that maps from the
twenty object types to an integer which is used as an index in your
emulated typecases, so you can just use a switch select statement.
Then when you start to use a 21th type of object in your list, you just
modify the static method to include that new type, and you search for
all calls to that static method to make sure all your code can handle
the new object type. As for the actual code you run after you've found
which type the object is: You can then cast to the actual type it is,
and use method overloading to make the syntax parallel so it looks nice
and can be eyeballed to see if it's all correct:
  else if (obj instanceof BigInteger) { return processObj((BigInteger) obj); }
  else if (obj instanceof Double) { return processObj((Double) obj); }
  else if (obj instanceof Character) { return processObj((Character) obj); }
or equivalent with static function returning index which is named constant.
  switch (MyTypes.objToTypeCode(obj)) {
    case MyTypes.TYPE_BIGINTEGER: return processObj((BigInteger) obj); break;
    case MyTypes.TYPE_DOUBLE: return processObj((Double) obj); break;
    case MyTypes.TYPE_CHARACTER: return processObj((Character) obj); break;
    default: throw new MyTypes.unknowntype... }

Referring to the generic sequence functions in CL, specifically in this
example used with a linked-list (although a general vector would work
just the same, with different syntax in the example):
> > In CL, if you pass an integer instead of a character, it looks for that
> > integer, not the character with that ASCII code, for example:
> > (position 65 '(#\A #\B 65 66))
> > will find the 65 instead of the #\A, returning 2 instead of 0 as the
> > index where it found that number.

> Strings are objects that wrap arrays of UTF-16 encoded characters, not
> ASCII, nor are they lists of typed objects as in your example. You can't
> create a string in Lisp with numbers in it, a string is a vector of
> characters, ...

That's irrelevant to my point, which was about generic sequences (lists
or vectors of generic element type), not specialized sequences of
characters-only. Suppose in java you make a linked list, or array, as
the representation of a sequence of Objects of various types. Does the
Java API provide any method(s) equivalent to this?
  position item sequence &key :from-end :test :test-not :start :end :key

> java.util.Arrays.asList(new Object[]{
> new Character('A'),
> new Character('B'),
> new Integer(65),
> new Integer(66),
> }).indexOf(new Integer(65))

The ugly part there is the creation of the list itself, in the absense
of any parser such as READ in lisp. But I thought Java had software to
handle serialization and deserialization of data for purpose of
communicating across the network? How hard is it to set up a a Java
equivalent to CL's READ-FROM-STRING function that created all the
necessary stringinput/bufferedreader daisy chain and fed it through a
deserialization method to allow something like:
  MyParser.deserializeLispSyntax("(#\A #\B 65 66)").indexOf(new Integer(65))
Too bad there's no way to add new methods to a system-supplied API
class, in this case String, or else you could maybe do this:
  "(#\A #\B 65 66)".deserializeLispSyntax().indexOf(new Integer(65))

> (normally I'd use a script to generate such lists in Java, with lisp
> being the scripting language of choice)

I don't quite understand what you mean there. Do you mean you actually
run CL as a sub-process under Java and pass it the s-expression as a
string and somehow get back a linked list or array in the jvm, such as
by CL doing callbacks to Java API methods to build up the Java object
piece by piece? Or do you mean you'd run a CL program to convert the
s-expresssion syntax to XML or other serial representation known by
Java, and then use Java's built-in XML-or-whatever deserializer to load
the object into the jvm?

> Most languages, Java included, are destined to evolve into lisp or
> remain niche languages.

Hmm, that's the opposite of what a certain very opinionated DeAnza
instructor said (LISP is an A.I. langauge, not useful for anything
except that niche -- paraphrased to fit the current context).
I agree with you, not him, of course, on this point. CL is the general
purpose language, all other languages are niche languages, but some are
evolving to escape their niche to become as general as CL.
(I have to count Scheme as a niche language, sigh.)
Still I would like CL to become even more general, such as including
what PSL (Portable Standard LISP) called "SysLisp", which is a way to
cross-compile s-expressions via LAP into low-level assembly code that
can be included in ordinary assembly-language programs that can be
assembled to run stand-alone as an application or as a module in some
non-LISP environment, thereby allowing using SysLisp to write the main
part of compilers and even operating systems, even the kernel,
replacing C as the standard language for writing such. Maybe this has
already been done but isn't and won't be in the ANSI standard because
it's not of enough general use?



Relevant Pages

  • Re: Is anything easier to do in java than in lisp?
    ... Is there any real difference between lisp ... debugging environments that allow introspection and Java debugging ... in java working with linked lists must be an awful pain. ...
    (comp.lang.lisp)
  • Re: Is anything easier to do in java than in lisp?
    ... Is there any real difference between lisp ... debugging environments that allow introspection and Java debugging ... in java working with linked lists must be an awful pain. ...
    (comp.lang.java)
  • Re: Learning Lisp the hard way
    ... Note I do not want to advocate Java over lisp, ... Unless you can use Windows to program AllegroCL (or also some *nixes, I forget which, where they have ported their IDE) because they do have a nice IDE closer to what you are used to in Java. ... Next on my list of disappointments is exception handling. ...
    (comp.lang.lisp)
  • Re: Learning Lisp the hard way
    ... Note I do not want to advocate Java over lisp, ... they have ported their IDE) because they do have a nice IDE closer to ... Next on my list of disappointments is exception handling. ...
    (comp.lang.lisp)
  • Beginner code - splitting lines on whitespace
    ... I've been lurking here for a bit, and trying to learn lisp in my spare ... And split each line into a list, returning a list of lists: ... "Splits string on whitespace, meaning spaces and tabs" ...
    (comp.lang.lisp)