You can subscribe to this list here.
2007 
_{Jan}

_{Feb}

_{Mar}

_{Apr}

_{May}

_{Jun}

_{Jul}

_{Aug}
(73) 
_{Sep}
(57) 
_{Oct}
(138) 
_{Nov}
(91) 
_{Dec}
(99) 

2008 
_{Jan}
(91) 
_{Feb}
(53) 
_{Mar}
(37) 
_{Apr}
(125) 
_{May}
(176) 
_{Jun}
(23) 
_{Jul}
(135) 
_{Aug}
(119) 
_{Sep}
(26) 
_{Oct}
(38) 
_{Nov}
(46) 
_{Dec}
(11) 
2009 
_{Jan}
(4) 
_{Feb}
(2) 
_{Mar}
(5) 
_{Apr}
(15) 
_{May}
(4) 
_{Jun}
(18) 
_{Jul}
(1) 
_{Aug}
(4) 
_{Sep}
(17) 
_{Oct}
(9) 
_{Nov}
(14) 
_{Dec}
(11) 
2010 
_{Jan}
(9) 
_{Feb}
(6) 
_{Mar}
(1) 
_{Apr}
(1) 
_{May}
(4) 
_{Jun}
(3) 
_{Jul}

_{Aug}
(10) 
_{Sep}
(7) 
_{Oct}
(7) 
_{Nov}
(36) 
_{Dec}
(23) 
2011 
_{Jan}
(2) 
_{Feb}
(1) 
_{Mar}
(1) 
_{Apr}
(11) 
_{May}
(5) 
_{Jun}
(17) 
_{Jul}
(2) 
_{Aug}
(26) 
_{Sep}
(14) 
_{Oct}
(51) 
_{Nov}
(39) 
_{Dec}
(7) 
2012 
_{Jan}
(24) 
_{Feb}
(7) 
_{Mar}
(9) 
_{Apr}
(2) 
_{May}
(9) 
_{Jun}
(7) 
_{Jul}
(3) 
_{Aug}
(1) 
_{Sep}
(8) 
_{Oct}
(12) 
_{Nov}
(1) 
_{Dec}

2013 
_{Jan}

_{Feb}

_{Mar}

_{Apr}
(35) 
_{May}
(28) 
_{Jun}
(14) 
_{Jul}
(10) 
_{Aug}
(3) 
_{Sep}
(6) 
_{Oct}

_{Nov}
(1) 
_{Dec}

2014 
_{Jan}

_{Feb}

_{Mar}

_{Apr}
(4) 
_{May}
(3) 
_{Jun}
(2) 
_{Jul}
(2) 
_{Aug}
(2) 
_{Sep}
(1) 
_{Oct}
(3) 
_{Nov}
(5) 
_{Dec}
(8) 
2015 
_{Jan}
(3) 
_{Feb}
(2) 
_{Mar}

_{Apr}

_{May}
(1) 
_{Jun}

_{Jul}

_{Aug}

_{Sep}

_{Oct}

_{Nov}

_{Dec}
(1) 
2016 
_{Jan}
(5) 
_{Feb}
(10) 
_{Mar}

_{Apr}

_{May}

_{Jun}

_{Jul}

_{Aug}

_{Sep}

_{Oct}

_{Nov}

_{Dec}
(5) 
2017 
_{Jan}
(2) 
_{Feb}
(2) 
_{Mar}
(5) 
_{Apr}
(1) 
_{May}

_{Jun}

_{Jul}

_{Aug}

_{Sep}

_{Oct}

_{Nov}

_{Dec}

S  M  T  W  T  F  S 




1

2
(10) 
3

4

5

6
(1) 
7
(1) 
8

9

10

11
(3) 
12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30



From: Gabriel Dos Reis <gdr@in...>  20090411 14:31:37

On Sat, Apr 11, 2009 at 2:37 AM, root <daly@...> wrote: > Since boot was written in boot we had a situation where we needed a > running Axiom in order to build Axiom. This was also true of the > algebra in that you needed a running system to build a running system. A data point: OpenAxiom has more codes written in Boot than any other in the AXIOMfamily. Yet, it does not need a running OpenAxiom system to build the entire compiler. I suspect we had this sort of discussion before...  Gaby 
From: Gabriel Dos Reis <gdr@in...>  20090411 14:23:44

On Sat, Apr 11, 2009 at 6:31 AM, Aleksej Saushev <asau@...> wrote: > And from my user point of view, Axiom should adopt either FriCAS' or > OpenAxiom's build system, whatever is closer, or develop similar one, A while ago, I rewrote Axiom's build system to use Autoconf and restructured the Makefiles so that people  most of the time  just say configure && make && make install That work is in the buildimprovements branch. That is the branch that both OpenAxiom and FriCAS use as common basis. The work is still there for Axiom to benefit from.  Gaby 
From: Gabriel Dos Reis <gdr@in...>  20090411 14:16:20

