[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

class method namespace - how to

Helmut Jarausch

4/1/2015 12:16:00 PM

(I think) I've understood the principles of CLOS and its generic functions instead of
methods in C++, Python et al.
Still I'm missing one link:
In C++, et al, a method belongs to the 'implicit namespace' (not a technical term)
generated by the class, e.g. the method foo of class Class has the name
Class::foo.
On the other hand, a generic function / method in CLOS is not part of any class.
Therefore it 'lives' in the package where it has been defined.

So, how can I have a "local namespace" for each class except defining each class in a separate package.
E.g., given several classes which (totally) different 'process' methods with incompatible parameter lists, these cannot be switched by one generic function
unless I use lots of optional parameters - which is ugly in this case.

Many thanks for bringing me from C++/Python to CLOS,
Helmut
6 Answers

Pascal J. Bourguignon

4/1/2015 2:17:00 PM

0

jarausch@skynet.be writes:

> So, how can I have a "local namespace" for each class except defining
> each class in a separate package.

You cannot.


Why do you define impossible conditions?
You could have asked:

- how can I have a "local namespace" for each class?
- how can I not define each class in a separate package?

each questions would have had a good answer, but no, you had to ask the
impossible conjunction!

Why?

> E.g., given several classes which (totally) different 'process'
> methods with incompatible parameter lists, these cannot be switched by
> one generic function

That's why packages are introduced. And that's why XML copied then
notion and renamed it "namespace"!

(defpackage "COMPUTER" (:use "CL") (:export "PROCESS"))
(defpackage "CHEMICAL" (:use "CL") (:export "PROCESS"))
(defpackage "ADMINISTRATIVE" (:use "CL") (:export "PROCESS"))

(defgeneric computer:process (p))
(defgeneric chemical:process (c))
(defgeneric administrative:process (a))



--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Nicolas Hafner

4/1/2015 2:28:00 PM

0

On 01/04/15 14:16, jarausch@skynet.be wrote:
> (I think) I've understood the principles of CLOS and its generic functions instead of
> methods in C++, Python et al.
> Still I'm missing one link:
> In C++, et al, a method belongs to the 'implicit namespace' (not a technical term)
> generated by the class, e.g. the method foo of class Class has the name
> Class::foo.
> On the other hand, a generic function / method in CLOS is not part of any class.
> Therefore it 'lives' in the package where it has been defined.
>
> So, how can I have a "local namespace" for each class except defining each class in a separate package.
> E.g., given several classes which (totally) different 'process' methods with incompatible parameter lists, these cannot be switched by one generic function
> unless I use lots of optional parameters - which is ugly in this case.
>
> Many thanks for bringing me from C++/Python to CLOS,
> Helmut
>

I wrote an article that explains how to add this kind of feature (I call
it class-bound methods) to CLOS using the MOP:
<https://reader.tymoon.eu/artic...

Unless I misunderstood what you want to do, that should explain it well
enough. It doesn't go quite into the depth of CLOS methods in that it
only supports primary methods and inheritance, no method combination.

--
http://everything.sh...

Helmut Jarausch

4/1/2015 2:44:00 PM

0

On Wednesday, 1 April 2015 16:25:36 UTC+2, informatimago wrote:
> jarausch@skynet.be writes:
>
> > So, how can I have a "local namespace" for each class except defining
> > each class in a separate package.
>
> You cannot.
>

Thanks Pascal.
I feared that packages are the only solution.
The, packages are a "substitute" for "class namespaces" as well as modules (in Python). I cannot say I like this combination.
Helmut

Helmut Jarausch

4/1/2015 2:46:00 PM

0

On Wednesday, 1 April 2015 16:27:56 UTC+2, Nicolas Hafner wrote:
> I wrote an article that explains how to add this kind of feature (I call
> it class-bound methods) to CLOS using the MOP:
> <https://reader.tymoon.eu/artic...
>

Thanks Nicolas, that's very interesting but a bit overkill at the moment.

Kaz Kylheku

4/1/2015 3:28:00 PM

0

On 2015-04-01, jarausch@skynet.be <jarausch@skynet.be> wrote:
> On Wednesday, 1 April 2015 16:25:36 UTC+2, informatimago wrote:
>> jarausch@skynet.be writes:
>>
>> > So, how can I have a "local namespace" for each class except defining
>> > each class in a separate package.
>>
>> You cannot.
>>
>
> Thanks Pascal.
> I feared that packages are the only solution.
> The, packages are a "substitute" for "class namespaces" as well as modules (in Python). I cannot say I like this combination.

"class namespace" is a mistake in language design; CLOS gets it right.

Think about it. You make a class "animal" and it has a slot "leg-count".

These are *symbols*.

Then you make a "bear" derived from "animal". The bear has a "leg-count".

This is the same symbol as the "leg-count" slot in "animal" and that is
why it refers to the same thing.

Now in some dumb languages like C++, the bear class can define its own leg-count.
That is still the same name, but now it refers to a different slot. The object
now has two slots called "leg-count". To distinguish them, the class name is
used: bear::leg-count versus animal::leg-count.

In the Lisp view, we have an object. The object has slots named by symbols.
And that's it. If there is a symbol leg-count, then that names a slot, and
only one slot in the entire object.

We do not have typed references to an object like "bear *" or "animal *" in C++.
(slot-value obj 'leg-count) just works on "the object", not "the object
regarded as an animal".

Moreover, in Lisp, the bear class *can* define leg-count also, even as it
inherits from animal. But this leg-count is understood as being the same slot.
Why would you do that? It is very useful: you can define the leg-count slot
of the bear class as being a "class slot": which means there is a single instance
of it shared by all bear instances. And you can make that instance have the
value 4. Poof: all bears automatically have four legs, even though not all
animals have four legs.

Note how in C++, bear::leg_count will "shadow" animal::leg_count if they
are "data members". But if "leg_count" is a virtual function in the animal
base class, then "bear::leg_count" will override it. The rules are inconsistent.
Soemtimes leg_count is the same thing, sometimes it isn't.

The absolute worst thing, though, is the idea that some pieces of code
are automatically in some class scope.

int foo_class::bar_func()
{
return x + y;
}

We don't know whether x or y are global variables or members. Of course,
we can get specific:

return this->x + ::y;

return foo_class::x + foo_class::y;

etc. But in the absence of these explicits, it is ambiguous. There is a surrounding
file scope, and into this scope, a class scope is imposed.

This is exactly like the ill-conceived WITH construct in Pascal:

with ^f ; begin (* f is a pointer to foo_record *)
z = x + y;
end

Suppose y is initially a global variable (or a local variable in an outer
scope). Then someone edits the foo_record (or foo_class) type so that y is now
a member. Oops, the meaning of x + y now silently changes; it no longer refers
to the global variable, but to foo_class::y. Or to ^f.y in the Pascal.

By manipulating type declarations, you're changing the meanings of expressions
which are considered to be in that scope, but are scattered elsewhere in the
program.

taruss

4/1/2015 9:36:00 PM

0

On Wednesday, April 1, 2015 at 5:16:38 AM UTC-7, jara...@skynet.be wrote:
> (I think) I've understood the principles of CLOS and its generic functions instead of
> methods in C++, Python et al.

Well, not entirely...

> Still I'm missing one link:
> In C++, et al, a method belongs to the 'implicit namespace' (not a technical term)
> generated by the class, e.g. the method foo of class Class has the name
> Class::foo.
> On the other hand, a generic function / method in CLOS is not part of any class.
> Therefore it 'lives' in the package where it has been defined.

Mostly correct. The generic function could also be using a name defined in another package that is visible in the current package via using, imports, etc.

Common Lisp has only a single[*] namespace mechanism, namely packages. If you want to have distinct, accessible names, they will have to be in different packages. So you don't get separate names associated with them.

>
> So, how can I have a "local namespace" for each class except defining each class in a separate package.

You can't. If you want the names to be separate you need them in different packages. You would need that in order to distinguish between the different names, since the symbols are differentiated at the package level.

I suppose that you could always use your own convention for local namespaces by, for example, adopting "!" or "." as your own namespace delimiting character and then write your functions like
class1!method class2!method or class1.method class2.method
since "!" and "." are just ordinary name characters, so you can just use them.
But then you always have to qualify the names and there is no other real namespace support. This is done by convention, for example in elisp, because it doesn't have real namespaces.


> E.g., given several classes which (totally) different 'process' methods with incompatible parameter lists, these cannot be switched by one generic function
> unless I use lots of optional parameters - which is ugly in this case.

This is where I think you haven't fully adopted the design philosophy of generic functions. You should not have generic functions with the same name that do radically different things. In other words, if you have a graphics:draw and a card-game:draw and a weapon:draw method, you want those methods to be in different packages because they represent different sorts of actions. You could then, for example, in some game have a playing-card object that supports both graphics:draw and card-game:draw, each of which has a very different effect.

So you don't want to have a shared name for very different sorts of operations. And if you introduced a separate namespace for each class, you wouldn't get any real method dispatch at all, because all of the generic functions would be different.

So what you need to do is figure out for each operation what a good name is for it, and use that name only for that one operation. But then share that operation name among all the methods that implement the same method, using the argument types to do the method selection for you. If you have a different operation, then you need to choose a different name, either by giving it a different symbol name or by using the same symbol name but having the symbols be in different packages.

If you think about it, having a local namespace for a class wouldn't help with method dispatch at all, especially given the multiple-dispatch that lies at the core of the generic function paradigm. How would you even choose which "class namespace" a generic function belongs in if it takes arguments of two different classes?

So, in summary, Common Lisp has separate mechanisms for classes (which encapsulate data and form a hierarchy), generic functions (which encapsulate a particular sort of computation that is carried out in various ways by using specialized methods), and namespaces (which is handled by packages). These are all orthogonal to each other.



[*] OK, if one wants to get pendantic, there are separate namespaces for looking up different things associated with the same symbol, such as value, function definition, class, etc.