How to instantiate a class suggestion?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|

How to instantiate a class suggestion?

Costas Menico-2
I would like a suggestion on instantiating unknown classes at runtime.

I need to intantiate a class whose name is in a symbol variable.
For example normally if I can have a class Date I would send it a new
message.

myApp := Date perform: #newDay:year: with: 12 with: 2000

However I want to do the same thing based on a class name that is a
variable.  So I tried the following which works:

myAppClass := #Date.
mySelector:= #newDay:year:.
myAppObject := (Smalltalk at: myAppClass )
        perform: mySelector with: 5 with: 2000.

Any other more elegant ways?

Costas


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Peter van Rooijen
> So I tried the following which works:
>
> myAppClass := #Date.
> mySelector:= #newDay:year:.
> myAppObject := (Smalltalk at: myAppClass )
> perform: mySelector with: 5 with: 2000.
>
> Any other more elegant ways?

Apart from not relying on the global Smalltalk holding all the classes, I
don't see what could be more elegant.

So, I'd just suggest using myAppClass asClass instead of Smalltalk at:.

Regards,

Peter van Rooijen


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Andy Bower
In reply to this post by Costas Menico-2
Costas,

> I need to intantiate a class whose name is in a symbol variable.
> For example normally if I can have a class Date I would send it a new
> message.
>
> myApp := Date perform: #newDay:year: with: 12 with: 2000
>
> However I want to do the same thing based on a class name that is a
> variable.  So I tried the following which works:
>
> myAppClass := #Date.
> mySelector:= #newDay:year:.
> myAppObject := (Smalltalk at: myAppClass )
> perform: mySelector with: 5 with: 2000.
>
> Any other more elegant ways?

I'm not sure whether your need is to have the method selector in a variable
or not. If not, then you can also do:

(Smalltalk at: myAppClass) newDay:5 year: 2000

Best regards,

Andy Bower
Dolphin Support
http://www.object-arts.com

---
Visit the Dolphin Smalltalk Wiki Web
http://www.object-arts.com/wiki/html/Dolphin/FrontPage.htm
---


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Andy Bower
In reply to this post by Peter van Rooijen
Peter,

> Apart from not relying on the global Smalltalk holding all the classes, I
> don't see what could be more elegant.
>
> So, I'd just suggest using myAppClass asClass instead of Smalltalk at:.

Dolphin, doesn't have #asClass (must be some other popular Smalltalk you are
thinking of).

In general, we frown upon the us of #asXXXX selectors and tend to follow the
recommendations in Beck's Smalltalk Best Practise Patterns.(which has
mysteriously disappeared from the bookshelf so I can't quote you the page
numbers at the moment). There was a discussion about this in the old
newsgroup some time ago so it'll probably be available in the archives.

What we usually do to avoid hard coding a reference to the Smalltalk global
(and to prepare the road for namespaces in future) is to use #environment to
look it up. i.e.

(self environment at: myAppClass) newDay:5 year: 2000

You'll see this is used quite a few times in the base image.

Best regards,

Andy Bower
Dolphin Support
http://www.object-arts.com

---
Visit the Dolphin Smalltalk Wiki Web
http://www.object-arts.com/wiki/html/Dolphin/FrontPage.htm
---


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Ted Bracht-2
In reply to this post by Andy Bower
Costas,

> > I need to intantiate a class whose name is in a symbol variable.
> > For example normally if I can have a class Date I would send it a new
> > message.
> >
> > myApp := Date perform: #newDay:year: with: 12 with: 2000
> >
> > However I want to do the same thing based on a class name that is a
> > variable.  So I tried the following which works:
> >
> > myAppClass := #Date.
> > mySelector:= #newDay:year:.
> > myAppObject := (Smalltalk at: myAppClass )
> > perform: mySelector with: 5 with: 2000.
> >
> > Any other more elegant ways?
>
> I'm not sure whether your need is to have the method selector in a
variable
> or not. If not, then you can also do:
>
> (Smalltalk at: myAppClass) newDay:5 year: 2000
>

Alternatively, create a method, say #myAppClass, which returns the real
class name.

MyApp>>myAppClass
    ^Date

MyApp>>mySelector
    ^#newDay:year:

then the method to create the date would look like:

(self myAppClass) perform: (self mySelector) withAll: #( 5 2000 )

Now you can have different subclasses, all returning a different class and a
different selector. The generic code in the superclass stays the same.


HTH

Ted


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Costas Menico-2
In reply to this post by Peter van Rooijen
"Peter van Rooijen" <[hidden email]> wrote:

>> So I tried the following which works:
>>
>> myAppClass := #Date.
>> mySelector:= #newDay:year:.
>> myAppObject := (Smalltalk at: myAppClass )
>> perform: mySelector with: 5 with: 2000.
>>
>> Any other more elegant ways?
>
>Apart from not relying on the global Smalltalk holding all the classes, I
>don't see what could be more elegant.
>
>So, I'd just suggest using myAppClass asClass instead of Smalltalk at:.
>

First thing I tried... but as you can see from Andy's response I have
to consult my patterns too <g>.  

Costas


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Costas Menico-2
In reply to this post by Andy Bower
"Andy Bower" <[hidden email]> wrote:

>
>What we usually do to avoid hard coding a reference to the Smalltalk global
>(and to prepare the road for namespaces in future) is to use #environment to
>look it up. i.e.

what version of Dolphin should we expect namespaces in?

Costas

>


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Peter van Rooijen
In reply to this post by Costas Menico-2
"Costas Menico" <[hidden email]> wrote in message
news:[hidden email]...

