stéphane ducasse wrote:
Hi Mike
we are heroically trying to clean Stream hierarchy (in fact making sure that the new and sexy one that damien is writing can be plugged in).
We are reading
PositionableStream>>pushBack: aString "Compatibility with SocketStreams" self skip: aString size negated
and it seems to me that pushBack argument is not good. It should not be a string but a number since it never take care of pushing back different elements in the stream but just moving the cursor of the stream.
Yes, but... On a SocketStream we can't position the cursor, once the characters are read they are no longer in the stream as there is no underlying collection. The buffer doesn't count, as the content can be replaced at any time during read or write.
Do you know if the method pushBack on the XMLTokenizer is ever used?
It's used when parsing and resolving entity definitions.
Michael
2007/8/2, Michael Rueger michael@impara.de:
stéphane ducasse wrote:
PositionableStream>>pushBack: aString "Compatibility with SocketStreams" self skip: aString size negated
and it seems to me that pushBack argument is not good. It should not be a string but a number since it never take care of pushing back different elements in the stream but just moving the cursor of the stream.
Yes, but... On a SocketStream we can't position the cursor, once the characters are read they are no longer in the stream as there is no underlying collection. The buffer doesn't count, as the content can be replaced at any time during read or write.
So? I don't understand your answer. In Squeak 3.8, 3.9 and 3.10, there is no other implementor of #pushBack nor is there any sender but XMLTokeniser.
Do you know if the method pushBack on the XMLTokenizer is ever used?
It's used when parsing and resolving entity definitions.
Can you put a 'self halt' on XMLTokeniser>>pushBack: and see if this method is ever called? I can't find any sender.
Damien Cassou wrote:
So? I don't understand your answer. In Squeak 3.8, 3.9 and 3.10, there is no other implementor of #pushBack nor is there any sender but XMLTokeniser.
Well, if you actually had cared to look you'll would have seen that it was in 3.8, but Goran's SocketStream which came in in 3.8.1 and 3.9 it is missing.
Do you know if the method pushBack on the XMLTokenizer is ever used?
It's used when parsing and resolving entity definitions.
Can you put a 'self halt' on XMLTokeniser>>pushBack: and see if this method is ever called? I can't find any sender.
There are three senders of pushBack: in XMLTokeniser.
And I sincerely hope that you are not cleaning up the Stream hierarchy in a way so that the rest of the community has then to struggle to make their stuff work again with the shiny new cleaned up hierarchy.
I'm not exactly bored right now...
Michael
2007/8/2, Michael Rueger michael@impara.de:
Damien Cassou wrote:
So? I don't understand your answer. In Squeak 3.8, 3.9 and 3.10, there is no other implementor of #pushBack nor is there any sender but XMLTokeniser.
Well, if you actually had cared to look you'll would have seen that it was in 3.8, but Goran's SocketStream which came in in 3.8.1 and 3.9 it is missing.
Ok, right. I tried on 3.8.1.
Do you know if the method pushBack on the XMLTokenizer is ever used?
It's used when parsing and resolving entity definitions.
Can you put a 'self halt' on XMLTokeniser>>pushBack: and see if this method is ever called? I can't find any sender.
There are three senders of pushBack: in XMLTokeniser.
Can you tell us which ones? I just found one and it does not seem to send #pushBack: to XMLTokeniser but to Stream.
And I sincerely hope that you are not cleaning up the Stream hierarchy in a way so that the rest of the community has then to struggle to make their stuff work again with the shiny new cleaned up hierarchy.
If this was the case, do you think we will bother asking the mailing list? What we are doing is:
- implementing a completely new Stream hierarchy which can work along with the current one. It's named Nile and there has been some announcements on this list about it. - implementing a lot of unit tests for the current Squeak hierarchy and Nile. - slowly studying all of the methods of the Stream hierarchy to find which one are useful, which one are buggy... - writing fixes to improve the current hierarchy (see the 3.10 mailing list archive and bugs.squeak.org for all the report I did on that hierarchy).
Stéphane and I are working hard to improve the current hierarchy and make Nile something worth to use.
Mike frankly I'm sad that you can say that - given that I know you - that the state of the stream hierarchy is so shitty and bad (I do not count the number of instance variables that are not used the overriding breaking behavior of some subclasses.....) - given that we always pay attention not to break code (but that indeed something we fixed broken behavior) - given that we are writing from scratch with test driven a new hierarchy.
And I sincerely hope that you are not cleaning up the Stream hierarchy in a way so that the rest of the community has then to struggle to make their stuff work again with the shiny new cleaned up hierarchy.
So even you can say this kind of shit to young guys willing to make squeak a better place to code, so I'm really sad. But I know in the future I should really create another Squeak like everybody else and do not really care.
I'm not exactly bored right now...
Michael
Stef
stephane ducasse wrote:
Mike frankly I'm sad that you can say that - given that I know you - that the state of the stream hierarchy is so shitty and bad (I do not count the number of instance variables that are not used the overriding breaking behavior of some subclasses.....) - given that we always pay attention not to break code (but that indeed something we fixed broken behavior) - given that we are writing from scratch with test driven a new hierarchy.
My (over)reaction probably was that way because I don't like the way Nile is designed at all...
But that's just my personal opinion and it wasn't my intention to doubt the effort you are putting into it.
Michael
2007/8/2, Michael Rueger michael@impara.de:
My (over)reaction probably was that way because I don't like the way Nile is designed at all...
What don't you like? If I have no feedback, I can't improve and learn.
But that's just my personal opinion and it wasn't my intention to doubt the effort you are putting into it.
Ok.
Even if finally we find that Nile must not replace the current hierarchy, we will have improve Squeak a lot. I've written hundreds of tests and they are now included in 3.10.
Damien Cassou wrote:
2007/8/2, Michael Rueger michael@impara.de:
My (over)reaction probably was that way because I don't like the way Nile is designed at all...
What don't you like? If I have no feedback, I can't improve and learn.
Unfortunately I don't have any time at all to provide extensive feedback.
I'm known (others would say notorious ;-) ) for being an extreme minimalist and Nile's structure just seems overly complicated to me.
But, I often don't like my own designs, just to put that statement into perspective ;-)
hierarchy, we will have improve Squeak a lot. I've written hundreds of tests and they are now included in 3.10.
Yes, and I appreciate this effort!
michael
2007/8/2, Michael Rueger michael@impara.de:
Damien Cassou wrote:
What don't you like? If I have no feedback, I can't improve and learn.
Unfortunately I don't have any time at all to provide extensive feedback.
I'm known (others would say notorious ;-) ) for being an extreme minimalist and Nile's structure just seems overly complicated to me.
We would also want to throw away most of the code.
Damien Cassou wrote:
What don't you like? If I have no feedback, I can't improve and learn.
One of the things that I personally don't like is that you seem to be repeating the same conceptual mistakes of the original library. For example, what is the *conceptual* difference between an NSReadableCollectionStream and an NSWriteableCollectionStream and an NSReadWriteCollectionStream? These seem arbitrary (and not very helpful) distinctions that would be better modeled by having a single NSCollectionStream which -if that is really necessary- has an attribute controlling whether it's going to be used read-only or not.
If I were to rewrite streams I'd actually start at a different point. Not by making these micro-distinctions about readability and writability (which seem to make up most of the traits in the version that I looked at) but rather define three basic types of streams: * Internal streams: Which are collections+cursor, providing the full collection interface to streams (which is hugely useful). * External streams: Which are modeling I/O (so they are potentially infinite sources, can block, are often asynchronous etc) * Translating streams: Which are streams that perform operations on other streams (CRLF conversions, compression, decompression)
If you were to structure a stream library along these lines I think you'll find that most of the uses for traits would go away because besides the core protocol (which would appear in class Stream) there is actually very little duplication of responsibilities in there.
Cheers, - Andreas
Thanks andreas This is indeed interesting.
In fact we follow the ansi decomposition and forced ourselves to be backward compatible to avoid that people complain as usual and bash us about wanting to break things and so on. But may be this was a mistake.
Now in the process we got a really good test suite for streams and we could rethink the traits recomposition. We should give some thoughts about your suggestions but thanks for having say that
Stef
On 3 août 07, at 00:37, Andreas Raab wrote:
Damien Cassou wrote:
What don't you like? If I have no feedback, I can't improve and learn.
One of the things that I personally don't like is that you seem to be repeating the same conceptual mistakes of the original library. For example, what is the *conceptual* difference between an NSReadableCollectionStream and an NSWriteableCollectionStream and an NSReadWriteCollectionStream? These seem arbitrary (and not very helpful) distinctions that would be better modeled by having a single NSCollectionStream which -if that is really necessary- has an attribute controlling whether it's going to be used read-only or not.
If I were to rewrite streams I'd actually start at a different point. Not by making these micro-distinctions about readability and writability (which seem to make up most of the traits in the version that I looked at) but rather define three basic types of streams:
- Internal streams: Which are collections+cursor, providing the
full collection interface to streams (which is hugely useful).
- External streams: Which are modeling I/O (so they are potentially
infinite sources, can block, are often asynchronous etc)
- Translating streams: Which are streams that perform operations on
other streams (CRLF conversions, compression, decompression)
If you were to structure a stream library along these lines I think you'll find that most of the uses for traits would go away because besides the core protocol (which would appear in class Stream) there is actually very little duplication of responsibilities in there.
Cheers,
- Andreas
2007/8/3, Andreas Raab andreas.raab@gmx.de:
Damien Cassou wrote:
What don't you like? If I have no feedback, I can't improve and learn.
One of the things that I personally don't like is that you seem to be repeating the same conceptual mistakes of the original library. For example, what is the *conceptual* difference between an NSReadableCollectionStream and an NSWriteableCollectionStream and an NSReadWriteCollectionStream? These seem arbitrary (and not very helpful) distinctions that would be better modeled by having a single NSCollectionStream which -if that is really necessary- has an attribute controlling whether it's going to be used read-only or not.
Thank you very much, I really appreciate that kind of feedback. And, without much more thinkning, I agree with you: we don't really need that distinction; it complicates things and this is not really useful. I will try and let the list know. However, we will break backward compatibility.
Do you suggest that we only need ReadWriteCollectionStream (which we have already)?
If I were to rewrite streams I'd actually start at a different point. Not by making these micro-distinctions about readability and writability (which seem to make up most of the traits in the version that I looked at)
There are 3 main traits:
- one for reading elements sequentially (you just have #next, #peek and derived methods like #do: #next:...) - one for writing elements (you just have #nextPut: and derived methods) - one for positioning in the stream (#position: #position...)
We chose this decomposition because it was the way ANSI defines Streams and to keep compatibility with the current stream hierarchy.
but rather define three basic types of streams:
- Internal streams: Which are collections+cursor, providing the full
collection interface to streams (which is hugely useful).
this is done but we could do better. For example, we have #do: and #select:, but other enumerating messages are missing. And #select: returns a new stream, not a collection. Is this what you are thinking about?
- External streams: Which are modeling I/O (so they are potentially
infinite sources, can block, are often asynchronous etc)
we already modeled File streams. It's incomplete however.
- Translating streams: Which are streams that perform operations on
other streams (CRLF conversions, compression, decompression)
This is done. Filters can be created easily.
If you were to structure a stream library along these lines I think you'll find that most of the uses for traits would go away because besides the core protocol (which would appear in class Stream) there is actually very little duplication of responsibilities in there.
I do not agree. We will see what I can do and will discuss about this later if you want. But, yes it's possible to avoid duplication, writing all the methods in the Stream class.
When you have a read-only stream (as with audio/video streams for example) you really don't want the writing protocol I think. In this case, you prefer using only the traits that make sense for your class.
Damien Cassou wrote:
If you were to structure a stream library along these lines I think you'll find that most of the uses for traits would go away because besides the core protocol (which would appear in class Stream) there is actually very little duplication of responsibilities in there.
I do not agree. We will see what I can do and will discuss about this later if you want. But, yes it's possible to avoid duplication, writing all the methods in the Stream class.
I understand that you can't possibly consider writing such a library without using traits ;-) But to be blunt, since traits are a form of MI, all the same methods of designing orthogonal systems apply that have for the last thirty years, and I'm pretty sure it's not only possible but actually (just as always with SI vs. MI) easier to understand.
Cheers, - Andreas
To be blunt back (but intending no disrespect of course, as I respect your code and conversational contributions a great deal), aren't you showing a bit of bias here? I see that you have a great dislike for MI and believe me, I share it with you. However you do see Java interfaces as a separate entity, no?
To me this is what Traits are, not a method of MI. And this is something missing we see in every "OO-ish" system. Ruby and Strongtalk (at least) made "mixins" to deal with it. Self went with something that looks like full-blown MI, etc., etc. What we seem to want in OO systems is basically a formalization of the protocols. Not just a textual category I can put the methods in, something first class. I can learn about an object by looking at the "interfaces", "traits" or "type classes" (which ever you prefer) it supports via runtime reflection. I know you can ask the classes what methods are in what categories but that isn't a guarantee; the classifications are pure convention.
Now, for sure people can abuse traits just as people abuse MI and even SI (look at half the Java hierarchies out there). In my first experience with Haskell type classes I abused them horribly to create effectively a class hierarchy. But misuse can indicate a faulty abstraction (e.g. MI IMO), or that we simply need better training with it.
In the case of Nile here, I have not personally seen the code and it may indeed be overly complex. But to get to a correct, intuitive stream system how would you deal with the fact that some streams are, by nature read-only and even write-only? Surely not by a "isReadOnly" variable switch?
Your concept of "Fixed Size", "Variable/Infinite Size" and "Transforming" is solid. But I think such a setup would be benefited with traits to make the first class distinction between "read", "write" or "read-write".
NOTE: Having said all this, my statements only stand for "state-less" traits. IMO "stateful" traits are exactly MI and therefor I am not a fan. :)
On 8/3/07, Andreas Raab andreas.raab@gmx.de wrote:
Damien Cassou wrote:
If you were to structure a stream library along these lines I think you'll find that most of the uses for traits would go away because besides the core protocol (which would appear in class Stream) there is actually very little duplication of responsibilities in there.
I do not agree. We will see what I can do and will discuss about this later if you want. But, yes it's possible to avoid duplication, writing all the methods in the Stream class.
I understand that you can't possibly consider writing such a library without using traits ;-) But to be blunt, since traits are a form of MI, all the same methods of designing orthogonal systems apply that have for the last thirty years, and I'm pretty sure it's not only possible but actually (just as always with SI vs. MI) easier to understand.
Cheers,
- Andreas
Jason Johnson wrote:
To be blunt back (but intending no disrespect of course, as I respect your code and conversational contributions a great deal), aren't you showing a bit of bias here? I see that you have a great dislike for MI and believe me, I share it with you. However you do see Java interfaces as a separate entity, no?
Yes. But the main reason is that Java interfaces a) implicitly encourage minimal interfaces (since you can't provide an implementation there is no reason to add anything but the minimal set of methods that need to be supported) and b) that they describe only the "what" (interface) not the "how" (implementation).
Contrast this with traits (or MI in general) where larger interfaces are implicitly encouraged (adding utility methods or "refactoring" the interface which ultimately leads to a *worse* interface which is much larger than it needs to be and that you can't get rid of since it's needed by the implementation) and the need to traverse a multitude of hierarchies to understand where some implementation comes from plus the need to disambiguate by renaming and you end up in a nice spaghetti bowl.
The ultimate problem with traits (MI) isn't state - it's that it drops the idea of encapsulation (objects staying individual entities) and simply merge the implementation into a common name space. That this isn't a great idea is known as far back as C's #include statement.
To me this is what Traits are, not a method of MI. And this is something missing we see in every "OO-ish" system. Ruby and Strongtalk (at least) made "mixins" to deal with it. Self went with something that looks like full-blown MI, etc., etc. What we seem to want in OO systems is basically a formalization of the protocols. Not just a textual category I can put the methods in, something first class. I can learn about an object by looking at the "interfaces", "traits" or "type classes" (which ever you prefer) it supports via runtime reflection. I know you can ask the classes what methods are in what categories but that isn't a guarantee; the classifications are pure convention.
Indeed. Having interfaces to describe what is expected of a particular responsibility is a very, very good idea. Sharing the implementations via MI-like mechanisms is not. Note however, that for example mixins preserve the encapsulation of objects in much stronger ways than traits by not merging the name spaces but rather constructing a unified inheritance chain. From my POV this is advantageous to what traits do.
In the case of Nile here, I have not personally seen the code and it may indeed be overly complex. But to get to a correct, intuitive stream system how would you deal with the fact that some streams are, by nature read-only and even write-only? Surely not by a "isReadOnly" variable switch?
Why not? I haven't seen very many streams which "by their nature" would be read-only or write-only. There are no such streams in Squeak for example; there are only those that have been made arbitrarily read-only (ReadStream) or that have attributes describing their readability state (FileStream). But even if there were, it is not clear to me that it is advantageous for a client to receive a MessageNotUnderstood instead of a ReadOnlyStream error. Since Squeak isn't statically typed, there is not much of an advantage here.
Cheers, - Andreas
On 8/4/07, Andreas Raab andreas.raab@gmx.de wrote:
Yes. But the main reason is that Java interfaces a) implicitly encourage minimal interfaces (since you can't provide an implementation there is no reason to add anything but the minimal set of methods that need to be supported) and b) that they describe only the "what" (interface) not the "how" (implementation).
Well that's one way for a language beat people into doing things the way it wants. :) But from what I have seen the inability to specify a default implementation causes people to either have the same code duplicated (which Java programmers don't mind because Java is a language one writes and uses tools to write), or hierarchies that make no sense, since they were only made to avoid duplication of code.
Contrast this with traits (or MI in general) where larger interfaces are
implicitly encouraged (adding utility methods or "refactoring" the interface which ultimately leads to a *worse* interface which is much larger than it needs to be and that you can't get rid of since it's needed by the implementation) and the need to traverse a multitude of hierarchies to understand where some implementation comes from plus the need to disambiguate by renaming and you end up in a nice spaghetti bowl.
Well, this is certainly true of MI, but it isn't true for type classes and I, therefore, don't believe it has to be this way for traits. It is a valid concern though and I have seen things already that look like what I would consider mis-uses of the technology (and for anyone who will ask, no I don't remember what, just methods too big for a trait IMO).
The ultimate problem with traits (MI) isn't state - it's that it drops
the idea of encapsulation (objects staying individual entities) and simply merge the implementation into a common name space. That this isn't a great idea is known as far back as C's #include statement.
If used that way then sure, of course you're right. But IMO traits are supposed to be a signal that says "I implement this protocol" in a first class manner. The fact that they allow you to define a default implementation is good to avoid code duplication but it should not be used to have a form of MI.
Indeed. Having interfaces to describe what is expected of a particular
responsibility is a very, very good idea. Sharing the implementations via MI-like mechanisms is not. Note however, that for example mixins preserve the encapsulation of objects in much stronger ways than traits by not merging the name spaces but rather constructing a unified inheritance chain. From my POV this is advantageous to what traits do.
Hrm, I guess I need to go dig deeper into exactly how mixins work because I don't understand what you mean here. I looked a little at Strongtalk mixins and they seemed to be a function that applied to a class to inject existing methods into it somehow. I mentally wrote it down as being the same thing as a Haskell type class and Squeak traits.
Why not? I haven't seen very many streams which "by their nature" would
be read-only or write-only. There are no such streams in Squeak for example; there are only those that have been made arbitrarily read-only (ReadStream) or that have attributes describing their readability state (FileStream). But even if there were, it is not clear to me that it is advantageous for a client to receive a MessageNotUnderstood instead of a ReadOnlyStream error. Since Squeak isn't statically typed, there is not much of an advantage here.
Cheers,
- Andreas
I was thinking of the user level, not the programmer level. For example, write-only streams would be /dev/null, one could see a UDP connection as a write-only as well as TCP in some cases (e.g. the data socket in an FTP transaction). Read-only are even more common (e.g. files on read-only media, files you have read-only access to, etc.).
I was also thinking of it as negative to have to have certain methods protected by a "isWritable/Readable" type flag in an OO language, but you bring up a good point about typing. On the other hand, in practice what the user will see is something like "ReadOnlyStream does not understand: writeData:", right? That would be just as informative to me as "ExternalStream is readonly", since once you see the DNU pop up you would say "oh yea, of course it doesn't understand writing", no?
Oh, and I forgot to mention:
I don't personally see traits as something that comes up that often. 99% of the time inheritance, or some OO pattern gives the best solution. But in that 1% something like a trait is the correct solution and not having it shows up a design wart.
Personally the thing that stuck out to me in my travels through the Squeak image was just the Magnitude class. I personally think that should just be a trait. In fact I would see at least equality and comparability as separate traits. By having it be a class causes certain design warts [1] imo.
[1] In the case where a class should really inherit somewhere else you either have to inherit from Magnitude and duplicate the other code, inherit from the correct class and duplicate the Magnitude code or change the highest class in your hierarchy to inherit from Magnitude instead of Object. These solutions are all code smell imo.
Jason Johnson a écrit :
Oh, and I forgot to mention:
I don't personally see traits as something that comes up that often. 99% of the time inheritance, or some OO pattern gives the best solution. But in that 1% something like a trait is the correct solution and not having it shows up a design wart.
Personally the thing that stuck out to me in my travels through the Squeak image was just the Magnitude class. I personally think that should just be a trait. In fact I would see at least equality and comparability as separate traits. By having it be a class causes certain design warts [1] imo.
[1] In the case where a class should really inherit somewhere else you either have to inherit from Magnitude and duplicate the other code, inherit from the correct class and duplicate the Magnitude code or change the highest class in your hierarchy to inherit from Magnitude instead of Object. These solutions are all code smell imo.
Very true. Try to extend algebra with matrices, vector space, or symbolic computation, and you will see that simple inheritance makes it hard to avoid duplications. This makes me think of axiom which has a separate hierarchy for inheriting mathematical properties...
Nicolas
Jason Johnson wrote:
I don't personally see traits as something that comes up that often. 99% of the time inheritance, or some OO pattern gives the best solution. But in that 1% something like a trait is the correct solution and not having it shows up a design wart.
I completely agree with this statement. And in return I *urge* you to look at actual code and stand corrected ;-) Let's take an example:
Here is what the base class hierarchy in Nile looks like:
AbstractCollectionStream ReadableCollectionStream ByteReader StringReader WritableCollectionStream ByteWriter StringWriter ReadWriteCollectionStream
Except from the -somewhat arbitrary- distinction between byte and string reader it's pretty standard and looks (if you replace AbstractCollectionStream with PositionableStream) fairly similar to what we have today:
PositionableStream ReadStream WriteStream ReadWriteStream
But now, let's look at how it works. Here is how the Nile class library looks when we add the traits (written as <trait>):
AbstractCollectionStream ReadableCollectionStream <ReadableCollectionStream - position, setPosition, collection, setCollection:> ByteReader <ByteReading - next, nextInto:, next:> StringReader <CharacterReading> WritableCollectionStream <NSTWriteableCollectionStream - position, setPosition:, collection, setCollection:> ByteWriter <ByteWriting - nextPut:, nextPutAll:> StringWriter <CharacterWriting - nextPut:> ReadWriteCollectionStream <ReadableCollectionStream - size, collection, setCollection:, position, setPosition:>
and the traits hierarchy itself is here:
<ByteReading> <ByteWriting> <CharacterReading> <CharacterWriting> <CollectionStream> <PositionableStream> <GettableStream> <Stream> <PositionableStream> <Stream> <PuttableStream> <Stream> <ReadableCollectionStream> <GettableStream @ basicBack -> back> <CollectionStream> <Stream> <WriteableCollectionStream> <PuttableStream> <CollectionStream>
Now let's start counting: Instead of a single inheritance hierarchy with 8 entities (classes) that I need to know about I have 19 entities (8 classes, 11 traits) in an MI hierarchy. In addition we have nested traits (so you'll have to know the other inheritance branches fairly well), renames (ReadableCollectionStream) and exclusions (6 out of 8 classes have exclusions) complicating the structure even further. A more realistic complexity measure (counting the number of occurrences of the various entities) ends up with about 4x the complexity of the traits version (which is certainly what it feels like).
So why would this be advantageous to a single inheritance hierarchy?
I'm pretty sure someone will come back and say "but wait! isn't the idea that *other* clients will use those traits and in return will be simpler and better and easier?" So let's look at this too:
I'll be looking at the Files hierarchy in Nile for the sole purpose that it is the only comparable piece that has counter parts in Squeak today and Squeak's files are certainly messy enough that they need a good makeover. So here is the hierarchy for files in Nile (again without the traits):
AbstractFileStream AbstractBinaryStream ReadFileBinaryStream WriteFileBinaryStream ReadWriteFileBinaryStream AbstractTextStream ReadFileTextStream WriteFileTextStream ReadWriteFileTextStream
The structure is ... shall we say unusual and (I think) heavily influenced by the desire to create permutations of existing traits instead of applying other OO design principles. And here is the version with traits information included:
AbstractFileStream AbstractBinaryStream ReadFileBinaryStream <ReadFileStream - fileName, bufferType, getFileID, setFileID: setFileName> <ByteReading> WriteFileBinaryStream <WriteFileStream - fileName, bufferType, getFileID, setFileID: setFileName> <ByteWriting> ReadWriteFileBinaryStream <ReadFileStream - fileName, bufferType, getFileID, setFileID: setFileName> <WriteFileStream - fileName, bufferType, getFileID, setFileID: setFileName> <ByteWriting> AbstractTextStream ReadFileTextStream <ReadFileStream - fuleName, bufferType, getFileID, setFileID: setFileName> <CharacterReading> WriteFileTextStream <WriteFileStream - fileName, bufferType, getFileID, setFileID: setFileName> <CharacterWriting> ReadWriteFileTextStream <ReadFileStream - fileName, bufferType, getFileID, setFileID: setFileName> <WriteFileStream - fileName, bufferType, getFileID, setFileID: setFileName> <ByteWriting>
<FileStream> <PositionableStream - isBinary> <ReadFileStream> <GettableStream - close, isBinary, isClosed> <FileStream> <WriteFileStream> <PuttableStream - close, isBinary, isClosed> <FileStream>
The amount of added complexity is mindboggling to me, and other than AbstractFileStream being a subclass of Object there doesn't seem to be *any* advantage of using traits. The disadvantages however, like the explosion in the number of entities are very real (I think anyone who has tried to understand the Squeak 3.9 and later meta class hierarchy will agree).
So ultimately, I agree with your statement. There may be *some* uses for traits, but those are few and far inbetween (and, realistically speaking, nobody has found one yet). In the cases that we have seen so far, traits are simply used as MI with all the same problems that MI has. Nile certainly shows the symptoms (added complexity, conflicts) that we've come to recognize as the hallmark of MI systems.
Cheers, - Andreas
On 8/6/07, Andreas Raab andreas.raab@gmx.de wrote:
Jason Johnson wrote:
I don't personally see traits as something that comes up that often. 99% of the time inheritance, or some OO pattern gives the best solution. But in that 1% something like a trait is the correct solution and not having it shows up a design wart.
I completely agree with this statement. And in return I *urge* you to look at actual code and stand corrected ;-) Let's take an example:
Well, I don't recall endorsing Nile itself (since I haven't looked at the code yet), nor saying that traits can't be abused. :) In Haskell it is possible to use Type classes to create single inheritance (albeit compile time only) or even MI, but that's not what type classes are for.
Likewise it is certainly possible to do MI with traits, but this is IMO not the itch they best scratch. So if I had said explicitly or seemed to imply otherwise then I do indeed stand corrected and apologize for misrepresenting myself. Any useful feature can be abused.
Here is what the base class hierarchy in Nile looks like:
<snip> So why would this be advantageous to a single inheritance hierarchy?
I'm pretty sure someone will come back and say "but wait! isn't the idea that *other* clients will use those traits and in return will be simpler and better and easier?" So let's look at this too:
<snip> The structure is ... shall we say unusual and (I think) heavily influenced by the desire to create permutations of existing traits instead of applying other OO design principles.
Oh my, this does strike me as more complicated then necessary (though I still need to look at the code). But if it is as you suggest (as it may well be), then I think something like this comes about by the constant innuendo that traits are a solution looking for a problem. Under that kind of pressure one might start looking for a place to force the solution in, unfortunately appearing to be a self fulfilled prophecy.
The amount of added complexity is mindboggling to me, and other than
AbstractFileStream being a subclass of Object there doesn't seem to be *any* advantage of using traits. The disadvantages however, like the explosion in the number of entities are very real (I think anyone who has tried to understand the Squeak 3.9 and later meta class hierarchy will agree).
So ultimately, I agree with your statement. There may be *some* uses for traits, but those are few and far inbetween (and, realistically speaking, nobody has found one yet).
With this part I still disagree. I think I have found one: Magnitude. I think that should be a trait not a class. But to your point that is the singular case of an obvious trait that I can think of in my whole Squeak image. But it *is* still useful in that context.
Personally, I think the best tact to take to *prove* traits is to go look at how Haskell uses Type classes. That is the best example I have seen in using this concept.
In the cases that we have seen so
far, traits are simply used as MI with all the same problems that MI has. Nile certainly shows the symptoms (added complexity, conflicts) that we've come to recognize as the hallmark of MI systems.
Cheers,
- Andreas
That is a shame, but you seem to agree that the concept does have value at least conceptually. So I guess the question is, is this a concept that is just getting a bad rap by what appear to be solutions made more complicated by it's use, or is this something simply too complicated for anyone to use correctly regardless of it's conceptual value?
P.S.
Just to give something concrete, here is basically what Haskell has for the Eq (equality) type class:
class Eq x == y = ! (x != y) x != y = ! ( x == y)
So what this is saying is that objects that are of type Eq have the == and != functions. It also provides default implementations for this, but notice: these implementations are defined from each other. No, this wont compile. But what this will do is allow you to just define the function that is easiest and the other definition will be correct then.
So in this case you can't just declare your new type as Eq and everything works (though you can say it derives from it, but that's something different). You still have to define at least one function and I think most if not all the Type classes behave like this.
Hi. I'm trying to create a simple chat connection between Croquet and Second Life, and it seems the most safe way to do this (to avoid leaking private IM into a Croquet island) is to simply let Squeak display the text i/o outside of Croquet.
So... how do I send a message to squeak and pass one back out of squeak?
This seems a fundamental thing to do, but I'm not sure how to start..
Thanks.
Lawson English.
One suggestion is to create a network connection using sockets. Another is to use files. For example, Second Life might write chat messages to a directory that Squeak would periodically check to see if new messages have arrived. It might be easiest to put each message into it's own file.
Josh
On Aug 4, 2007, at 12:49 PM, Lawson English wrote:
Hi. I'm trying to create a simple chat connection between Croquet and Second Life, and it seems the most safe way to do this (to avoid leaking private IM into a Croquet island) is to simply let Squeak display the text i/o outside of Croquet.
So... how do I send a message to squeak and pass one back out of squeak?
This seems a fundamental thing to do, but I'm not sure how to start..
Thanks.
Lawson English.
Thanks. I found something named OSProcess, but from the documentation, I can't tell if it i s actualy workign on a Mac, or on any other OS for that matter. Nor can I figure out how to download it if need be since the latest version is listed as 4.2.2 while the SqueakMap Package Loader only lists 4.0.1, which won't load anyway due to some kind of error.
Joshua Gargus wrote:
One suggestion is to create a network connection using sockets. Another is to use files. For example, Second Life might write chat messages to a directory that Squeak would periodically check to see if new messages have arrived. It might be easiest to put each message into it's own file.
Josh
On Aug 4, 2007, at 12:49 PM, Lawson English wrote:
Hi. I'm trying to create a simple chat connection between Croquet and Second Life, and it seems the most safe way to do this (to avoid leaking private IM into a Croquet island) is to simply let Squeak display the text i/o outside of Croquet.
So... how do I send a message to squeak and pass one back out of squeak?
This seems a fundamental thing to do, but I'm not sure how to start..
Thanks.
Lawson English.
SqueakSource has newer versions. For example: http:// www.squeaksource.com/OSProcess/OSProcess-dtl.36.mcz
How do you intend to use OSProcess? Unix sockets or pipes would be more efficient than a TCP socket (although it hardly matters for text chat messages). But then you have to have a different solution for Windows. It seems like more trouble than necessary.
Josh
On Aug 4, 2007, at 5:03 PM, Lawson English wrote:
Thanks. I found something named OSProcess, but from the documentation, I can't tell if it i s actualy workign on a Mac, or on any other OS for that matter. Nor can I figure out how to download it if need be since the latest version is listed as 4.2.2 while the SqueakMap Package Loader only lists 4.0.1, which won't load anyway due to some kind of error.
Joshua Gargus wrote:
One suggestion is to create a network connection using sockets. Another is to use files. For example, Second Life might write chat messages to a directory that Squeak would periodically check to see if new messages have arrived. It might be easiest to put each message into it's own file.
Josh
On Aug 4, 2007, at 12:49 PM, Lawson English wrote:
Hi. I'm trying to create a simple chat connection between Croquet and Second Life, and it seems the most safe way to do this (to avoid leaking private IM into a Croquet island) is to simply let Squeak display the text i/o outside of Croquet.
So... how do I send a message to squeak and pass one back out of squeak?
This seems a fundamental thing to do, but I'm not sure how to start..
Thanks.
Lawson English.
Joshua Gargus wrote:
SqueakSource has newer versions. For example: http://www.squeaksource.com/OSProcess/OSProcess-dtl.36.mcz
How do I get that into squeak? It doesnt seem to appear in the Montecello browser, and I'm not sure how to load it from the download.
How do you intend to use OSProcess? Unix sockets or pipes would be more efficient than a TCP socket (although it hardly matters for text chat messages). But then you have to have a different solution for Windows. It seems like more trouble than necessary.
I might be. The sample source code I have from IBM just uses pies for Linux. I'd like a generic solution to something that should be trivial, but right now, I'd settle for a proof of concept working on any platform.
Not that appears likely at the moment.
On Aug 4, 2007, at 5:37 PM, Lawson English wrote:
Joshua Gargus wrote:
SqueakSource has newer versions. For example: http:// www.squeaksource.com/OSProcess/OSProcess-dtl.36.mcz
How do I get that into squeak? It doesnt seem to appear in the Montecello browser,
Do you have the OSProcess repository in Monticello's list of repositories? You should have an entry like 'http://squeaksource.com/ OSProcess'. If not, you must add it.
and I'm not sure how to load it from the download.
There is a 'load' option when a .mcz file is selected in a Squeak 'file list'.
Josh
How do you intend to use OSProcess? Unix sockets or pipes would be more efficient than a TCP socket (although it hardly matters for text chat messages). But then you have to have a different solution for Windows. It seems like more trouble than necessary.
I might be. The sample source code I have from IBM just uses pies for Linux. I'd like a generic solution to something that should be trivial, but right now, I'd settle for a proof of concept working on any platform.
Not that appears likely at the moment.
Joshua Gargus wrote:
On Aug 4, 2007, at 5:37 PM, Lawson English wrote:
Joshua Gargus wrote:
SqueakSource has newer versions. For example: http://www.squeaksource.com/OSProcess/OSProcess-dtl.36.mcz
How do I get that into squeak? It doesnt seem to appear in the Montecello browser,
Do you have the OSProcess repository in Monticello's list of repositories? You should have an entry like 'http://squeaksource.com/OSProcess'. If not, you must add it.
and I'm not sure how to load it from the download.
There is a 'load' option when a .mcz file is selected in a Squeak 'file list'.
Josh
Thanks, got it to load. Stil lnot sure the best way to proceedd though. Windows requires one to use sockets for Interapplication communication?
On Aug 4, 2007, at 5:03 PM, Lawson English wrote:
Thanks. I found something named OSProcess, but from the documentation, I can't tell if it i s actualy workign on a Mac, or on any other OS for that matter. Nor can I figure out how to download it if need be since the latest version is listed as 4.2.2 while the SqueakMap Package Loader only lists 4.0.1, which won't load anyway due to some kind of error.
The 3.8.18beta1U mac carbon VM in the 3.9 distribution folder now has the OSProcess plugin included. You just need the latest smalltalk software to use. The instructions should tell you "hopefully" how to quickly test it to see if it works for you.
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
John M McIntosh wrote:
On Aug 4, 2007, at 5:03 PM, Lawson English wrote:
Thanks. I found something named OSProcess, but from the documentation, I can't tell if it i s actualy workign on a Mac, or on any other OS for that matter. Nor can I figure out how to download it if need be since the latest version is listed as 4.2.2 while the SqueakMap Package Loader only lists 4.0.1, which won't load anyway due to some kind of error.
The 3.8.18beta1U mac carbon VM in the 3.9 distribution folder now has the OSProcess plugin included. You just need the latest smalltalk software to use. The instructions should tell you "hopefully" how to quickly test it to see if it works for you.
Thanks very much.
Hi
Thanks. I found something named OSProcess, but from the documentation, I can't tell if it i s actualy workign on a Mac, or on any other OS for that matter. Nor can I figure out how to download it if need be since the latest version is listed as 4.2.2 while the SqueakMap Package Loader only lists 4.0.1, which won't load anyway due to some kind of error.
The 3.8.18beta1U mac carbon VM in the 3.9 distribution folder now has the OSProcess plugin included. You just need the latest smalltalk software to use. The instructions should tell you "hopefully" how to quickly test it to see if it works for you.
Thanks very much.
I myself had problems to install CommandShell via UniverseBrowser. What I did to get it working on my Powerbook was:
I take the latest squeak-dev image, then install OSProcess via UniverseBrowser, then download
http://wiki.squeak.org/squeak/uploads/1914/CommandShellV3-0-5-dtl.sar
and install it via FileList (load)
open a workspace and do Alt-p on
OSProcess thisOSProcess waitForCommandOutput: '/bin/ls'
Everything okay? Enno
John M McIntosh wrote:
On Aug 4, 2007, at 5:03 PM, Lawson English wrote:
Thanks. I found something named OSProcess, but from the documentation, I can't tell if it i s actualy workign on a Mac, or on any other OS for that matter. Nor can I figure out how to download it if need be since the latest version is listed as 4.2.2 while the SqueakMap Package Loader only lists 4.0.1, which won't load anyway due to some kind of error.
The 3.8.18beta1U mac carbon VM in the 3.9 distribution folder now has the OSProcess plugin included. You just need the latest smalltalk software to use. The instructions should tell you "hopefully" how to quickly test it to see if it works for you.
Hmmm. For some reason, the version with 3.8.18beta specified doesnt' quite work. A different folder, labled Squeak3.9-final-7067, seemed to work better, but it may have just be "cleaner" than the other one when I started testing.
Now that I know that it works (I can even do a few simple shell commands from the shell window, whee), I have ot figure out how to use it. Are they any existing examples I might look at for implementing I/O via pipes?
Thanks.
On Sun, Aug 05, 2007 at 07:33:01PM -0700, Lawson English wrote:
John M McIntosh wrote:
On Aug 4, 2007, at 5:03 PM, Lawson English wrote:
Thanks. I found something named OSProcess, but from the documentation, I can't tell if it i s actualy workign on a Mac, or on any other OS for that matter. Nor can I figure out how to download it if need be since the latest version is listed as 4.2.2 while the SqueakMap Package Loader only lists 4.0.1, which won't load anyway due to some kind of error.
The 3.8.18beta1U mac carbon VM in the 3.9 distribution folder now has the OSProcess plugin included. You just need the latest smalltalk software to use. The instructions should tell you "hopefully" how to quickly test it to see if it works for you.
Hmmm. For some reason, the version with 3.8.18beta specified doesnt' quite work. A different folder, labled Squeak3.9-final-7067, seemed to work better, but it may have just be "cleaner" than the other one when I started testing.
Now that I know that it works (I can even do a few simple shell commands from the shell window, whee), I have ot figure out how to use it. Are they any existing examples I might look at for implementing I/O via pipes?
Look at the class side methods in PipeableOSProcess. There are a number of examples there, and many of the methods have examples in the method comments. A PipeableOSProcess is a proxy for an external OS process that has its stdin/stdout/stderr pipes connected and accessible from Squeak.
You can also create instances of OSPipe if you want to work with pipes directly, but pay attention to blocking versus non-blocking pipes, as you can hang up your Squeak VM by reading a blocking pipe that has no data available.
Dave
David T. Lewis wrote:
On Sun, Aug 05, 2007 at 07:33:01PM -0700, Lawson English wrote:
John M McIntosh wrote:
On Aug 4, 2007, at 5:03 PM, Lawson English wrote:
Thanks. I found something named OSProcess, but from the documentation, I can't tell if it i s actualy workign on a Mac, or on any other OS for that matter. Nor can I figure out how to download it if need be since the latest version is listed as 4.2.2 while the SqueakMap Package Loader only lists 4.0.1, which won't load anyway due to some kind of error.
The 3.8.18beta1U mac carbon VM in the 3.9 distribution folder now has the OSProcess plugin included. You just need the latest smalltalk software to use. The instructions should tell you "hopefully" how to quickly test it to see if it works for you.
Hmmm. For some reason, the version with 3.8.18beta specified doesnt' quite work. A different folder, labled Squeak3.9-final-7067, seemed to work better, but it may have just be "cleaner" than the other one when I started testing.
Now that I know that it works (I can even do a few simple shell commands from the shell window, whee), I have ot figure out how to use it. Are they any existing examples I might look at for implementing I/O via pipes?
Look at the class side methods in PipeableOSProcess. There are a number of examples there, and many of the methods have examples in the method comments. A PipeableOSProcess is a proxy for an external OS process that has its stdin/stdout/stderr pipes connected and accessible from Squeak.
You can also create instances of OSPipe if you want to work with pipes directly, but pay attention to blocking versus non-blocking pipes, as you can hang up your Squeak VM by reading a blocking pipe that has no data available.
Thanks for the pointers to the examples. Unfortunately, none of them seem to work. They all return either a message that the Accessor cannot access the system. I'm no doubt missing something.
On Aug 6, 2007, at 9:28 AM, Lawson English wrote:
Thanks for the pointers to the examples. Unfortunately, none of them seem to work. They all return either a message that the Accessor cannot access the system. I'm no doubt missing something.
You should first confirm your copy of Squeak 3.8.18beta1U.app Resources folder contains UnixOSProcessPlugin.bundle In checking the copy of the on my ftp site does contain that.
If I do
UnixOSProcessAccessor basicNew primGetSession
I get back magic bits.
Also check SmalltalkImage current listLoadedModules which shows for me
'UnixOSProcessPlugin 11 October 2006 (e)'
I believe I just loaded OSProcess (4.3) on SqueakMap
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
John M McIntosh wrote:
On Aug 6, 2007, at 9:28 AM, Lawson English wrote:
Thanks for the pointers to the examples. Unfortunately, none of them seem to work. They all return either a message that the Accessor cannot access the system. I'm no doubt missing something.
You should first confirm your copy of Squeak 3.8.18beta1U.app Resources folder contains UnixOSProcessPlugin.bundle In checking the copy of the on my ftp site does contain that.
If I do
UnixOSProcessAccessor basicNew primGetSession
I get back magic bits.
Also check SmalltalkImage current listLoadedModules which shows for me
'UnixOSProcessPlugin 11 October 2006 (e)'
I believe I just loaded OSProcess (4.3) on SqueakMap
Thanks very much. I just discovred I had an obsolete version of SqueakMap, so I had to install THAT before I could see other recent updates.
squeak-dev@lists.squeakfoundation.org