Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Given SI-5009, can case classes with repeated params get a copy method now? #6016

Closed
scabug opened this issue Jul 2, 2012 · 15 comments
Closed

Comments

@scabug
Copy link

scabug commented Jul 2, 2012

In 2.9, when the copy method had defaults for all parameter lists, having a repeated parameter in any of the lists would prevent the copy method from being generated, since repeated parameters and default arguments can't coexist (though this isn't explicitly spec'd, see #4783). Now that #5009 makes copy return a function type instead of being a multi-param list method, I don't see why it shouldn't be generated if parameter lists after the first one have repeated parameters.

E.g.:

case class Foo(a: Int)(b: String*)

should get a method

def copy(a: Int = this.a): (String*) => Foo
@scabug
Copy link
Author

scabug commented Jul 2, 2012

Imported From: https://issues.scala-lang.org/browse/SI-6016?orig=1
Reporter: Ryan Hendrickson (ryan.hendrickson_bwater)
Affected Versions: 2.10.0-M4
See #5009

@scabug
Copy link
Author

scabug commented Jul 2, 2012

@lrytz said:
(String*) => Foo is not a valid function type, unfortunately..

@scabug scabug closed this as completed Jul 2, 2012
@scabug
Copy link
Author

scabug commented Jul 2, 2012

@lrytz said:
#3652

@scabug
Copy link
Author

scabug commented Jul 2, 2012

Ryan Hendrickson (ryan.hendrickson_bwater) said:

case class SureItIs(a: Int)(b: String*) {
  def copy(a: Int = this.a): (String*) => SureItIs = new ((String*) => SureItIs) {
    def apply(b: String*) = SureItIs(a)(b:_*)
  }
}

It's just not a valid anonymous function type, but it is most assuredly a valid type.

@scabug
Copy link
Author

scabug commented Jul 2, 2012

@retronym said:
The spec is actually bit lacking in this area. This is syntactically allowed, but there is no mention on how it should be type checked. Is ((Animal*) => Any) a subtype of ((Dog*) => Any)? Of Seq[Animal] => Any?

All we are told is that:

The type of such a repeated parameter inside the method is then the sequence type scala.Seq[T].

By name parameters are similarly underspecced.

@scabug
Copy link
Author

scabug commented Jul 2, 2012

