--
You received this message because you are subscribed to the Google Groups "scala-debate" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-debate...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups "scala-debate" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-debate...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
That's a bit condecending. Please maintain a good tone.
Cheers,
V
Specification the silently chooses an ambiguous overload is wrong at any level of programmer sophistication, for the same reason that we use static typing
On Fri, Sep 20, 2013 at 11:04 AM, Shelby <she...@coolpage.com> wrote:
Specification the silently chooses an ambiguous overload is wrong at any level of programmer sophistication, for the same reason that we use static typing
I think you're underestimating the amount of ambiguity to be had.def foo(a: Int)(implicit b: Int): Array[Int] = Array(b, a)
implicit val x = 5
val bar = foo(3)(1)What is the type of bar? What is the result? Is it 3 or Array(1,3)?It's not hard to make constructs that can be ambiguous, especially in the presence of optional parameters, optional parameter lists, and implicit conversions.
On Fri, Sep 20, 2013 at 11:04 AM, Shelby <she...@coolpage.com> wrote:
Specification the silently chooses an ambiguous overload is wrong at any level of programmer sophistication, for the same reason that we use static typing
I think you're underestimating the amount of ambiguity to be had.def foo(a: Int)(implicit b: Int): Array[Int] = Array(b, a)
implicit val x = 5
val bar = foo(3)(1)What is the type of bar? What is the result? Is it 3 or Array(1,3)?
It's not hard to make constructs that can be ambiguous, especially in the presence of optional parameters, optional parameter lists, and implicit conversions.
This is one of the taxes you have to pay to gain the expressive power of Scala.
Making a rule that foo(x) means foo(x), not foo(x, defaultY) seems fine to me.
You do need to know it, and you can if you choose use it to obfuscate your code, but in any reasonably constructed and properly documented code it shouldn't be an issue at all because (1) foo(x) and foo(x, y = Y) are next to each other in the code, and (2) they're also next to each other in the Scaladoc.
If you're going to allow overloads at all, that is. (If you allow overloads and you find foo(x) where the type doesn't match, you again don't know whether you've found the right method until you are sure that there's no foo(y: Y) where Y does match the type.)
That is reasonable point to raise
Why would they write it, if the default can never be employed. It an entirely useful snippet of code they have written, and so they must not be aware of it, otherwise they wouldn't write it.
On Fri, Sep 20, 2013 at 11:12 PM, Rex Kerr <ich...@gmail.com> wrote:On Fri, Sep 20, 2013 at 11:04 AM, Shelby <she...@coolpage.com> wrote:
Specification the silently chooses an ambiguous overload is wrong at any level of programmer sophistication, for the same reason that we use static typing
I think you're underestimating the amount of ambiguity to be had.def foo(a: Int)(implicit b: Int): Array[Int] = Array(b, a)
implicit val x = 5
val bar = foo(3)(1)What is the type of bar? What is the result? Is it 3 or Array(1,3)?It's not hard to make constructs that can be ambiguous, especially in the presence of optional parameters, optional parameter lists, and implicit conversions.
Actually, I was meaning to write a lint check to flag a pretty similar case (def f / def f(implicit ...)). [1]
It was sufficiently subtle to lead a certain language designer astray for a day or two.That case also showed that the duelling methods need not be proximal given inheritance.
I think this is a good area for a linters, rather than baking the rules into the specification for overload resolution.
[I have some comments]( http://stackoverflow.com/a/2512001/615784 ) (see my comments below the linked answer) about Scala making overloading frowned upon and a second-class citizen. If we continue to purposely weaken overloading in Scala, we are replacing typing with names, which IMO is a regressive direction.
I hope you never use Java. :-)
On Saturday, September 21, 2013 5:12:06 AM UTC+8, Rex Kerr wrote:
On Fri, Sep 20, 2013 at 11:04 AM, Shelby <she...@coolpage.com> wrote:
Specification the silently chooses an ambiguous overload is wrong at any level of programmer sophistication, for the same reason that we use static typing
I think you're underestimating the amount of ambiguity to be had.def foo(a: Int)(implicit b: Int): Array[Int] = Array(b, a)
implicit val x = 5
val bar = foo(3)(1)What is the type of bar? What is the result? Is it 3 or Array(1,3)?That is reasonable point to raise, yet I don't see any ambiguity above, because the programmer has communicated his intention unambiguously
analogous to we don't imagine what the ambiguity would be in a case where we require a cast and use a cast, e.g.trait Atrait B extends Acase class C extends Bcase class D extends Aimplicit def DFromC(a: C) = Ddef foo(a: B) ...def foo(a: D) ....val bar = foo(C : B)
It's not hard to make constructs that can be ambiguous, especially in the presence of optional parameters, optional parameter lists, and implicit conversions.I define ambiguous is there is nothing the programmer has written to give the compiler an unambiguous indication of the priority to choose. With that definition can you show me something in Scala that is ambiguous besides what I am arguing is a bug in the specification in this thread?
This is one of the taxes you have to pay to gain the expressive power of Scala.
I am not convinced. I don't like to assume that expressive power necessarily requires loss of correctness.
If you can show me that is the case, then I will acquiesce.Making a rule that foo(x) means foo(x), not foo(x, defaultY) seems fine to me.I strongly and emphatically disagree and if I could scream louder I would. This is a defeatist philosophy IMO (not you personally but the overall thrust to allow such logic into the language design and I would like to try to put a stop to it, if we can get consensus).
The reason is because as you say, there are many complex combinations that can occur with the various expressive power features in Scala, thus when the user writes the above, they may not even consciously realize they've made such a choice. Why would they write it, if the default can never be employed. It an entirely useless snippet of code they have written, and so they must not be aware of it, otherwise they wouldn't write it.
And more saliently, because choices between ambiguities should be explicitly specified by the programmer, so that intent is conscious.You do need to know it, and you can if you choose use it to obfuscate your code, but in any reasonably constructed and properly documented code it shouldn't be an issue at all because (1) foo(x) and foo(x, y = Y) are next to each other in the code, and (2) they're also next to each other in the Scaladoc.
Rex I hope you don't get offended if I say that if we start allowing that sort of sweeping incorrectness under the rug, we've lost.
If you're going to allow overloads at all, that is. (If you allow overloads and you find foo(x) where the type doesn't match, you again don't know whether you've found the right method until you are sure that there's no foo(y: Y) where Y does match the type.)Yup. So what is the problem? The compiler needs to search all the possibilities.
On Fri, Sep 20, 2013 at 8:12 PM, Shelby <she...@coolpage.com> wrote:
On Saturday, September 21, 2013 5:12:06 AM UTC+8, Rex Kerr wrote:
On Fri, Sep 20, 2013 at 11:04 AM, Shelby <she...@coolpage.com> wrote:
Specification the silently chooses an ambiguous overload is wrong at any level of programmer sophistication, for the same reason that we use static typing
I think you're underestimating the amount of ambiguity to be had.def foo(a: Int)(implicit b: Int): Array[Int] = Array(b, a)
implicit val x = 5
val bar = foo(3)(1)What is the type of bar? What is the result? Is it 3 or Array(1,3)?That is reasonable point to raise, yet I don't see any ambiguity above, because the programmer has communicated his intention unambiguouslyReally? So, uh, which is it?Argument for one way:val temp = foo(3)val bar = temp(1)Argument for another way:
(foo _)Int => Int => Array[Int]Can you explain why this is so unambiguous?
analogous to we don't imagine what the ambiguity would be in a case where we require a cast and use a cast, e.g.trait Atrait B extends Acase class C extends Bcase class D extends Aimplicit def DFromC(a: C) = Ddef foo(a: B) ...def foo(a: D) ....val bar = foo(C : B)I don't see the analogy. You will have to spell out the parallels; this looks entirely different to me.
(In particular, I don't know why you bother with C: B; C should do the trick alone.)
It's not hard to make constructs that can be ambiguous, especially in the presence of optional parameters, optional parameter lists, and implicit conversions.I define ambiguous is there is nothing the programmer has written to give the compiler an unambiguous indication of the priority to choose. With that definition can you show me something in Scala that is ambiguous besides what I am arguing is a bug in the specification in this thread?
object O {
def f(l: Long) = l*l
def f(d: Double) = 1.0/d
}O.f(5) // What do I print?
This is one of the taxes you have to pay to gain the expressive power of Scala.
I am not convinced. I don't like to assume that expressive power necessarily requires loss of correctness.That implicit arguments normally vanish into thin air is exactly one of these cases. (See my first example.)
If you can show me that is the case, then I will acquiesce.Making a rule that foo(x) means foo(x), not foo(x, defaultY) seems fine to me.I strongly and emphatically disagree and if I could scream louder I would. This is a defeatist philosophy IMO (not you personally but the overall thrust to allow such logic into the language design and I would like to try to put a stop to it, if we can get consensus).The reason is because as you say, there are many complex combinations that can occur with the various expressive power features in Scala, thus when the user writes the above, they may not even consciously realize they've made such a choice. Why would they write it, if the default can never be employed. It an entirely useless snippet of code they have written, and so they must not be aware of it, otherwise they wouldn't write it.Within the same class, yes, you can't use the default value. Butclass A { def foo(a: Int, b: Long = 0) = a + b }
class B extends A { def foo(a: Int): Long = foo(a, 1) }
so the question is whether it's worth a special case (and whether it should be an error or a warning or only come up with a lint-like tool).
And more saliently, because choices between ambiguities should be explicitly specified by the programmer, so that intent is conscious.You do need to know it, and you can if you choose use it to obfuscate your code, but in any reasonably constructed and properly documented code it shouldn't be an issue at all because (1) foo(x) and foo(x, y = Y) are next to each other in the code, and (2) they're also next to each other in the Scaladoc.
Rex I hope you don't get offended if I say that if we start allowing that sort of sweeping incorrectness under the rug, we've lost.
See the valid use case above.
If you're going to allow overloads at all, that is. (If you allow overloads and you find foo(x) where the type doesn't match, you again don't know whether you've found the right method until you are sure that there's no foo(y: Y) where Y does match the type.)Yup. So what is the problem? The compiler needs to search all the possibilities.The problem is that the _coder_ needs to search all the possibilities. (Or the IDE.) Otherwise, how do you know whether you've missed the exact match?
Without implicits, it's much easier: if the type doesn't match the method, you ignore it.
On Saturday, September 21, 2013 11:57:25 AM UTC+8, Rex Kerr wrote:On Fri, Sep 20, 2013 at 8:12 PM, Shelby <she...@coolpage.com> wrote:
On Saturday, September 21, 2013 5:12:06 AM UTC+8, Rex Kerr wrote:
On Fri, Sep 20, 2013 at 11:04 AM, Shelby <she...@coolpage.com> wrote:
Specification the silently chooses an ambiguous overload is wrong at any level of programmer sophistication, for the same reason that we use static typing
I think you're underestimating the amount of ambiguity to be had.def foo(a: Int)(implicit b: Int): Array[Int] = Array(b, a)
implicit val x = 5
val bar = foo(3)(1)What is the type of bar? What is the result? Is it 3 or Array(1,3)?That is reasonable point to raise, yet I don't see any ambiguity above, because the programmer has communicated his intention unambiguouslyReally? So, uh, which is it?Argument for one way:val temp = foo(3)val bar = temp(1)Argument for another way:
(foo _)Int => Int => Array[Int]Can you explain why this is so unambiguous?I understood that point from your prior post, yet the prior example code is not assigning the curried partial function to another value, rather it is explicitly supply the 2nd argument immediately.With your new example above, temp should contain the result of the function with the implicit argument applied.There is no ambiguity because the choice is made at each local decision point, not across multiple expressions.
It's not hard to make constructs that can be ambiguous, especially in the presence of optional parameters, optional parameter lists, and implicit conversions.
I define ambiguous is there is nothing the programmer has written to give the compiler an unambiguous indication of the priority to choose. With that definition can you show me something in Scala that is ambiguous besides what I am arguing is a bug in the specification in this thread?
object O {
def f(l: Long) = l*l
def f(d: Double) = 1.0/d
}O.f(5) // What do I print?Neither. Should be an error, "ambiguous overloads". Is this not an error in Scala?
This is one of the taxes you have to pay to gain the expressive power of Scala.
I am not convinced. I don't like to assume that expressive power necessarily requires loss of correctness.That implicit arguments normally vanish into thin air is exactly one of these cases. (See my first example.)
I don't see the ambiguity.
If you can show me that is the case, then I will acquiesce.Making a rule that foo(x) means foo(x), not foo(x, defaultY) seems fine to me.I strongly and emphatically disagree and if I could scream louder I would. This is a defeatist philosophy IMO (not you personally but the overall thrust to allow such logic into the language design and I would like to try to put a stop to it, if we can get consensus).The reason is because as you say, there are many complex combinations that can occur with the various expressive power features in Scala, thus when the user writes the above, they may not even consciously realize they've made such a choice. Why would they write it, if the default can never be employed. It an entirely useless snippet of code they have written, and so they must not be aware of it, otherwise they wouldn't write it.Within the same class, yes, you can't use the default value. Butclass A { def foo(a: Int, b: Long = 0) = a + b }
class B extends A { def foo(a: Int): Long = foo(a, 1) }
so the question is whether it's worth a special case (and whether it should be an error or a warning or only come up with a lint-like tool).Huh? You still haven't employed the default value.
What special case? The simple rule is that ambiguous overloads should always be an error. No exceptions ever. No warnings.
IMO Google groups really needs a preview feature. And perhaps also an edit feature (with a Post Delayed button) where they don't send the message to the list for a minute or two.
It's not hard to make constructs that can be ambiguous, especially in the presence of optional parameters, optional parameter lists, and implicit conversions.
I define ambiguous is there is nothing the programmer has written to give the compiler an unambiguous indication of the priority to choose. With that definition can you show me something in Scala that is ambiguous besides what I am arguing is a bug in the specification in this thread?
object O {
def f(l: Long) = l*l
def f(d: Double) = 1.0/d
}O.f(5) // What do I print?Neither. Should be an error, "ambiguous overloads". Is this not an error in Scala?It's runnable code. Why not run it instead of asking?
This is one of the taxes you have to pay to gain the expressive power of Scala.
I am not convinced. I don't like to assume that expressive power necessarily requires loss of correctness.That implicit arguments normally vanish into thin air is exactly one of these cases. (See my first example.)
I don't see the ambiguity.It's ambiguous until you dig enough. Then it isn't. Same deal with foo(x) vs. foo(x, y) w/ default y.
If you can show me that is the case, then I will acquiesce.Making a rule that foo(x) means foo(x), not foo(x, defaultY) seems fine to me.I strongly and emphatically disagree and if I could scream louder I would. This is a defeatist philosophy IMO (not you personally but the overall thrust to allow such logic into the language design and I would like to try to put a stop to it, if we can get consensus).The reason is because as you say, there are many complex combinations that can occur with the various expressive power features in Scala, thus when the user writes the above, they may not even consciously realize they've made such a choice. Why would they write it, if the default can never be employed. It an entirely useless snippet of code they have written, and so they must not be aware of it, otherwise they wouldn't write it.Within the same class, yes, you can't use the default value. Butclass A { def foo(a: Int, b: Long = 0) = a + b }
class B extends A { def foo(a: Int): Long = foo(a, 1) }
so the question is whether it's worth a special case (and whether it should be an error or a warning or only come up with a lint-like tool).Huh? You still haven't employed the default value.I changed the effective default value for classes typed as B.
What special case? The simple rule is that ambiguous overloads should always be an error. No exceptions ever. No warnings.Is the case above ambiguous or not? I can't tell based on your criterion.
I agree in principle, but detecting honest ambiguity is surprisingly difficult. I'm not sure it's a clear win when the statement of what is ambiguous is too difficult. (And your compiler either needs to contain a general proof system or a special rule for each case.)
Anyway, it might be kind of nice if the compiler poked you if you wrote that kind of ambiguity. But the implication that you can't trust a compiler that doesn't poke you, when there are so many other ways in which you could be confused much worse, contains rather ridiculous amounts of hyperbole.
--Rex