This page is no longer maintained — Please continue to the home page at www.scala-lang.org

SAM closures?

32 replies
odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.

In the recent thread on applyIfDefined, the issue of SAM closures has come up again.

To recap:

To avoid double evaluation of pattern matching code in PartialFunction's isDefined/apply methods,
one promising approach is to allow anonymous function syntax for arbitrary subclasses of Function1. Such subclasses could then override a method "missingCase", defined in Function1 or else PartialFunction (not clear yet which is preferable). Pattern matching closures invoke missingCase in case no pattern matches.

A generalization would be to implement SAM closures (as in project Lambda terminology):
If an anonymous function

  { params => body }

appears in a context where the expected type is a class type `C[Ts]` with a single abstract method `m`, rewrite the closure to

  new C[Ts] {
    def m(params) = body
  }

If the closure appears without such an expected type, assume FunctionN[Ts] as expected type where N and Ts are derived from the formal parameters `params`.

That's the rough outline. There will be some tricky bits dealing with type inference. Type inference for anonymous functions is already quite hard, and it would need to be generalized further.
But I think it would be doable.

I can see two benefits in making the generalization:

  - We get a solution for the double evaluation problem for PartialFunctions
  - Scala can seamlessly interact with Java closures. By now it looks pretty clear
    that Java will also go the SAM way.

The downside is that, maybe, this can be misused, because some classes or traits might have a single abstract method by accident, but are not really suitable for closure syntax. But Scala traditionally has not let itself held back by fear of misuse, so this is a fairly weak argument.

Any other arguments in favor or against?

Cheers

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: SAM closures?

I think this could go a long way to unifying functional-ish java libraries with scala.  In particular, Google collections and guava will be far more "scala-esque" without requiring a wrapper library.

Before... We had to continually implement or import function->predicate wrappers and tuple->tuple wrapper. I think this would bring it down to just tuple differences.

On Jan 29, 2011 6:07 AM, "martin odersky" <martin [dot] odersky [at] epfl [dot] ch> wrote:


In the recent thread on applyIfDefined, the issue of SAM closures has come up again.

To recap:

To avoid double evaluation of pattern matching code in PartialFunction's isDefined/apply methods,
one promising approach is to allow anonymous function syntax for arbitrary subclasses of Function1. Such subclasses could then override a method "missingCase", defined in Function1 or else PartialFunction (not clear yet which is preferable). Pattern matching closures invoke missingCase in case no pattern matches.

A generalization would be to implement SAM closures (as in project Lambda terminology):
If an anonymous function

  { params => body }

appears in a context where the expected type is a class type `C[Ts]` with a single abstract method `m`, rewrite the closure to

  new C[Ts] {
    def m(params) = body
  }

If the closure appears without such an expected type, assume FunctionN[Ts] as expected type where N and Ts are derived from the formal parameters `params`.

That's the rough outline. There will be some tricky bits dealing with type inference. Type inference for anonymous functions is already quite hard, and it would need to be generalized further.
But I think it would be doable.

I can see two benefits in making the generalization:

  - We get a solution for the double evaluation problem for PartialFunctions
  - Scala can seamlessly interact with Java closures. By now it looks pretty clear
    that Java will also go the SAM way.

The downside is that, maybe, this can be misused, because some classes or traits might have a single abstract method by accident, but are not really suitable for closure syntax. But Scala traditionally has not let itself held back by fear of misuse, so this is a fairly weak argument.

Any other arguments in favor or against?

Cheers

Burak Emir
Joined: 2009-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: SAM closures?
This is a wonderful proposal. SAM closures would be a good idea for Java, too, but regardless of what makes it in there and when, people can and do define traits (resp Java interfaces) with single abstract methods all the time.

It can make code appear more readable and organized, in the same way that people use struct-like classes (resp case classes) instead of tuples when they want to keep a bunch of values together. It is really a strong point of the proposal that existing programs keep their semantics and people can choose between A => B and C[A,B].

I can already see how we would want to define a style guideline that goes something like "functions in the mathematical sense should be of function type but others, like with side-effects or non-threadsafe stuff should be defined their own SAM trait".

There may be downsides to readability, too: the same syntax means two different things in different contexts. Not much of an argument, in the postmodern age of implicit conversions.

+1 to inferring SAM types from anonymous function syntax... if it can be done, of course.

-- Burak

On Sat, Jan 29, 2011 at 4:13 AM, Josh Suereth <joshua [dot] suereth [at] gmail [dot] com> wrote:

I think this could go a long way to unifying functional-ish java libraries with scala.  In particular, Google collections and guava will be far more "scala-esque" without requiring a wrapper library.

Before... We had to continually implement or import function->predicate wrappers and tuple->tuple wrapper. I think this would bring it down to just tuple differences.

On Jan 29, 2011 6:07 AM, "martin odersky" <martin [dot] odersky [at] epfl [dot] ch> wrote:


In the recent thread on applyIfDefined, the issue of SAM closures has come up again.

To recap:

To avoid double evaluation of pattern matching code in PartialFunction's isDefined/apply methods,
one promising approach is to allow anonymous function syntax for arbitrary subclasses of Function1. Such subclasses could then override a method "missingCase", defined in Function1 or else PartialFunction (not clear yet which is preferable). Pattern matching closures invoke missingCase in case no pattern matches.

A generalization would be to implement SAM closures (as in project Lambda terminology):
If an anonymous function

  { params => body }

appears in a context where the expected type is a class type `C[Ts]` with a single abstract method `m`, rewrite the closure to

  new C[Ts] {
    def m(params) = body
  }

If the closure appears without such an expected type, assume FunctionN[Ts] as expected type where N and Ts are derived from the formal parameters `params`.

That's the rough outline. There will be some tricky bits dealing with type inference. Type inference for anonymous functions is already quite hard, and it would need to be generalized further.
But I think it would be doable.

I can see two benefits in making the generalization:

  - We get a solution for the double evaluation problem for PartialFunctions
  - Scala can seamlessly interact with Java closures. By now it looks pretty clear
    that Java will also go the SAM way.

The downside is that, maybe, this can be misused, because some classes or traits might have a single abstract method by accident, but are not really suitable for closure syntax. But Scala traditionally has not let itself held back by fear of misuse, so this is a fairly weak argument.

Any other arguments in favor or against?

Cheers