On Sat, Apr 11, 2009 at 12:26 AM, Scott Morrison <scott.c.morrison@...> wrote: > As Dick Jenks explained it to me when I joined the Axiom project in 1984, > the Boot language was intended as a bootstrap step to eventually implement > the entire system in the Spad language. The idea was first to convert to a > language that was syntactically similar to Spad, then convert it to actually > use Spad. Of course the second step never happened. That's why the > language was named Boot. > While Boot does have the semantics of Lisp, to me, the distinguishing > feature is it's very nice syntax for list pattern matching. You can do the > same things in Lisp, but the syntactic elegance of Boot for pattern matching > is undeniable. It was so nice that we got away without real structured data > throughout the entire project. I love the syntax: I couldn't agree more. I think Boot was a real master piece  just look at the size of the parser and translator. Yes, definitely the pattern matching syntax is really nice.  Gaby 
From: Ralf Hemmecke <ralf@he...>  20090407 09:05:38

> Having looked at this code in more detail I find I have doubts about > Gaby's claim: "those domains can be profitably rewritten without > having to know how FreeModule is implemented". It seems likely to me > that any attempt to do so could result in a significant loss of > performance in a very critical and central part of the panAxiom > library. If performance suffers then the compiler must improve. I don't see a reason why the compiler couldn't optimize away needless function wrappers. > Of course we can retain the current notation in panAxiom that allows > Rep to be explicitly specified, separate from 'add', but if we want a > less idiosyncratic approach were Rep is tied to addinheritance it > seems to me we need to seriously consider the option I mentioned > earlier of making the (default?) Rep X in > > A: C2 == add > Rep == X > > equal to the Rep of C2 and not C2 itself. I think that before choosing > either option for the treatment of addinheritance and Rep, it would > be a worthwhile project to attempt to convert the above addchain to > the 'Rep==C2' style of representation and to evaluate the impact that > that might have on performance. Bill, you think too much in terms of having all the sources available. But imagine that you had no chance in looking inside the domain you inherit from. You are definitely not told about the internal representation. If you just get Rep(X) as you proposed, then what type would that have, i.e. what functions can you apply to elements of Rep(X)? Where would you look for them? Note that X hides its implementation details. If one really exports Rep(X) that is against the information hiding principle and you need lots of programmer's discipline to produce code that does what it should do. I am sure, you already know the implementation of PrimitiveArray in LibAldor. http://svn.origo.ethz.ch/wsvn/algebraist/trunk/aldor/lib/aldor/src/datastruc/sal_parray.as PrimitiveArray(T:Type): PrimitiveArrayType T == add { import from Machine; #if DEBUG Rep == Record(sz:Z, data:Arr); local size(x:%):Z == { import from Rep; { empty? x => 0; rep(x).sz }} local arr(x:Arr, n:Z):% == { import from Rep; { zero? n => empty; per [n,x]}} local data(x:%):Arr == { import from Rep; empty? x => (nil$Pointer) pretend Arr; rep(x).data; } #else Rep == Arr; local data(x:%):Arr == rep x; local arr(x:Arr, n:Z):% == per x; local arr(x:Arr):% == per x; #endif ... } Now suppose you want to implement a SortedPrimitiveArray (in a file sortarr.as) like SortedPrimitiveArray(T: OrderedType): PrimitiveArrayType T == PrimitiveArray(T) add { Rep == X; ... } what would you write for X? And what is the type of X? Note that you are not allowed to look inside the source code for PrimitiveArray. Furthermore, SortedPrimitiveArray should produce noncrashing code for the compilation "aldor sortarr.as" as well as for the compilation "aldor DDEBUG sortarr.as". What options for X do you really have under these constraints? Ralf 
From: Bill Page <bill.page@ne...>  20090406 16:33:43

