axiom-developer
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Axiom-developer] Re: libaxiom.a


From: Ralf Hemmecke
Subject: Re: [Axiom-developer] Re: libaxiom.a
Date: Fri, 24 Mar 2006 14:49:53 +0100
User-agent: Thunderbird 1.5 (X11/20051201)

On 03/24/2006 10:44 AM, Page, Bill wrote:
On Wednesday, March 22, 2006 5:26 AM you wrote:

Maybe I should be quiet, but I have a vision for Axiom and that simply
says: Use higher level language constructs instead of lower level ones.
It also says that people contributing to Axiom should write in Aldor (or
any even higher level language). Lower level constructs would only be
accepted, if there is no way to do it in Aldor. I don't think that idea
is so bad.

And for the library to make it "cleaner", I think it's cleaner if all
the lowlevel stuff is concentrated in a few files. Don't you agree?

Think of it from the point of view of people who think that Axiom is in
some sense great and they now decide to contribute to it. If they delve
deeper and find that besides Aldor they have to learn SPAD, BOOT, LISP,
in order to understand existing code and in order to contribute, then I
am sure that many people simply look for something simpler and turn
their back to Axiom.

I don't say that Lisp is bad, but it should be mostly hidden from the
final user/contributer to the algebra library. People should not need to
care how the underlying things are implemented until they want to
contribute there, too. I just argue against Lisp (or C or Fortran or
...) in any **higher layer** of the Axiom library.

> One can think of $Lisp as a package that naturally
accompanies the SExpression domain.

Well, if I look at it from an Aldor point of view it IS a package call.
As you said, Aldor allows "import ... from Foreign Lisp" where "..."
list the functions that are to be imported.
(Unfortunately, I haven't seen an import from "Foreign Lisp", but

  import { osCpuTime: () -> MachineInteger } from Foreign C;

actually appears in libaldor). After that import, one can use osCpuTime
as if it were a function defined in Aldor. No package calling is
necessary, because of the import.

The SExpression is a very important domain for Axiom.

Sorry, I cannot say much about it, but I just looked at it. It seems to
me that this should be the abstraction from the underlying Lisp that I
was talking about.

But $Lisp is something else. In SPAD it allows to access any Lisp
function. In Aldor that looks like a package call so it must be a
package call (not a foreign function call --- maybe it is possible to write "osCpuTime()$Foreign(C)"). In other words, if you want
that code to compile in Aldor, you have to make a package "Lisp" that
exports ALL the functions that are ever used in the Axiom library
(including NIL).

Maybe more of the commonly
used Lisp constructs could be implemented in SExpression,
but the change would be mostly cosmetic at the expense of
some function call overhead.

Well, shouldn't that "expense" depend on optimisations that the compiler
can perform?

Your argument might be that $Lisp is "too powerful" as a
package since it implements a complete, albeit lower-level,
symbolic programming language in itself. As such it allows
programmers to abuse this flexibility and write programs
that are more difficult to maintain.

Why was Aldor invented then? Why do people invent something like BOOT or
RLISP (the Reduce Lisp without brackets?)? Code written in higher level
languages are easier to maintain, IMHO.

For example, I see "NIL$Lisp" all over the place (153 times).
Brrrhh. Wouldn't just "nil" do?

Well, no. NIL$Lisp is of type SExpression but nil is of
type List. Maybe NIL should really be a constant defined
in SExpression.

For the latter, I would think so. The first is maybe true for the Axiom
library, but is false in general. "nil" is just an identifier, it could
denote anything. Let me quote from libaldor...

Pointer:  PrimitiveType with {
        coerce:  % -> MachineInteger;
        coerce:  MachineInteger -> %;
        nil:     %;
        nil?:    % -> Boolean;
} == add {
        macro Z == MachineInteger;
        Rep == Ptr;
        coerce(p:%):Z           == convert(rep p)@SInt ::MachineInteger;
        coerce(n:Z):%           == per convert(n::SInt);
        nil:%                   == per nil;
        nil?(p:%):Boolean       == nil?(rep p)::Boolean;
        (a:%) = (b:%):Boolean   == (rep a = rep b)::Boolean;

        -- THOSE ARE BETTER THAN THE CORRESPONDING CATEGORY DEFAULTS
        (a:%) ~= (b:%):Boolean  == (rep a ~= rep b)::Boolean;
}

If you say "import from Pointer" then "nil" is of type "Pointer", not
"List". BTW, nil is never of type List in libaldor. There is no reason
for it.

And to be honest, I mostly wouldn't like to see NIL at
all. Aldor/SPAD should deal with domains and their elements and mostly forget about a pointer view.

I am not sure I understand what you mean by a "pointer
view". SExpression is a domain within SPAD whose
representation is provided by Lisp. NIL is a name for
the empty SExpression just like 'nil' is a name for the
empty List.

The constant for the empty list in libaldor is "empty". Isn't that more
intuitive? If you have never come across LISP in your career, would you
know what NIL stands for?

> Or by "forget about pointer" are you
suggesting that we should discourage the use of such
mutable data structures as lists?

Of course not, but it's a difference between exports and implementation.
Nobody (except the implementor) needs to know about the internal representation of lists. Suppose I want to implement the List interface by an array? Should that be wrong? Do you have an idea what NIL could mean then? All that a user of LIST needs to know is in the interface (the category). The nasty details should be hidden.

I think this would
have unfortunate consequences for representing "infinite"
objects such as sequences and graphs/networks with
loops, etc.

I am not proposing to remove List. I am proposing to remove NIL (or at least to hide it in some low level library), since in my eyes that sounds not very mathematical. If I want an empty list, it is much better to say "empty$List(...)" than "NIL$Lisp". Don't you agree? BTW, there are several "empty" depending on the argument of "List".

There would be only rare reasons to use NIL and
they should be abstracted through an Aldor Pointer domain (which then could be mapped to Lisp (or whatever)).

Could say a little more about the Aldor Pointer domain?
How is it used?

Grep the libaldor sources. It is mostly used to get some low level functionality, for example, I/O done be C routines.

And I know that Manuel Bronstein introduced "address@hidden" in order to avoid "nil$Pointer pretend Record(...)" in some places. Sometimes "nil" is good for efficiency reasons. But maybe even that should be re-thought.

> I tend to think of NIL as equivalent to emtpy() for a list.

That is thinking in terms of implementation. But if I implement

MyList(T: Type): ListType T == add {
  Rep == Record(numEntries: Integer, l: List T);
  ...
  nil: % == per [0, empty$List(T)];
}

wouldn't that make a perfect list?

Perhaps you are saying that there really shouldn't be
two list-type structures in Axiom and that all of the
necessary SExpression functionality should be abstracted
as a List?

I am not at all saying that.

Except that we now have this Lisp'ish SPAD code for historical reasons, I think it would be much cleaner
to make a clear cut between the underlying Lisp
infrastructure and the Algebra code.

Is my view so wrong (except that it means lots of
work)?

It seems to me that only thing really "Lisp'ish" about
this is the use of SExpression as one of the fundamental
data structures.

How can SExpression be so fundamental, if it doesn't even exist in the libalgebra library of Aldor and one could still do symbolic computation? Are you saying SExpressoin is fundamental to the interpreter? Or fundamental to symbolic domains that are not yet in libalgebra? (I doubt the latter one.)

Ralf





reply via email to

[Prev in Thread] Current Thread [Next in Thread]