Ismael Juma 2
Joined: 2011-01-22,
User offline. Last seen 42 years 45 weeks ago.
Re: SAM closures?

On Sat, Jan 29, 2011 at 11:06 AM, martin odersky wrote:
> Any other arguments in favor or against?

Another argument for is that people that would like a specialized
Function3 or a Function1 specialized for Byte can do it themselves
while still being able to use the nice syntax.

Best,
Ismael

Ismael Juma 2
Joined: 2011-01-22,
User offline. Last seen 42 years 45 weeks ago.
Re: SAM closures?

On Sat, Jan 29, 2011 at 12:13 PM, Josh Suereth wrote:
> Before... We had to continually implement or import function->predicate
> wrappers and tuple->tuple wrapper. I think this would bring it down to just
> tuple differences.

And also libraries like Trove that have primitive collections (for performance).

Ismael

Tiark Rompf
Joined: 2009-02-18,
User offline. Last seen 42 years 45 weeks ago.
Re: SAM closures?

> Any other arguments in favor or against?

+1

it would be nice to implement Runnable, Callable, FJTask etc. using closure syntax without extra indirection/allocation.

- Tiark

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: SAM closures?
There's one thing that I haven't seen stated explicitly, or maybe missed it, but seems likely to me. Say I have a method like this:
def f(g: SamClass) = ...
If I call it like
f { x => y }
Will that be equivalent to
f(new SamClass { x => y})
?
There are plenty of places in Java were that would be ambiguous (Runnable vs PrivilegeActions, for example), but, then again, there are plenty f places were it is not.
At any rate, I know lots of code I can barely wait to rewrite to take advantage of that. Very worthwhile feature.
On Sat, Jan 29, 2011 at 09:06, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:

In the recent thread on applyIfDefined, the issue of SAM closures has come up again.

To recap:

To avoid double evaluation of pattern matching code in PartialFunction's isDefined/apply methods,
one promising approach is to allow anonymous function syntax for arbitrary subclasses of Function1. Such subclasses could then override a method "missingCase", defined in Function1 or else PartialFunction (not clear yet which is preferable). Pattern matching closures invoke missingCase in case no pattern matches.

A generalization would be to implement SAM closures (as in project Lambda terminology):
If an anonymous function

  { params => body }

appears in a context where the expected type is a class type `C[Ts]` with a single abstract method `m`, rewrite the closure to

  new C[Ts] {
    def m(params) = body
  }

If the closure appears without such an expected type, assume FunctionN[Ts] as expected type where N and Ts are derived from the formal parameters `params`.

That's the rough outline. There will be some tricky bits dealing with type inference. Type inference for anonymous functions is already quite hard, and it would need to be generalized further.
But I think it would be doable.

I can see two benefits in making the generalization:

  - We get a solution for the double evaluation problem for PartialFunctions
  - Scala can seamlessly interact with Java closures. By now it looks pretty clear
    that Java will also go the SAM way.

The downside is that, maybe, this can be misused, because some classes or traits might have a single abstract method by accident, but are not really suitable for closure syntax. But Scala traditionally has not let itself held back by fear of misuse, so this is a fairly weak argument.

Any other arguments in favor or against?

Cheers