> "Peter van Rooijen" <[hidden email]> wrote:
>
> >> So I tried the following which works:
> >>
> >> myAppClass := #Date.
> >> mySelector:= #newDay:year:.
> >> myAppObject := (Smalltalk at: myAppClass )
> >> perform: mySelector with: 5 with: 2000.
> >>
> >> Any other more elegant ways?
> >
> >Apart from not relying on the global Smalltalk holding all the classes, I
> >don't see what could be more elegant.
> >
> >So, I'd just suggest using myAppClass asClass instead of Smalltalk at:.
> >
>
> First thing I tried... but as you can see from Andy's response I have
> to consult my patterns too <g>.

Ho! Not so fast!

1. Because Kent says so, doesn't make it right.
2. Kent doesn't say so. What he says (p. 28-29) is that he doesn't want
protocol explosion, which he sees as a danger because there is no
theoretical limit to the number of conversion methods you could add. This in
*not* a case where you are in danger of a conversion protocol explosion.
3. In fact, Kent explicitly mentions (p. 29) that he would be happy to use a
conversion method where there is only one reasonable way to do the
conversion, as is the case with the conversion from Symbol to Class.
4. Don't take my word for it, ask Kent what he thinks about #asClass.
5. #asClass isn't really a standard conversion method. If you feel it could
be unrevealing of its intention (I think, slim chance of that), use Class
withName: aString. It's a little longer, but it also communicates just a
little more.

Finally, I wasn't suggesting the method is in the Dolphin base system. I was
suggesting Costas use it, for elegance, as per his request.

Regards,

Peter


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Peter van Rooijen
In reply to this post by Andy Bower
"Andy Bower" <[hidden email]> wrote in message
news:91n9pd$4hltt$[hidden email]...
> Peter,
>
> > Apart from not relying on the global Smalltalk holding all the classes,
I
> > don't see what could be more elegant.
> >
> > So, I'd just suggest using myAppClass asClass instead of Smalltalk at:.
>
> Dolphin, doesn't have #asClass (must be some other popular Smalltalk you
are
> thinking of).
>
> In general, we frown upon the us of #asXXXX selectors and tend to follow
the
> recommendations in Beck's Smalltalk Best Practise Patterns.(which has
> mysteriously disappeared from the bookshelf so I can't quote you the page
> numbers at the moment).

That's okay. I looked it up and what you say is his recommendation, actually
isn't. See my post to Costas.

> There was a discussion about this in the old
> newsgroup some time ago so it'll probably be available in the archives.
> What we usually do to avoid hard coding a reference to the Smalltalk
global
> (and to prepare the road for namespaces in future) is to use #environment
to
> look it up. i.e.
>
> (self environment at: myAppClass) newDay:5 year: 2000
>
> You'll see this is used quite a few times in the base image.

Might I respectfully suggest you refactor that code duplication ;-).

Best regards,

Peter

> Best regards,
>
> Andy Bower
> Dolphin Support
> http://www.object-arts.com
>
> ---
> Visit the Dolphin Smalltalk Wiki Web
> http://www.object-arts.com/wiki/html/Dolphin/FrontPage.htm
> ---
>
>


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Costas Menico
In reply to this post by Peter van Rooijen
Peter,

>1. Because Kent says so, doesn't make it right.
>2. Kent doesn't say so. What he says (p. 28-29) is that he doesn't want
>protocol explosion, which he sees as a danger because there is no
>theoretical limit to the number of conversion methods you could add. This in
>*not* a case where you are in danger of a conversion protocol explosion.
>3. In fact, Kent explicitly mentions (p. 29) that he would be happy to use a
>conversion method where there is only one reasonable way to do the
>conversion, as is the case with the conversion from Symbol to Class.

I agree that just because Kent said it it does not make it right.
Patterns are advisory as are many things in Smalltalk. There are many
exceptions to the rules.

>4. Don't take my word for it, ask Kent what he thinks about #asClass.

Hmmm, does he still work with Smalltalk?

>5. #asClass isn't really a standard conversion method. If you feel it could
>be unrevealing of its intention (I think, slim chance of that), use Class
>withName: aString. It's a little longer, but it also communicates just a
>little more.
>
>Finally, I wasn't suggesting the method is in the Dolphin base system. I was
>suggesting Costas use it, for elegance, as per his request.

No question #asClass or Class withname: asString would be more
meaningful. However I for my own reasons am trying to refrain from
adding code to the base image of Dolphin.

I think for this I will just use what is available and just write a
comment next to it.

Costas


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

David Simmons
Hi guys,

If I might make a suggestion that would be a more general mapping pattern
(that also happens to be compatible with features in SmallScript :-).

You might want to try implementing:

    #as: ... "in <Object>"

This has the advantage that there is only ONE generalized selector #as:.
Then a variety of techniques like double dispatching or multi-method
checking can be done to handle the conversion.

As in:
===================
<?method [
as: aMapper
    ^aMapper asMapped: self
]?>

<?method class=Class [
asMapped: descriptor

    ^Smalltalk at: descriptor "or whatever is appropriate"
]?>

<?method class=Boolean [
asMapped: descriptor
   ^descriptor !== false
        and: [descriptor !== nil
            and: [descriptor != 0]]
]?>

<?method class=Interface "in SmallScript" [
asMapped: descriptor
    ...
]?>
===================

Then one can write code like:

a)
    anObject as: #String.

b)
    anObject as: Boolean.

*)
    anObject as: <some-class or some-interface>

--
-- Dave Simmons [www.qks.com / www.smallscript.com]
  "Effectively solving a problem begins with how you express it."


