Creation procedures of deferred types

8 messages Options
Embed this post
Permalink
Daniel Furrer

Creation procedures of deferred types

Reply Threaded More More options
Print post
Permalink
Dear fellow Eiffel users and creators,

I ran into a problem lately and after discussing it with a friend I think
it's safe to bring it up here :)My usecase is somewhat artificial (I ran
into the problem when working on the Cocoa Objective-C bridge) but there may
be others. Let me try to explain:

Many classes inherit from PROXYABLE and proxy returns an instance of the
same class being called on, though with somewhat different semantics for all
the feature calls.
Ideally the proxy feature could be implemented as below (instead of in all
the subclasses). The 'problem' is that the compiler sees `proxy' creating an
object of type "like Current" which it interprets as PROXYABLE and thus
complains about a creation call. PROXYABLE is deferred and cannot be
instantiated.

Since PROXIABLE is deferred though there will never actually be an object of
this type at run-time, but only of its effective subclasses.
The compiler should thus accept the code if indeed every effective subclass
provides the creation feature needed by the deferred ancestor (which can
easily be verified. Optionally the creation procedures could be listed in
the create clause of a deferred class).

What are your feelings about this?


deferred class
    PROXYABLE

feature

    proxy: like Current
        do
            create Result.make_with_arg (foo)
        end
....

Best Regards,
Daniel


[Non-text portions of this message have been removed]

Emmanuel Stapf

RE: Creation procedures of deferred types

Reply Threaded More More options
Print post
Permalink
> What are your feelings about this?

This has been discussed in the past but no real decision was taken on the subject.
The main issue is introducing a context bound validity rule and that's what we
have always tried to avoid in Eiffel.

I'll bring the topic to the ECMA committee for further discussion. In the
meantime, you have two solutions:
- make PROXYABLE non-deferred and have its creation routine `make_with_arg'
exported to PROXYABLE for creation (this forces all descendants to have
`make_with_arg' as creation procedure).
- make your factory function deferred in the deferred class and implement it
accordingly in your descendants (there you are not bound to a particular creation
procedure).

Regards,
Manu


------------------------------------------------------------------------  
Eiffel Software
805-685-1006
http://www.eiffel.com       
Customer support: http://support.eiffel.com       
User group: http://groups.eiffel.com/join       
------------------------------------------------------------------------  
panfriedwoggle

Re: Creation procedures of deferred types

Reply Threaded More More options
Print post
Permalink
In reply to this post by Daniel Furrer
I ran into exactly the same problem that Daniel describes below (though with a different set of classes) last week. I would very much like to see a solution such as that described below.

Perhaps there could even be some sort of "deferred creation" clause that would would make it clear that the routines listed were not in fact creation routines in this class, but must be implemented in any concrete subclass.

--- In [hidden email], Daniel Furrer <daniel.furrer@...> wrote:

>
> Dear fellow Eiffel users and creators,
>
> I ran into a problem lately and after discussing it with a friend I think
> it's safe to bring it up here :)My usecase is somewhat artificial (I ran
> into the problem when working on the Cocoa Objective-C bridge) but there may
> be others. Let me try to explain:
>
> Many classes inherit from PROXYABLE and proxy returns an instance of the
> same class being called on, though with somewhat different semantics for all
> the feature calls.
> Ideally the proxy feature could be implemented as below (instead of in all
> the subclasses). The 'problem' is that the compiler sees `proxy' creating an
> object of type "like Current" which it interprets as PROXYABLE and thus
> complains about a creation call. PROXYABLE is deferred and cannot be
> instantiated.
>
> Since PROXIABLE is deferred though there will never actually be an object of
> this type at run-time, but only of its effective subclasses.
> The compiler should thus accept the code if indeed every effective subclass
> provides the creation feature needed by the deferred ancestor (which can
> easily be verified. Optionally the creation procedures could be listed in
> the create clause of a deferred class).
>
> What are your feelings about this?
>
>
> deferred class
>     PROXYABLE
>
> feature
>
>     proxy: like Current
>         do
>             create Result.make_with_arg (foo)
>         end
> ....
>
> Best Regards,
> Daniel
>
>
> [Non-text portions of this message have been removed]
>


Alexander Kogtenkov [ES]-2

Re: Creation procedures of deferred types

Reply Threaded More More options
Print post
Permalink
In reply to this post by Daniel Furrer
Daniel Furrer wrote:

> Ideally the proxy feature could be implemented as below (instead of in all
> the subclasses). The 'problem' is that the compiler sees `proxy' creating an
> object of type "like Current" which it interprets as PROXYABLE and thus
> complains about a creation call. PROXYABLE is deferred and cannot be
> instantiated.
...
> deferred class
>    PROXYABLE
>
> feature
>
>    proxy: like Current
>        do
>            create Result.make_with_arg (foo)
>        end

Would it make sense to do something like that:

deferred class
   PROXYABLE [G -> PROXYABLE [G] create make_with_arg end]
feature
   proxy: G
       do
           create Result.make_with_arg (foo)
       end
   make_with_arg (foo: BAR)
       deferred
       end
?

Then the descendants can look like

class
   WHATEVER
inherit
   PROXYABLE [WHATEVER]
...

It does not look as straightforward as it could if "like Current" was allowed
to be used instead of "G", but probably it's pretty close to what you need.

Regards,
Alexander Kogtenkov
fivaarno

Re: Creation procedures of deferred types

Reply Threaded More More options
Print post
Permalink

I had a similar issue lately creating a tree data structure. The declaration

PROXYABLE [G -> PROXYABLE [G]]

is an interesting approach. The only problem I found is that you make it impossible for a client to use a general PROXYABLE, right?

Regards,
Arno Fiva


Alexander Kogtenkov [ES]-2

Re: Re: Creation procedures of deferred types

Reply Threaded More More options
Print post
Permalink
Arno Fiva wrote:

> I had a similar issue lately creating a tree data structure. The declaration
>
> PROXYABLE [G -> PROXYABLE [G]]
>
> is an interesting approach. The only problem I found is that you make it impossible for a client to use a general PROXYABLE,
> right?

That's correct. The issue can be solved by adding one more non-generic parent
that lists the required features, so that the structure becomes similar to
    MY_PROXYABLE -> PROXYABLE (defines "proxy") -> PROXYABLE_INTERFACE (defines required features)

If required, PROXYABLE_INTERFACE can even define deferred feature "proxy":

    proxy: PROXYABLE_INTERFACE
        deferred
        end

And this feature will be effected in PROXYABLE.

Regards,
Alexander Kogtenkov

Daniel Furrer

Re: Re: Creation procedures of deferred types

Reply Threaded More More options
Print post
Permalink
On Tue, Jun 30, 2009 at 10:07 AM, Alexander Kogtenkov <[hidden email]> wrote:

> Would it make sense to do something like that:
> ....
>
>



Yes, thanks for your suggestions. The structure with PROXYABLE [G ->
PROXYABLE [G]] seemed very interesting and better than those I heard so far
but what Arno pointed out is certainly an issue.Let me try and see if I
understand your solution for that correctly:

deferred class
    PROXYABLE_INTERFACE [G -> PROXYABLE_INTERFACE [G] create make_with_arg
end]
feature
    proxy: PROXYABLE_INTERFACE
        deferred
        end

class
    PROXYABLE
inherit
    PROXYABLE_INTERFACE [PROXYABLE]
create
    make_with_arg
feature
    ....
    proxy: like Current
        do
            create Result.make_with_arg (foo)
        end

So basically your solution is then to just introduce a non-deferred class
which can define the creation procedure. In that case there's not much
difference to Manu's first suggestion (and one could directly make PROXYABLE
non-deferred, which defeats the original point).

Do you agree that my initial solution would be the most elegant?

I may post more when I have found out what you mean by a context bound
validity rule.

The general philosophical question that I can see here is how much some
validity rules, written to generally make sense, should be relaxed in
(exceptional) situations where soundness is still guaranteed thus making
them harder to fully understand.
Another example I have in mind could be the redefinition of attributes as
functions.

Best Regards,
Daniel

ps. My current solution is now Alexander's first suggestion as in my use
case it hardly makes sense for clients to use the general PROXIABLE.

On Tue, Jun 30, 2009 at 11:37 AM, Alexander Kogtenkov <[hidden email]> wrote:

>
>
> Arno Fiva wrote:
>
> > I had a similar issue lately creating a tree data structure. The
> declaration
> >
> > PROXYABLE [G -> PROXYABLE [G]]
> >
> > is an interesting approach. The only problem I found is that you make it
> impossible for a client to use a general PROXYABLE,
> > right?
>
> That's correct. The issue can be solved by adding one more non-generic
> parent
> that lists the required features, so that the structure becomes similar to
> MY_PROXYABLE -> PROXYABLE (defines "proxy") -> PROXYABLE_INTERFACE (defines
> required features)
>
> If required, PROXYABLE_INTERFACE can even define deferred feature "proxy":
>
> proxy: PROXYABLE_INTERFACE
> deferred
> end
>
> And this feature will be effected in PROXYABLE.
>
> Regards,
> Alexander Kogtenkov
>
>  
>


[Non-text portions of this message have been removed]

Alexander Kogtenkov [ES]-2

Re: Re: Creation procedures of deferred types

Reply Threaded More More options
Print post
Permalink
Daniel Furrer wrote:

> but what Arno pointed out is certainly an issue.Let me try and see if I
> understand your solution for that correctly:
>
> deferred class
>    PROXYABLE_INTERFACE [G -> PROXYABLE_INTERFACE [G] create make_with_arg
> end]
> feature
>    proxy: PROXYABLE_INTERFACE
>        deferred
>        end
>
> class
>    PROXYABLE
> inherit
>    PROXYABLE_INTERFACE [PROXYABLE]
> create
>    make_with_arg
> feature
>    ....
>    proxy: like Current
>        do
>            create Result.make_with_arg (foo)
>        end

No, I mean

deferred class
   PROXYABLE_INTERFACE
feature -- Features that are expected by the clients
    ...
feature -- Proxy
   proxy: PROXYABLE_INTERFACE
       deferred
       end
...

deferred class
   PROXYABLE [G -> PROXYABLE [G] create make_with_arg end]
inherit
   PROXYABLE_INTERFACE
feature
   proxy: like Current
       do
           create Result.make_with_arg (foo)
       end
    make_with_arg (foo: BAR)
...

Then one can use

    p: PROXYABLE_INTERFACE

that should address Arno's issue.

Regards,
Alexander Kogtenkov