Burak Emir
Joined: 2009-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: SAM closures?
Hey,
More precisely, the f { x=> y } should turn into 
f(new SamClass() { override def samMethod(x) = { y })
If "samMethod" would be "run" (like in Runnable or PrivilegeAction) it would still not be ambiguous: there is a given expected type SamClass, and which should have a single abstract method (an its constructor takes no arguments)

Maybe you mean the case where f is overloaded
def f(arg: Runnable) = ...def f(arg: PrivilegeAction) = ...
then yes, there would be a conflict. This kind of conflict already exists, though, and could maybe be handled by a type annotation, like so:
f ({ x => y }:Runnable)
-- Burak
On Sat, Jan 29, 2011 at 5:47 PM, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:
There's one thing that I haven't seen stated explicitly, or maybe missed it, but seems likely to me. Say I have a method like this:
def f(g: SamClass) = ...
If I call it like
f { x => y }
Will that be equivalent to
f(new SamClass { x => y})
?
There are plenty of places in Java were that would be ambiguous (Runnable vs PrivilegeActions, for example), but, then again, there are plenty f places were it is not.
At any rate, I know lots of code I can barely wait to rewrite to take advantage of that. Very worthwhile feature.
On Sat, Jan 29, 2011 at 09:06, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:

In the recent thread on applyIfDefined, the issue of SAM closures has come up again.

To recap:

To avoid double evaluation of pattern matching code in PartialFunction's isDefined/apply methods,
one promising approach is to allow anonymous function syntax for arbitrary subclasses of Function1. Such subclasses could then override a method "missingCase", defined in Function1 or else PartialFunction (not clear yet which is preferable). Pattern matching closures invoke missingCase in case no pattern matches.

A generalization would be to implement SAM closures (as in project Lambda terminology):
If an anonymous function

  { params => body }

appears in a context where the expected type is a class type `C[Ts]` with a single abstract method `m`, rewrite the closure to

  new C[Ts] {
    def m(params) = body
  }

If the closure appears without such an expected type, assume FunctionN[Ts] as expected type where N and Ts are derived from the formal parameters `params`.

That's the rough outline. There will be some tricky bits dealing with type inference. Type inference for anonymous functions is already quite hard, and it would need to be generalized further.
But I think it would be doable.

I can see two benefits in making the generalization:

  - We get a solution for the double evaluation problem for PartialFunctions
  - Scala can seamlessly interact with Java closures. By now it looks pretty clear
    that Java will also go the SAM way.

The downside is that, maybe, this can be misused, because some classes or traits might have a single abstract method by accident, but are not really suitable for closure syntax. But Scala traditionally has not let itself held back by fear of misuse, so this is a fairly weak argument.

Any other arguments in favor or against?

Cheers

spoon
Joined: 2008-07-01,
User offline. Last seen 1 year 21 weeks ago.
Re: SAM closures?
On Sat, Jan 29, 2011 at 8:59 AM, Ismael Juma <ismael [at] juma [dot] me [dot] uk> wrote:
On Sat, Jan 29, 2011 at 11:06 AM, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
> Any other arguments in favor or against?

Another argument for is that people that would like a specialized
Function3 or a Function1 specialized for Byte can do it themselves
while still being able to use the nice syntax.

Similarly, it would help on ScalaGWT. When you are shipping the code to a web browser, each extra class increases the download latency. When you are running code on a web browser, each extra layer in the call stack slows down the run-time speed.
Lex
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: SAM closures?

On Sat, Jan 29, 2011 at 12:06:59PM +0100, martin odersky wrote:
> The downside is that, maybe, this can be misused, because some classes
> or traits might have a single abstract method by accident, but are not
> really suitable for closure syntax. But Scala traditionally has not
> let itself held back by fear of misuse, so this is a fairly weak
> argument.
>
> Any other arguments in favor or against?

So far it seems like nobody is having much trouble seeing the good
parts, so we would be smart to focus on what might make us regret it.
I'm usually better at finding out what is wrong with things by
implementing them because I find reality speaks with a clear treble
voice: I depend on the big brains of academia when I want to learn
anything without bumping into it face-first.

We would be, approximately, introducing a new implicit in the global
scope: an implicit the language doesn't let you write because you can't
abstract over the name of a method or identity of a class. Or arity of
a function/method for that matter, although we could cheat that one.
But in the language we can't write:

implicit def makeMeASam[Args, R, Class, Method](f: Args => R): Class =
new Class { def Method(x: Args): R = f(x) }

So what would the arguments against that implicit be? Typically, a loss
of safety. Hard to see much being lost here on that basis: not that
much else one could mean passing a closure to something expecting some
java class. Although this does raise the question of which has priority:

implicit def makeRunnable(f: () => Unit): Runnable =
new Runnable { def run() { println("I'm an implicit!") ; f() } }
def fn(r: Runnable) = ()
fn(() => println("I'm a body!"))

So I think it has to be as with implicits, that it doesn't happen unless
the expression doesn't typecheck. (Even lower than implicits, that is.)

I'm very much in favor of it, but in general I think we could do a
better job of seeing the downsides of things before too much inertia
builds behind them, so, just practicing.

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: SAM closures?
On Sat, Jan 29, 2011 at 17:14, Paul Phillips <paulp [at] improving [dot] org> wrote:
So I think it has to be as with implicits, that it doesn't happen unless the expression doesn't typecheck.  (Even lower than implicits, that is.)


This has been bothering me. Suppose I have a CollectableFunction class:
abstract class CollectableFunction[-T,+R] extends  Function1[T,R] {   def missingCase // as appropriate}
This will work for cases like this:
list collect { case x if guard => y }
But not in this case:
val conditions = pfList filter predicate reduceLeft (_ orElse _)list collect conditions
To fix that, I'd just create an implicit inside CollectableFunction, but, at that point, the first case will always be solved through the implicit. I'm not sure I like that.
--
Daniel C. Sobral

I travel to the future all the time.
rytz
Joined: 2008-07-01,
User offline. Last seen 45 weeks 5 days ago.
Re: SAM closures?


On Sat, Jan 29, 2011 at 12:06, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:

In the recent thread on applyIfDefined, the issue of SAM closures has come up again.

To recap:

To avoid double evaluation of pattern matching code in PartialFunction's isDefined/apply methods,
one promising approach is to allow anonymous function syntax for arbitrary subclasses of Function1. Such subclasses could then override a method "missingCase", defined in Function1 or else PartialFunction (not clear yet which is preferable). Pattern matching closures invoke missingCase in case no pattern matches.

A generalization would be to implement SAM closures (as in project Lambda terminology):
If an anonymous function

  { params => body }

appears in a context where the expected type is a class type `C[Ts]` with a single abstract method `m`, rewrite the closure to

  new C[Ts] {
    def m(params) = body
  }

If the closure appears without such an expected type, assume FunctionN[Ts] as expected type where N and Ts are derived from the formal parameters `params`.


So the following would be a type error?
def run(r: Runnable) { r.run() }val f = () => { println("hello") } run(f)
 

That's the rough outline. There will be some tricky bits dealing with type inference. Type inference for anonymous functions is already quite hard, and it would need to be generalized further.
But I think it would be doable.

I can see two benefits in making the generalization:

  - We get a solution for the double evaluation problem for PartialFunctions
  - Scala can seamlessly interact with Java closures. By now it looks pretty clear
    that Java will also go the SAM way.

The downside is that, maybe, this can be misused, because some classes or traits might have a single abstract method by accident, but are not really suitable for closure syntax. But Scala traditionally has not let itself held back by fear of misuse, so this is a fairly weak argument.

Any other arguments in favor or against?

Cheers

Burak Emir
Joined: 2009-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: SAM closures?


On Mon, Jan 31, 2011 at 9:16 AM, Lukas Rytz <lukas [dot] rytz [at] epfl [dot] ch> wrote:


On Sat, Jan 29, 2011 at 12:06, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:

In the recent thread on applyIfDefined, the issue of SAM closures has come up again.

To recap:

To avoid double evaluation of pattern matching code in PartialFunction's isDefined/apply methods,
one promising approach is to allow anonymous function syntax for arbitrary subclasses of Function1. Such subclasses could then override a method "missingCase", defined in Function1 or else PartialFunction (not clear yet which is preferable). Pattern matching closures invoke missingCase in case no pattern matches.

A generalization would be to implement SAM closures (as in project Lambda terminology):
If an anonymous function

  { params => body }

appears in a context where the expected type is a class type `C[Ts]` with a single abstract method `m`, rewrite the closure to

  new C[Ts] {
    def m(params) = body
  }

If the closure appears without such an expected type, assume FunctionN[Ts] as expected type where N and Ts are derived from the formal parameters `params`.


So the following would be a type error?
def run(r: Runnable) { r.run() }val f = () => { println("hello") } run(f)
 

Yes.  

That's the rough outline. There will be some tricky bits dealing with type inference. Type inference for anonymous functions is already quite hard, and it would need to be generalized further.
But I think it would be doable.

I can see two benefits in making the generalization:

  - We get a solution for the double evaluation problem for PartialFunctions
  - Scala can seamlessly interact with Java closures. By now it looks pretty clear
    that Java will also go the SAM way.

The downside is that, maybe, this can be misused, because some classes or traits might have a single abstract method by accident, but are not really suitable for closure syntax. But Scala traditionally has not let itself held back by fear of misuse, so this is a fairly weak argument.

Any other arguments in favor or against?

Cheers

rytz
Joined: 2008-07-01,
User offline. Last seen 45 weeks 5 days ago.
Re: SAM closures?


On Mon, Jan 31, 2011 at 09:49, Burak Emir <burak [dot] emir [at] gmail [dot] com> wrote:


On Mon, Jan 31, 2011 at 9:16 AM, Lukas Rytz <lukas [dot] rytz [at] epfl [dot] ch> wrote:


On Sat, Jan 29, 2011 at 12:06, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:

In the recent thread on applyIfDefined, the issue of SAM closures has come up again.

To recap:

To avoid double evaluation of pattern matching code in PartialFunction's isDefined/apply methods,
one promising approach is to allow anonymous function syntax for arbitrary subclasses of Function1. Such subclasses could then override a method "missingCase", defined in Function1 or else PartialFunction (not clear yet which is preferable). Pattern matching closures invoke missingCase in case no pattern matches.

A generalization would be to implement SAM closures (as in project Lambda terminology):
If an anonymous function

  { params => body }

appears in a context where the expected type is a class type `C[Ts]` with a single abstract method `m`, rewrite the closure to

  new C[Ts] {
    def m(params) = body
  }

If the closure appears without such an expected type, assume FunctionN[Ts] as expected type where N and Ts are derived from the formal parameters `params`.


So the following would be a type error?
def run(r: Runnable) { r.run() }val f = () => { println("hello") } run(f)
 

Yes.

Then the loss of safety that Paul mentions is less significant, the conversion is less powerful than a global implicit converting fromfunction types to arbitrary SAM types.I agree with Daniels concerns.
  

That's the rough outline. There will be some tricky bits dealing with type inference. Type inference for anonymous functions is already quite hard, and it would need to be generalized further.
But I think it would be doable.

I can see two benefits in making the generalization:

  - We get a solution for the double evaluation problem for PartialFunctions
  - Scala can seamlessly interact with Java closures. By now it looks pretty clear
    that Java will also go the SAM way.

The downside is that, maybe, this can be misused, because some classes or traits might have a single abstract method by accident, but are not really suitable for closure syntax. But Scala traditionally has not let itself held back by fear of misuse, so this is a fairly weak argument.

Any other arguments in favor or against?

Cheers

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: SAM closures?


On Mon, Jan 31, 2011 at 9:16 AM, Lukas Rytz <lukas [dot] rytz [at] epfl [dot] ch> wrote:


On Sat, Jan 29, 2011 at 12:06, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:

In the recent thread on applyIfDefined, the issue of SAM closures has come up again.

To recap:

To avoid double evaluation of pattern matching code in PartialFunction's isDefined/apply methods,
one promising approach is to allow anonymous function syntax for arbitrary subclasses of Function1. Such subclasses could then override a method "missingCase", defined in Function1 or else PartialFunction (not clear yet which is preferable). Pattern matching closures invoke missingCase in case no pattern matches.

A generalization would be to implement SAM closures (as in project Lambda terminology):
If an anonymous function

  { params => body }

appears in a context where the expected type is a class type `C[Ts]` with a single abstract method `m`, rewrite the closure to

  new C[Ts] {
    def m(params) = body
  }

If the closure appears without such an expected type, assume FunctionN[Ts] as expected type where N and Ts are derived from the formal parameters `params`.


So the following would be a type error?
def run(r: Runnable) { r.run() }val f = () => { println("hello") } run(f)
Correct.

 -- Martin

Mark Harrah 2
Joined: 2011-02-05,
User offline. Last seen 42 years 45 weeks ago.
Re: SAM closures?

On 1/29/11, martin odersky wrote:
> In the recent thread on applyIfDefined, the issue of SAM closures has come
> up again.
>
> To recap:
>
> To avoid double evaluation of pattern matching code in PartialFunction's
> isDefined/apply methods,
> one promising approach is to allow anonymous function syntax for arbitrary
> subclasses of Function1. Such subclasses could then override a method
> "missingCase", defined in Function1 or else PartialFunction (not clear yet
> which is preferable). Pattern matching closures invoke missingCase in case
> no pattern matches.
>
> A generalization would be to implement SAM closures (as in project Lambda
> terminology):
> If an anonymous function
>
> { params => body }
>
> appears in a context where the expected type is a class type `C[Ts]` with a
> single abstract method `m`, rewrite the closure to
>
> new C[Ts] {
> def m(params) = body
> }
>
> If the closure appears without such an expected type, assume FunctionN[Ts]
> as expected type where N and Ts are derived from the formal parameters
> `params`.
>
> That's the rough outline. There will be some tricky bits dealing with type
> inference. Type inference for anonymous functions is already quite hard, and
> it would need to be generalized further.
> But I think it would be doable.
>
> I can see two benefits in making the generalization:
>
> - We get a solution for the double evaluation problem for PartialFunctions
> - Scala can seamlessly interact with Java closures. By now it looks pretty
> clear
> that Java will also go the SAM way.

Would methods with type parameters be supported? This would be a very
nice benefit on its own, since there is no literal syntax for this and
of course FunctionN can't be converted to such an interface like can
be done for Runnable.

-Mark

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: SAM closures?

On Sat, Feb 5, 2011 at 1:49 AM, Mark Harrah wrote:
> On 1/29/11, martin odersky wrote:
>> In the recent thread on applyIfDefined, the issue of SAM closures has come
>> up again.
>>
>> To recap:
>>
>> To avoid double evaluation of pattern matching code in PartialFunction's
>> isDefined/apply methods,
>> one promising approach is to allow anonymous function syntax for arbitrary
>> subclasses of Function1. Such subclasses could then override a method
>> "missingCase", defined in Function1 or else PartialFunction (not clear yet
>> which is preferable). Pattern matching closures invoke missingCase in case
>> no pattern matches.
>>
>> A generalization would be to implement SAM closures (as in project Lambda
>> terminology):
>> If an anonymous function
>>
>>   { params => body }
>>
>> appears in a context where the expected type is a class type `C[Ts]` with a
>> single abstract method `m`, rewrite the closure to
>>
>>   new C[Ts] {
>>     def m(params) = body
>>   }
>>
>> If the closure appears without such an expected type, assume FunctionN[Ts]
>> as expected type where N and Ts are derived from the formal parameters
>> `params`.
>>
>> That's the rough outline. There will be some tricky bits dealing with type
>> inference. Type inference for anonymous functions is already quite hard, and
>> it would need to be generalized further.
>> But I think it would be doable.
>>
>> I can see two benefits in making the generalization:
>>
>>   - We get a solution for the double evaluation problem for PartialFunctions
>>   - Scala can seamlessly interact with Java closures. By now it looks pretty
>> clear
>>     that Java will also go the SAM way.
>
> Would methods with type parameters be supported?  This would be a very
> nice benefit on its own, since there is no literal syntax for this and
> of course FunctionN can't be converted to such an interface like can
> be done for Runnable.
>
It would be nice if we could do this. Type inference issues remain to
be worked out, though.

Cheers

Ingo Maier
Joined: 2009-11-23,
User offline. Last seen 42 years 45 weeks ago.
Re: SAM closures?

Would the body of the closure be type checked in the context of the
abstract class? That would be wonderful for DSLs indeed. No more need
for thread local self references (as in scala.actors) or implicit
closure parameters (as in SSTM), just refer to one of the non-abstract
members in the expected SAM class. It would go a long way to ease the
choice between the following DSL syntaxes:

new DSL {
def body() = ...
}

and

DSL { ... }

or

DSL { implicit self => ... }

Cheers,
Ingo

On Jan 29, 12:06 pm, martin odersky wrote:
> In the recent thread on applyIfDefined, the issue of SAM closures has come
> up again.
>
> To recap:
>
> To avoid double evaluation of pattern matching code in PartialFunction's
> isDefined/apply methods,
> one promising approach is to allow anonymous function syntax for arbitrary
> subclasses of Function1. Such subclasses could then override a method
> "missingCase", defined in Function1 or else PartialFunction (not clear yet
> which is preferable). Pattern matching closures invoke missingCase in case
> no pattern matches.
>
> A generalization would be to implement SAM closures (as in project Lambda
> terminology):
> If an anonymous function
>
>   { params => body }
>
> appears in a context where the expected type is a class type `C[Ts]` with a
> single abstract method `m`, rewrite the closure to
>
>   new C[Ts] {
>     def m(params) = body
>   }
>
> If the closure appears without such an expected type, assume FunctionN[Ts]
> as expected type where N and Ts are derived from the formal parameters
> `params`.
>
> That's the rough outline. There will be some tricky bits dealing with type
> inference. Type inference for anonymous functions is already quite hard, and
> it would need to be generalized further.
> But I think it would be doable.
>
> I can see two benefits in making the generalization:
>
>   - We get a solution for the double evaluation problem for PartialFunctions
>   - Scala can seamlessly interact with Java closures. By now it looks pretty
> clear
>     that Java will also go the SAM way.
>
> The downside is that, maybe, this can be misused, because some classes or
> traits might have a single abstract method by accident, but are not really
> suitable for closure syntax. But Scala traditionally has not let itself held
> back by fear of misuse, so this is a fairly weak argument.
>
> Any other arguments in favor or against?
>
> Cheers
>
>  -- Martin

Kevin Wright 2
Joined: 2010-05-30,
User offline. Last seen 26 weeks 4 days ago.
Re: Re: SAM closures?


On 6 February 2011 15:03, Ingo Maier <ingoem [at] googlemail [dot] com> wrote:
Would the body of the closure be type checked in the context of the
abstract class? That would be wonderful for DSLs indeed. No more need
for thread local self references (as in scala.actors) or implicit
closure parameters (as in SSTM), just refer to one of the non-abstract
members in the expected SAM class. It would go a long way to ease the
choice between the following DSL syntaxes:

new DSL {
 def body() = ...
}

and

DSL { ... }

or

DSL { implicit self => ... }

Cheers,
Ingo


Ho ho, now we're cooking with gas!Can I second this motion?
 
odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Re: SAM closures?

On Sun, Feb 6, 2011 at 4:03 PM, Ingo Maier wrote:
> Would the body of the closure be type checked in the context of the
> abstract class? That would be wonderful for DSLs indeed. No more need
> for thread local self references (as in scala.actors) or implicit
> closure parameters (as in SSTM), just refer to one of the non-abstract
> members in the expected SAM class. It would go a long way to ease the
> choice between the following DSL syntaxes:
>

That looks very tempting indeed. Yum! -- Martin

Kevin Wright 2
Joined: 2010-05-30,
User offline. Last seen 26 weeks 4 days ago.
Re: Re: SAM closures?


On 6 February 2011 15:28, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
On Sun, Feb 6, 2011 at 4:03 PM, Ingo Maier <ingoem [at] googlemail [dot] com> wrote:
> Would the body of the closure be type checked in the context of the
> abstract class? That would be wonderful for DSLs indeed. No more need
> for thread local self references (as in scala.actors) or implicit
> closure parameters (as in SSTM), just refer to one of the non-abstract
> members in the expected SAM class. It would go a long way to ease the
> choice between the following DSL syntaxes:
>

That looks very tempting indeed. Yum! -- Martin


Could I then further propose that this is something big enough to justify 3.0 as a release number...
The Zeitgeist seems to be moving towards a viable reflection library in the near future. Couple that with full integration of SAM types and objects from dynamic languages then we have something that's going to have people sit up and take notice, even those who are well outside of the current Scala community.
Nothing like a nice juicy "3" to suggest how interesting this all is, especially after so much was added-in just going from 2.7 to 2.8

--
Kevin Wright

gtalk / msn : kev [dot] lee [dot] wright [at] gmail [dot] comkev [dot] lee [dot] wright [at] gmail [dot] commail: kevin [dot] wright [at] scalatechnology [dot] com
vibe / skype: kev.lee.wrightquora: http://www.quora.com/Kevin-Wright
twitter: @thecoda

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: SAM closures?
FWIW, that's exactly what I had in mind in my last post to the applyIfDefined thread.

On Sun, Feb 6, 2011 at 13:03, Ingo Maier <ingoem [at] googlemail [dot] com> wrote:
Would the body of the closure be type checked in the context of the
abstract class? That would be wonderful for DSLs indeed. No more need
for thread local self references (as in scala.actors) or implicit
closure parameters (as in SSTM), just refer to one of the non-abstract
members in the expected SAM class. It would go a long way to ease the
choice between the following DSL syntaxes:

new DSL {
 def body() = ...
}

and

DSL { ... }

or

DSL { implicit self => ... }

Cheers,
Ingo



On Jan 29, 12:06 pm, martin odersky <martin [dot] oder [dot] [dot] [dot] [at] epfl [dot] ch> wrote:
> In the recent thread on applyIfDefined, the issue of SAM closures has come
> up again.
>
> To recap:
>
> To avoid double evaluation of pattern matching code in PartialFunction's
> isDefined/apply methods,
> one promising approach is to allow anonymous function syntax for arbitrary
> subclasses of Function1. Such subclasses could then override a method
> "missingCase", defined in Function1 or else PartialFunction (not clear yet
> which is preferable). Pattern matching closures invoke missingCase in case
> no pattern matches.
>
> A generalization would be to implement SAM closures (as in project Lambda
> terminology):
> If an anonymous function
>
>   { params => body }
>
> appears in a context where the expected type is a class type `C[Ts]` with a
> single abstract method `m`, rewrite the closure to
>
>   new C[Ts] {
>     def m(params) = body
>   }
>
> If the closure appears without such an expected type, assume FunctionN[Ts]
> as expected type where N and Ts are derived from the formal parameters
> `params`.
>
> That's the rough outline. There will be some tricky bits dealing with type
> inference. Type inference for anonymous functions is already quite hard, and
> it would need to be generalized further.
> But I think it would be doable.
>
> I can see two benefits in making the generalization:
>
>   - We get a solution for the double evaluation problem for PartialFunctions
>   - Scala can seamlessly interact with Java closures. By now it looks pretty
> clear
>     that Java will also go the SAM way.
>
> The downside is that, maybe, this can be misused, because some classes or
> traits might have a single abstract method by accident, but are not really
> suitable for closure syntax. But Scala traditionally has not let itself held
> back by fear of misuse, so this is a fairly weak argument.
>
> Any other arguments in favor or against?
>
> Cheers
>
>  -- Martin



--
Daniel C. Sobral

I travel to the future all the time.
Tiark Rompf
Joined: 2009-02-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: SAM closures?

Just writing

dsl { ... }

would indeed be wonderful. The question is how we can get there in a backwards compatible way.

More precisely, how can we specifiy whether we want to lookup something in the lexical scope of the closure literal or as a member of the target class?. In other words, if you write

object Foo {
dsl { ... this ... }
}

does 'this' refer to object Foo or to the closure object? Of course 'this' is kind of a corner case but the same applies to super, toString, hashCode, return or any other name/keyword which could have meaning in both contexts.

Currently, closure objects are not accessible at all from within themselves, so 'this' is always resolved lexically. That means we cannot simply change the rules or the following would break:

object Bar {
def apply(x:Int) = ...
List(1,2,3).foreach(z => apply(z)))
}

For dsls, on the other hand, we sometimes (though not always) want to choose the other extreme, i.e. make *none* of the lexically defined things available and completely isolate a dsl program.

Ideally the (application or dsl) programmer could choose. Maybe one could use a marker trait on the expected type of the closure?

- Tiark

P.S: it looks like thread local refs for transactions would still be needed unless we can ensure that there is only one closure per thread

P.P.S: It's only tangentially related, but I was wondering whether DelayedInit could be recast in terms of SAM-closures.

On Feb 6, 2011, at 4:03 PM, Ingo Maier wrote:

> Would the body of the closure be type checked in the context of the
> abstract class? That would be wonderful for DSLs indeed. No more need
> for thread local self references (as in scala.actors) or implicit
> closure parameters (as in SSTM), just refer to one of the non-abstract
> members in the expected SAM class. It would go a long way to ease the
> choice between the following DSL syntaxes:
>
> new DSL {
> def body() = ...
> }
>
> and
>
> DSL { ... }
>
> or
>
> DSL { implicit self => ... }
>
> Cheers,
> Ingo
>
>
>
> On Jan 29, 12:06 pm, martin odersky wrote:
>> In the recent thread on applyIfDefined, the issue of SAM closures has come
>> up again.
>>
>> To recap:
>>
>> To avoid double evaluation of pattern matching code in PartialFunction's
>> isDefined/apply methods,
>> one promising approach is to allow anonymous function syntax for arbitrary
>> subclasses of Function1. Such subclasses could then override a method
>> "missingCase", defined in Function1 or else PartialFunction (not clear yet
>> which is preferable). Pattern matching closures invoke missingCase in case
>> no pattern matches.
>>
>> A generalization would be to implement SAM closures (as in project Lambda
>> terminology):
>> If an anonymous function
>>
>> { params => body }
>>
>> appears in a context where the expected type is a class type `C[Ts]` with a
>> single abstract method `m`, rewrite the closure to
>>
>> new C[Ts] {
>> def m(params) = body
>> }
>>
>> If the closure appears without such an expected type, assume FunctionN[Ts]
>> as expected type where N and Ts are derived from the formal parameters
>> `params`.
>>
>> That's the rough outline. There will be some tricky bits dealing with type
>> inference. Type inference for anonymous functions is already quite hard, and
>> it would need to be generalized further.
>> But I think it would be doable.
>>
>> I can see two benefits in making the generalization:
>>
>> - We get a solution for the double evaluation problem for PartialFunctions
>> - Scala can seamlessly interact with Java closures. By now it looks pretty
>> clear
>> that Java will also go the SAM way.
>>
>> The downside is that, maybe, this can be misused, because some classes or
>> traits might have a single abstract method by accident, but are not really
>> suitable for closure syntax. But Scala traditionally has not let itself held
>> back by fear of misuse, so this is a fairly weak argument.
>>
>> Any other arguments in favor or against?
>>
>> Cheers
>>
>> -- Martin

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: SAM closures?
Well, Java seems to be going pretty much in the direction of having SAM closures be typed as the class they'll be cast as. I quote http://mail.openjdk.java.net/pipermail/lambda-dev/2010-July/001775.html for example:
the type of 'this' inside the
lambda expression is (a subtype of) the SAM type to which the lambda
expression is being converted.  So the following code will print
"Yes":

     Runnable r = { ->
                      if (this instanceof Runnable)
                          System.out.println("Yes");
                  };
     r.run();

On Mon, Feb 7, 2011 at 21:24, Tiark Rompf <tiark [dot] rompf [at] epfl [dot] ch> wrote:
Just writing

       dsl { ... }

would indeed be wonderful. The question is how we can get there in a backwards compatible way.

More precisely, how can we specifiy whether we want to lookup something in the lexical scope of the closure literal or as a member of the target class?. In other words, if you write

       object Foo {
               dsl { ... this ... }
       }

does 'this' refer to object Foo or to the closure object? Of course 'this' is kind of a corner case but the same applies to super, toString, hashCode, return or any other name/keyword which could have meaning in both contexts.

Currently, closure objects are not accessible at all from within themselves, so 'this' is always resolved lexically. That means we cannot simply change the rules or the following would break:

       object Bar {
               def apply(x:Int) = ...
               List(1,2,3).foreach(z => apply(z)))
       }