"Costas Menico" <[hidden email]> wrote in message
news:[hidden email]...
> Peter,
>
> >1. Because Kent says so, doesn't make it right.
> >2. Kent doesn't say so. What he says (p. 28-29) is that he doesn't want
> >protocol explosion, which he sees as a danger because there is no
> >theoretical limit to the number of conversion methods you could add. This
in
> >*not* a case where you are in danger of a conversion protocol explosion.
> >3. In fact, Kent explicitly mentions (p. 29) that he would be happy to
use a

> >conversion method where there is only one reasonable way to do the
> >conversion, as is the case with the conversion from Symbol to Class.
>
> I agree that just because Kent said it it does not make it right.
> Patterns are advisory as are many things in Smalltalk. There are many
> exceptions to the rules.
>
> >4. Don't take my word for it, ask Kent what he thinks about #asClass.
>
> Hmmm, does he still work with Smalltalk?
>
> >5. #asClass isn't really a standard conversion method. If you feel it
could
> >be unrevealing of its intention (I think, slim chance of that), use Class
> >withName: aString. It's a little longer, but it also communicates just a
> >little more.
> >
> >Finally, I wasn't suggesting the method is in the Dolphin base system. I
was

> >suggesting Costas use it, for elegance, as per his request.
>
> No question #asClass or Class withname: asString would be more
> meaningful. However I for my own reasons am trying to refrain from
> adding code to the base image of Dolphin.
>
> I think for this I will just use what is available and just write a
> comment next to it.
>
> Costas


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

David Simmons
In reply to this post by Costas Menico-2
"David Simmons" <[hidden email]> wrote in message news:...

> Hi guys,
>
> If I might make a suggestion that would be a more general mapping pattern
> (that also happens to be compatible with features in SmallScript :-).
>
> You might want to try implementing:
>
>     #as: ... "in <Object>"
>
> This has the advantage that there is only ONE generalized selector #as:.
> Then a variety of techniques like double dispatching or multi-method
> checking can be done to handle the conversion.
>
> As in:
> ===================
> <?method [
> as: aMapper
>     ^aMapper asMapped: self
> ]?>
>
> <?method class=Class [
> asMapped: descriptor
>
>     ^Smalltalk at: descriptor "or whatever is appropriate"
> ]?>
>
> <?method class=Boolean [
> asMapped: descriptor
>    ^descriptor !== false
>         and: [descriptor !== nil
>             and: [descriptor != 0]]
> ]?>
>
> <?method class=Interface "in SmallScript" [
> asMapped: descriptor
>     ...
> ]?>
> ===================
>
> Then one can write code like:
>
> a)
>     anObject as: #String. "WRONG -- I'm a dummy"

Uhhh, duh. I went to all the trouble to write the post and then stupidly
wrote the wrong answer here...
"SHOULD BE"
a)
      #someClassName as: Class.

>
> b)
>     anObject as: Boolean.
>
> *)
>     anObject as: <some-class or some-interface>
>
> --
> -- Dave Simmons [www.qks.com / www.smallscript.com]
>   "Effectively solving a problem begins with how you express it."
>
>
> "Costas Menico" <[hidden email]> wrote in message
> news:[hidden email]...
> > Peter,
> >
> > >1. Because Kent says so, doesn't make it right.
> > >2. Kent doesn't say so. What he says (p. 28-29) is that he doesn't want
> > >protocol explosion, which he sees as a danger because there is no
> > >theoretical limit to the number of conversion methods you could add.
This
> in
> > >*not* a case where you are in danger of a conversion protocol
explosion.

> > >3. In fact, Kent explicitly mentions (p. 29) that he would be happy to
> use a
> > >conversion method where there is only one reasonable way to do the
> > >conversion, as is the case with the conversion from Symbol to Class.
> >
> > I agree that just because Kent said it it does not make it right.
> > Patterns are advisory as are many things in Smalltalk. There are many
> > exceptions to the rules.
> >
> > >4. Don't take my word for it, ask Kent what he thinks about #asClass.
> >
> > Hmmm, does he still work with Smalltalk?
> >
> > >5. #asClass isn't really a standard conversion method. If you feel it
> could
> > >be unrevealing of its intention (I think, slim chance of that), use
Class
> > >withName: aString. It's a little longer, but it also communicates just
a
> > >little more.
> > >
> > >Finally, I wasn't suggesting the method is in the Dolphin base system.
I

> was
> > >suggesting Costas use it, for elegance, as per his request.
> >
> > No question #asClass or Class withname: asString would be more
> > meaningful. However I for my own reasons am trying to refrain from
> > adding code to the base image of Dolphin.
> >
> > I think for this I will just use what is available and just write a
> > comment next to it.
> >
> > Costas
>
>


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion? [3rd and hopefully final version]

David Simmons
Dag nammit. I did it again. I was called to dinner a while ago and I've been
rushing to get this post out. It's stupid I know. I apologize for a third
try to get it right...

"David Simmons" <[hidden email]> wrote in message
news:XGU%5.10938$[hidden email]...
> "David Simmons" <[hidden email]> wrote in message news:...
> > Hi guys,
> >
> > If I might make a suggestion that would be a more general mapping
pattern

> > (that also happens to be compatible with features in SmallScript :-).
> >
> > You might want to try implementing:
> >
> >     #as: ... "in <Object>"
> >
> > This has the advantage that there is only ONE generalized selector #as:.
> > Then a variety of techniques like double dispatching or multi-method
> > checking can be done to handle the conversion.
> >
> > As in:
> > ===================

"THIS SHOULD SPECIFY class=Object"
> > <?method [
> > as: aMapper
> >     ^aMapper asMapped: self
> > ]?>

As in:

<?method class=Object [
as: aMapper
    ^aMapper asMapped: self
]?>

