New Type Checking System Idea

S

Sean O'Dell

Taking comments into consideration, a totally new approach strikes me
regarding type checking.

As briefly as I can:

What if we had a way to describe a class interface that basically does this:
"from this point forward, any methods added to this class definition will be
checked against an interface description, and any methods whose names matches
a method described in the interface must take the number and type of
parameters described, and the class will be considered incomplete until the
very last method described by the interface is added to the class."

*** Some basic rules about this:

Classes do not *need* an interface. They can go on just the way the are now,
completely open and free. For someone who doesn't like to use interfaces,
they are completely unaffected.

Interfaces are immutable and cannot be extended, but you can subclass other
interfaces from them.

Interfaces have unique, global names based on where they were defined. They
take the name of the class or module they were described in, but they are not
otherwise related to the class or module.

Interfaces can be assigned to any class regardless of its proximity to the
interface description.

Once a class has been assigned an interface, it's an error to change the
number or types of parameters described methods take.

You can still add methods any way you like, so long as they're not part of the
described interface for the class.

When you subclass from a class with an interface, or mix-in a module that has
an interface, the subclass has that interface as well.

You can re-implement methods in a subclass which has inherited an interface,
but the methods must have the same number and types of parameters.

*** Some performance notes:

These checks are only being as the class is assembled, or when it is modified.
I believe this is called at compile-time regarding Ruby. (?)

Once marked complete, objects generated from that class are marked with a
simple flag stating that it adheres to the interface.

*** Syntax sugar

Parameter and return types are interface names.

If a method needs to enforce a parameter type check, objects passed to that
parameter must contain a "complete" flag for the interface required.

*** Chicken-and-the-egg

Build-in interfaces for all the predefined Ruby classes like T_NIL, T_OBJECT,
T_CLASS, T_MODULE, etc.

*** Example of interface declaration

module IO

class Stream
interface
def Boolean eof?
end

class Input < IO::Stream
interface
def Integer read(Integer maxbytes)
end
end
end

end

*** Example of class definition using an interface

class Stdin
implements IO::Stream::Input
# interface is incompletely fulfilled here

def Boolean eof?
return is-at-end-of-file
end # ==> implemented correctly, but class is still partially incomplete


def Integer read(Integer maxbytes)
return bytes-read
end # ==> class is now marked complete

def someothermethod
end # ==> perfectly ok too

end

*** Example of re-implementing class methods

class Stdin
def Integer read(Integer maxbytes)
return do-something-completely-different-and-return
end
# ==> allowed because it matches the interface description
# for this method
end

*** Example of re-implementing object methods

class <<$stdin
def Integer read(Integer maxbytes)
return do-something-completely-different-and-return
end
# ==> also allowed because it matches the interface
# description for this method
end

*** Summary

1) It doesn't affect existing classes
2) It can be ignored by people who don't want it
3) Performance hit at runtime is merely a very short interface table lookup
4) Integrity of the type checking is high

Anything wrong with this way of doing it?

Sean O'Dell
 
G

Greg McIntyre

I like your idea, Sean, but it's too much effort! If it is onerous then
it won't be used. Perhaps if we based it upon method name and arity
(essentially replacing a bunch of respond_to?() calls with arity
checks added in as a bonus). This is because it requires no extra effort
on the programmer's part, so it fits into the existing Ruby syntax.

I took your code and rewrote it a bit...


class IO
class Stream
def eof?
# ...
end
end

# Class IO::Stream defined. Interface IO::Stream defined:
# [[eof?,0]]

class InputStream < IO::Stream
def read(maxbytes)
# ...
end
end

# Class IO::InputStream defined. Interface IO::InputStream
# defined: [[eof?,0], [read,1]]
end

# Class IO defined. Interface IO defined: []


### Example of class definition using an interface

class Stdin
implements IO::InputStream

# Interface: []
# Needed: [[eof?,0], [read,1]]

def eof?
# ...
end

# Interface: [[eof?,0]]
# Needed: [[eof?,0], [read,1]]

def read(maxbytes)
# ...
end

# Interface: [[eof?,0], [read,1]]
# Needed: [[eof?,0], [read,1]]

def someothermethod
end

# Interface: [[eof?,0], [read,1], [someothermethod,0]]
# Needed: [[eof?,0], [read,1]]

end # RUN-TIME CHECK: Promises fulfilled. Interface Stdin produced.


### Example of re-implementing class methods

class Stdin
def read(maxbytes=20)
# do something different
end

# Interface: [[eof?,0], [read,-1], [someothermethod,0]]
# Needed: [[eof?,0], [read,1]]

end # RUN-TIME CHECK: Promises fulfilled. Interface Stdin kept.
# => Warning, default value for maxbytes in method read may
# never be used by interface(?)
# => No warning, interface made more general(?)


### Example of breaking class interface

class Stdin
def read(maxbytes, retries)
# do something different
end

# Interface: [[eof?,0], [read,2], [someothermethod,0]]
# Needed: [[eof?,0], [read,1]]

end # RUN-TIME CHECK: Promises broken. Interface Stdin deleted.
# => Raise type error(?)


### Example of re-implementing object methods

class << $stdin
def read(maxbytes)
# do something different again
end

# Interface: [[eof?,0], [read,1], [someothermethod,0]]
# Needed: [[eof?,0], [read,1]]

end # RUN-TIME CHECK: Interface fulfilled. No action taken.
 
S

Sean O'Dell

I like your idea, Sean, but it's too much effort! If it is onerous then
it won't be used. Perhaps if we based it upon method name and arity
(essentially replacing a bunch of respond_to?() calls with arity
checks added in as a bonus). This is because it requires no extra effort
on the programmer's part, so it fits into the existing Ruby syntax.

Very funny. =)

Actually, I sort of meant my proposal to require a very minimal effort for
both sides. On Matz' end (save for syntax sugar) it's not a heck of a lot to
code, and it doesn't screech hard against the existing code (at least not
from what I've seen, could be wrong), and on our side it's just a short block
of interface description to write. It really couldn't get a heck of a lot
easier except to just not do it, or to do some sort of interface id tagging
thing like my first proposal, where no enforcement was performed at all.
I took your code and rewrote it a bit...

Ha. Ha. =)

It looks like too much happens at run-time, always checking and querying for
certain methods, etc. Also, the concept of a whole interface, rather than
querying for a set of required methods, I always think is easier to grasp.

I mean, there will always be respond_to? and for those people who see no use
in interface checking, they can, as always, keep just asking respond_to? or
not asking anything at all. Your changes seemed to be sort of a souped-up
respond_to? engine.

Not to mention, no information about required parameter types.

My feeling is, a short run of overhead at compile-time is better than constant
overhead at run-time. My proposal does all the interface fulfillment
checking at compile-time, then conformance checks are done with a simple flag
test internally.

Sean O'Dell
 
G

Geoff Youngs

Taking comments into consideration, a totally new approach strikes me
regarding type checking.
As briefly as I can:
What if we had a way to describe a class interface that basically does
this: "from this point forward, any methods added to this class
definition will be checked against an interface description, and any
methods whose names matches a method described in the interface must
take the number and type of parameters described, and the class will
be considered incomplete until the very last method described by the
interface is added to the class."
*** Some basic rules about this:
Classes do not *need* an interface. They can go on just the way the
are now, completely open and free. For someone who doesn't like to
use interfaces, they are completely unaffected.
Interfaces are immutable and cannot be extended, but you can subclass
other interfaces from them.

Why? Is there any reason that interfaces shouldn't be as mutable as
classes and/or modules are?

I've played with a soft interface implementation which works reasonably
well where I've used it, but it's worth considering existing ruby usage.
And the most common example I come across of a Ruby interface is
Enumerable.

The problems (as I see it) with the current implementation of Enumerable
are that:

1/ It doesn't check for the existance of 'each' until you call a
method.
2/ It has brute force methods which could be implemented more
efficiently in specialised collections, e.g. Range, or a sorted
array.
3/ It supports reflection poorly. ie. there's no easy way to look at
Enumerable and work out what a class needs as a pre-requisite
in order to use Enumerable usefully.

1/ Could be solved using Iface.append_features(aClassOrModule) to check
that the class defines 'each' as an instance method.
3/ Could be solved by making the interface keep track of the required
methods (which would help generically solve 1)
2/ Could be solved by allowing the interface to provide methods which
don't override class methods of the same name.

There are also non-functional interfaces:
e.g. Marshal requires _dump and class._load to be defined.

The advantage of using a specified interface is that duck-typing isn't
enough. And as language doesn't have a infinite list of suitable
methods names, there's the chance that there may well be a clash.

e.g.

class AmericanClothes
attr_reader :pants
end

class BritishPerson
def put_on_underwear(clothesSource)
if @underwear.nil?
if clothesSources.respond_to?:)pants)
put_on(clothesSource.pants)
else
raise ClothingError, "No suitable underwear"
end
end
end
end

Which is a tongue in cheek example, but the point is that there is no
universal atomic source of method names.

But an interface could exist in a global namespace, and thus guarantee
(as much as anything does in Ruby at the moment) that method :x does
what is expected of it, because the class declares it's conformance.

Another reason for a clear interface definitions which I haven't
noticed being mentioned is that for some purposes libraries need types
which are more complex than Ruby's simple builtin types. The library
will either need a large number of respond_to? calls or a simple "does
it claim to conform to interface X?". The advantages of interfaces as
proposed are twofold - for the programmer a clear definition of the
expectations as regard a complex object, for the library a simple check
for conformance. And regardless of what some detractors have said, I do
believe that this adds rather than detracts from the dynamism of Ruby -
so much Ruby code checks for kind_of?(IO) when it really means
implements?(IORead). With interfaces this could and should be clearer
and promote better programming practices.
Interfaces have unique, global names based on where they were defined.
They take the name of the class or module they were described in, but
they are not otherwise related to the class or module.

Aren't/Couldn't they be a specialised module?
Interfaces can be assigned to any class regardless of its proximity to
the interface description.
Once a class has been assigned an interface, it's an error to change
the number or types of parameters described methods take.

Isn't this an unlikely contingency to cater for? And more trouble than
it's worth?

If there's a library with an interface which accepts string arguments to
a particular methods, for example.

--- in foo.rb
interface Foo
def bar(String title)
end

--- in myprog.rb
class Bob
implements Foo
def bar(String|IORead title)
...
end
end

Couldn't the programmer end up in the situation where they have to
modify a library (and either hope that the change is accepted by the
library author or distribute a modified version of the library) so that
they can have a class which behaves as they wish when used by their
code, but which is also accepted by the library?

With dynamic interface definitions this sort of thing could be worked
around, but if they were immutable then every application author would
have to rely on every interface using library author anticipating all
possible uses of their library.
You can still add methods any way you like, so long as they're not
part of the described interface for the class.

See above.
When you subclass from a class with an interface, or mix-in a module
that has an interface, the subclass has that interface as well.

This is pretty much essential, but you'd get it "for free" if interfaces
were specialised modules.
You can re-implement methods in a subclass which has inherited an
interface, but the methods must have the same number and types of
parameters.

Ok - but I still don't see why a program that knows what it's doing
can't take a class and use alias_method to insert hooks in a particular
function.
*** Syntax sugar
Parameter and return types are interface names.
If a method needs to enforce a parameter type check, objects passed to
that parameter must contain a "complete" flag for the interface
required.

Nice, but automated parameter type checking is not essential for a basic
interface implementation.

[snip]
Anything wrong with this way of doing it?

