by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 19:57
    smarter commented #9535
  • 19:54
    nicolasstucki commented #9535
  • 19:05
    smarter assigned #9523
  • 19:05
    smarter review_requested #9523
  • 19:05
    smarter ready_for_review #9523
  • 19:02
    smarter commented #9535
  • 18:54
    nicolasstucki commented #9535
  • 18:50
    smarter commented #9535
  • 18:26
    nicolasstucki assigned #9535
  • 18:26
    nicolasstucki unassigned #9535
  • 18:26
    nicolasstucki unassigned #9535
  • 18:26
    nicolasstucki ready_for_review #9535
  • 18:10
    smarter commented #9523
  • 18:08
    smarter synchronize #9523
  • 17:32
    smarter synchronize #9536
  • 17:27
    smarter review_requested #9536
  • 17:27
    smarter assigned #9536
  • 17:27
    smarter opened #9536
  • 17:24
    smarter synchronize #9523
  • 16:53
    nicolasstucki synchronize #9535
Nicolas Rinaudo
@nrinaudo
Ah. scala.reflect.Selectable.reflectiveSelectable
Nicolas Rinaudo
@nrinaudo
I'm probably missing something very obvious, but I don't understand by what mechanism the reflection-based Selectable instance manages to fail at compile time...
Nicolas Rinaudo
@nrinaudo
ok, now that I think I understand all this a bit better, I realise my questions make no sense. Apologies :/
Nicolas Rinaudo
@nrinaudo

Gitven the following code:

object ExtractSome {
  def unapply[A](s: Some[A]): Option[A] = s
}

def unwrap(oi: Option[Int]): Int = oi match {
  case ExtractSome(i) => i
}

I get the following warning:

[warn] -- [E029] Pattern Match Exhaustivity Warning: /home/nicolas/dev/nrinaudo/test/dotty/src/main/scala/PattMatch.scala:6:37 
[warn] 6 |  def unwrap(oi: Option[Int]): Int = oi match {
[warn]   |                                     ^^
[warn]   |                             match may not be exhaustive.
[warn]   |                             
[warn]   |                             It would fail on pattern case: _: Option[Int]
it's an improvement on Scala 2 who'd not warn at all, but the pattern case is weird - it doesn't fail on any Option[Int], it specifically fails on None
if I change the return type of ExtractSome.unapply to Some[A], I do get the warning I'd expect:
[warn] -- [E029] Pattern Match Exhaustivity Warning: /home/nicolas/dev/nrinaudo/test/dotty/src/main/scala/PattMatch.scala:6:37 
[warn] 6 |  def unwrap(oi: Option[Int]): Int = oi match {
[warn]   |                                     ^^
[warn]   |                                     match may not be exhaustive.
[warn]   |                                     
[warn]   |                                     It would fail on pattern case: None
is that normal or expected behaviour?
Srepfler Srdan
@schrepfler
peeps, JavaScript these days has some pretty nice syntactic sugar for destructuring of objects and arrays, what if we try to introduce their syntax in scala 3?
Jamie Thompson
@bishabosha
@schrepfler would that be for dynamic interfaces like json decoding?
Guillaume Martres
@smarter
@nrinaudo Yes. How can the compiler know that your custom unapply will not fail on Some if it returns an Option ?
Nicolas Rinaudo
@nrinaudo
understood. Thank you!
Nicolas Rinaudo
@nrinaudo
mmm...
actually, how does it know that the custom unapply will not fail on Some, even if it returns a Some?
Guillaume Martres
@smarter
Because it takes Some as input
this would be less confusing if you were matching on something other than Option :)
Nicolas Rinaudo
@nrinaudo
it's a bit confusing, yes :)
let me try and play with it a bit more
Nicolas Rinaudo
@nrinaudo

If I change my unapply to:

    def unapply[A](o: Option[A]): Some[A] = o match {
      case s: Some[A] => s
      case _ => sys.error("fail")
    }

I don't get a warning. I understand that as far as the types are concerned, this makes sense, but how does the compiler know without special handling of Some?

Guillaume Martres
@smarter
this is too confusing to explain when you're matching on an Option
Nicolas Rinaudo
@nrinaudo
OK. Is it alright to still use an Option or a Some as the return type though?
Guillaume Martres
@smarter
here's a better example:
sealed trait Foo[A]
case class One[A](a: A) extends Foo[A]
case class Two[A](a: A) extends Foo[A]

object ExtractOne {
  def unapply[A](s: One[A]): Some[A] = Some(s.a)
}

def unwrap(fi: Foo[Int]): Int = fi match {
  case ExtractOne(i) => i
}
This will complain about a missing case for Two
Nicolas Rinaudo
@nrinaudo
It does indeed
Guillaume Martres
@smarter
Because the unapply cannot fail, since it returns a Some it will always be used if the input has type One
Nicolas Rinaudo
@nrinaudo
isn't that making assumptions about unapply's body, such as the fact that it doesn't use reflection?
Guillaume Martres
@smarter
I'm not sure what you mean by that
Nicolas Rinaudo
@nrinaudo
probably nothing intelligent. Let's ignore it.
Guillaume Martres
@smarter
The unapply is a method that takes a One and returns a Some
Nicolas Rinaudo
@nrinaudo
but then - is it the Some type, or the shape of the type?
Guillaume Martres
@smarter
we know that an unapply succeeds if it returns a Some
if we know statically that it returns a Some then we know statically that it cannot fail
Nicolas Rinaudo
@nrinaudo

we know that an unapply succeeds if it returns a Some

This is what I'm struggling with. I thought dotty's pattern matching didn't rely on Option

Guillaume Martres
@smarter
Some is special-cased exactly for this reason.
Nicolas Rinaudo
@nrinaudo
OK, that was exactly what I was struggling with
Option-less pattern matching
Nicolas Rinaudo
@nrinaudo
this lead me to believe that pattern matching didn't rely on Option, when it meant it can work without Option
Guillaume Martres
@smarter
yes
Nicolas Rinaudo
@nrinaudo
ok, so that clarifies everything. I was stuck by the fact that it magically worked without special casing Some
thank you for your time and explanations
Guillaume Martres
@smarter
:)
it's true that http://dotty.epfl.ch/docs/reference/changed-features/pattern-matching.html is missing documentation on the concept of an irrefutable apply
Nicolas Rinaudo
@nrinaudo
I would actually really like to know more about that, and how the behaviour changed since Scala 2. It clearly changed, and I'd love to know to what extent
Guillaume Martres
@smarter
Opened an issue: lampepfl/dotty#6490
Nicolas Rinaudo
@nrinaudo
the code you linked clarifies it quite a bit as well, thanks
I have another, entirely unrelated question. Is there a particular reason for enum types not to extend Serializable and, when all cases are products, Product?
Guillaume Martres
@smarter
no particular reason
Nicolas Rinaudo
@nrinaudo
is this something that could be considered?
scala> enum Foo {
     |   case Bar(i: Int)
     |   case Baz(b: Boolean)
     | }
     | 
     | List(new Foo.Bar(1), new Foo.Baz(true))
// defined class Foo
val res1: List[Foo & Product & Serializable] = List(Bar(1), Baz(true))
I was really hoping for the Product & Serializable wart to disappear :/