martin odersky | 1 Mar 2009 10:43
Picon
Picon
Favicon

Re: Equality and case objects

On Sat, Feb 28, 2009 at 12:15 AM, David MacIver
<david.maciver@...> wrote:
> On Fri, Feb 27, 2009 at 11:11 PM, Lex Spoon <lex@...> wrote:
>>
>> On Feb 28, 2009, at 12:23 AM, David MacIver wrote:
>>>
>>> So the match expression would be translated to:
>>>
>>>  x match {
>>>    case (_: C) => ...
>>>    case (_: object O) => ...
>>>    case y if (y == this.V) => ...
>>>  }
>>>
>>> What's your opinion on this?
>>>
>>> I agree that the errors caused by this case are somewhat problematic, but
>>> I'm not sure they occur commonly enough for it to be worth the spec
>>> complication, particularly if (as suggested above) matching on inner objects
>>> of a class becomes a warning. I'm also a little concerned that it's not
>>> caught statically. If x is known to come from a different instance of Outer,
>>> why is this not being rejected as the types of the matches not being
>>> subtypes of the matched object? Between that and warning on matching inner
>>> case classes I think that would catch most of the use cases adequately.
>>
>> This is my initial reaction, too, but more broadly.  How important is it
>> to support custom equality methods for case class hierarchies?
>
> I think it's pretty important. Case classes are basically used for creating
> custom interesting data structures, and it can be unnecessarily difficult to
(Continue reading)

David MacIver | 1 Mar 2009 14:10
Picon

Re: Equality and case objects

On Sun, Mar 1, 2009 at 9:43 AM, martin odersky <martin.odersky@...> wrote:
> On Sat, Feb 28, 2009 at 12:15 AM, David MacIver
<david.maciver@...> wrote:
>> On Fri, Feb 27, 2009 at 11:11 PM, Lex Spoon <lex@...> wrote:
>>>
>>> On Feb 28, 2009, at 12:23 AM, David MacIver wrote:
>>>>
>>>> So the match expression would be translated to:
>>>>
>>>>  x match {
>>>>    case (_: C) => ...
>>>>    case (_: object O) => ...
>>>>    case y if (y == this.V) => ...
>>>>  }
>>>>
>>>> What's your opinion on this?
>>>>
>>>> I agree that the errors caused by this case are somewhat problematic, but
>>>> I'm not sure they occur commonly enough for it to be worth the spec
>>>> complication, particularly if (as suggested above) matching on inner objects
>>>> of a class becomes a warning. I'm also a little concerned that it's not
>>>> caught statically. If x is known to come from a different instance of Outer,
>>>> why is this not being rejected as the types of the matches not being
>>>> subtypes of the matched object? Between that and warning on matching inner
>>>> case classes I think that would catch most of the use cases adequately.
>>>
>>> This is my initial reaction, too, but more broadly.  How important is it
>>> to support custom equality methods for case class hierarchies?
>>
>> I think it's pretty important. Case classes are basically used for creating
(Continue reading)

martin odersky | 1 Mar 2009 14:15
Picon
Picon
Favicon

Re: Equality and case objects

Hi David,

That's fine. Thanks for doing this in the first place! I completely
understand that there are constraints how much time you can put into
this when.

Cheers

 -- Martin

On Sun, Mar 1, 2009 at 2:10 PM, David MacIver
<david.maciver@...> wrote:
> On Sun, Mar 1, 2009 at 9:43 AM, martin odersky <martin.odersky@...> wrote:
>> On Sat, Feb 28, 2009 at 12:15 AM, David MacIver
<david.maciver@...> wrote:
>>> On Fri, Feb 27, 2009 at 11:11 PM, Lex Spoon <lex@...> wrote:
>>>>
>>>> On Feb 28, 2009, at 12:23 AM, David MacIver wrote:
>>>>>
>>>>> So the match expression would be translated to:
>>>>>
>>>>>  x match {
>>>>>    case (_: C) => ...
>>>>>    case (_: object O) => ...
>>>>>    case y if (y == this.V) => ...
>>>>>  }
>>>>>
>>>>> What's your opinion on this?
>>>>>
>>>>> I agree that the errors caused by this case are somewhat problematic, but
(Continue reading)

David MacIver | 1 Mar 2009 16:48
Picon

Re: Equality and case objects

Thanks. :-)

Back on the previous subject, what should this code do?

object Test {

  def foo(x : Any) : Any = {
    case class Foo();
    println(x match {
      case Foo() => true
      case _ => false;
    })
    new Foo;
  }

  def main(args : Array[String]){
    foo(foo(new AnyRef))
  }
}

The two Foos come from different invocations of the method (which are
morally equivalent to different instances of an enclosing class in my
opinion), but they still match as eachother. This seems wrong, but I'm
not sure what to suggest as an alternative.

On Sun, Mar 1, 2009 at 1:15 PM, martin odersky <martin.odersky@...> wrote:
> Hi David,
>
> That's fine. Thanks for doing this in the first place! I completely
> understand that there are constraints how much time you can put into
(Continue reading)

David MacIver | 1 Mar 2009 17:13
Picon

Re: Equality and case objects

On Sun, Mar 1, 2009 at 3:48 PM, David MacIver
<david.maciver@...> wrote:
> Thanks. :-)
>
> Back on the previous subject, what should this code do?
>
> object Test {
>
>  def foo(x : Any) : Any = {
>    case class Foo();
>    println(x match {
>      case Foo() => true
>      case _ => false;
>    })
>    new Foo;
>  }
>
>  def main(args : Array[String]){
>    foo(foo(new AnyRef))
>  }
> }
>
> The two Foos come from different invocations of the method (which are
> morally equivalent to different instances of an enclosing class in my
> opinion), but they still match as eachother. This seems wrong, but I'm
> not sure what to suggest as an alternative.