> >
> > <?method class=Class [
> > asMapped: descriptor
> >
> >     ^Smalltalk at: descriptor "or whatever is appropriate"
> > ]?>
> >
> > <?method class=Boolean [
> > asMapped: descriptor
> >    ^descriptor !== false
> >         and: [descriptor !== nil
> >             and: [descriptor != 0]]
> > ]?>
> >
> > <?method class=Interface "in SmallScript" [
> > asMapped: descriptor
> >     ...
> > ]?>
> > ===================
> >
> > Then one can write code like:
> >
> > a)
> >     anObject as: #String. "WRONG -- I'm a dummy"
>
> Uhhh, duh. I went to all the trouble to write the post and then stupidly
> wrote the wrong answer here...
> "SHOULD BE"
> a)
>       #someClassName as: Class.
> >
> > b)
> >     anObject as: Boolean.
> >
> > *)
> >     anObject as: <some-class or some-interface>
> >
> > --
> > -- Dave Simmons [www.qks.com / www.smallscript.com]
> >   "Effectively solving a problem begins with how you express it."
> >
> >
> > "Costas Menico" <[hidden email]> wrote in message
> > news:[hidden email]...
> > > Peter,
> > >
> > > >1. Because Kent says so, doesn't make it right.
> > > >2. Kent doesn't say so. What he says (p. 28-29) is that he doesn't
want
> > > >protocol explosion, which he sees as a danger because there is no
> > > >theoretical limit to the number of conversion methods you could add.
> This
> > in
> > > >*not* a case where you are in danger of a conversion protocol
> explosion.
> > > >3. In fact, Kent explicitly mentions (p. 29) that he would be happy
to

> > use a
> > > >conversion method where there is only one reasonable way to do the
> > > >conversion, as is the case with the conversion from Symbol to Class.
> > >
> > > I agree that just because Kent said it it does not make it right.
> > > Patterns are advisory as are many things in Smalltalk. There are many
> > > exceptions to the rules.
> > >
> > > >4. Don't take my word for it, ask Kent what he thinks about #asClass.
> > >
> > > Hmmm, does he still work with Smalltalk?
> > >
> > > >5. #asClass isn't really a standard conversion method. If you feel it
> > could
> > > >be unrevealing of its intention (I think, slim chance of that), use
> Class
> > > >withName: aString. It's a little longer, but it also communicates
just
> a
> > > >little more.
> > > >
> > > >Finally, I wasn't suggesting the method is in the Dolphin base
system.

> I
> > was
> > > >suggesting Costas use it, for elegance, as per his request.
> > >
> > > No question #asClass or Class withname: asString would be more
> > > meaningful. However I for my own reasons am trying to refrain from
> > > adding code to the base image of Dolphin.
> > >
> > > I think for this I will just use what is available and just write a
> > > comment next to it.
> > >
> > > Costas
> >
> >
>
>


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion? [3rd and hopefully final version]

Costas Menico-2
"David Simmons" <[hidden email]> wrote:

>Dag nammit. I did it again. I was called to dinner a while ago and I've been
>rushing to get this post out. It's stupid I know. I apologize for a third
>try to get it right...
>

I think I will wait until later to study your posts. Make sure there
is nothing else you left out <g>...


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

John Clonts-2
In reply to this post by David Simmons
David Simmons wrote:

>
> Hi guys,
>
> If I might make a suggestion that would be a more general mapping pattern
> (that also happens to be compatible with features in SmallScript :-).
>
> You might want to try implementing:
>
>     #as: ... "in <Object>"
>
> This has the advantage that there is only ONE generalized selector #as:.
[snipped excellent elaboration]

Thank you, this helped me in something I was doing the other day.

I found even that squeak already had
   Object>>as: aSimilarClass
       ^ aSimilarClass newFrom: self

So I just added:
   Class class>>newFrom: aSymbolOrString
       ^ Smalltalk at: aSymbolOrString asSymbol


'Date' as: Class ==>Date

Great! Thanks again!

Cheers,
John


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

David Simmons
"John Clonts" <[hidden email]> wrote in message
news:[hidden email]...
> David Simmons wrote:
> >
> > Hi guys,
> >
> > If I might make a suggestion that would be a more general mapping
pattern

> > (that also happens to be compatible with features in SmallScript :-).
> >
> > You might want to try implementing:
> >
> >     #as: ... "in <Object>"
> >
> > This has the advantage that there is only ONE generalized selector #as:.
> [snipped excellent elaboration]
>
> Thank you, this helped me in something I was doing the other day.
>
> I found even that squeak already had
>    Object>>as: aSimilarClass
>        ^ aSimilarClass newFrom: self
>
> So I just added:
>    Class class>>newFrom: aSymbolOrString
>        ^ Smalltalk at: aSymbolOrString asSymbol

Cool. I'm glad it helped despite my rewrites.

By the way, did you notice that you still use #asSymbol.

    ^Smalltalk at: (aSymbolOrString as: Symbol)

I'm not suggesting you shouldn't but it is worth noticing...

-- Dave Simmons [www.qks.com / www.smallscript.com]
  "Effectively solving a problem begins with how you express it."

>
>
> 'Date' as: Class ==>Date
>
> Great! Thanks again!
>
> Cheers,
> John


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion? Dynamic Type Safety and Contract Enforcement

David Simmons
"David Simmons" <[hidden email]> wrote in message
news:A0Z%5.13077$[hidden email]...

> "John Clonts" <[hidden email]> wrote in message
> news:[hidden email]...
> > David Simmons wrote:
> > >
> > > Hi guys,
> > >
> > > If I might make a suggestion that would be a more general mapping
> pattern
> > > (that also happens to be compatible with features in SmallScript :-).
> > >
> > > You might want to try implementing:
> > >
> > >     #as: ... "in <Object>"
> > >
> > > This has the advantage that there is only ONE generalized selector
#as:.