For dsls, on the other hand, we sometimes (though not always) want to choose the other extreme, i.e. make *none* of the lexically defined things available and completely isolate a dsl program.

Ideally the (application or dsl) programmer could choose. Maybe one could use a marker trait on the expected type of the closure?

- Tiark

P.S: it looks like thread local refs for transactions would still be needed unless we can ensure that there is only one closure per thread

P.P.S: It's only tangentially related, but I was wondering whether DelayedInit could be recast in terms of SAM-closures.




On Feb 6, 2011, at 4:03 PM, Ingo Maier wrote:

> Would the body of the closure be type checked in the context of the
> abstract class? That would be wonderful for DSLs indeed. No more need
> for thread local self references (as in scala.actors) or implicit
> closure parameters (as in SSTM), just refer to one of the non-abstract
> members in the expected SAM class. It would go a long way to ease the
> choice between the following DSL syntaxes:
>
> new DSL {
>  def body() = ...
> }
>
> and
>
> DSL { ... }
>
> or
>
> DSL { implicit self => ... }
>
> Cheers,
> Ingo
>
>
>
> On Jan 29, 12:06 pm, martin odersky <martin [dot] oder [dot] [dot] [dot] [at] epfl [dot] ch> wrote:
>> In the recent thread on applyIfDefined, the issue of SAM closures has come
>> up again.
>>
>> To recap:
>>
>> To avoid double evaluation of pattern matching code in PartialFunction's
>> isDefined/apply methods,
>> one promising approach is to allow anonymous function syntax for arbitrary
>> subclasses of Function1. Such subclasses could then override a method
>> "missingCase", defined in Function1 or else PartialFunction (not clear yet
>> which is preferable). Pattern matching closures invoke missingCase in case
>> no pattern matches.
>>
>> A generalization would be to implement SAM closures (as in project Lambda
>> terminology):
>> If an anonymous function
>>
>>   { params => body }
>>
>> appears in a context where the expected type is a class type `C[Ts]` with a
>> single abstract method `m`, rewrite the closure to
>>
>>   new C[Ts] {
>>     def m(params) = body
>>   }
>>
>> If the closure appears without such an expected type, assume FunctionN[Ts]
>> as expected type where N and Ts are derived from the formal parameters
>> `params`.
>>
>> That's the rough outline. There will be some tricky bits dealing with type
>> inference. Type inference for anonymous functions is already quite hard, and
>> it would need to be generalized further.
>> But I think it would be doable.
>>
>> I can see two benefits in making the generalization:
>>
>>   - We get a solution for the double evaluation problem for PartialFunctions
>>   - Scala can seamlessly interact with Java closures. By now it looks pretty
>> clear
>>     that Java will also go the SAM way.
>>
>> The downside is that, maybe, this can be misused, because some classes or
>> traits might have a single abstract method by accident, but are not really
>> suitable for closure syntax. But Scala traditionally has not let itself held
>> back by fear of misuse, so this is a fairly weak argument.
>>
>> Any other arguments in favor or against?
>>
>> Cheers
>>
>>  -- Martin




--
Daniel C. Sobral

I travel to the future all the time.
odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Re: SAM closures?

On Tue, Feb 8, 2011 at 12:24 AM, Tiark Rompf wrote:
> Just writing
>
>        dsl { ... }
>
> would indeed be wonderful. The question is how we can get there in a backwards compatible way.
>
> More precisely, how can we specifiy whether we want to lookup something in the lexical scope of the closure literal or as a member of the target class?. In other words, if you write
>
>        object Foo {
>                dsl { ... this ... }
>        }
>
> does 'this' refer to object Foo or to the closure object? Of course 'this' is kind of a corner case but the same applies to super, toString, hashCode, return or any other name/keyword which could have meaning in both contexts.
>
Ouch. Yes, that looks like a showstopper. Never mind the backwards
compatibility problems this would pose. I firmly believe that the way
we handle `this' in closures is correct, no matter what Java decides
to do. I.e. if you write

foo { ... this ... }|

You want `this' to resolve to the currently enclosing class or object.
Having an inferred type for the closure determine the meaning of
`this' (and with it all other members) looks like too much dynamic
scoping to me. So, nice as it would be I do not see this part of the
proposal playing out, in the end.

Note that with DelayedInit you can achieve something like

new DSL { ... }

instead. That's almost as concise, and the `new' makes it clear where
`this' is bound.

Cheers

Ingo Maier
Joined: 2009-11-23,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: SAM closures?


On Tue, Feb 8, 2011 at 10:00 AM, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
Note that with DelayedInit you can achieve something like

 new DSL { ... }

instead. That's almost as concise, and the `new' makes it clear where
`this' is bound.

Cheers

boisvert
Joined: 2009-11-11,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: SAM closures?
On Tue, Feb 8, 2011 at 1:00 AM, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
Ouch. Yes, that looks like a showstopper. Never mind the backwards compatibility problems this would pose. I firmly believe that the way
we handle `this' in closures is correct, no matter what Java decides
to do. I.e. if you write

  foo { ... this ... }|

You want `this' to resolve to the currently enclosing class or object.
Having an inferred type for the closure determine the meaning of
`this' (and with it all other members) looks like too much dynamic
scoping to me. So, nice as it would be I do not see this part of the
proposal playing out, in the end.

Hi Martin,
Assuming,
def DSL(x: SAM) = ...
DSL { ...args... =>   ...body...}
then to maintain 'this' resolving to the currently enclosing class or object, perhaps the closure expansion could be as follows,
DSL {  def _samMethod_(...args...)(sam: SAM) = {     import sam._    ...body...  }  new SAM {    def samMethod(...args...) = _samMethod_(...args...)(this)  }}
This seems to be similar in spirit to the { implicit foo => ...} syntax combined with a generalized implicit conversion tailored to SAM classes.
alex
prokopec
Joined: 2010-02-19,
User offline. Last seen 34 weeks 5 days ago.
Re: Re: SAM closures?

> Ideally the (application or dsl) programmer could choose. Maybe one could use a marker trait on the expected type of the closure?
>

+1 for the marker trait.

prokopec
Joined: 2010-02-19,
User offline. Last seen 34 weeks 5 days ago.
Re: Re: SAM closures?

1uO65J [at] mail [dot] gmail [dot] com" type="cite">
DSL {   def _samMethod_(...args...)(sam: SAM) = {     import sam._     ...body...   }   new SAM {     def samMethod(...args...) = _samMethod_(...args...)(this)   } }
This seems to be similar in spirit to the { implicit foo => ...} syntax combined with a generalized implicit conversion tailored to SAM classes.

Perhaps this solution could go hand in hand with the marker trait idea.

Alex
Nathan Bronson
Joined: 2010-11-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: SAM closures?
Has anyone mentioned the option of magically providing an implicit when type-checking the SAM, either of the SAM type itself or of a Manifest-like wrapper (maybe SAMContext[A])?  DSL operations could get access to their SAM instance (and could be statically enforced to be callable only inside the SAM), but "this" would retain its current semantics.
For the STM example, instead of requiring an implicit Txn parameter for Ref access we would require an implicit AtomicBlock[_] or SAMContext[AtomicBlock[_]].
 - Nathan

On Tue, Feb 8, 2011 at 8:18 AM, Aleksandar Prokopec <aleksandar [dot] prokopec [at] epfl [dot] ch> wrote:


DSL {   def _samMethod_(...args...)(sam: SAM) = {     import sam._     ...body...   }   new SAM {     def samMethod(...args...) = _samMethod_(...args...)(this)   } }
This seems to be similar in spirit to the { implicit foo => ...} syntax combined with a generalized implicit conversion tailored to SAM classes.

Perhaps this solution could go hand in hand with the marker trait idea.

Alex

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Re: SAM closures?

On 2/9/11 1:13 PM, Nathan Bronson wrote:
> Has anyone mentioned the option of magically providing an implicit when
> type-checking the SAM, either of the SAM type itself or of a
> Manifest-like wrapper (maybe SAMContext[A])?

I like this one. An implicit parameter gives us not only an isolated
namespace but offers a way to customize the closure conversion
semantics. I bet there's a winner in here somewhere.

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: SAM closures?
On Wed, Feb 9, 2011 at 19:13, Nathan Bronson <ngbronson [dot] sub [at] gmail [dot] com> wrote:
Has anyone mentioned the option of magically providing an implicit when type-checking the SAM, either of the SAM type itself or of a Manifest-like wrapper (maybe SAMContext[A])?  DSL operations could get access to their SAM instance (and could be statically enforced to be callable only inside the SAM), but "this" would retain its current semantics.
For the STM example, instead of requiring an implicit Txn parameter for Ref access we would require an implicit AtomicBlock[_] or SAMContext[AtomicBlock[_]].

Do you mean like:
collect { x => f(x) }
gets translated into
collect (new Collectable {  def apply(x) = {     implicit val ev: Collectable = this      // the rest of the block is typed by standard closure rules, not Collectable     f(x)   }}) More or less?

 - Nathan

On Tue, Feb 8, 2011 at 8:18 AM, Aleksandar Prokopec <aleksandar [dot] prokopec [at] epfl [dot] ch> wrote:


DSL {   def _samMethod_(...args...)(sam: SAM) = {     import sam._     ...body...   }   new SAM {     def samMethod(...args...) = _samMethod_(...args...)(this)   } }
This seems to be similar in spirit to the { implicit foo => ...} syntax combined with a generalized implicit conversion tailored to SAM classes.

Perhaps this solution could go hand in hand with the marker trait idea.

Alex




--
Daniel C. Sobral

I travel to the future all the time.
Nathan Bronson
Joined: 2010-11-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: SAM closures?
Yes.  With the wrapping object option:
trait SAMContext[A] { def closure: A }
collect(new Collectable {  implicit val withNoName = new SAMContextImpl[Collectable](this)
  ...})
or maybe the SAMContext instance is part of the concrete class (to avoid an object allocation):
collect(new Collectable with SAMContext[Collectable] {   implicit val withNoName: SAMContext[Collectable] = this  def closure: Collectable = this
  ...})
which is heading towards an annotation on the SAM type's implicit declarations that explicitly causes them to be imported
trait Collectable {  @samInherit implicit val collectableThis = this  def apply}
Hmm.
 - Nathan
On Wed, Feb 9, 2011 at 3:49 PM, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:
On Wed, Feb 9, 2011 at 19:13, Nathan Bronson <ngbronson [dot] sub [at] gmail [dot] com> wrote:
Has anyone mentioned the option of magically providing an implicit when type-checking the SAM, either of the SAM type itself or of a Manifest-like wrapper (maybe SAMContext[A])?  DSL operations could get access to their SAM instance (and could be statically enforced to be callable only inside the SAM), but "this" would retain its current semantics.
For the STM example, instead of requiring an implicit Txn parameter for Ref access we would require an implicit AtomicBlock[_] or SAMContext[AtomicBlock[_]].

Do you mean like:
collect { x => f(x) }
gets translated into
collect (new Collectable {  def apply(x) = {     implicit val ev: Collectable = this      // the rest of the block is typed by standard closure rules, not Collectable     f(x)   }}) More or less?

 - Nathan

On Tue, Feb 8, 2011 at 8:18 AM, Aleksandar Prokopec <aleksandar [dot] prokopec [at] epfl [dot] ch> wrote:


DSL {   def _samMethod_(...args...)(sam: SAM) = {     import sam._     ...body...   }   new SAM {     def samMethod(...args...) = _samMethod_(...args...)(this)   } }
This seems to be similar in spirit to the { implicit foo => ...} syntax combined with a generalized implicit conversion tailored to SAM classes.

Perhaps this solution could go hand in hand with the marker trait idea.

Alex




--
Daniel C. Sobral

I travel to the future all the time.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland