[Lift] Re: is there a name for this pattern?

2009-06-20 Thread Eric Bowman

Eric Bowman wrote:
 The basic trick where a superclass has its subclass as a type parameter,
 e.g.

 class User extends MegaProtoUser[User]

 I've run into this before, I remember struggling to get it, then
 getting it, but I can't recall the epiphany.  But obviously this is a
 relatively common technique, so something to google is much appreciated.
   

Thanks all for the great replies!

cheers,
Eric

-- 
Eric Bowman
Boboco Ltd
ebow...@boboco.ie
http://www.boboco.ie/ebowman/pubkey.pgp
+35318394189/+353872801532


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: is there a name for this pattern?

2009-06-20 Thread David Pollak
Having type parameters on Mapper classes helps with a lot of things and is
not going to go away.  Marius and I discussed this a bunch of months ago
onlist.
Basically, the QueryParam (stuff that's passed to find(), findAll(), etc.)
must be type checked against the current Mapper so you don't pass in queries
for fields not on the current mapper.  To get this to play nicely with the
type inferencer (so you don't have to type By[User, Long](User.friend,
33L)), you need type parameters.  There are shadow dependent types in the
Mapper class so that things like IdPK work without having to type
IdPK[Address].

But, this issue has popped up every 6 months since Lift began and I've
looked at the issue and tried to have less verbose types declarations, but
at the end of the day, type parameters serve an important purpose in Mapper
and will be staying in Mapper (and Record).

On Fri, Jun 19, 2009 at 5:22 PM, Alex Boisvert boisv...@intalio.com wrote:

 On Thu, Jun 18, 2009 at 11:18 PM, Eric Bowman ebow...@boboco.ie wrote:


 The basic trick where a superclass has its subclass as a type parameter,
 e.g.

 class User extends MegaProtoUser[User]

 I've run into this before, I remember struggling to get it, then
 getting it, but I can't recall the epiphany.  But obviously this is a
 relatively common technique, so something to google is much appreciated.


 I agree with Kris, this circular/recursive type pattern has two edges and
 I'm not sure one is worth the other.

 The main benefit I see with this pattern is that it enforces class User to
 pass the User type parameter to Mapper, so you don't end up with a mixin
 that doesn't make sense... although I doubt this error would actually happen
 in reality because you'd quickly realize at design-time that calling any
 method on User/MetaUser would return you something different than what you
 expect.   (

 The drawback is that type signatures are more verbose, complex and viral
 (if you care about extensibility).   Just try explaining the type signature
 to Scala newbie and they'll run away scared! :)

 An alternative design would be something of the form,

 trait Mapper {
   type MapperType
 }

 class User extends Mapper {
   type MapperType : User
 }

 I think this design would be simpler to read and understand, without any
 practical loss in type checking.

 (As a side note, if you don't specify the correct type to Mapper with the
 current design, you get an error message that's hardly helpful to newbies,
 so it doesn't help much either... but I disgress.)

 While I'm at it, there are also places in the code that could use
 this.type instead of MapperType (also called A as parameter) to give out
 an even more specific type without any tradeoffs.  A prime example of this
 would be Mapper.saveMe().

 Just to be clear, I'm not proposing anything be changed in Lift's current
 mapper since it would break compatibility  I'm just suggesting it for
 consideration in future design work... perhaps in Lift's new record module?

 alex




 



-- 
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: is there a name for this pattern?

2009-06-19 Thread Jeremy Day
Eric,

I believe that something like that, in C++ at least, is referred to as the
curiously recurring template pattern.

Jeremy

On Fri, Jun 19, 2009 at 1:18 AM, Eric Bowman ebow...@boboco.ie wrote:


 The basic trick where a superclass has its subclass as a type parameter,
 e.g.

 class User extends MegaProtoUser[User]

 I've run into this before, I remember struggling to get it, then
 getting it, but I can't recall the epiphany.  But obviously this is a
 relatively common technique, so something to google is much appreciated.

 Thanks,
 Eric

 --
 Eric Bowman
 Boboco Ltd
 ebow...@boboco.ie
 http://www.boboco.ie/ebowman/pubkey.pgp
 +35318394189/+353872801532http://www.boboco.ie/ebowman/pubkey.pgp%0A+35318394189/+353872801532


 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: is there a name for this pattern?

2009-06-19 Thread David Pollak
On Thu, Jun 18, 2009 at 11:18 PM, Eric Bowman ebow...@boboco.ie wrote:


 The basic trick where a superclass has its subclass as a type parameter,
 e.g.

 class User extends MegaProtoUser[User]


The circular dependent type that gives Martin and the compiler fits? :-)




 I've run into this before, I remember struggling to get it, then
 getting it, but I can't recall the epiphany.  But obviously this is a
 relatively common technique, so something to google is much appreciated.

 Thanks,
 Eric

 --
 Eric Bowman
 Boboco Ltd
 ebow...@boboco.ie
 http://www.boboco.ie/ebowman/pubkey.pgp
 +35318394189/+353872801532http://www.boboco.ie/ebowman/pubkey.pgp%0A+35318394189/+353872801532


 



-- 
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: is there a name for this pattern?

2009-06-19 Thread Kris Nuttycombe

I've always called this recursive type parameterization. It's useful
when the base class needs to know the type that it's eventually
instantiated as, usually so that it can provide implementations of
methods where dispatch is based upon the instantiated type. I've found
myself using the pattern mostly in cases where I wanted to have
parallel class hierarchies, say of model objects and rendering
strategies for those models. In this case, the model base class would
have a recursive type parameter, and the rendering strategy would be
parameterized with respect to the model type.

ex:

class Model[T : Model[T]] {
   self: T =
   def render(r: Renderer[T]) {
  r.render(this)
   }
}

class ConcreteModel extends Model[ConcreteModel]

class Renderer[T : Model[T]] {
   abstract def render(model: T)
}

class ConcreteModelRenderer extends Renderer[ConcreteModel] {
   def render(model: ConcreteModel) { ... }
}

In Java, you have a little more boilerplate because you don't have an
explicit self-type, so you have to define an abstract method self: T
which you implement trivially in each subclass.

Recursive self-types can be really useful but they're definitely a
double-edged sword because they're sort of viral; you have to add a
bunch of boilerplate type information everywhere that you refer to the
base type, and if you ever discard the more specific type information
(in the example above, say by putting a bunch of different subclasses
of Model into a List[Model[_]]) then you can never get it back without
reflection, and any use of the members of that list in a contravariant
position (say as an argument to another method call) becomes
impossible.

Kris

On Fri, Jun 19, 2009 at 12:18 AM, Eric Bowmanebow...@boboco.ie wrote:

 The basic trick where a superclass has its subclass as a type parameter,
 e.g.

 class User extends MegaProtoUser[User]

 I've run into this before, I remember struggling to get it, then
 getting it, but I can't recall the epiphany.  But obviously this is a
 relatively common technique, so something to google is much appreciated.

 Thanks,
 Eric

 --
 Eric Bowman
 Boboco Ltd
 ebow...@boboco.ie
 http://www.boboco.ie/ebowman/pubkey.pgp
 +35318394189/+353872801532


 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: is there a name for this pattern?

2009-06-19 Thread Xavi Ramirez

This is also a common technique in C# too.  Unfortunately, I'm not
sure of the pattern's name either.  I usually just google for
non-generic inheritance from generic class

On Fri, Jun 19, 2009 at 10:31 AM, Jeremy Dayjeremy@gmail.com wrote:
 Eric,

 I believe that something like that, in C++ at least, is referred to as the
 curiously recurring template pattern.

 Jeremy

 On Fri, Jun 19, 2009 at 1:18 AM, Eric Bowman ebow...@boboco.ie wrote:

 The basic trick where a superclass has its subclass as a type parameter,
 e.g.

 class User extends MegaProtoUser[User]

 I've run into this before, I remember struggling to get it, then
 getting it, but I can't recall the epiphany.  But obviously this is a
 relatively common technique, so something to google is much appreciated.

 Thanks,
 Eric

 --
 Eric Bowman
 Boboco Ltd
 ebow...@boboco.ie
 http://www.boboco.ie/ebowman/pubkey.pgp
 +35318394189/+353872801532





 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: is there a name for this pattern?

2009-06-19 Thread Randall R Schulz

On Thursday June 18 2009, Eric Bowman wrote:
 The basic trick where a superclass has its subclass as a type
 parameter, e.g.

 class User extends MegaProtoUser[User]

 I've run into this before, I remember struggling to get it, then
 getting it, but I can't recall the epiphany.  But obviously this is a
 relatively common technique, so something to google is much
 appreciated.

The example I find helps the most to make this comprehensible is Ordered 
(generically, not necessarily Scala's actual Ordered class):

What does it mean for something to be able to be ordered? It means that 
if you give me two instances of such a thing, I can tell you whether 
they stand in a particular order (which may be numeric but need not be; 
other examples include lexicographic ordering or something defined on a 
metric space like edit distance). No breathtaking insight there.

So naturally when I want to capture orderability generically, I have to 
say that it establishes a relationship with other things of the same 
(or compatible / conformant) type. Thus:

class Ordered[WithRespectToWhat]

Now, to define a class that conforms to Ordered, we have to 
specify ordered with respect to what? And the usual answer is with 
respect to the same type:

class Numeric extends Ordered[Numeric]

You might reasonably want that to be covariant:

   class Ordered[+WithRespectToWhat]

But by cheating (me cheating in writing this up, that is) we find in the 
ScalaDocs this note on the page for Ordered [1]:

Note that since version 2006-07-24 this trait is no longer covariant in 
a. It is important that the equals method for an instance of Ordered[A] 
be consistent with the compare method. However, due to limitations 
inherent in the type erasure semantics, there is no reasonable way to 
provide a default implementation of equality for instances of 
Ordered[A]. Therefore, if you need to be able to use equality on an 
instance of Ordered[A] you must provide it yourself either when 
inheiriting or instantiating.


[1] http://www.scala-lang.org/docu/files/api/scala/Ordered.html


 Thanks,
 Eric


Randall Schulz

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: is there a name for this pattern?

2009-06-19 Thread Alex Boisvert
On Thu, Jun 18, 2009 at 11:18 PM, Eric Bowman ebow...@boboco.ie wrote:


 The basic trick where a superclass has its subclass as a type parameter,
 e.g.

 class User extends MegaProtoUser[User]

 I've run into this before, I remember struggling to get it, then
 getting it, but I can't recall the epiphany.  But obviously this is a
 relatively common technique, so something to google is much appreciated.


I agree with Kris, this circular/recursive type pattern has two edges and
I'm not sure one is worth the other.

The main benefit I see with this pattern is that it enforces class User to
pass the User type parameter to Mapper, so you don't end up with a mixin
that doesn't make sense... although I doubt this error would actually happen
in reality because you'd quickly realize at design-time that calling any
method on User/MetaUser would return you something different than what you
expect.   (

The drawback is that type signatures are more verbose, complex and viral (if
you care about extensibility).   Just try explaining the type signature to
Scala newbie and they'll run away scared! :)

An alternative design would be something of the form,

trait Mapper {
  type MapperType
}

class User extends Mapper {
  type MapperType : User
}

I think this design would be simpler to read and understand, without any
practical loss in type checking.

(As a side note, if you don't specify the correct type to Mapper with the
current design, you get an error message that's hardly helpful to newbies,
so it doesn't help much either... but I disgress.)

While I'm at it, there are also places in the code that could use
this.type instead of MapperType (also called A as parameter) to give out
an even more specific type without any tradeoffs.  A prime example of this
would be Mapper.saveMe().

Just to be clear, I'm not proposing anything be changed in Lift's current
mapper since it would break compatibility  I'm just suggesting it for
consideration in future design work... perhaps in Lift's new record module?

alex

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---