@paulp said:
Lukas is correct. In 2.10 you can still get away with typing in the above (it's more broken in 2.9) but the copy method is not assigned the type (String*) => SureItIs, it is given the type Seq[String] => SureItIs.

The varargs star can only appear in method types, not function types.

scala> def f(xs: String*): Int = 5
f: (xs: String*)Int

scala> f _
res0: Seq[String] => Int = <function1>

scala> class A { def g: ((String*) => Int) = f _ }
defined class A

scala> (new A).g _
res1: () => Seq[String] => Int = <function0>

@scabug
Copy link
Author

scabug commented Jul 2, 2012

@paulp said:
It is definitely underspecified, but I'm drawing on additional sources of information to make this assessment. It'd be nice if we were all working from the same spec sheet, yes.

@scabug
Copy link
Author

scabug commented Jul 2, 2012

Ryan Hendrickson (ryan.hendrickson_bwater) said:
Paul: I get that eta-expansion never produces a function type containing a repeated parameter, but such function types are still valid value types, yes? I can still write

val f: (String*) => Int = new ((String*) => Int) {
  def apply(xs: String*) = 5
}

f("hello", "world")

Not a method type to be seen, just an anonymous class implementing a valid value type.

Jason: I agree that the conformance relation of function types with repeated parameters is underspecified. The existence of those types, however, seems less ambiguous:

Syntax:

Type         ::= FunctionArgs '=>' Type
FunctionArgs ::= '(' [ ParamType {',' ParamType } ] ')'
ParamType    ::= Type '*'

Semantics:

Function types are shorthands for class types that define {{apply}} functions.

(In particular, this does not say "function types are shorthands for method types".)

So since Any { def apply(xs: String*): Int } is a valid (value, not method!) type, ((String*) => Int) is as well, right?

@scabug
Copy link
Author

scabug commented Jul 2, 2012

@paulp said:
You can't write it in 2.10.

scala> val f: (String*) => Int = new ((String*) => Int) { def apply(xs: String*) = 5 }
<console>:4: error: type mismatch;
 found   : String* => Int
 required: Seq[String] => Int

It's pointless to debate it too much because all we can do is chase angels around the head of a pin. What we need is a clear statement, not to be spending our time parsing and reparsing the spec hoping it will suddenly become unambiguous through spontaneous disambiguation.

@scabug
Copy link
Author

scabug commented Jul 2, 2012

Ryan Hendrickson (ryan.hendrickson_bwater) said:
Well, if I haven't convinced you that it's unambiguous then I'll accept that as evidence of its ambiguity. :-) So fair enough. The slew of tickets around repeated and by-name parameters that I've been submitting have largely been attempts to get that clarifying statement through a body of case law, assuming that someone had a self-consistent view on this already and that the spec was merely incomplete or imperfectly implemented. But if not, and you're going to just go off and develop a less ambiguous formulation for those pseudo-types, that's even better, and I will happily withhold my whining about case class copy methods until that appears. (Should I hold my breath? Is this something that you're discussing currently or is it deprioritized given all the exciting macro/reflection/other groundbreaking 2.10 stuff?)

@scabug
Copy link
Author

scabug commented Jul 2, 2012

@paulp said:
The boat I'm in is a lot more like the boat you're in than you probably think. I'm no longer willing to spend time on this sort of issue because it's nothing but blank walls, dead ends, and stairways to nowhere. If you have an idea how to see some kind of progress you should pursue it, because that idea already puts you ahead of me.

@scabug
Copy link
Author

scabug commented Jul 3, 2012

Ryan Hendrickson (ryan.hendrickson_bwater) said (edited on Jul 3, 2012 1:08:20 AM UTC):
I'd like to help in the most constructive way possible. I have my own interpretation of the spec, which (to my limited ability to judge) seems self-consistent and also consistent with the way Scala users have been thinking about function types in the language, but it may or may not be an avenue you guys have already considered and rejected. I don't want to cause you further frustration by forcing you to repeat a debate you've already had, but I'm enthusiastic about seeing this family of issues resolved in a logical way (regardless of whether it's the way I have in mind). How should I proceed? Are there older bugs or threads I should read up on to get a better appreciation for the things you've tried and the scope of the problem? Should I just post what I'm thinking here or to scala-debate, dead horses be damned? Write a formal SIP? Offer a patch? Back off and shut up until 2.10 is out the door and Team Scala has more time to engage on questions like this? What's the most helpful way I can contribute?

@scabug
Copy link
Author

scabug commented Jul 3, 2012

@retronym said:
Ryan,

Don't feel discouraged -- just because it's hard to solve these issues doesn't mean that you shouldn't be raising them. Unfortunately JIRA is pretty cluttered, and it has a pretty small audience, so discussions in here aren't really that productive.

Try the mailing lists instead. The challenge is to summarize and demonstrate the inconsistencies in a way that triggers awareness and discussion from the broader community. You might get a few good ideas there (or you might just here crickets chirping, who knows.)

The inconsistencies aren't of the highest priority because you can avoid them by staying away from the underpecified fringes of the languange. There are about 500 other tickets in here that are much harder to avoid. Plenty of those could benefit from your insights and attention to detail, so don't limit yourself to the "repeated and by-name" guy :)

@scabug
Copy link
Author

scabug commented Jul 3, 2012

@retronym said:
One more suggestion: Collect the snippets of code from this family of tickets, and create a pair of test cases (one that compiles, one that provokes compile errors) to document the current behaviour of by-name/repeated types. Comment these with references to the spec, and notes from/links to these tickets.

We can add these to the compiler test suite to make sure the behaviour doesn't drift over time; and it will provide a concrete basis for a wider discussion.

@scabug
Copy link
Author

scabug commented Jul 3, 2012

Ryan Hendrickson (ryan.hendrickson_bwater) said:
Thanks Jason, I'll do that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant