Retrofit Iterable to extend AutoCloseable
Colin Decker
cgdecker at gmail.com
Tue Nov 22 10:27:48 PST 2011
Streams/Readers/Writers are all stateful Iterator-type things. Has there
been any consideration of equivalent Iterable-type abstractions for I/O
resources? A File/Path is one example, since you can derive multiple
streams from it. Guava has this concept with its
InputSupplier/OutputSupplier interfaces. A consistent interface for things
from which new, independent streams can be retrieved could allow for some
powerful library functionality that can control both the opening and
closing of streams. Of course this sort of thing can't really be used in
something like a Servlet where you're limited to one input and one output
stream, but there are a lot of other situations where it could be used.
--
Colin
On Tue, Nov 22, 2011 at 12:15 PM, Brian Goetz <brian.goetz at oracle.com>wrote:
> More generally, how far we can stretch Iter{ator,able} to cover things
> like IO ops, which are not simply views of existing finite-sized
> aggregates (collections, arrays) is an open question. For example, it
> would be nice if we could add something like this to Reader:
>
> interface Reader {
> ...
> Iterable<String> lines() default { ... }
> }
>
> Note that this is probably better than the obvious:
>
> interface Reader {
> ...
> void eachLine(Block<String>) default { ... }
> }
>
> because by returning an Iterable, you then have easy access to the
> extension methods of Iterable like filter(), map(), and friends; you can
> say:
>
> List<String> nonEmptyLines = reader.lines()
> .filter(s -> !s.isEmpty())
> .into(new ArrayList<>());
>
> whereas with an eachLine method, you'd have to do it more imperatively.
>
> But this is a funky kind of Iterable for two reasons:
> - Iterating it might throw exceptions
> - You can only iterate it once.
>
> The latter issue is the killer, because we have been for 15 years
> encouraging the notion that you can iterate an Iterable multiple times.
>
> Options:
> - Introduce IterableOnce as a subtype of Iterable. This has good
> doc-value, and easily picks up the extension methods from Iterable, but
> does not play no nicely with the LiskovSubstitutionPrinciple.
> - Introduce IterableOnce as a supertype of Iterable. This arguably
> plays better with the LSP (since can-iterate-many is-a
> can-iterate-once), but requires more thought to understand.
>
> Neither is all that attractive.
>
> The exception issue similarly offers some options:
> - Adopt exception transparency. The design we've got for ET is OK,
> but not great, requires a lot more thought, and we haven't come across
> all that many cases (like this one) where it's needed.
> - Wrap exceptions. Not great, but probably OK here.
>
> On 11/22/2011 11:37 AM, Reinier Zwitserloot wrote:
> > Having the 'owner' instance autoclose its iterables/itself on GC also
> > wouldn't be backwards compatible (in that lots of code is out there today
> > that doesn't start closing resources on GC).
> >
> > We'd also have to retrofit the extended for loop (for (String x :
> > iterable)) to call close at the end and then have to answer hairy
> questions
> > like the distinction between Iterable and Iterator (which one is supposed
> > to get the close() method? Tough question!).
> >
> > This is a pretty big step that would require lots of further research,
> > though my gut instinct tells me its not a feasible option due primarily
> due
> > significant backwards compatibility issues. Even introducing a new
> subtype
> > (ClosableIterable or some such) will cause backwards compatibility issues
> > because the JVM does not treat 2 methods with the same name and parameter
> > types equal if the return type is different. AutoClosable is a supertype
> in
> > many places and that _DOES_ work for backwards compatibility, that's the
> > key. (And the trywith construct is entirely new, so a lot less to worry
> > about for backwards compatibility!).
> >
> > Lastly, the JVM already has destructors; it's called Object.finalize(),
> > though you could write an entire book on how relying on them is a
> horrible
> > idea and how their mere existence really gets in the way of a lot of GC
> > optimizations. If memory serves, any object with a non-empty finalize
> > method gets special (slow) treatment to make it work. That solution is
> > therefore also unlikely to be the right answer.
> >
> > --Reinier Zwitserloot
> >
> >
> >
> > On Tue, Nov 22, 2011 at 1:33 AM, Zhong Yu<zhong.j.yu at gmail.com> wrote:
> >
> >> I think this is very different from adding some helper methods on
> >> collection interfaces.
> >>
> >> Adding close() to Iterator significantly changes how the interface
> >> should be used. Old code ignorant of the close() method would now
> >> become incorrect.
> >>
> >> We can remedy this by requiring that any subclass with a non-trivial
> >> close() must arrange to effectively trigger close() when the object is
> >> GC-ed. However this is not an easy thing to do. (Maybe JDK can help us
> >> here by providing a "destructor" utility like `void onGC(object,
> >> action)`
> >>
> >> Zhong Yu
> >>
> >> On Mon, Nov 21, 2011 at 12:18 PM, Cleber Muramoto
> >> <cleber at nightcoders.com.br> wrote:
> >>> I've been following the list for a while, but I couldn't find any
> mention
> >>> about this.
> >>>
> >>> I think it would be interesting for Iterable/Iterator to extend
> >>> AutoCloseable providing a default no-op close(), allowing, for example,
> >> the
> >>> creation Iterables backed by IO resources without the need to expose
> >>> neither a specific interface nor the IO resource itself.
> >>>
> >>> Of course it would be much cooler if we had python-like yielders! But I
> >>> think that this poor's man solution would suffice for a variety of use
> >>> cases.
> >>>
> >>> Regards.
> >>>
> >>> Cleber.
> >>>
> >>>
> >>
> >>
> >
>
>
More information about the lambda-dev
mailing list