The main disadvantages I see are as follows:
1/ Compatibility
Libraries using this will not be usable earlier versions of
Ruby. As in they will break completely or displayed undefined
behaviour - this is a Bad Thing(TM) and will damage uptake.
(The great thing about so many of the changes between 1.6 and
1.8 is that many of them can be utilised but 1.6 still supported
by means of a compatibility layer written in Ruby - (I, for
example, still have a machine running 1.6 which I'm not in a
position to upgrade at the moment - hence pretty much anything
I write in Ruby for work needs to run on both).
2/ Dynamic extensibillity
I have a big problem with making interfaces immutable - it just
doesn't feel right in Ruby. And greater certainty that the
object isn't lying seems to be the only reason given for doing
it. (Ignoring the fact that the Object could be lie about the
return value of kind_of? anyway)
3/ Core interpreter
There are already various "core" features implemented in pure
Ruby - the most prominent being the Singleton mix-in. I don't
see evidence supporting the notion that unless it's done in
Ruby's C source, interfaces won't/can't become a meaningful and
useful tool - I would agree though that they are unlikely to
have significant penetration unless an implementation is chosen
and included in the core distribution.

Hope this is of interest,


Geoff.
 
G

Greg McIntyre

Sean O'Dell said:
Very funny. =)

Gee, I wasn't trying to be funny. I really would be annoyed if I had to
write as much as you did to have interfaces. A lot of what you would
end up writing would be repeditive, in the same way that with C++,
writing .h and.cpp files repeats a lot of information (i.e. the type
signatures).

Actually, I sort of meant my proposal to require a very minimal effort
for both sides. On Matz' end (save for syntax sugar) it's not a heck
of a lot to code, and it doesn't screech hard against the existing
code (at least not from what I've seen, could be wrong), and on our
side it's just a short block of interface description to write. It
really couldn't get a heck of a lot easier except to just not do it,
or to do some sort of interface id tagging thing like my first
proposal, where no enforcement was performed at all.

The main problem I see, with both versions, is that they put the onus on
the class provider to define all supported interfaces, whereas use of
respond_to? puts the onus on the class client to assert the object
supports the minimally required interface. Where _should_ the
responsibility be? If it's up to the provider then the client may end up
with an object which does not promise to support an interface it could
because it is ignorant of it: i.e. it may restrict duck typing. If it's
up to the class consumer then all that checking becomes a pain (and
inefficient). Hmm...

Can you clarify your idea in the following regard?

Can I check one object against another's interface at run-time if I
desire it?

def read_from(object)
if object.complies(IO::InputStream.interface)
# ...
end
end

Ha. Ha. =)

It looks like too much happens at run-time, always checking and
querying for certain methods, etc.

At "definition" time, yes (when the class is defined). Isn't that what
your code does? Ruby has no "compile" time, after all...

Also, the concept of a whole
interface, rather than querying for a set of required methods, I
always think is easier to grasp.

Yes, I'm all for grouping these queries into identifiable interfaces. I
think that's a Good Thing.

I mean, there will always be respond_to? and for those people who see
no use in interface checking, they can, as always, keep just asking
respond_to? or not asking anything at all. Your changes seemed to be
sort of a souped-up respond_to? engine.

Yes, that's a good way to describe it... which is interface checking. :)
It's just that the interface contains a little less information than the
type signatures of statically typed languages.

In practice (and we've had a decade of it), Guido and matz have shown us
that we don't really need such strong type safety -- it's a frictional
force while programming and the difference it makes in practice is
minimal.

Not to mention, no information about required parameter types.

Exactly, that's what it leaves out. Then you could, optionally, ask Ruby
whether object X fulfils interface Y and it would tell you without any
respond_to? action. It's like... precalculated respond_to? :) I think
it could work because of inheritance (wow, it comes in handy after all)
-- more general classes like IO::Stream can define fewer or more
abstract methods and create abstract interfaces *at the same time*
without the effort of defining the interface explicitly, separately.

You'd probably want to allow explicit interface definitions too, I just
think you're creating more work for yourself if you ingore what you
already have...

My feeling is, a short run of overhead at compile-time is better than
constant overhead at run-time.

I agree, except yoursentence.gsub!(/compile/, 'definition'), or whatever
the more accepted term is for that stage of execution.

My proposal does all the interface fulfillment checking at
compile-time, then conformance checks are done with a simple flag test
internally.

I thought my suggestion would too. It's based closely upon your
suggestion after all... I just "Rubied" the information you keep in your
interface so it did not tread on the pretty ducks. ;)
 
G

Greg McIntyre

Geoff Youngs said:
I've played with a soft interface implementation which works
reasonably well where I've used it...

Oooh, how does it work?

I tried redefining Module#append_features to call a hook which can be
defined to check for the methods the module needs. The only drawback is
you have to include your modules down the bottom of the class. It
doesn't work for inheritance however because Class::inherited is called
at the start of a class definition, not at the end.

So far that's the best Ruby 1 patch-up job I can do to get, as you put
it, soft interface checking. That is, the best without introducing a lot
more ugly code...
 
S

Sean O'Dell

Gee, I wasn't trying to be funny. I really would be annoyed if I had to
write as much as you did to have interfaces. A lot of what you would
end up writing would be repeditive, in the same way that with C++,
writing .h and.cpp files repeats a lot of information (i.e. the type
signatures).

Oh, you didn't mean it? Oops ... I saw a close resemblance between your code
and something someone else proposed, and your suggestions were so far from my
proposal, I thought you were ribbing me!

Anyway, how little can you write to describe an interface? I mean, somewhere
you have to write it out. It can't be avoided. Someone has to put the
requirement down in type somewhere. If it's not the interface designer, then
the developers have to ask for their requirements. I think the least amount
of typing is a situation where the interface designer types it out once,
gives it a name, and developers just refer to it by name thereafter.
The main problem I see, with both versions, is that they put the onus on
the class provider to define all supported interfaces, whereas use of
respond_to? puts the onus on the class client to assert the object
supports the minimally required interface. Where _should_ the
responsibility be? If it's up to the provider then the client may end up
with an object which does not promise to support an interface it could
because it is ignorant of it: i.e. it may restrict duck typing. If it's
up to the class consumer then all that checking becomes a pain (and
inefficient). Hmm...

I think when you are talking about interfaces, you are describing a contract,
and that goes to the interface designer.
Can you clarify your idea in the following regard?

Can I check one object against another's interface at run-time if I
desire it?

def read_from(object)
if object.complies(IO::InputStream.interface)
# ...
end
end

Yes, if you didn't use syntax sugar to tell Ruby to please enforce that object
completely fulfilled the IO::InputStream interface, you could ask
object.implements?(IO::InputStream) (which is how I think my proposal worded
it, but yours is equivalent).
At "definition" time, yes (when the class is defined). Isn't that what
your code does? Ruby has no "compile" time, after all...

Yes, that's when I mean.
Yes, that's a good way to describe it... which is interface checking. :)
It's just that the interface contains a little less information than the
type signatures of statically typed languages.

Yes, my proposal did not say anything about the end developer any way to ask
about the types required. But if Matz does the internals for interface
checking, he can also add methods to the Method class to do that sort of
thing. Internally, he's going to have to come up with some way to encode
method names, parameter numbers and interface requirements into an nifty,
easy-to-use internal structure. The information in that structure can be
exported back to Ruby in any number of ways. I think it comes with the
territory eventually. I think discussions about that would be down the line,
and lots of nifty ideas could surface.
In practice (and we've had a decade of it), Guido and matz have shown us
that we don't really need such strong type safety -- it's a frictional
force while programming and the difference it makes in practice is
minimal.

People have their reasons for wanting it, though, as do I. I think there are
a myriad of reasons they would be good, and I can list them all, and others
can add to the list, but ultimately those reasons can be argued down. I
don't think any way to do anything is imminently set in stone; almost
everything has a work around.
You'd probably want to allow explicit interface definitions too, I just
think you're creating more work for yourself if you ingore what you
already have...

I think the problem is partially that we don't have enough type information to
try anything with, just to see, so we need something to start down that path.
Once it's there, we can see where else such information would be useful.

Ultimately, though, I think interfaces will be their most important use. Some
people will still do things by querying one method at a time, getting a
little more information than they were before.
I thought my suggestion would too. It's based closely upon your
suggestion after all... I just "Rubied" the information you keep in your
interface so it did not tread on the pretty ducks. ;)

In your modification, you were building these arrays every time, and then for
conformance, I assume Ruby would have to do an array-to-array comparison to
determine compliance. It's sort of the same thing, but since that would
happen constantly at run-time, I think it's probably more overhead than we're
aiming for. But yeah, it's definitely the same thing.

Though, of course, the method information could be reported in a similar way.
I guess we'd have to look at the interface implementation to tell what we can
and can't report back.

Sean O'Dell
 
G

Greg McIntyre

Sean O'Dell said:
In your modification, you were building these arrays every time, and
then for conformance, I assume Ruby would have to do an array-to-array
comparison to determine compliance. It's sort of the same thing, but
since that would happen constantly at run-time, I think it's probably
more overhead than we're aiming for. But yeah, it's definitely the
same thing.

Ah, that wasn't clear in my email. Ruby must do something like that
already because at any stage you can get a list of a classes's public
instance methods. I was just putting it in a comment for clarity. There
were no checks between the methods, just at the end of the class
definition (or partial class definition, if it spans multiple files), to
assert whether or not what's there so far implements the promised
interfaces.

I think that's necessary though because it can't build a list of
required methods at the start based upon the interfaces promised and
then slowly destroy it, then check it's empty at the end, because the
list of "unfulfilled methods" may grow again and I don't see how that
would happen if you destroyed the list of interface methods needed...

And just to clarify, what I meant by "too much work" was that when you
define a class, you implicity define its interface (although this
interface in Ruby 1 only has method names and arities), so I wouldn't
want to have to define a class's interface separately in order to say
"ensure this object implements this _class's_ interface".

So it's like your proposal, only with an implicit shortcut. You could
either define interfaces by defining classes and referring to their
interfaces (in that respect a Class object "has" an Interface object),
or define standalone interfaces unrelated to classes and assert
that objects implement them at run-time, or include them in classes to
prevent forgetfulness when implementing (see Enumerable's problem with
#each). :)

I think that's what you meant, I just wanted to be clear about it.

However I'm still thinking about what Geoff Youngs suggested about
uniquely identifying the purpose of components in an interface. With
fine-grained respond_to? checking, you wouldn't know what :pants really
was for, it could mean several things. Whereas if this were part of an
interface, would that interface provide enough context to identify its
purpose? Is it possible to uniquely identify a method's purpose given
its context in a well-written set of interfaces? My brain's fizzled and
I need time to think about it. It's probably not perfect but it's
good, I think. :)
 
S

Sean O'Dell

Ah, that wasn't clear in my email. Ruby must do something like that
already because at any stage you can get a list of a classes's public
instance methods. I was just putting it in a comment for clarity. There
were no checks between the methods, just at the end of the class
definition (or partial class definition, if it spans multiple files), to
assert whether or not what's there so far implements the promised
interfaces.

I think that's necessary though because it can't build a list of
required methods at the start based upon the interfaces promised and
then slowly destroy it, then check it's empty at the end, because the
list of "unfulfilled methods" may grow again and I don't see how that
would happen if you destroyed the list of interface methods needed...

Internally, though, Ruby would store the interface information in its own way.
When a class declared that it implements it, as methods are added to the
class which fulfill the interface requirements, they would be checked off
until the last one, then a flag would be raised for the class to indicate
that it fully implements the interface.

It would all be done at class-load-time.
And just to clarify, what I meant by "too much work" was that when you
define a class, you implicity define its interface (although this
interface in Ruby 1 only has method names and arities), so I wouldn't
want to have to define a class's interface separately in order to say
"ensure this object implements this _class's_ interface".

No, the definition is written once and then methods refer to the interface by
its name only.
However I'm still thinking about what Geoff Youngs suggested about
uniquely identifying the purpose of components in an interface. With
fine-grained respond_to? checking, you wouldn't know what :pants really
was for, it could mean several things. Whereas if this were part of an
interface, would that interface provide enough context to identify its
purpose? Is it possible to uniquely identify a method's purpose given
its context in a well-written set of interfaces? My brain's fizzled and
I need time to think about it. It's probably not perfect but it's
good, I think. :)

Interfaces usually imply a purpose, and since an object usually has multiple
methods, all of which do something different, but for one general purpose,
wrapping the purpose up as an interface is convenient.

Sean O'Dell
 
G

Greg McIntyre

Sean O'Dell said:
Internally, though, Ruby would store the interface information in its
own way. When a class declared that it implements it, as methods are
added to the class which fulfill the interface requirements, they
would be checked off until the last one, then a flag would be raised
for the class to indicate that it fully implements the interface.

I don't think they need to be checked off. Couldn't the "end" which
finishes the class definition (or part-thereof) signal a single check?
It might be a more complex check and hence the same overall efficiency,
or it might be better. *shrug*

I'm trying not to think *too* hard about efficiency. Premature
optimization and all that...

It would all be done at class-load-time.
Yes.



No, the definition is written once and then methods refer to the
interface by its name only.

Well, matz in another post says he's against implicit interface
definition through class definitions.

Perhaps an additional line at the end of the class would be a
compromise?

class Foo
# ...
end

interface IFoo from class Foo

Or something. In fact, I could probably do this in Ruby 1 by doing this:

class Foo
# ...

define_interface:)IFoo)
end

Interfaces usually imply a purpose, and since an object usually has
multiple methods, all of which do something different, but for one
general purpose, wrapping the purpose up as an interface is
convenient.

This is where the use of interfaces really beats, I think, use of
respond_to?. Interfaces provide context.

I think I might have a go at implementing my proposal (or
over-simplification as the case may be) in Ruby 1.8 because it's a
hybrid between Ruby 1 and your proposal. Then I could observe how the
interfaces get broken and fixed with the removal and addition of
methods. :) I can also include an explicit method call to check a set of
parameters implement a set of interfaces, so you'd have optional
parameter type (or rather interface) checking too.
 
S

Sean O'Dell

I don't think they need to be checked off. Couldn't the "end" which
finishes the class definition (or part-thereof) signal a single check?
It might be a more complex check and hence the same overall efficiency,
or it might be better. *shrug*

Well, code can be called during class loading that might also inject new
methods. I guess it still could all be saved for one big check at end. I
think that is definitely a possibility!
Well, matz in another post says he's against implicit interface
definition through class definitions.

I meant, the interface is written once separately from the class definition,
sorry!
I think I might have a go at implementing my proposal (or
over-simplification as the case may be) in Ruby 1.8 because it's a
hybrid between Ruby 1 and your proposal. Then I could observe how the
interfaces get broken and fixed with the removal and addition of
methods. :) I can also include an explicit method call to check a set of
parameters implement a set of interfaces, so you'd have optional
parameter type (or rather interface) checking too.

Oh definitely, you should! At least give it a test run and see if wants to
float. The end solution will probably be some sort of conglomeration of
ideas boiled down into one simple idea.

Sean O'Dell
 
G

Greg McIntyre

It occured to me on the bus today...

Can interfaces be changed at run-time? I think they shouldn't because
allowing interfaces to be updated any time after they've been created
would mean that every object implementing the interface would have to be
re-checked. Maybe one could iterate (or some faster search) through the
object space (ObjectSpace), but it seems better avoided.

So this should be an error:

interface IFoo
# some stuff
end

# ...

interface IFoo
# add more stuff to IFoo
end # => Error, redefinition of interface IFoo

The reason I say this is because it works differently to the way Ruby
classes work in a similar situation. It therefore has baring on deriving
interfaces from classes implicitly (which I'm still thinking about, a
little bit). However if you do it explicitly and optionally, on a
particular line of code, I think you're fine because you choose at which
point to grab the class's interface.
 
G

Geoff Youngs

Oooh, how does it work?
I tried redefining Module#append_features to call a hook which can be
defined to check for the methods the module needs. The only drawback
is you have to include your modules down the bottom of the class. It
doesn't work for inheritance however because Class::inherited is
called at the start of a class definition, not at the end.

It's not perfect, but with a decent interface definition you're less
likely to be using inheritance that way and you will also have inherited
the required methods from the parent class anyway, unless you go on to
re-define them which can't be easily prevented anyway, even in the same
class.
So far that's the best Ruby 1 patch-up job I can do to get, as you put
it, soft interface checking. That is, the best without introducing a
lot more ugly code...

That's pretty much what it does. It's possible that something else
could be acheived with redefinitions of initialize or new or something
so that a class can't be instantiated until the interface requirements
are complete, but that might be a bit like overkill...

It's not perfect, but this approach has met my needs for interfaces so
far,

TTFN,


Geoff.
 
G

Geoff Youngs

It occured to me on the bus today...
Can interfaces be changed at run-time? I think they shouldn't because
allowing interfaces to be updated any time after they've been created
would mean that every object implementing the interface would have to
be re-checked. Maybe one could iterate (or some faster search) through
the object space (ObjectSpace), but it seems better avoided.
So this should be an error:
interface IFoo
# some stuff
end
interface IFoo
# add more stuff to IFoo
end # => Error, redefinition of interface IFoo
The reason I say this is because it works differently to the way Ruby
classes work in a similar situation. It therefore has baring on
deriving interfaces from classes implicitly (which I'm still thinking
about, a little bit). However if you do it explicitly and optionally,
on a particular line of code, I think you're fine because you choose
at which point to grab the class's interface.

I see no reason why interfaces shouldn't provide methods themselves. If
they can provide methods, why shouldn't it be possible to add a utility
method to an interface (such that it would work with any compliant
object) to perform a specific job which is not otherwise catered for by
the interface?

If you take Enumerable as an example of an existing Ruby interface, you
know that adding a method to Enumerable affects arrays, hashes, ranges
and more. This I like. It means that I can add a method to Enumerable
that logically belongs in Enumerable, rather than having, in effect, a
method lying around in another class which only operates on Enumerable
objects, but which claims to be a member of a completely unrelated
class.

Changing the required functions for an interface should be a no-no, but
it would serve little or no point anyway.

All in all, I would advocate the approach (which seems rubyish to me) of
assuming that the programmer knows what they're doing and if they wish
to modify an interface letting them do it.

TTFN,


Geoff.
 
S

Sean O'Dell

It occured to me on the bus today...

Can interfaces be changed at run-time? I think they shouldn't because
allowing interfaces to be updated any time after they've been created
would mean that every object implementing the interface would have to be
re-checked. Maybe one could iterate (or some faster search) through the
object space (ObjectSpace), but it seems better avoided.

So this should be an error:

interface IFoo
# some stuff
end

# ...

interface IFoo
# add more stuff to IFoo
end # => Error, redefinition of interface IFoo

The reason I say this is because it works differently to the way Ruby
classes work in a similar situation. It therefore has baring on deriving
interfaces from classes implicitly (which I'm still thinking about, a
little bit). However if you do it explicitly and optionally, on a
particular line of code, I think you're fine because you choose at which
point to grab the class's interface.

Not in my proposal. An interface is completely immutable. For that exact
reason. =)

Sean O'Dell
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,140
Latest member
SweetcalmCBDreview
Top