Hi - > Of course if we want to define intuitive as "do it like Java", we make > def an alias for var, take its semantics and give up on Flow typing in > general.
Nobody wants to give up flow typing. > If we do not give up on flow typing, then I would like to > know why the assignment should not be legal. And if it is legal in the > if-branch, then why not in the Closure block? All assignments should be legal, and assignment in Closure block as well. Let me annotate the last example with types: class A {} class B extends A{ def b() {}} class C extends A{} A x // inferred to A because LUB(B,C) = A x = new B() // typeOf(x) as this point is B due to flow typing if (true) { x = new C() // typeOf(x) as this point is C due to flow typing } // typeOf(x) as this point is A due to flow typing merging branches where typeOf(x) is B and C A z // inferred to A because LUB(A) = A z = x // typeOf(z) as this point is A z.b() // STC error, no method b in A — Daniil Ovchinnikov JetBrains > On 4 Jun 2020, at 21:47, Jochen Theodorou <blackd...@gmx.org> wrote: > > On 04.06.20 18:55, Milles, Eric (TR Tech, Content & Ops) wrote: >> I am suggesting that when a closure is encountered, it is treated like an >> optional branch of the code. So assignments within alter the inferred type >> the same way an assignment within an if with no else would. > > sure I am for that, but I am not sure we are doing those right either ;) > >> I am not looking to examine the code flow and distinguish between closure >> executed immediately and closure that is executed asynchronously or later or >> not at all. > > me neither > > [...] >> If you are talking about using a union type, > > did not want to really use that word, because I think people understand > different things about it, but basically yes. Let me call it Least Upper > Bounds Union Type (LUBU) > >> I don't think that is the safe way to go. Static compilation is enforcing a >> typecast to the inferred type and this is a runtime error for 9344. > > If you say that then > >> class A{} >> class B{} >> >> def a = new A() >> a = new B() > > must fail, because the inferred type for a is A, so I cannot assign B to > it. That is quite far away from the initial idea. Of course you are more > referring to > >> class A{} >> class B{} >> class C{} >> >> def a = new A() >> if (b) { >> a = new B() >> } >> a = new C() > > but again, each of these assignments are legal in my opinion. The real > question should be if in > >> class A {} >> class B extends A{ def b() {}} >> class C extends A{} >> >> def x = new B() >> if (true) { x = new C() } >> def z = x >> z.b() > > The call z.b() is legal. And my answer is here with LUBU yes, with LUB, > as we have defined it probably no. But I find the later not intuitive. > > Of course if we want to define intuitive as "do it like Java", we make > def an alias for var, take its semantics and give up on Flow typing in > general. Then my two examples here should both fail compilation on the > reassignment. If we do not give up on flow typing, then I would like to > know why the assignment should not be legal. And if it is legal in the > if-branch, then why not in the Closure block? > > > bye Jochen