Yet another lurker here.
While I'm not at all qualified to speak for the seasoned Squeaker communities, I am qualified to comment on the issues I've found attempting to implement some sample applications for contract bids on top of Squeak. I've also tracked the progress of Pharo with great anticipation, and have spent a lot of time pondering what needs to change to make it useful for my production work.
Here's a few thoughts, inspired by Dan Ingalls's famous 1981 Byte article on the principles of Smalltalk. Principle 9: Modularity: No component in a complex system should depend on the internal details of any other component. Well if you look in the latest Pharo image, you'll find there's around 38 methods of the Object class that amount to: isFoo ^ false Each of these methods violate this principle, not only in spirit but also in practice. While this has been common practice for ages, it means that building downloadable modules that can be easily merged with any given image is practically impossible. As soon as you have two packages that define their own class that wants to use
the same name, and register its own methods in a "base object", you both violate the principle of modularity AND break other packages. Principle 12: Factoring: Each independent component in a system would appear in only one place. This is probably the single greatest reason for moving towards Traits across the board. But look at this concept in the context of two seemingly entirely different methods:
Object acceptDroppingMorph: transferMorph event: evt inMorph: dstListMorph If you look at both of these methods, you'll quickly realize that they are in fact the exact same method! This is because they have the exact same bytecode representation. These two methods are also exactly the same as the 38 isFoo methods I mentioned above. The only different is the semantics as viewed by the programmer, but the reality is none of these methods should be necessary, and should be factored out. These methods only exist due to a flaw in the design of the API and its semantics. This brings up the issue of
Principle 2: Good Design: A system should be built with a minimum set of unchangeable parts; those parts should be as general as possible; and all parts of the system should be held in a uniform framework. If you look at the problems of creating packages (see principle 9 above) or the excessive verbosity which leads to inordinate redundancy (see principle 12), these ultimately stem from lapses in principle 2. Over the years, cruft has accumulated, people's code has become fragile and dependent on that cruft (remember message passing's and modularity's purpose is to reduce fragility), and result in an inertia against fixing the fundamental design flaws. We end up with arguments over Squeak vs. Pharo vs. Etoys because the design of the core system has lapsed into disrepair, much like the US's infrastructure. A serious effort to address this short coming,
and re-examine old design decisions to improve the core infrastructure would dramatically impact the future of all of these projects (as they all inherit the same problems). Principle 17:
Natural Selection: Languages and systems that are of sound design will persist, to be supplanted only by better ones. The concept of forking the language, fixing core issues, and addressing design flaws is a core principle of Smalltalk. Maybe it is time for a better one. Just my two cents,
Dave -- -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/ |
On Mon, Jun 29, 2009 at 9:16 AM, David Goehrig<[hidden email]> wrote:
I agree that Squeak has accumulated a lot of cruft and it needs to be removed. This happens to most systems as they age. But I disagree with a lot of the detailed things you said. > Modularity: No component in a complex system should depend on the internal > details of any other component. > > Well if you look in the latest Pharo image, you'll find there's around 38 > methods of the Object class that amount to: > isFoo > > ^ false > > Each of these methods violate this principle, not only in spirit but also in practice. No, they do not. You are assuming that Object is a component. Classes in Smalltalk are not necessarily components. Often a component is a set of classes. Sometimes it is a set of classes plus some methods on other classes. Components often add methods to existing classes. > Principle 12: > > Factoring: Each independent component in a system would appear in only one place. > > This is probably the single greatest reason for moving towards Traits across > the board. Maybe. This is certainly the purpose of traits, but there is disagreement about whether traits actually succeed. >But look at this concept in the context of two seemingly entirely different methods: > > Object acceptDroppingMorph: transferMorph event: evt inMorph: dstListMorph > > Object hasLiteralSuchThat: testBlock > > If you look at both of these methods, you'll quickly realize that they are > in fact the exact same method! This is because they have the exact same > bytecode representation. Again, I disgree. They are not the same method. They are just methods with the same implementation. There is much more to a method than its byte-code. The name of the method is important. The type of the argument is important. The number of arguments is important. The meaning of the the method is important, i.e. what is its precondition and what do you expect to be true after you call it. -Ralph Johnson |
In reply to this post by David Goehrig
2009/6/29 David Goehrig <[hidden email]>:
> Yet another lurker here. > While I'm not at all qualified to speak for the seasoned Squeaker > communities, I am qualified to comment on the issues I've found attempting > to implement some sample applications for contract bids on top of Squeak. > I've also tracked the progress of Pharo with great anticipation, and have > spent a lot of time pondering what needs to change to make it useful for my > production work. > Here's a few thoughts, inspired by Dan Ingalls's famous 1981 Byte article on > the principles of Smalltalk. > Principle 9: > > Modularity: No component in a complex system should depend on the internal > details of any other component. > > Well if you look in the latest Pharo image, you'll find there's around 38 > methods of the Object class that amount to: > isFoo > > ^ false > I feel uneasy each time, when adding own isXXX methods to Object. But i don't know another plausible way how to make a difference between an objects which having a certain capability vs rest of objects in a universe. Here the code snippets of CVLambda class ( a quick & dirty lambda calculus implementation, which i using in own project). This class represents a lambda-message-send, i.e. it keeps all what a message send needs: receiver, selector, arguments. any of its slots can be a free variable or, in own turn, be another lambda and so on, without any limitations. I need to compare, if two lambdas are equivalent: = aLambda ^ aLambda isCVLambda and: [ aLambda isCVLambdaSlot not and: [ self size = aLambda size and: [ self do: [:i :obj | obj = (aLambda at: i) ifFalse: [ ^ false ]]. true ]]] Sometimes i need to not reduce the lambdas immediately (because some of them could have a side effects), but keep them for a while as a message send, not yet performed , even if there is no free variables left, but i want to test, if it can be reduced: hasSlots self do: [:i :obj | ( obj isCVLambda and: [ obj hasSlots ]) ifTrue: [ ^ true ] ]. ^ false Sometimes i need to walk over all lambdas (contained in a topmost one): lambdasDo: aBlock | copy | copy := self class basicNew: self size. self do: [:i :obj | copy at: i put: (obj isCVLambda ifTrue:[aBlock value: obj] ifFalse:[obj]) ]. ^ copy so, here the question, can i implement the same behavior w/o using #isCVLambda , and without putting any additional methods to Object class? Maybe the design is plainly wrong! Maybe i don't need any of the above behavior in correctly designed class. I don't know. > Each of these methods violate this principle, not only in spirit but also in > practice. While this has been common practice for ages, it means that > building downloadable modules that can be easily merged with any given image > is practically impossible. As soon as you have two packages that define > their own class that wants to use > the same name, and register its own methods in a "base object", you both > violate the principle of modularity AND break other packages. > Principle 12: > > Factoring: Each independent component in a system would appear in only one > place. > > This is probably the single greatest reason for moving towards Traits across > the board. But look at this concept in the context of two seemingly > entirely different methods: > > Object acceptDroppingMorph: transferMorph event: evt inMorph: dstListMorph > > Object hasLiteralSuchThat: testBlock > > If you look at both of these methods, you'll quickly realize that they are > in fact the exact same method! This is because they have the exact same > bytecode representation. These two methods are also exactly the same as the > 38 isFoo methods I mentioned above. The only different is the semantics as > viewed by the programmer, but the reality is none of these methods should be > necessary, and should be factored out. These methods only exist due to a > flaw in the design of the API and its semantics. This brings up the issue > of > Principle 2: > > Good Design: A system should be built with a minimum set of unchangeable > parts; those parts should be as general as possible; and all parts of the > system should be held in a uniform framework. > > If you look at the problems of creating packages (see principle 9 above) or > the excessive verbosity which leads to inordinate redundancy (see principle > 12), these ultimately stem from lapses in principle 2. Over the years, > cruft has accumulated, people's code has become fragile and dependent on > that cruft (remember message passing's and modularity's purpose is to reduce > fragility), and result in an inertia against fixing the fundamental design > flaws. We end up with arguments over Squeak vs. Pharo vs. Etoys because the > design of the core system has lapsed into disrepair, much like the US's > infrastructure. A serious effort to address this short coming, > and re-examine old design decisions to improve the core infrastructure would dramatically impact the future of all of these projects (as they all inherit the same problems). > Principle 17: > > Natural Selection: Languages and systems that are of sound design will > persist, to be supplanted only by better ones. > > The concept of forking the language, fixing core issues, and addressing > design flaws is a core principle of Smalltalk. Maybe it is time for a > better one. > Just my two cents, > Dave > -- > -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/ > > > > -- Best regards, Igor Stasenko AKA sig. |
I didn't read your example closely, but, generally....
(obj respondsTo: #isCVLambda) and: [ obj isCVLambda ] is very general (independent of hierarchy), or if you want to trap people on a class tree... obj isKindOf: CVLambda or trap exceptions for when something doesn't respond to isCVLambda ... or... -- BUT, it will be slower. an intriguing idea is having Object always respond to any pattern isXXX with false, unless the method is explicitly defined. (Now there I go, changing the root behavior...) -Cam On Jun 29, 2009, at 1:18 PM, Igor Stasenko wrote: > so, here the question, can i implement the same behavior w/o using > #isCVLambda , and |
In reply to this post by Igor Stasenko
> This class represents a lambda-message-send, i.e. it keeps all what a
> message send needs: > receiver, selector, arguments. > any of its slots can be a free variable or, in own turn, be another > lambda and so on, without any limitations. are you aware of this: http://www.zogotounga.net/comp/squeak/functionaltalk.htm ... one of my mostly unnoticed contribution to Squeak :) Stef |
In reply to this post by Cameron Sanders-2
What I typically what I've been doing to eliminate all of these methods with a single simple change:
Object doesNoUnderstand: aMessage ^ false
Occasionally, I'll add a line in there to log the message to a transcript just to see if I'm doing something stupid, but 99.9 out of 100, the edit time method checks are enough to catch most typo bugs. Surprisingly enough, this breaks incredibly little existing code, since anything that would fire off the exception ends up user trapped :) And false is a pretty good default, following the principle "when in doubt return false"!
Then again I also like replacing "respondsTo: canUnderstand: and canPerform:" with a single "can:" method, because semantically they're all asking the same basic question. There's so much of the system that can be refactored this way, where you have multiple methods with the same semantic meaning but slight variations in implementation that you could squash the vocabulary to a more manageable base with some careful thought.
Of course, I'm not married to a large existing code base :)
|
In reply to this post by Stéphane Rollandin
2009/6/29 Stéphane Rollandin <[hidden email]>:
>> This class represents a lambda-message-send, i.e. it keeps all what a >> message send needs: >> receiver, selector, arguments. >> any of its slots can be a free variable or, in own turn, be another >> lambda and so on, without any limitations. > > are you aware of this: > http://www.zogotounga.net/comp/squeak/functionaltalk.htm > > ... one of my mostly unnoticed contribution to Squeak :) > Of course i am. And your package inspired me to use lambdas in own project. But i did own. Because i don't need so much generality as in your implementation. And i wanted it to behave a little differently. Don't want to go in details right now. > Stef > > > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Cameron Sanders-2
2009/6/29 Cameron Sanders <[hidden email]>:
> I didn't read your example closely, but, generally.... > > (obj respondsTo: #isCVLambda) and: [ obj isCVLambda ] > can't do that for lambdas, because it traps all DNU's and in this case a send of #respondsTo: (or any other unknown message) will be converted into a lambda message send instead of answering expected result. Because: lambda := LambdaSlot id: #x. lambda foo ==> lambda( <x> #foo) > is very general (independent of hierarchy), or if you want to trap people on > a class tree... > > obj isKindOf: CVLambda > sorry, but this even worse than using #isXXX > or trap exceptions for when something doesn't respond to isCVLambda ... > > or... > > -- > BUT, it will be slower. > > an intriguing idea is having Object always respond to any pattern isXXX with > false, unless the method is explicitly defined. (Now there I go, changing > the root behavior...) > Exactly :) Maybe it worth add and standardize the #is: message for Object ? Which by default can be implemented as: Object is: object ^ self == object and if you need to add the differentiation, then could be something like: Object is: object ^ object == #lambda or: [ super is: object ] > -Cam > > > On Jun 29, 2009, at 1:18 PM, Igor Stasenko wrote: > >> so, here the question, can i implement the same behavior w/o using >> #isCVLambda , and > > > -- Best regards, Igor Stasenko AKA sig. |
2009/6/30 Igor Stasenko <[hidden email]>:
> 2009/6/29 Cameron Sanders <[hidden email]>: >> I didn't read your example closely, but, generally.... >> >> (obj respondsTo: #isCVLambda) and: [ obj isCVLambda ] >> > > can't do that for lambdas, because it traps all DNU's and in this case > a send of #respondsTo: (or any other unknown message) will be > converted into a lambda message send instead of answering expected > result. > Because: > > lambda := LambdaSlot id: #x. > lambda foo ==> lambda( <x> #foo) > >> is very general (independent of hierarchy), or if you want to trap people on >> a class tree... >> >> obj isKindOf: CVLambda >> > > sorry, but this even worse than using #isXXX > >> or trap exceptions for when something doesn't respond to isCVLambda ... >> >> or... >> >> -- >> BUT, it will be slower. >> >> an intriguing idea is having Object always respond to any pattern isXXX with >> false, unless the method is explicitly defined. (Now there I go, changing >> the root behavior...) >> > > Exactly :) > > Maybe it worth add and standardize the #is: > message for Object ? > Which by default can be implemented as: > > Object is: object > ^ self == object > > and if you need to add the differentiation, then could be something like: > > Object is: object > ^ object == #lambda or: [ super is: object ] > Sorry.. it can be confusing, because i wrote it not very clear: Object>>is: object ^ self == object SomeOtherThing>>is: object ^ object == #otherThing or: [ super is: object] > >> -Cam >> >> >> On Jun 29, 2009, at 1:18 PM, Igor Stasenko wrote: >> >>> so, here the question, can i implement the same behavior w/o using >>> #isCVLambda , and >> >> >> > > > > -- > Best regards, > Igor Stasenko AKA sig. > -- Best regards, Igor Stasenko AKA sig. |
>> >>> is very general (independent of hierarchy), or if you want to trap people on >>> a class tree... >>> >>> obj isKindOf: CVLambda >>> >>> >> sorry, but this even worse than using #isXXX >> >> Hence my preference for askFor: http://bugs.squeak.org/view.php?id=5319 anObject askFor: #isRectangle where askFor: returns the value if it is defined and false otherwise. Keith |
In reply to this post by David Goehrig
On Tue, Jun 30, 2009 at 7:43 AM, David Goehrig <[hidden email]> wrote: What I typically what I've been doing to eliminate all of these methods with a single simple change: /me runs away screaming. Gulik. -- http://gulik.pbwiki.com/ |
In reply to this post by David Goehrig
What you write (down below) is close to what I was thinking when I
said have all #isXXX return false by default; although I would test that the first two characters match 'i' and 's' and that more characters exist, if so, return false, otherwise, normal #doesNotUnderstand: behavior. I would treat #is by itself differently... it is ... or it couldn't be tested! So I would do nothing for simple #is. and I don't like #is: because it looks like a class type test... but that is part of the point, eh? I'll have to go back to the original example (by [hidden email], and read more about lambdas) but I thought that CVLambda would implement #isCVLambda to return true when it can be verified to be one. The example did not illustrate #doesNotUnderstand:. Back to the question of adding behavior to classes that you don't own. VisualWorks has a means to extend a class in a different package ... as I recall. As I recall, squeak has no such capability, right? Thanks. You have given me food for thought... Ciao, Cam On Jun 29, 2009, at 3:43 PM, David Goehrig wrote: > What I typically what I've been doing to eliminate all of these > methods with a single simple change: > > Object > doesNoUnderstand: aMessage > ^ false |
2009/6/30 Cameron Sanders <[hidden email]>:
> What you write (down below) is close to what I was thinking when I said have > all #isXXX return false by default; > although I would test that the first two characters match 'i' and 's' and > that more characters exist, if so, return false, otherwise, normal > #doesNotUnderstand: behavior. > > I would treat #is by itself differently... it is ... or it couldn't be > tested! So I would do nothing for simple #is. and I don't like #is: because > it looks like a class type test... but that is part of the point, eh? > I wouldn't say that. It is more trait-based approach than class-based. The concept of #is: are: When object foo having some trait, it should answer true on 'foo is: sometrait ', otherwise false. Obviously since most subclasses inherit the behavior & traits of base class, you should honor this rule in overrides of #is: method i.e.: Someclass>>is: object ^ (your tests here) or: [ super is: object ] otherwise, if you omit the super send, some of the traits will become unavailable. But of course, except when you doing this intentionally. > I'll have to go back to the original example (by [hidden email], and > read more about lambdas) but I thought that CVLambda would implement > #isCVLambda to return true when it can be verified to be one. The example > did not illustrate #doesNotUnderstand:. > > Back to the question of adding behavior to classes that you don't own. > VisualWorks has a means to extend a class in a different package ... as I > recall. As I recall, squeak has no such capability, right? > MC having this capability for a years. > Thanks. You have given me food for thought... > > Ciao, > Cam > > On Jun 29, 2009, at 3:43 PM, David Goehrig wrote: > >> What I typically what I've been doing to eliminate all of these methods >> with a single simple change: >> >> Object >> doesNoUnderstand: aMessage >> ^ false > > > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Cameron Sanders-2
Please reply under posts. It makes things less confusing.
Squeak certainly has that capability, but I would discourage you from using it. Changing the implementation of doesNotUnderstand: is a code smell. You're starting to play with voodoo and you need a *very* good reason to do it. Otherwise you'll have made yourself a very difficult application to debug. In my opinion (which doubtless isn't shared by everyone here), base classes such as Object should not have a lot of >>isXXX methods. >>isBoolean and >>isString are okay (although I never use them), but >>isMorph or >>isColor or anything not related to the Kernel classes are pollution. If you're using an >>isXXX method, then your code probably needs refactoring. It means you're implementing class specific behaviour using conditional >>ifTrue: blocks. Typically, your code will be working with subclasses of a specific class, and you'd invoke polymorphic methods to get class specific behaviour rather than using conditional blocks such as >>ifTrue:, >>ifFalse: etc. If your code really does handle an object of any possible class (which is rare but does occur), then you can use >>isKindOf:, >>isMemberOf: and >>respondsTo:. Igor's lambda example was a bit complex for me to work through so I can't really comment on it. Gulik. -- http://gulik.pbwiki.com/ |
In reply to this post by Igor Stasenko
Oh... ... oh... the CVLambda class was/is trait based. Confession: I
haven't done my homework on traits. That might explain a little! I was not aware of the rules/origin for #is: -- thank you! <more down below> On Jun 29, 2009, at 11:59 PM, Igor Stasenko wrote: > 2009/6/30 Cameron Sanders <[hidden email]>: >> > The concept of #is: are: When object foo having some trait, it should > answer true on 'foo is: sometrait ', otherwise false. > Obviously since most subclasses inherit the behavior & traits of base > class, you should honor this rule in overrides of #is: method > i.e.: > > Someclass>>is: object > ^ (your tests here) or: [ super is: object ] > > otherwise, if you omit the super send, some of the traits will become > unavailable. But of course, except when you doing this intentionally. > > >> I'll have to go back to the original example (by >> [hidden email], and >> read more about lambdas) but I thought that CVLambda would implement >> #isCVLambda to return true when it can be verified to be one. The >> example >> did not illustrate #doesNotUnderstand:. >> >> Back to the question of adding behavior to classes that you don't >> own. >> VisualWorks has a means to extend a class in a different >> package ... as I >> recall. As I recall, squeak has no such capability, right? >> > > MC having this capability for a years. So how do I do extend a class. Simply define it again for a given package? I did not know this was in Squeak. Again, thank you... now I am glad I offered up answers to things I didn't understand! Cheers, Cam |
In reply to this post by Michael van der Gulik-2
2009/6/30 Michael van der Gulik <[hidden email]>:
> Please reply under posts. It makes things less confusing. > >> >> >> On Jun 29, 2009, at 3:43 PM, David Goehrig wrote: >> >>> What I typically what I've been doing to eliminate all of these methods >>> with a single simple change: >>> >>> Object >>> doesNoUnderstand: aMessage >>> ^ false > > >> >> On Tue, Jun 30, 2009 at 3:26 PM, Cameron Sanders >> <[hidden email]> wrote: >> What you write (down below) is close to what I was thinking when I said >> have all #isXXX return false by default; >> although I would test that the first two characters match 'i' and 's' and >> that more characters exist, if so, return false, otherwise, normal >> #doesNotUnderstand: behavior. >> >> I would treat #is by itself differently... it is ... or it couldn't be >> tested! So I would do nothing for simple #is. and I don't like #is: because >> it looks like a class type test... but that is part of the point, eh? >> >> I'll have to go back to the original example (by [hidden email], and >> read more about lambdas) but I thought that CVLambda would implement >> #isCVLambda to return true when it can be verified to be one. The example >> did not illustrate #doesNotUnderstand:. >> >> Back to the question of adding behavior to classes that you don't own. >> VisualWorks has a means to extend a class in a different package ... as I >> recall. As I recall, squeak has no such capability, right? >> > > Squeak certainly has that capability, but I would discourage you from using > it. > > Changing the implementation of doesNotUnderstand: is a code smell. You're > starting to play with voodoo and you need a *very* good reason to do it. > Otherwise you'll have made yourself a very difficult application to debug. > > In my opinion (which doubtless isn't shared by everyone here), base classes > such as Object should not have a lot of >>isXXX methods. >>isBoolean and >>>isString are okay (although I never use them), but >>isMorph or >>isColor > or anything not related to the Kernel classes are pollution. > > If you're using an >>isXXX method, then your code probably needs > refactoring. It means you're implementing class specific behaviour using > conditional >>ifTrue: blocks. Typically, your code will be working with > subclasses of a specific class, and you'd invoke polymorphic methods to get > class specific behaviour rather than using conditional blocks such as >>>ifTrue:, >>ifFalse: etc. > > If your code really does handle an object of any possible class (which is > rare but does occur), then you can use >>isKindOf:, >>isMemberOf: and >>>respondsTo:. > > Igor's lambda example was a bit complex for me to work through so I can't > really comment on it. > Your suggestion is correct , except from situations like with my lambdas: sometimes you need to differentiate a single kind of objects from the rest of objects in universe. isKindOf: doesn't helps , because then if we go that road , we're soon will need isKindOf:orOf: simply because different objects could have same trait but belong to different class hierarchies. Concerning #respondsTo: - its also smells a bit, because you are depending not on a specific behavior (by invoking some method) but rather testing the class method dictionary, which is mostly static. This approach (use of #respondsTo:) also doesn't fits well with proxies (and we need them sometimes). > Gulik. > > -- > http://gulik.pbwiki.com/ > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Michael van der Gulik-2
On Jun 30, 2009, at 12:22 AM, Michael van der Gulik wrote: > Back to the question of adding behavior to classes that you don't > own. VisualWorks has a means to extend a class in a different > package ... as I recall. As I recall, squeak has no such capability, > right? > > > Squeak certainly has that capability, but I would discourage you > from using it. Why? > Changing the implementation of doesNotUnderstand: is a code smell. > You're starting to play with voodoo and you need a *very* good > reason to do it. Otherwise you'll have made yourself a very > difficult application to debug. I have done it a fair amount for mapping symbols in broker objects... so that symbols may look like unary messages. It is slower than simply invoking some keyword message directly, but it really gives the right feel for some objects. e.g. ResultsSet. And you are right, it will likely lead to a debugging nightmare. In some cases I have built symbol stacks to aid in debugging -- i'm tired, this is hurried.... my apologies if it is unclear. (Besides, I doubt you care...) > In my opinion (which doubtless isn't shared by everyone here), base > classes such as Object should not have a lot of >>isXXX methods. > >>isBoolean and >>isString are okay (although I never use them), but > >>isMorph or >>isColor or anything not related to the Kernel classes > are pollution. I agree with you here too. > If you're using an >>isXXX method, then your code probably needs > refactoring. It means you're implementing class specific behaviour > using conditional >>ifTrue: blocks. Typically, your code will be > working with subclasses of a specific class, and you'd invoke > polymorphic methods to get class specific behaviour rather than > using conditional blocks such as >>ifTrue:, >>ifFalse: etc. Some specialized containers may wish to process some things differently than others. But I agree that OO code should not frequently be branching on type-tests. Cheers, Cam |
In reply to this post by Cameron Sanders-2
2009/6/30 Cameron Sanders <[hidden email]>:
> Oh... ... oh... the CVLambda class was/is trait based. Confession: I haven't > done my homework on traits. That might explain a little! > > I was not aware of the rules/origin for #is: -- thank you! > Don't take a 'trait' word literally. I didn't mean an implemetation specific Traits (introduced in Squeak 3.9) but rather some 'label' which you, as developer want to put on some kind/group of objects. The main point is, that often, such labels not in sync with class hierarchy (imagine you could treat a Number subclasses and DatabaseConnection subclasses as objects which share some common trait). But of course, my #is: proposal lays perfectly on Traits basis. If you implement this method in Trait, and then use this trait in multiple different classes - then it will work exactly as i describing. > <more down below> > > On Jun 29, 2009, at 11:59 PM, Igor Stasenko wrote: > >> 2009/6/30 Cameron Sanders <[hidden email]>: >>> >> The concept of #is: are: When object foo having some trait, it should >> answer true on 'foo is: sometrait ', otherwise false. >> Obviously since most subclasses inherit the behavior & traits of base >> class, you should honor this rule in overrides of #is: method >> i.e.: >> >> Someclass>>is: object >> ^ (your tests here) or: [ super is: object ] >> >> otherwise, if you omit the super send, some of the traits will become >> unavailable. But of course, except when you doing this intentionally. >> >> >>> I'll have to go back to the original example (by [hidden email], and >>> read more about lambdas) but I thought that CVLambda would implement >>> #isCVLambda to return true when it can be verified to be one. The >>> example >>> did not illustrate #doesNotUnderstand:. >>> >>> Back to the question of adding behavior to classes that you don't own. >>> VisualWorks has a means to extend a class in a different package ... as I >>> recall. As I recall, squeak has no such capability, right? >>> >> >> MC having this capability for a years. > > So how do I do extend a class. Simply define it again for a given package? > you can put an extension method to any class, by putting it into a category named by your package name, prepended by '*' character: *MyPackage > I did not know this was in Squeak. > > Again, thank you... now I am glad I offered up answers to things I didn't > understand! > You welcome :) > Cheers, > Cam > > > -- Best regards, Igor Stasenko AKA sig. |
Since multiple people seem don't grok my example, let me simplify it a bit:
Suppose you have a special collection of objects over which you can iterate. The items in that collection could be anything - you don't really care on almost any of them, except those ones which is also a special collections of same kind as a container. so, then you could have a method, which by iterating through your special collection, ignores all objects except those who also can be iterated in same manner: MySpecialCollection>>mySpecialCollect: aBlock ^ self collect: [:each | each isMySpecialCollection ifTrue: [ each mySpecialCollect: aBlock] ifFalse: [each] ] -- Best regards, Igor Stasenko AKA sig. |
2009/6/30 Igor Stasenko <[hidden email]>:
> Since multiple people seem don't grok my example, let me simplify it a bit: > > Suppose you have a special collection of objects over which you can iterate. > > The items in that collection could be anything - you don't really care > on almost any of them, except those ones which is also a special > collections of same kind as a container. > > so, then you could have a method, which by iterating through your > special collection, ignores all objects except those who > also can be iterated in same manner: > > MySpecialCollection>>mySpecialCollect: aBlock > ^ self collect: [:each | > each isMySpecialCollection ifTrue: [ each mySpecialCollect: > aBlock] ifFalse: [each] > ] > oops. looks like aBlock is not used :) Okay.. how about that: MySpecialCollection>>mySpecialCollect: aBlock | copy | copy := self collect: [:each | each isMySpecialCollection ifTrue: [ each mySpecialCollect: aBlock] ifFalse: [each] ]. ^ aBlock value: copy > -- > Best regards, > Igor Stasenko AKA sig. > -- Best regards, Igor Stasenko AKA sig. |
Free forum by Nabble | Edit this page |