> > [snipped excellent elaboration]
> >
> > Thank you, this helped me in something I was doing the other day.
> >
> > I found even that squeak already had
> >    Object>>as: aSimilarClass
> >        ^ aSimilarClass newFrom: self
> >
> > So I just added:
> >    Class class>>newFrom: aSymbolOrString
> >        ^ Smalltalk at: aSymbolOrString asSymbol
>
> Cool. I'm glad it helped despite my rewrites.
>
> By the way, did you notice that you still use #asSymbol.
>
>     ^Smalltalk at: (aSymbolOrString as: Symbol)
>
> I'm not suggesting you shouldn't but it is worth noticing...
>
> -- Dave Simmons [www.qks.com / www.smallscript.com]
>   "Effectively solving a problem begins with how you express it."

Ok, so I probably should elaborate on this. And, it turns out to be a good
basis for explaining a number of other related benefits and reasons for
utilizing this kind of design/architecture.

First, let me point out that executing #asSymbol is a single dispatch for
the case of <self> being a <Symbol>, vis-a-vis #as:<Symbol> which results in
a double dispatch.

Without multi-method dispatch one could argue that double dispatching all
conversions is more expensive in terms of performance. I.e., "aSymbol
asSymbol" is about as efficient as it gets for jitted execution. Whereas
"aSymbol as: Symbol" results in a double dispatch and probably a type check
in the second method -- so it is quite a bit more expensive. Read on to see
how multi-method dispatch restores the performance balance while retaining
the ability to generalize with #as:.

I.e., you would want both:

"General method to obtain a canonically unique Symbol given a String"
<?method class='Symbol.class' [
asMapped: <String> descriptor
    ...String to Symbol parse and intern code...
]?>

"This is the method that gets you the same performance
 as you have with traditional #asSymbol."
<?method class=Symbol [
as: <Symbol>
    ^self
]?>
===============

How does this work?

Given:
    x as: Symbol

If <x> is a <Symbol>, then the multi-method Symbol::as:(<Symbol>) would be
invoked with exactly the same performance benefits as #asSymbol. I.e., no
double dispatch. One-arg multi-method dispatch is almost identical
performance as non-multi-method dispatch.

If, on the other hand, <x> is a <String> then it would be double-dispatched
via Object::as:(<any>) to Symbol.class::asMapped:(<String>). Furthermore, as
we note later on, the intern code will only be invoked if the <descriptor>
is a type of <String> (an instance of <String> or one of its subclasses).

Which is the same mechanism that #asSymbol typically uses. Unless, the
<Symbol> intern code is actually performed in the Object::asSymbol() method.
While that is not how I would write it (because it is both a <Symbol>
operation and it clutters <Object>), one could achieve that same mechanism
by moving the code from Symbol.class::asMapped:(<String>).

AS IN:

<?method class='Symbol.class' [
asMapped: <String> descriptor
    ...String to Symbol parse and intern code...
]?>

TO

<?method class=Object [
as: <Symbol.class> aMapper
    ...String to Symbol parse and intern code...
]?>

Finally, with multi-method binding we have added type safety. First our
<Symbol> intern code will only be invoked with a <descriptor> that is a
<String> or one of its subclasses. Second, as a result, we've pushed the
contract compliance responsibility off our implementation shoulders and onto
the callee's implementation shoulders (where it belongs).

In other words, multi-methods have allowed us to have runtime guaranteed
behavior/contract safety in our methods. That means contract failure is no
longer the responsibility of the provider, it becomes the exclusive
responsibility of the consumer/client.

In this system we would get a DNR at the callsite for an expression of the
form:

    123 as: Symbol

Whereas, without multi-method contract support the validation and thus
failure point would be shifted to somewhere in the internals of the callee.
Which: (1) might make it much harder to figure out what the real problem
was; (2) mean that as a "provider" we have to have more
assertion/type-checks; (3) we might end up with side-effects for actions
taken in the internals of the "provider" and therefore require more design
work to add transaction semantics that allow reversing of the side-effects.

I.e.,

    123 as: Symbol

Would presumably cause some exception inside the bowels of the <Symbol>
intern code.

If you extrapolate this reasonably simple example to a complex
application/framework architecture it could be much more challenging to
validate and/or debug problems because the contract is not runtime enforced.
Hence, we would want to write/provide a significantly larger set of unit
tests just to achieve a corresponding level of contract
assertion/enforcement.

And that, in a nutshell, is the dynamic runtime equivalent of static
(compile time) type safety/correctness behavior. Interfaces (mixin types),
parametric polymorphism, and a few other things make the story even more
attractive for dynamic type systems.

-- Dave Simmons [www.qks.com / www.smallscript.com]
  "Effectively solving a problem begins with how you express it."

>
> >
> >
> > 'Date' as: Class ==>Date
> >
> > Great! Thanks again!
> >
> > Cheers,
> > John
>
>


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion? Dynamic Type Safety and Contract Enforcement

David Simmons
"David Simmons" <[hidden email]> wrote in message
news:qDZ%5.13164$[hidden email]...

> "David Simmons" <[hidden email]> wrote in message
> news:A0Z%5.13077$[hidden email]...
> > "John Clonts" <[hidden email]> wrote in message
> > news:[hidden email]...
> > > David Simmons wrote:
> > > >
> > > > Hi guys,
> > > >
> > > > If I might make a suggestion that would be a more general mapping
> > pattern
> > > > (that also happens to be compatible with features in SmallScript
:-).

> > > >
> > > > You might want to try implementing:
> > > >
> > > >     #as: ... "in <Object>"
> > > >
> > > > This has the advantage that there is only ONE generalized selector
> #as:.
> > > [snipped excellent elaboration]
> > >
> > > Thank you, this helped me in something I was doing the other day.
> > >
> > > I found even that squeak already had
> > >    Object>>as: aSimilarClass
> > >        ^ aSimilarClass newFrom: self
> > >
> > > So I just added:
> > >    Class class>>newFrom: aSymbolOrString
> > >        ^ Smalltalk at: aSymbolOrString asSymbol
> >
> > Cool. I'm glad it helped despite my rewrites.
> >
> > By the way, did you notice that you still use #asSymbol.
> >
> >     ^Smalltalk at: (aSymbolOrString as: Symbol)
> >
> > I'm not suggesting you shouldn't but it is worth noticing...
> >
> > -- Dave Simmons [www.qks.com / www.smallscript.com]
> >   "Effectively solving a problem begins with how you express it."
>
> Ok, so I probably should elaborate on this. And, it turns out to be a good
> basis for explaining a number of other related benefits and reasons for
> utilizing this kind of design/architecture.
>
> First, let me point out that executing #asSymbol is a single dispatch for
> the case of <self> being a <Symbol>, vis-a-vis #as:<Symbol> which results
in
> a double dispatch.
>
> Without multi-method dispatch one could argue that double dispatching all
> conversions is more expensive in terms of performance. I.e., "aSymbol
> asSymbol" is about as efficient as it gets for jitted execution. Whereas
> "aSymbol as: Symbol" results in a double dispatch and probably a type
check
> in the second method -- so it is quite a bit more expensive. Read on to
see

> how multi-method dispatch restores the performance balance while retaining
> the ability to generalize with #as:.
>
> I.e., you would want both:
>
> "General method to obtain a canonically unique Symbol given a String"
> <?method class='Symbol.class' [
> asMapped: <String> descriptor
>     ...String to Symbol parse and intern code...
> ]?>
>
> "This is the method that gets you the same performance
>  as you have with traditional #asSymbol."
> <?method class=Symbol [
> as: <Symbol>
>     ^self
> ]?>

-------
BUG FIX: Today is clearly not a good day for me :(
-------
<?method class=Symbol [
as: <Symbol.class> "<-- Symbol.class not Symbol"
   ^self
]?>

I really should just grab real code from the system rather than writing this
stuff off the top of my clearly overtaxed head.

> ===============
>
> How does this work?
>
> Given:
>     x as: Symbol
>
> If <x> is a <Symbol>, then the multi-method Symbol::as:(<Symbol>) would be
> invoked with exactly the same performance benefits as #asSymbol. I.e., no
> double dispatch. One-arg multi-method dispatch is almost identical
> performance as non-multi-method dispatch.
>
> If, on the other hand, <x> is a <String> then it would be
double-dispatched
> via Object::as:(<any>) to Symbol.class::asMapped:(<String>). Furthermore,
as
> we note later on, the intern code will only be invoked if the <descriptor>
> is a type of <String> (an instance of <String> or one of its subclasses).
>
> Which is the same mechanism that #asSymbol typically uses. Unless, the
> <Symbol> intern code is actually performed in the Object::asSymbol()
method.

> While that is not how I would write it (because it is both a <Symbol>
> operation and it clutters <Object>), one could achieve that same mechanism
> by moving the code from Symbol.class::asMapped:(<String>).
>
> AS IN:
>
> <?method class='Symbol.class' [
> asMapped: <String> descriptor
>     ...String to Symbol parse and intern code...
> ]?>
>
> TO
>
> <?method class=Object [
> as: <Symbol.class> aMapper
>     ...String to Symbol parse and intern code...
> ]?>
>
> Finally, with multi-method binding we have added type safety. First our
> <Symbol> intern code will only be invoked with a <descriptor> that is a
> <String> or one of its subclasses. Second, as a result, we've pushed the
> contract compliance responsibility off our implementation shoulders and
onto

> the callee's implementation shoulders (where it belongs).
>
> In other words, multi-methods have allowed us to have runtime guaranteed
> behavior/contract safety in our methods. That means contract failure is no
> longer the responsibility of the provider, it becomes the exclusive
> responsibility of the consumer/client.
>
> In this system we would get a DNR at the callsite for an expression of the
> form:
>
>     123 as: Symbol
>
> Whereas, without multi-method contract support the validation and thus
> failure point would be shifted to somewhere in the internals of the
callee.
> Which: (1) might make it much harder to figure out what the real problem
> was; (2) mean that as a "provider" we have to have more
> assertion/type-checks; (3) we might end up with side-effects for actions
> taken in the internals of the "provider" and therefore require more design
> work to add transaction semantics that allow reversing of the
side-effects.

>
> I.e.,
>
>     123 as: Symbol
>
> Would presumably cause some exception inside the bowels of the <Symbol>
> intern code.
>
> If you extrapolate this reasonably simple example to a complex
> application/framework architecture it could be much more challenging to
> validate and/or debug problems because the contract is not runtime
enforced.

> Hence, we would want to write/provide a significantly larger set of unit
> tests just to achieve a corresponding level of contract
> assertion/enforcement.
>
> And that, in a nutshell, is the dynamic runtime equivalent of static
> (compile time) type safety/correctness behavior. Interfaces (mixin types),
> parametric polymorphism, and a few other things make the story even more
> attractive for dynamic type systems.
>
> -- Dave Simmons [www.qks.com / www.smallscript.com]
>   "Effectively solving a problem begins with how you express it."
>
> >
> > >
> > >
> > > 'Date' as: Class ==>Date
> > >
> > > Great! Thanks again!
> > >
> > > Cheers,
> > > John
> >
> >
>
>


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Blair McGlashan
In reply to this post by Peter van Rooijen
Peter

You wrote in message news:91odoc$q0s$[hidden email]...
>
> "Costas Menico" <[hidden email]> wrote in message
> >...
> > First thing I tried... but as you can see from Andy's response I have
> > to consult my patterns too <g>.
>
> Ho! Not so fast!

Apologies for belatedly stepping into the middle of this conversation, but
as I do posess a copy of the aforementioned tome I am going to support my
colleague.

>
> 1. Because Kent says so, doesn't make it right.

Actually I don't think Andy was citing Kent because he is a blind follower
of the Beck faith. He (Kent) does happen to be a person who has a lucid way
of setting down opinions with which we tend to feel an affinity based on our
own experience. A citation is an economical way to transmit a well argued
point of view without regurgitating it. When the citee is also a well
respected individual then that opinion should rightly carry more weight.
Your contradiction may also not be right, and that of course the reader must
judge. Of course when your own book is published Peter, we'll doubtless have
another lucid reference to cite.

> 2. Kent doesn't say so. What he says (p. 28-29) is that he doesn't want
> protocol explosion, which he sees as a danger because there is no
> theoretical limit to the number of conversion methods you could add.

Well, your interpretation may be that Kent doesn't say so. Whether he does
or does not, he does say rather more than that over those 2 pages. He
mentions another problem - that of creating a tie between the classes.
Classes and Symbols are fundamental base classes, so this is probably not an
issue in practical terms. It is though creating a coupling that need not
exist.

>...This in
> *not* a case where you are in danger of a conversion protocol explosion.

I don't think one should attribute the explosion to any one case. Each
converter method contributes a little, so it is blind application of the
pattern which causes the explosion.

> 3. In fact, Kent explicitly mentions (p. 29) that he would be happy to use
a
> conversion method where there is only one reasonable way to do the
> conversion, as is the case with the conversion from Symbol to Class.

He does say that, but you have omitted his first precondition for
implementing a converter method, which is that the "source and destination
of conversion share the same protocol." Clearly not the case here.

Personally I don't think it is even correct to say that there is only one
way to perform that conversion. That is probably true in Dolphin as it
stands today (although the presence of demand loaded binary classes that
don't appear in the system dictionary is a possible counter example), but in
a future system with namespaces there might be a choice of binding
algorithms to use to locate the class. How should the converter method
locate the class (i.e. in which namespace). Does it have sufficient context
to do that? The natural lookup path would seem to be to first try the
namespace of the calling context, information which is not available without
using reflective means to access the sender on the stack.

Lastly there is a third precondition that I think should apply but which
Kent does not mention - the conversion should be possible without error for
the majority of cases. Perhaps this doesn't merit status as a pre-condition,
but I hope you will agree that a conversion method which fails for 92% of
existing instances (only 8% of the Symbols in my D4 image are class names)
has a fishy smell about it.

> 4. Don't take my word for it, ask Kent what he thinks about #asClass.

I'll have leave that to you - we haven't been introduced :-)

> 5. #asClass isn't really a standard conversion method. If you feel it
could
> be unrevealing of its intention (I think, slim chance of that), use Class
> withName: aString. It's a little longer, but it also communicates just a
> little more.

I'd agree with that. If a method in Symbol is needed (certainly it is
useful, however dubious) then it should have a name that indicates that it
is a class lookup since I wouldn't consider this to be a "conversion" at
all.

Though it pains me to say it, what is really needed here is some more
syntax. There should be a way to specify a late-bound reference to a class
in a declarative manner, rather than using some arbitrary expression. The
ability to identify and track such binding references is important for both
automated tools (image stripping springs to mind) and programmers alike.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: How to instantiate a class suggestion?

Peter van Rooijen
Hi Blair,

"Blair McGlashan" <[hidden email]> wrote in message
news:92daqb$6iv88$[hidden email]...

> Peter
>
> You wrote in message news:91odoc$q0s$[hidden email]...
> >
> > "Costas Menico" <[hidden email]> wrote in message
> > >...
> > > First thing I tried... but as you can see from Andy's response I have
> > > to consult my patterns too <g>.
> >
> > Ho! Not so fast!
>
> Apologies for belatedly stepping into the middle of this conversation,

You are very welcome!

> but
> as I do posess a copy of the aforementioned tome I am going to support my
> colleague.

Good.

> >
> > 1. Because Kent says so, doesn't make it right.
>
> Actually I don't think Andy was citing Kent because he is a blind follower
> of the Beck faith.

And I didn't say or think that. It was mostly Costas' remark that I was
reacting to, who suggested that it was necessary for us to consult our
patterns.

> He (Kent) does happen to be a person who has a lucid way
> of setting down opinions with which we tend to feel an affinity based on
our
> own experience.

I completely agree with that.

> A citation is an economical way to transmit a well argued
> point of view without regurgitating it. When the citee is also a well
> respected individual then that opinion should rightly carry more weight.

Absolutely.

> Your contradiction may also not be right, and that of course the reader
must
> judge.

Actually, I agree with Kent. The main intent of my material remarks was to
offer a different interpretation of what Kent wrote, than Andy's.

> Of course when your own book is published Peter, we'll doubtless have
> another lucid reference to cite.

Well, thanks! I can't tell you when it will be out, but It's now almost
certain it will be an e-book (that means non-paper, folks), and the title is
expected to be 'How To Code Smalltalk' and it will likely have the subtitle
'IBM Smalltalk / VisualAge edition'. You could probably pay me to do the
Dolphin edition first, though ;-).

> > 2. Kent doesn't say so. What he says (p. 28-29) is that he doesn't want
> > protocol explosion, which he sees as a danger because there is no
> > theoretical limit to the number of conversion methods you could add.
>
> Well, your interpretation may be that Kent doesn't say so.

And it may be wrong, certainly. Especially as I have been exploiting some
ambiguity in what Kent wrote ;-).

> Whether he does
> or does not, he does say rather more than that over those 2 pages. He
> mentions another problem - that of creating a tie between the classes.
> Classes and Symbols are fundamental base classes, so this is probably not
an
> issue in practical terms.

I agree, and I put it to you, that that in itself probably makes all the
other arguments moot, because it makes Symbol>asClass acceptable (or am I
misunderstanding you?).

> It is though creating a coupling that need not
> exist.

Why? And where is the coupling? I see coupling in the implementation of

Symbol>>asClass

^Smalltalk classAt: self "will return nil if no class of the name is found"

This is only one method in Symbol with one reference to a global, and one
foreign selector! There is no coupling in the reverse direction. How much
lower coupling can you get without staying entirely inside your own module?
Besides, the coupling is the whole idea of the programmer calling the
method, isn't it?

> >...This in
> > *not* a case where you are in danger of a conversion protocol explosion.
>
> I don't think one should attribute the explosion to any one case. Each
> converter method contributes a little, so it is blind application of the
> pattern which causes the explosion.

I read Kent's story about the group who wrote asXXX for every class in the
domain code as illustration of what he means by 'protocol explosion'; that
situation lead to every new class starting out with dozens of methods just
for converting, without it adding anything to the system otherwise. I can
see that you don't want that. And I contend that Symbol>>asClass is a
completely different case.

> > 3. In fact, Kent explicitly mentions (p. 29) that he would be happy to
use
> a
> > conversion method where there is only one reasonable way to do the
> > conversion, as is the case with the conversion from Symbol to Class.
>
> He does say that, but you have omitted his first precondition for
> implementing a converter method, which is that the "source and destination
> of conversion share the same protocol."
> Clearly not the case here.

That only holds if the conditions are cumulative. If they are alternative
(which is not an ureasonable position to take, I would say), it doesn't.

Certainly, Kent's own examples don't conform to the criteria as you (seem to
:-)) interpret them:

Collection>>asSet
- Set supports Collection's protocol, but not the other way around
(condition 1 only half satisfied)
- Is there only one reasonable implementation? ^(Set new: self size) addAll:
self; yourself seems reasonable. Is it the only one? I'd want to redefine it
as ^self in Set. Does that count as more than one way?

Number>>asFloat
- Condition 1 only half satisfied, as above
- Integer>>asFloat is a good candidate for a primitive, some others come to
mind for different Number subclasses. Condition 2 most probably not
satisfied.

> Personally I don't think it is even correct to say that there is only one
> way to perform that conversion.

I'm agreeing.

> That is probably true in Dolphin as it
> stands today (although the presence of demand loaded binary classes that
> don't appear in the system dictionary is a possible counter example), but
in
> a future system with namespaces there might be a choice of binding
> algorithms to use to locate the class. How should the converter method
> locate the class (i.e. in which namespace). Does it have sufficient
context
> to do that? The natural lookup path would seem to be to first try the
> namespace of the calling context, information which is not available
without
> using reflective means to access the sender on the stack.

Interesting issue, still. Binding things to names is what programming is all
about.

> Lastly there is a third precondition that I think should apply but which
> Kent does not mention - the conversion should be possible without error
for
> the majority of cases. Perhaps this doesn't merit status as a
pre-condition,
> but I hope you will agree that a conversion method which fails for 92% of
> existing instances (only 8% of the Symbols in my D4 image are class names)
> has a fishy smell about it.

I'm pretty sure nowhere mear that percentage of calls to Symbol>>asClass
fails in the image of anyone using it :-). And I think you'd most probably
agree. The metric you're proposing is not a very relevant criterium. Or have
you ever thought, hey let's write Symbol>>asClass, then run Symbol
allInstances do: #asClass and see if it fails? I'll bet you haven't!

> > 4. Don't take my word for it, ask Kent what he thinks about #asClass.
>
> I'll have leave that to you - we haven't been introduced :-)

Kent's (yes/no) answer is not important to me. I decide for myself, based on
thought, knowing Kent's excellent writings. Perhaps to someone else, it
matters.

> > 5. #asClass isn't really a standard conversion method. If you feel it
> could
> > be unrevealing of its intention (I think, slim chance of that), use
Class
> > withName: aString. It's a little longer, but it also communicates just a
> > little more.
>
> I'd agree with that. If a method in Symbol is needed (certainly it is
> useful, however dubious) then it should have a name that indicates that it
> is a class lookup since I wouldn't consider this to be a "conversion" at
> all.

Well, I believe that there is little concern that #AbcDatabaseConnection
asClass will be misunderstood. So, what's wrong with it? That seems to be
the central question, after all.

> Though it pains me to say it, what is really needed here is some more
> syntax. There should be a way to specify a late-bound reference to a class
> in a declarative manner, rather than using some arbitrary expression. The
> ability to identify and track such binding references is important for
both
> automated tools (image stripping springs to mind) and programmers alike.

I think I agree with that general idea. But when is the right time for
binding, then? All I can think of, if not compile-time, is the latest
possible time. With the variations 'bound once', and 'bound at each
activation'. Interesting, indeed. Think you'll do it? I've long yearned for
'once blocks' anyway, BTW.

Best regards,

Peter