On Thu, Apr 2, 2009 at 4:27 PM, Ralf Hemmecke wrote: > >>  Note: This code is currently the same in both FriCAS and OpenAxiom. >> >> OpenAxiom issues this warning: >> >> Warnings: >> [1] OpenAxiom suggests removing assignment to Rep > > Very nice. > >>  Since BinarySearchTree is a particular class of BinaryTree for >>  consistency in BinarySearchTree I would expect to see: >>  >>  Implementation == BinaryTree(S) add >>  Rep == List Tree S > >> As I said, I would not. I would not expect any definition of Rep at >> all. The domain extension says BinaryTree(S) is the Rep of >> BinarySearchTree(S). > > In fact, in addinherited domains > > D: C == A add > Rep == X > ... > > one should not even be allowed to ever write anything else for X than > just A. I think OpenAxiom is right to remove the necessity of the > (redundant line "Rep == A"). > > And why would one want that in Rep==X, X must be the same as A? Because > suppose that A is defined like > > A: C2 == add > Rep == X > ... > > and for some reason you decide (as a maintainer for A) that it would be > better to change your internal (not exported) representation from X to Y > in an incompatible way (for example, Y=List(X)), then recompilation will > break at compiling D, since then A and X have different underlying > bitlayout. > I have been thinking about this for a while and I find that I am not (yet) convinced by the arguments of Ralf and Gaby. I appreciate the desire to avoid "leakage" of internal implementation details into code that depends on external packages and domains, but it seems to me that the concept of representation (as implemented by Rep, rep and per) does in fact explicitly allow this in a fairly controlled manner  and I think that the current panAxiom library seems to take good advantage of that. I think this treatment of Rep in SPAD makes it different than most (all?) other programming languages. If we decide to tie Rep directly to add in the manner described by Gaby and Ralf, and as currently implemented in OpenAxiom, and if that became the only way to introduce Rep, then SPAD would seem to become a language not so different than most other objectoriented languages, e.g. Python, that depend class inheritance (so called: subclassing) as the only builtin mechanism for implementing representation. It is interesting perhaps to compare Sage which does implement some additional notions related to representation by adding the "parent" structure on top of Python. Take a look at the following addchains: xlpoly.spad.pamphlet: LiePolynomial == FreeModule1 add TERM ==> Record(k: LWORD, c: R Rep := List TERM LieExponentials == XPBWPolynomial add Rep := XPBWPolynomial XPBWPolynomial == FreeModule1 add TERM ==> Record(k:BASIS, c:R) LTERMS ==> List(TERM) Rep:= LTERMS xpoly.spad.pamphlet: XDistributedPolynomial == XPolynomialRing add TERM ==> Record(k:WORD, c:R) Rep := List TERM XPolynomialRing == FreeModule1 add TERM ==> Record(k: E, c: R) Rep:= List TERM FreeModule1 == FreeModule add TERM ==> Record(k:S,c:R) Rep := List TERM poly.spad.pamphlet UnivariatePolynomial == SparseUnivariatePolynomial add Rep:=SparseUnivariatePolynomial(R) SparseUnivariatePolynomial == PolynomialRing add Term := Record(k:NonNegativeInteger,c:R) Rep := List Term PolynomialRing == FreeModule add Term:= Record(k:E,c:R) Rep:= List Term FreeModule == IndexedDirectProductAbelianGroup add Term:= Record(k:S,c:R) Rep:= List Term indexedp.spad.pamphlet: IndexedDirectProductAbelianGroup == IndexedDirectProductAbelianMonoid add Term:= Record(k:S,c:A) Rep:= List Term IndexedDirectProductOrderedAbelianMonoid == IndexedDirectProductAbelianMonoid add Term:= Record(k:S,c:A) Rep:= List Term IndexedDirectProductAbelianMonoid == IndexedDirectProductObject add Term:= Record(k:S,c:A) Rep:= List Term IndexedDirectProductObject == add Rep:= List Term There are only two cases in the chains above where the current add domain is chosen as Rep. Having looked at this code in more detail I find I have doubts about Gaby's claim: "those domains can be profitably rewritten without having to know how FreeModule is implemented". It seems likely to me that any attempt to do so could result in a significant loss of performance in a very critical and central part of the panAxiom library. Of course we can retain the current notation in panAxiom that allows Rep to be explicitly specified, separate from 'add', but if we want a less idiosyncratic approach were Rep is tied to addinheritance it seems to me we need to seriously consider the option I mentioned earlier of making the (default?) Rep X in A: C2 == add Rep == X equal to the Rep of C2 and not C2 itself. I think that before choosing either option for the treatment of addinheritance and Rep, it would be a worthwhile project to attempt to convert the above addchain to the 'Rep==C2' style of representation and to evaluate the impact that that might have on performance. Regards, Bill Page. 
From: Ralf Hemmecke <ralf@he...>  20090402 20:52:46

>  Note: This code is currently the same in both FriCAS and OpenAxiom. > > OpenAxiom issues this warning: > > Warnings: > [1] OpenAxiom suggests removing assignment to Rep Very nice. >  Since BinarySearchTree is a particular class of BinaryTree for >  consistency in BinarySearchTree I would expect to see: >  >  Implementation == BinaryTree(S) add >  Rep == List Tree S > As I said, I would not. I would not expect any definition of Rep at > all. The domain extension says BinaryTree(S) is the Rep of > BinarySearchTree(S). In fact, in addinherited domains D: C == A add Rep == X ... one should not even be allowed to ever write anything else for X than just A. I think OpenAxiom is right to remove the necessity of the (redundant line "Rep == A"). And why would one want that in Rep==X, X must be the same as A? Because suppose that A is defined like A: C2 == add Rep == X ... and for some reason you decide (as a maintainer for A) that it would be better to change your internal (not exported) representation from X to Y in an incompatible way (for example, Y=List(X)), then recompilation will break at compiling D, since then A and X have different underlying bitlayout. Ralf 
From: Gabriel Dos Reis <gdr@cs...>  20090402 19:58:34

Bill Page <bill.page@...> writes:  On Thu, Apr 2, 2009 at 2:19 PM, Gabriel Dos Reis <gdr@...> wrote:  > Bill Page writes:  >  >  Since BinarySearchTree is a particular class of BinaryTree for  >  consistency in BinarySearchTree I would expect to see:  >   >  ═Implementation == BinaryTree(S) add  >  ═ ═Rep == List Tree S  >  > As I said, I would not. ═I would not expect any definition of Rep  > at all. ═ The domain extension says BinaryTree(S) is the Rep of  > BinarySearchTree(S).  >   Sorry, then this is my confusion. confusion seems cleared then.  As I said, I expected that the Rep  of BinarySearchTree should be the same as the Rep of the domain from  which it inherits  *not* the domain itself. I think that is unnecessary leakage. Indeed, if I understand your description correctly, 'rep' would return a value of the Rep of old domain, this achieve the effective effect of exporting Rep  because, you can now write functions to get access to that representation. That breaks abstraction. On the other hand, if BinaryTree(S) is the Rep, any change in the representation of BinaryTree(S)'s Rep will not leak out. This is one of the advantages of using abstract datatypes. Note that at the VMlevel, the Rep will be the same  by simple transitivity.  My (perhaps poor) understanding of addinheritance   NewDomain(): with  ... exports ...  == OldDomain add  ... body ...   was that all functions and constants defined in the OldDomain  (regardless of whether they are exported or not) are visible to code  in the body of the new domain. Is that true or not? What do you mean by 'visible'? The semantics is that only functions exported by OldDomain are available. NewDomain does not have any special access to OlDomain's nonexported functions, no more than any other domain.  In the Axiom Book it says:   13.8 Add Domain  ...  The Implementation part of a definition can optionally specify an ⌠add  domain■ to the left of an add (for QuadraticForm, defines SquareMatrix(n,K)  is the adddomain). The meaning of an adddomain is simply this: if the cap  sule part of the Implementation does not supply a function for an operation,  Axiom goes to the adddomain to find the function.     Perhaps it is not so clear what "Axiom goes to the adddomain to find  the function" means.   In clifford.spad.pamphlet I see:   SM ==> SquareMatrix  ...  Impl ==> SM(n,K) add  Rep := SM(n,K)   which obviously corresponds to your interpretation, Gaby. Yes. I must emphasize that the above is about exported function. Nonexported functiosn don't cross abstraction barriers (the capsule.)  There are numerous other examples of this in the library.   But in 'xlpoly.spad.pamphlet' I see:   LiePolynomial(VarSet:OrderedSet, R:CommutativeRing) : Public == Private where  ...  Private == FreeModule1(R, LWORD) add  import(TERM)   representation  Rep := List TERM   and in 'xpoly.spad.pamphlet' we have: This is a breakage of the capsule abstraction barrier. One that I've always thought should be fixed. However, it is not one that is urgent because those constructs are so few in number.   FreeModule1(R:Ring,S:OrderedSet): FMcat == FMdef where  ...  FMdef == FreeModule(R,S) add   representation  Rep := List TERM   and in 'poly.spad.pamphlet':   FreeModule(R:Ring,S:OrderedSet):  Join(BiModule(R,R),IndexedDirectProductCategory(R,S)) with  if R has CommutativeRing then Module(R)  == IndexedDirectProductAbelianGroup(R,S) add  representations  Term:= Record(k:S,c:R)  Rep:= List Term  ...   which looks more like what I expected to find. >From my perspective, these are abstraction barrier breakage. I think those domains can be profitably rewritten without having to know how FreeModule is implemented. There is exactly one case where I'm undecided about what to do  that is about a domain I introduced in OpenAxiom. But, I don't think the solution needs leakage of implementation details.  Gaby 
From: Bill Page <bill.page@ne...>  20090402 19:31:32

On Thu, Apr 2, 2009 at 2:19 PM, Gabriel Dos Reis <gdr@...> wrote: > Bill Page writes: > >  Since BinarySearchTree is a particular class of BinaryTree for >  consistency in BinarySearchTree I would expect to see: >  >  Implementation == BinaryTree(S) add >  Rep == List Tree S > > As I said, I would not. I would not expect any definition of Rep > at all. The domain extension says BinaryTree(S) is the Rep of > BinarySearchTree(S). > Sorry, then this is my confusion. As I said, I expected that the Rep of BinarySearchTree should be the same as the Rep of the domain from which it inherits  *not* the domain itself. My (perhaps poor) understanding of addinheritance NewDomain(): with ... exports ... == OldDomain add ... body ... was that all functions and constants defined in the OldDomain (regardless of whether they are exported or not) are visible to code in the body of the new domain. Is that true or not? In the Axiom Book it says: 13.8 Add Domain ... The Implementation part of a definition can optionally specify an “add domain” to the left of an add (for QuadraticForm, defines SquareMatrix(n,K) is the adddomain). The meaning of an adddomain is simply this: if the cap sule part of the Implementation does not supply a function for an operation, Axiom goes to the adddomain to find the function.  Perhaps it is not so clear what "Axiom goes to the adddomain to find the function" means. In clifford.spad.pamphlet I see: SM ==> SquareMatrix ... Impl ==> SM(n,K) add Rep := SM(n,K) which obviously corresponds to your interpretation, Gaby. There are numerous other examples of this in the library. But in 'xlpoly.spad.pamphlet' I see: LiePolynomial(VarSet:OrderedSet, R:CommutativeRing) : Public == Private where ... Private == FreeModule1(R, LWORD) add import(TERM) representation Rep := List TERM and in 'xpoly.spad.pamphlet' we have: FreeModule1(R:Ring,S:OrderedSet): FMcat == FMdef where ... FMdef == FreeModule(R,S) add  representation Rep := List TERM and in 'poly.spad.pamphlet': FreeModule(R:Ring,S:OrderedSet): Join(BiModule(R,R),IndexedDirectProductCategory(R,S)) with if R has CommutativeRing then Module(R) == IndexedDirectProductAbelianGroup(R,S) add representations Term:= Record(k:S,c:R) Rep:= List Term ... which looks more like what I expected to find. >  Note: The 2nd line above is not required in OpenAxiom. > > And I think that is a coherent, simple notation for a simple semantics. > If were true that functions local to OldDomain are available in NewDomain and if the Rep in NewDomain is just OldDomain then I would be worried about how to correctly call these functions. Regards, Bill Page. 
From: Gabriel Dos Reis <gdr@cs...>  20090402 18:19:25

Bill Page <bill.page@...> writes:  >  On Thu, Apr 2, 2009 at 12:06 AM, Gabriel Dos Reis wrote:  >  > If you're not proposing to export the Rep, then your proposal is a bit  >  > obscure to me. Would you mind clarifying why the above does not  >  > amount to exporting the Rep of SomeDomain?  >  >  > Bill Page wrote:  >  Because it is not part of the 'with' clause and appears to the right  >  of ==.  >   On Thu, Apr 2, 2009 at 10:38 AM, Gabriel Dos Reis wrote:  > But with your construct, in the capsule I would be able to tell what  > Rep(SomeDomain) is. That reveals the Rep of SomeDomain, and  > effectively exports it.  >   Let's take a real example from 'src/algebra/tree.spad.pamphlet': I already addressed this in my previous mail. [...]  Note: This code is currently the same in both FriCAS and OpenAxiom. OpenAxiom issues this warning: Warnings: [1] OpenAxiom suggests removing assignment to Rep  Since BinarySearchTree is a particular class of BinaryTree for  consistency in BinarySearchTree I would expect to see:   Implementation == BinaryTree(S) add  Rep == List Tree S As I said, I would not. I would not expect any definition of Rep at all. The domain extension says BinaryTree(S) is the Rep of BinarySearchTree(S).  Note: The 2nd line above is not required in OpenAxiom. And I think that is a coherent, simple notation for a simple semantics. 
From: Gabriel Dos Reis <gdr@cs...>  20090402 18:15:38

Bill Page <bill.page@...> writes:  >  On Thu, Apr 2, 2009 at 12:06 AM, Gabriel Dos Reis wrote:  >  > If you're not proposing to export the Rep, then your proposal is a bit  >  > obscure to me. Would you mind clarifying why the above does not  >  > amount to exporting the Rep of SomeDomain?  >  >  > Bill Page wrote:  >  Because it is not part of the 'with' clause and appears to the right  >  of ==.  >   On Thu, Apr 2, 2009 at 10:38 AM, Gabriel Dos Reis wrote:  > But with your construct, in the capsule I would be able to tell what  > Rep(SomeDomain) is. That reveals the Rep of SomeDomain, and  > effectively exports it.  >   Let's take a real example from 'src/algebra/tree.spad.pamphlet':   <<domain BSTREE BinarySearchTree>>=  )abbrev domain BSTREE BinarySearchTree  ++ Description: BinarySearchTree(S) is the domain of  ++ a binary trees where elements are ordered across the tree.  ++ A binary search tree is either empty or has  ++ a value which is an S, and a  ++ right and left which are both BinaryTree(S)  ++ Elements are ordered across the tree.  BinarySearchTree(S: OrderedSet): Exports == Implementation where  Exports == BinaryTreeCategory(S) with  binarySearchTree: List S > %  ++ binarySearchTree(l) \undocumented  insert_!: (S,%) > %  ++ insert!(x,b) inserts element x as leaves into binary search tree b.  insertRoot_!: (S,%) > %  ++ insertRoot!(x,b) inserts element x as a root of binary search tree b.  split: (S,%) > Record(less: %, greater: %)  ++ split(x,b) splits binary tree b into two trees, one with  elements greater  ++ than x, the other with elements less than x.  Implementation == BinaryTree(S) add  Rep := BinaryTree(S)  binarySearchTree(u:List S) ==  null u => empty()  tree := binaryTree(first u)  for x in rest u repeat insert_!(x,tree)  tree  insert_!(x,t) ==  empty? t => binaryTree(x)  x >= value t =>  setright_!(t,insert_!(x,right t))  t  setleft_!(t,insert_!(x,left t))  t  split(x,t) ==  empty? t => [empty(),empty()]  x > value t =>  a := split(x,right t)  [node(left t, value t, a.less), a.greater]  a := split(x,left t)  [a.less, node(a.greater, value t, right t)]  insertRoot_!(x,t) ==  a := split(x,t)  node(a.less, x, a.greater)   @   Apparently your analysis would require that 'BinaryTree(S)' is  "effectively exported" but of course it is not. And of course, that is not my reasoning. My reasoning, the semantics implemented in OpenAxiom, is that BinaryTree(S) is the Rep of BinarySearchTree(S). And it is never exported. And the assignment Rep := BinaryTree(S) is redundant, and OpenAxiom will issue a warning Warnings: [1] OpenAxiom suggests removing assignment to Rep and if you try to assign a different value, you should get an error.  In my proposal one  would write:   Implementation == Rep BinaryTree(S) add  binarySearchTree(u:List S) ==  null u => empty()  ... In OpenAxiom, you just leave out the leading Rep, and you are just fine. I confess I do not see the benefit of your proposed notation, since the semantics you want it already there with less to write.   I can see no reason why this might imply to someone that BinaryTree(S)  is somehow "exported" when the example above does not. I had assumed that you were somehow familiar with the OpenAxiom semantics, and consequently you were proposing an enhancement which I could not see. It turns out that, the proposal was a confusing notation for something already implemented.     But there is an interesting problem in the example above.  BinaryTree(S) is *both* addinherited and specified as Rep. This is a  mistake. Yes. One that is warned about by OpenAxiom.  We should not say that a BinarySearchTree is represented as a  BinaryTree but rather that a BinarySearchTree is a particular class of  BinaryTree, i.e one where the nodes of the tree are in a specific  order. They share the same underlying representation but they are  constructed by a slightly different set of methods.   The Rep of BinaryTree(S) is 'List Tree S':   <<domain BTREE BinaryTree>>=  )abbrev domain BTREE BinaryTree  ++ Description: \spadtype{BinaryTree(S)} is the domain of all  ++ binary trees. A binary tree over \spad{S} is either empty or has  ++ a \spadfun{value} which is an S and a \spadfun{right}  ++ and \spadfun{left} which are both binary trees.  BinaryTree(S: SetCategory): Exports == Implementation where  Exports == BinaryTreeCategory(S) with  binaryTree: S > %  ++ binaryTree(v) is an nonempty binary tree  ++ with value v, and left and right empty.  binaryTree: (%,S,%) > %  ++ binaryTree(l,v,r) creates a binary tree with  ++ value v with left subtree l and right subtree r.  Implementation == add  Rep := List Tree S  t1 = t2 == (t1::Rep) =$Rep (t2::Rep)  ...   Note: This code is currently the same in both FriCAS and OpenAxiom.   Since BinarySearchTree is a particular class of BinaryTree for  consistency in BinarySearchTree I would expect to see:   Implementation == BinaryTree(S) add  Rep == List Tree S In fact, I do not expect this at all. It is just an invitation for breaking abstraction barrier, and maintaince nightmarre. I do not expect a Rep definition in an domain extension. Currently the OpenAxiom library violates that principle only in the cases where the representation are the same. I have no plan to encourage that.  Note: The 2nd line above is not required in OpenAxiom. Exactly.  But then we must change the implementation slightly.   binarySearchTree(u:List S) ==  tree := empty()  for x in u repeat insert_!(x,tree)  tree  insert_!(x,t) ==  empty? t => node(t,x,t)  x >= value t =>  setright_!(t,insert_!(x,right t))  t  setleft_!(t,insert_!(x,left t))  t I do not understand what you mean   >  Similarly, the operations of OldDomain are not automatically  >  exported in  >   >  Foo(...): with  >  ...  >  == OldDomain add  >  ... rep ... per ...  >    That is my main point. The next paragraph in my email was misplaced. I  am sorry for the resulting confusion.   >  The result is exactly the same as if I had written:  >   >  Foo(...): with  >  ...  >  == add  >  Rep==SomeDomain  >  ... rep ... per ...  >  > No, the result is not the same. In the second form, you'll have to  > write bunch of functions (for Foo) that implement functions  > implemented by OldDomain and exported by both.  >   I only meant to repeat here that the intended semantics of   > # Foo(...): with  > # ...  > # == Rep(SomeDomain) add  > # ... rep ... per ...   is exactly the same as writing:   >  Foo(...): with  >  ...  >  == add  >  Rep==SomeDomain  >  ... rep ... per ...   Regards,  Bill Page. 
From: Bill Page <bill.page@ne...>  20090402 17:01:02

