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 <[email protected]> wrote:

> On Thu, Jun 18, 2009 at 11:18 PM, Eric Bowman <[email protected]> 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 [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to