Paul has pointed out a good solution: Simply create a "local scope"
object for the call and treat all classes defined within the scope to
be inner classes of that object.
(Continue reading)

Paul Phillips | 2 Mar 2009 18:12

expanded names

Symbols has machinery for providing the expanded name of a setter:

    final def setter(base: Symbol): Symbol = setter(base, false)
    final def setter(base: Symbol, hasExpandedName: Boolean): Symbol = {
      [...]
      if (hasExpandedName) sname = base.expandedSetterName(sname)

However there is no similar machinery for getters:

    final def getter(base: Symbol): Symbol = {

Is this because getters should not finish up with expanded names, or is 
it necessary but missing? I ask because of this bug:

  https://lampsvn.epfl.ch/trac/scala/ticket/1722

The broken classfile is apparently a result of disagreement as to the 
name of the accessor for private object P - is it C$$P() or P()?

  public abstract C$P$ C$$P();  // if P is private - broken classfile
  public abstract C$P$ P();     // if P is public - works

--

-- 
Paul Phillips      | Every election is a sort of advance auction sale
Vivid              | of stolen goods. 
Empiricist         |     -- H. L. Mencken
i'll ship a pulp   |----------* http://www.improving.org/paulp/ *----------

Lex Spoon | 3 Mar 2009 16:38

Re: Equality and case objects

On Feb 27, 2009, at 6:59 AM, martin odersky wrote:
> Specifically, the unqualified type name $t$ where $t$ is bound in some
> class, object, or package $C$ is taken as a shorthand for C.this.type
> # t, except if the type $t$ occurs as a part
> of a typed pattern (\sref{sec:typed-patterns}) and C is an inner
> class. In the latter case, $t$ is taken as a shorthand for just C # t.

Of course, that would be a second irregularity in the language that is  
added for this feature.

I'm also not sure the current proposal suffices for the goal.  Here's  
a new thorny case:  suppose someone defines two case objects, Zero and  
NegativeZero, and defines them to be == but not eq.  Some poor user  
then walks into this trap:

   NegativeZero match {
     case Zero => "not reached"
     case _ => "safe to divide... except not really"
   }

I'm also worried that there might be other instances than case objects  
where the definition of equals might accidentally get into an infinite  
loop.  I can't come up with one off-hand, however.

The overall goal seems to be to have a low-level pattern match used to  
define the meaning of a high-level pattern match.  That is, a  
programmer wants to define how pattern matching should work on the  
case class they are defining, and they want to use pattern matching to  
do it.  Is there perhaps a way to come up with a syntax that means  
don't even try to use ==  ?  That way might be more explicit and  
(Continue reading)

Lex Spoon | 3 Mar 2009 16:44

Re: type matching in for comprehensions

On Feb 27, 2009, at 2:52 PM, martin odersky wrote:
> My initial reaction to the for comprehension issue was essentally
> similar to #140, and was caused by the old style for syntax, whic is
> now abandoned. Essentially, I was worrried that in
>
> for (val x: String <- e1; val y: String = e2)
>
> the two annotations of ": String" would have different meanings. The
> new for syntax removes this concern to some degree, as

Oh, right, of course.   -Lex

martin odersky | 3 Mar 2009 16:54
Picon
Picon
Favicon

Re: Equality and case objects

On Tue, Mar 3, 2009 at 4:38 PM, Lex Spoon <lex@...> wrote:
> On Feb 27, 2009, at 6:59 AM, martin odersky wrote:
>>
>> Specifically, the unqualified type name $t$ where $t$ is bound in some
>> class, object, or package $C$ is taken as a shorthand for C.this.type
>> # t, except if the type $t$ occurs as a part
>> of a typed pattern (\sref{sec:typed-patterns}) and C is an inner
>> class. In the latter case, $t$ is taken as a shorthand for just C # t.
>
> Of course, that would be a second irregularity in the language that is added
> for this feature.

I think the feature is already retracted. We'll stick to the current
meaning of pattern matching and adapt asInstanceOf.

>
> I'm also not sure the current proposal suffices for the goal.  Here's a new
> thorny case:  suppose someone defines two case objects, Zero and
> NegativeZero, and defines them to be == but not eq.  Some poor user then
> walks into this trap:
>
>  NegativeZero match {
>    case Zero => "not reached"
>    case _ => "safe to divide... except not really"
>  }
>
> I'm also worried that there might be other instances than case objects where
> the definition of equals might accidentally get into an infinite loop.  I
> can't come up with one off-hand, however.
>
(Continue reading)

David MacIver | 3 Mar 2009 17:08
Picon

Re: Equality and case objects

I'm a little confused as to the current state of proposals and who is
agreeing with which parts. Let's see if I have this right.  As I
understand it there are two orthogonal questions and suggestions under
consideration:

Q) What happens when pattern matching on inner classes?
A)

Current suggestion is that we adapt isInstanceOf so that it checks prefixes.

i.e. given

class Foo{
   class Bar;

   def stuff(that : Any) = that.isInstanceOf[Bar];
}

val x = new Foo;
val y = new Foo;

x.stuff(new y.Bar) == false;
x.stuff(new x.Bar) == true;

Pattern matching would inherit this behaviour automatically.

Q) What happens to pattern matching on case objects when a custom
equality method is defined?
A)

(Continue reading)


Gmane