A general-use For-comprehensible Loan Pattern
As long as you restrict yourself to simple uses, I think it's ok. When you try complex tricks, however, the lack of definition of the filter (or withFilter) method leads to certain inconveniences. Here are examples:

Binding to a tuple

for {
  // opens two files at once and returns a tuple of Input/OutputStreams
  (is, os) &lt;- withIOStream("input.txt", "output.txt") // (doesn't work)
} { ... }


This doesn't work because assigning to a tuple (or more generally, a pattern) involves a call to filter. If you want to use pattern matching, bind it to a variable first, and then match it against a tuple in the for expression.

Guards

for {
  // handle only if the file is not empty
  is &lt;- withInputStream("input.txt") if is.available() &gt; 0 // (doesn't work)
} { ... }


This doesn't work because an "if" guard is translated to a call to filter. Since the guard (usually) depends on the loaned object (in this example, is), such conditionals must be put into the body of the for expression.



The trait is still "safe" because both of the above are catched at compilation time. However, experienced Scala programmers may find it cumbersome when they write up a complex generator and then get errors.

Can we get them work? A naïve approach is to define filter and withFilter like:

// unsafe, incorrect for certain uses
trait ForComprehensible[+A] {
  ...

  // ignore the filtering and just return itself
  def filter(f: A =&gt; Boolean): ForComprehensible[A] = this
  // not essential here, just to suppress compiler warnings
  def withFilter(f: A =&gt; Boolean) = filter(f)
}


this enables binding to a tuple (for some reason I don't fully understand), but causes guards to be silently ignored (i.e. assumes true). This makes ForComprehensible an unsafe construct.

If we are to implement filter (and withFilter) properly, we have to open a FileInputStream (in our example) in the filter method. It means the stream must be opened twice (in filter and apply), or we open it once in filter and then keep it open using some magic until the callback of apply returns. The former is simply unacceptable, and the latter would make the implementation of the trait too complicated.

EDIT: after some more experiments, I found out that a guard on ForComprehensible is not an implementation problem but rather a semantic problem.

Consider:

for {
  is &lt;- withInputStream("input.txt") if is.available() &gt; 0
} yield { ... }


note the yield. What this whole expression has to return if the guard is.available() &gt; 0 doesn't hold?

It depends on the body of the for-expression. For example, if it loads the lines of the file into a Seq[String], it would return Seq(). If it counts the number of lines in the file, it would return 0 (if the body returns Int) or None (Option[Int]).

Guards, or filters, only make sense when they operate on a collection (Option can be considered a kind of collection whose maximum size is 1). Since ForComprehensible is just a syntactic trick to enable a loaner-function to be in for-generators, I conclude for now that we should stick to for-body if we want to check some conditions for acquiring resources.