>  On Thu, Apr 2, 2009 at 12:06 AM, Gabriel Dos Reis wrote: >  > If you're not proposing to export the Rep, then your proposal is a bit >  > obscure to me. Would you mind clarifying why the above does not >  > amount to exporting the Rep of SomeDomain? >  > > Bill Page wrote: >  Because it is not part of the 'with' clause and appears to the right >  of ==. > On Thu, Apr 2, 2009 at 10:38 AM, Gabriel Dos Reis wrote: > But with your construct, in the capsule I would be able to tell what > Rep(SomeDomain) is. That reveals the Rep of SomeDomain, and > effectively exports it. > Let's take a real example from 'src/algebra/tree.spad.pamphlet': <<domain BSTREE BinarySearchTree>>= )abbrev domain BSTREE BinarySearchTree ++ Description: BinarySearchTree(S) is the domain of ++ a binary trees where elements are ordered across the tree. ++ A binary search tree is either empty or has ++ a value which is an S, and a ++ right and left which are both BinaryTree(S) ++ Elements are ordered across the tree. BinarySearchTree(S: OrderedSet): Exports == Implementation where Exports == BinaryTreeCategory(S) with binarySearchTree: List S > % ++ binarySearchTree(l) \undocumented insert_!: (S,%) > % ++ insert!(x,b) inserts element x as leaves into binary search tree b. insertRoot_!: (S,%) > % ++ insertRoot!(x,b) inserts element x as a root of binary search tree b. split: (S,%) > Record(less: %, greater: %) ++ split(x,b) splits binary tree b into two trees, one with elements greater ++ than x, the other with elements less than x. Implementation == BinaryTree(S) add Rep := BinaryTree(S) binarySearchTree(u:List S) == null u => empty() tree := binaryTree(first u) for x in rest u repeat insert_!(x,tree) tree insert_!(x,t) == empty? t => binaryTree(x) x >= value t => setright_!(t,insert_!(x,right t)) t setleft_!(t,insert_!(x,left t)) t split(x,t) == empty? t => [empty(),empty()] x > value t => a := split(x,right t) [node(left t, value t, a.less), a.greater] a := split(x,left t) [a.less, node(a.greater, value t, right t)] insertRoot_!(x,t) == a := split(x,t) node(a.less, x, a.greater) @ Apparently your analysis would require that 'BinaryTree(S)' is "effectively exported" but of course it is not. In my proposal one would write: Implementation == Rep BinaryTree(S) add binarySearchTree(u:List S) == null u => empty() ... I can see no reason why this might imply to someone that BinaryTree(S) is somehow "exported" when the example above does not.  But there is an interesting problem in the example above. BinaryTree(S) is *both* addinherited and specified as Rep. This is a mistake. We should not say that a BinarySearchTree is represented as a BinaryTree but rather that a BinarySearchTree is a particular class of BinaryTree, i.e one where the nodes of the tree are in a specific order. They share the same underlying representation but they are constructed by a slightly different set of methods. The Rep of BinaryTree(S) is 'List Tree S': <<domain BTREE BinaryTree>>= )abbrev domain BTREE BinaryTree ++ Description: \spadtype{BinaryTree(S)} is the domain of all ++ binary trees. A binary tree over \spad{S} is either empty or has ++ a \spadfun{value} which is an S and a \spadfun{right} ++ and \spadfun{left} which are both binary trees. BinaryTree(S: SetCategory): Exports == Implementation where Exports == BinaryTreeCategory(S) with binaryTree: S > % ++ binaryTree(v) is an nonempty binary tree ++ with value v, and left and right empty. binaryTree: (%,S,%) > % ++ binaryTree(l,v,r) creates a binary tree with ++ value v with left subtree l and right subtree r. Implementation == add Rep := List Tree S t1 = t2 == (t1::Rep) =$Rep (t2::Rep) ... Note: This code is currently the same in both FriCAS and OpenAxiom. Since BinarySearchTree is a particular class of BinaryTree for consistency in BinarySearchTree I would expect to see: Implementation == BinaryTree(S) add Rep == List Tree S Note: The 2nd line above is not required in OpenAxiom. But then we must change the implementation slightly. binarySearchTree(u:List S) == tree := empty() for x in u repeat insert_!(x,tree) tree insert_!(x,t) == empty? t => node(t,x,t) x >= value t => setright_!(t,insert_!(x,right t)) t setleft_!(t,insert_!(x,left t)) t >  Similarly, the operations of OldDomain are not automatically >  exported in >  >  Foo(...): with >  ... >  == OldDomain add >  ... rep ... per ... >  That is my main point. The next paragraph in my email was misplaced. I am sorry for the resulting confusion. >  The result is exactly the same as if I had written: >  >  Foo(...): with >  ... >  == add >  Rep==SomeDomain >  ... rep ... per ... > > No, the result is not the same. In the second form, you'll have to > write bunch of functions (for Foo) that implement functions > implemented by OldDomain and exported by both. > I only meant to repeat here that the intended semantics of > # Foo(...): with > # ... > # == Rep(SomeDomain) add > # ... rep ... per ... is exactly the same as writing: >  Foo(...): with >  ... >  == add >  Rep==SomeDomain >  ... rep ... per ... Regards, Bill Page. 
From: Gabriel Dos Reis <gdr@cs...>  20090402 14:38:58

Bill Page <bill.page@...> writes:  On Thu, Apr 2, 2009 at 12:06 AM, Gabriel Dos Reis wrote:  > Your earlier suggestion  >  > Bill Page <bill.page@...> writes:  > # On the other hand, if there is no OldDomain then it is necessary to  > # specify the domain that will represent this new domain. We could do it  > # like this:  > #  > # Foo(...): with  > # ...  > # == Rep(SomeDomain) add  > # ... rep ... per ...  >  > reads to me that somehow the Rep of SomeDomain is exported.  > I'm saying I would like to see datasets that demonstrate the clear  > benifits of exporting the representation of a domain.  >  > If you're not proposing to export the Rep, then your proposal is a bit  > obscure to me. Would you mind clarifying why the above does not  > amount to exporting the Rep of SomeDomain?  >   Because it is not part of the 'with' clause and appears to the right  of ==. But with your construct, in the capsule I would be able to tell what Rep(SomeDomain) is. That reveals the Rep of SomeDomain, and effectively exports it.  Similarly, the operations of OldDomain are not automatically  exported in   Foo(...): with  ...  == OldDomain add  ... rep ... per ...   The result is exactly the same as if I had written:   Foo(...): with  ...  == add  Rep==SomeDomain  ... rep ... per ... No, the result is not the same. In the second form, you'll have to write bunch of functions (for Foo) that implement functions implemented by OldDomain and exported by both.  In SPAD a natural variant might also allow replacement of the  parenthesis with indentation. For example:   Foo(...): with  ...  == Rep  Record(A: ...  B: ...)  add  ... rep ... per ...      The point of this construction is just to give Rep a more prominant  place in the SPAD syntax and make it syntactically incorrect to  specify Rep in the case of addinheritance or by placing it in some  odd location in the body of the domain. It is already the case that if you define Rep in an addinheritance, you get a diagnosyic. I don't understand the comment about 'odd'.  Gaby 
From: Bill Page <bill.page@ne...>  20090402 12:56:43

On Thu, Apr 2, 2009 at 12:06 AM, Gabriel Dos Reis wrote: > Your earlier suggestion > > Bill Page <bill.page@...> writes: > # On the other hand, if there is no OldDomain then it is necessary to > # specify the domain that will represent this new domain. We could do it > # like this: > # > # Foo(...): with > # ... > # == Rep(SomeDomain) add > # ... rep ... per ... > > reads to me that somehow the Rep of SomeDomain is exported. > I'm saying I would like to see datasets that demonstrate the clear > benifits of exporting the representation of a domain. > > If you're not proposing to export the Rep, then your proposal is a bit > obscure to me. Would you mind clarifying why the above does not > amount to exporting the Rep of SomeDomain? > Because it is not part of the 'with' clause and appears to the right of ==. Similarly, the operations of OldDomain are not automatically exported in Foo(...): with ... == OldDomain add ... rep ... per ... The result is exactly the same as if I had written: Foo(...): with ... == add Rep==SomeDomain ... rep ... per ... In SPAD a natural variant might also allow replacement of the parenthesis with indentation. For example: Foo(...): with ... == Rep Record(A: ... B: ...) add ... rep ... per ...  The point of this construction is just to give Rep a more prominant place in the SPAD syntax and make it syntactically incorrect to specify Rep in the case of addinheritance or by placing it in some odd location in the body of the domain. Regards, Bill Page. 
From: Gabriel Dos Reis <gdr@cs...>  20090402 04:06:36

Bill Page <bill.page@...> writes:  On Wed, Apr 1, 2009 at 11:27 PM, Gabriel Dos Reis wrote:  >  > In general, I like the abstract datatype approach taken by both  > OpenAxiom and Aldor. I would like to see critical use cases and  > sound programming styles or scalable idioms that are eased by  > exposing implementation details by exporting Rep.  >   I am not sure I understand. Are you proposing that the Rep of a domain  should be exported or that it should *not* be exported? If it is the  latter, then I agree. Your earlier suggestion # On the other hand, if there is no OldDomain then it is necessary to # specify the domain that will represent this new domain. We could do it # like this: # # Foo(...): with # ... # == Rep(SomeDomain) add # ... rep ... per ... reads to me that somehow the Rep of SomeDomain is exported. I'm saying I would like to see datasets that demonstrate the clear benifits of exporting the representation of a domain. If you're not proposing to export the Rep, then your proposal is a bit obscure to me. Would you mind clarifying why the above does not amount to exporting the Rep of SomeDomain?  Of course there are domains in the Axiom library  right now for which this is not true. I know of exactly one instance, and I've documented that horrible case.  I think there are some cases  where correct functioning depends on the fact that one or more domains  share the same underlying representation. The OpenAxiom compiler warns in such cases, and give suggestions.  But I believe that with a  little more programming effort these could be completely eliminated. Indeed.  Gaby 
From: Gabriel Dos Reis <gdr@cs...>  20090402 03:27:51

