Closed som-snytt closed 9 years ago
@som-snytt: Thanks! I take it this is intended as a puzzler suggestion?
I'm getting this, which I guess is what you're referring to in the SO thread?
scala> val vs = List(Some(42),None,Some(17))
vs: List[Option[Int]] = List(Some(42), None, Some(17))
scala> vs flatMap (x => x)
res0: List[Int] = List(42, 17)
scala> vs flatMap identity
<console>:9: error: type mismatch;
found : Option[Int] => Option[Int]
required: Option[Int] => scala.collection.GenTraversableOnce[?]
vs flatMap identity
^
Yes, I was too lazy to check if you already had a related puzzler, which you probably do, since mixing Option and collections comes up often. I thought an issue was a light-weight way of recording the idea for a future appendix or outtake reel. Or suggesting it if it turns into a suggestion.
I was too lazy to check if you already had a related puzzler, which you probably do
Well, not really, I'd say...it depends what we regard as the "puzzling" bit here. As far as I can make out, vs flatMap (x => x)
only actually works because of the implicit option2Iterable
, which allows the input x
to be treated as an iterable, as required by the signature of flatMap
:
@SerialVersionUID(value = 0) final <synthetic> class anonfun$1 extends scala.r
untime.AbstractFunction1 with Serializable {
final def apply(x: Option): Iterable = scala.this.Option.option2Iterable(x);
That obviously doesn't work for Predef.identity
.
Was the insertion of the implicit the "puzzling piece" you had in mind here?
Backing up, did you not expect x => x
and identity
to be interchangeable?
Maybe that's just sloppy thinking, but it highlights how expected type makes all the diff.
Backing up, did you not expect x => x and identity to be interchangeable?
I would if the argument passed was indeed x => x
. But what we're actually passing - probably without realizing it immediately - is x => option2iterable(x)
, which I wouldn't expect to be interchangeable with identity
, no.
The "puzzle" here is then that the compiler can also use implicits within a function argument, I guess...or am I missing a comment you're trying to make here..?
OK, in that case, you're a better man than me. (Please don't test me on the prepositional use of "than".) I'd expect x => x
, identity
and identity(_)
to do the same thing with the given expected type.
Is it possible that after years at this game, you have lost all empathy with the puzzled people?
Maybe you need a long journey into the Himalayas to restore your sense of the essential puzzlement underlying all human endeavor.
Or if you prefer, endeavour.
Alternatively, I must realize that everything I do is really stupid. But I thought I knew that already.
Wait, have I surpassed Socrates in realizing that I not only know that I know nothing, but I also know that I am entirely mistaken in my supposed knowledge that my knowledge is null and void?
I'd expect x => x, identity and identity(_) to do the same thing with the given expected type.
I would too. I'm not expressing myself clearly.
What I'm trying to say is that what you're passing to flatMap
isn't actually x => x
, because that wouldn't type check. As far as I can see, flatMap
in this case expects something like Option[Int] => GenTraversableOnce[B]
, and if x
is an Option[Int]
, then x => x
is Option[Int] => Option[Int]
, so doesn't match the required type. So I wouldn't expect identity
or identity(_)
to work here either, since their type also doesn't match.
As far as I can make out, the only reason vs flatMap (x => x)
actually compiles is because the compiler can resolve the mismatch between the type of x => x
, i.e. Option[Int] => Option[Int]
, and the required type Option[Int] => GenTraversableOnce[B]
is by applying the implicit conversion Option.option2iterable
to the RHS of the function. I.e. the compiler implicitly converts the return value to option2iterable(x)
, which means that the function overall now has a type of Option[Int] => Iterable[Int]
, so type checks and can be passed to flatMap
.
I guess it's worth asking why the compiler can't also apply that kind of implicit transformation to the function as a whole (i.e. "if f: Option[Int] => Option[Int]
is given and Option[Int] => GenTraversableOnce[B]
is expected and imp: Option[A] => Iterable[A]
is available as an implicit conversion, then try the function imp ∘ f: Option[Int] => Iterable[Int]
"), but would you say it's surprising that the compiler doesn't do that?
I hope that makes a bit more sense...and I'll gladly take you up on that Himalayan break ;-)
Going over this again, I would say this boils down to whether we feel that
val l: Iterable[Int] = Option(10)
compiling successfully is a puzzler or not.
@nermin: your thoughts..?
@nermin: Ping..?
@nermin: Ping..?
This one "got" Nermin, so I think we may have a puzzler here after all ;-)
@som-snytt: Discussion to be continued over at #133..? ;-)
http://stackoverflow.com/a/29217414/1296806