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

function types as default arguments

2 replies
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.

Nothing strikes again:

scala> def transform(s: String, f: (String) => String = identity _) = f(s)
transform: (s: String,f: (String) => String)String

scala> transform("abc")
:6: error: type mismatch;
found : (Nothing) => Nothing
required: (String) => String
transform("abc")
^

Oh, but I just noticed it works this way, which lessens the pain. I
think these two versions ought to compile identically.

scala> def transform(s: String, f: (String) => String =
identity[String] _) = f(s)
transform: (s: String,f: (String) => String)String

scala> transform("abc")
res0: String = abc

rytz
Joined: 2008-07-01,
User offline. Last seen 45 weeks 5 days ago.
Re: function types as default arguments
Good catch!

The reason is: when generating default getters (the methods computing
defaults), the return type is set to be empty, i.e. the typer will infer it.

This is needed for:

  def foo[T](a: T = 1)
  def foo$default$1[T] = 1  // compiler infers Int return type

We can't set the parameter type "T" as return type, the default getter
would not type check.

In your case this gives:
  def transform(s: String, f: String => String = identity _)
  def transform$default$2 = identity _  // compiler infers Nothing => Nothing


What we *should* do: after type checking the parameter ValDef,
use the type computed for it's rhs as return type of the default getter.

It's not obvious how to do that, because when generating the default
getter (Namer), this this information is not yet available. I'll have a look.


Lukas


On Thu, Jun 4, 2009 at 19:38, Paul Phillips <paulp@improving.org> wrote:
Nothing strikes again:

scala> def transform(s: String, f: (String) => String = identity _) = f(s)
transform: (s: String,f: (String) => String)String

scala> transform("abc")
<console>:6: error: type mismatch;
 found   : (Nothing) => Nothing
 required: (String) => String
      transform("abc")
               ^

Oh, but I just noticed it works this way, which lessens the pain.  I
think these two versions ought to compile identically.

scala> def transform(s: String, f: (String) => String =
               identity[String] _) = f(s)
transform: (s: String,f: (String) => String)String

scala> transform("abc")
res0: String = abc

--
Paul Phillips      | Eschew mastication.
Caged Spirit       |
Empiricist         |
i'll ship a pulp   |----------* http://www.improving.org/paulp/ *----------

rytz
Joined: 2008-07-01,
User offline. Last seen 45 weeks 5 days ago.
Re: function types as default arguments
This is fixed now in trunk (r18069). If the parameter type does not dependon any type parameter of the method, it is re-used as return type of thedefault getter. Otherwise, the return type is inferred.

Lukas

On Fri, Jun 5, 2009 at 10:23, Lukas Rytz <lukas.rytz@epfl.ch> wrote:
Good catch!

The reason is: when generating default getters (the methods computing
defaults), the return type is set to be empty, i.e. the typer will infer it.

This is needed for:

  def foo[T](a: T = 1)
  def foo$default$1[T] = 1  // compiler infers Int return type

We can't set the parameter type "T" as return type, the default getter
would not type check.

In your case this gives:
  def transform(s: String, f: String => String = identity _)
  def transform$default$2 = identity _  // compiler infers Nothing => Nothing


What we *should* do: after type checking the parameter ValDef,
use the type computed for it's rhs as return type of the default getter.

It's not obvious how to do that, because when generating the default
getter (Namer), this this information is not yet available. I'll have a look.


Lukas


On Thu, Jun 4, 2009 at 19:38, Paul Phillips <paulp@improving.org> wrote:
Nothing strikes again:

scala> def transform(s: String, f: (String) => String = identity _) = f(s)
transform: (s: String,f: (String) => String)String

scala> transform("abc")
<console>:6: error: type mismatch;
 found   : (Nothing) => Nothing
 required: (String) => String
      transform("abc")
               ^

Oh, but I just noticed it works this way, which lessens the pain.  I
think these two versions ought to compile identically.

scala> def transform(s: String, f: (String) => String =
               identity[String] _) = f(s)
transform: (s: String,f: (String) => String)String

scala> transform("abc")
res0: String = abc

--
Paul Phillips      | Eschew mastication.
Caged Spirit       |
Empiricist         |
i'll ship a pulp   |----------* http://www.improving.org/paulp/ *----------


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