Bill Page <bill.page@...> writes: [...]  Notice that the "add" keyword introduces a domain from which some code  and it's associated **representation** while be inherited, so really  there is no need to specify Rep in the following case:   Foo(...): with  ...  == OldDomain add  ... rep ... per ... This construct is already supported by OpenAxiom, with the uses of 'rep' and 'per' as usual. The difference with what you want, I think, is that this is the construct for extending OldDomain into Foo. Consequently, OldDomain must export a subset of the signatures exported by Foo. At the moment, you only get a warning if you fail to meet that requirement, but that may change in the near future.  The Rep in Foo must be the same as Rep in OldDomain. The semantics of the above construct in OpenAxiom is that OldDomain domain becomes the Rep of Foo. Consequently, both Foo and OldDomain are conformant to each other (this is a theorem), e.g. their VMlevel representations are the same.  On the other hand, if there is no OldDomain then it is necessary to  specify the domain that will represent this new domain. We could do it  like this:   Foo(...): with  ...  == Rep(SomeDomain) add  ... rep ... per ... In general, I like the abstract datatype approach taken by both OpenAxiom and Aldor. I would like to see critical use cases and sound programming styles or scalable idioms that are eased by exposing implementation details by exporting Rep.  The general semantics of Rep(SomeDomain) would be exactly the same as   Rep == SomeDomain   in Aldor and OpenAxiom.  Gaby 