tag:blogger.com,1999:blog-178174920347765771.post4829031039331534097..comments2023-10-30T09:20:21.742-07:00Comments on One Div Zero: Java Has Type Inference and Refinement Types (But With Strange Restrictions)James Iryhttp://www.blogger.com/profile/02835376424060382389noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-178174920347765771.post-2463509088880961382011-08-29T02:57:42.321-07:002011-08-29T02:57:42.321-07:00As others have pointed out, this is not at all typ...As others have pointed out, this is not at all type refinement. It's literally defining a class whose name is never given. This is easy to see if you know the Java bytecodes at all.<br /><br />In the example given, it's equivalent to <br /><br /> class Test$1 { … }; ... new Test$1().<br /><br />Any closure variables are sugared into constructor variables.If you look at the internals of Sarah A180noreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-74142558234652745332010-03-09T07:32:58.371-08:002010-03-09T07:32:58.371-08:00public class Test {
public static void main(String...public class Test {<br />public static void main(String[] args) {<br />int i = times10((new Object() {<br /> public int bar() {<br /> System.out.println("bar!");<br />return 10;<br /> }<br />}).bar());<br /> <br /> <br />System.out.println("i = " + i);<br />}<br /> <br />private static final int times10(int n) {<br /> return n * 10;<br />}<br />}<br /><br /><br />This Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-42907676541283588852009-07-11T23:50:14.835-07:002009-07-11T23:50:14.835-07:00Sorry, I forgot the example to prove the point tha...Sorry, I forgot the example to prove the point that one is *not* loosing the (refined) type when passing on the reference in a method call, if a local class with an interface (see my first comment) is used:<br /> <br />public void method(Interface i)<br />{<br /> i.foo();<br />}<br /><br />...<br /><br />method(new Interface() { public void foo() { out.println("foo"); } }); <br wolfynoreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-10276308409567711472009-07-11T23:26:39.870-07:002009-07-11T23:26:39.870-07:00Note: The <pre>-tag should really be support...<b>Note:</b> The <pre>-tag should really be supported in comments, it's quite cumbersome to do indentation with &nbsp;....<br /><br /><br /><i>"But if you want to do anything interesting with the (new Object {public void bar() {...}};) object, like assign it to a variable, return it from a method, or apply it as an argument to a method then Java has a problem. It has no way to wolfynoreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-23525124740507479252009-07-10T07:01:56.253-07:002009-07-10T07:01:56.253-07:00compiler 'knows' the type but might need t...compiler 'knows' the type but might need to do a bit of work to find it out in some situations.<br /><br />ie: <br /><br />var x;<br /><br />if (test()) {<br /> x = foo();<br />} else {<br /> x = bar();<br />}<br /><br />x.z();<br /><br />what is the type of x? removing type inference can save you a bit work in the compiler :)benhttps://www.blogger.com/profile/02909457195189273974noreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-88880926885213199522009-07-08T09:26:28.973-07:002009-07-08T09:26:28.973-07:00Brian, I'm not clear on what you're talkin...Brian, I'm not clear on what you're talking about. Type inference is entirely a static concept that can be taken care of by the compiler and needs no support from the runtime. By the time Scala code is executed by the JVM, the bytecode looks pretty much like what you'd expect from Java.<br /><br />Now, if you're talking about refinement types then you'd be right. Scala James Iryhttps://www.blogger.com/profile/02835376424060382389noreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-88262949709386119832009-07-08T09:16:19.371-07:002009-07-08T09:16:19.371-07:00The issue with all of this isn't Java or Scala...The issue with all of this isn't Java or Scala, but the JVM. The JVM doesn't infer types or methods. I haven't looked at Scala, but I'm guessing it suffers from a dynamic method lookup and incurs a really large amount of overhead try to figure out how to pass objects around. <br /><br />This could be pre-compiled with anonymous interfaces or classes, but that's still overhead Brian Pontarellihttps://www.blogger.com/profile/10399440205203203938noreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-88378070781412807872009-07-06T16:06:44.917-07:002009-07-06T16:06:44.917-07:00Type inference is unacceptable except if it generi...Type inference is unacceptable except if it generics inference, and even then only on the right side of the expression.<br /><br />Structural types are ace, but only at api borders.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-49028652522201924772009-05-18T12:09:00.000-07:002009-05-18T12:09:00.000-07:00Sorry for the late comment, but I just discovered ...Sorry for the late comment, but I just discovered your post and thought I'd clarify a bit.<br /><br />The difference between type <I>inference</I> and mere type <I>checking</I> as a degenerate case is the following: as long as types can be derived in a (roughly) bottom-up manner, without the necessity to guess, it is simply checking. If that is not sufficient then you enter the realm of inferenceAndreas Rossbergnoreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-90899562475838225512009-04-26T23:07:00.000-07:002009-04-26T23:07:00.000-07:00A nice little trick in Java is to create factory m...A nice little trick in Java is to create factory methods for maps, lists etc. that do type inferencing on the right hand side of the expression, e.g.:<br /><br />Map<String, Map<Int, Long>> m = MapUtil.makeMap();<br /><br />...<br /><br />public static <K,V> Map<K,V> makeMap() {<br />return new HashMap<K,V>();<br />}<br /><br />Can save quite a bit of typing if you fredrikhttps://www.blogger.com/profile/08833756769211183446noreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-6986756631248044952009-04-25T12:15:00.000-07:002009-04-25T12:15:00.000-07:00@Bill,
I know most people think it's fundamentall...@Bill,<br /><br />I know most people think it's fundamentally different. But it's not. Unfortunately, Java has no syntactic distinction between up casts and down casts, so I'll go with Scala to illustrate. You argue that the difference is that expressions can only have one type while variables can have many. But that's not true. Expressions can be explicitly annotated with any compatible James Iryhttps://www.blogger.com/profile/02835376424060382389noreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-1274886803032874182009-04-25T11:14:00.000-07:002009-04-25T11:14:00.000-07:00Hi James,
I wouldn't call keeping track of th...Hi James,<br /><br />I wouldn't call keeping track of the type of an expression type "inference." But mainly, I see a difference between keeping track of an expression type and inferring the type of a variable, because a variable can usually have any of several types. In Java I would usually do:<br /><br />List<String> myList = new ArrayList<String>();<br /><br />I did Bill Vennersnoreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-75409843086144565632009-04-25T06:03:00.000-07:002009-04-25T06:03:00.000-07:00In:
Foo f = new Foo();
I'm pretty sure this res...In:<br /><br />Foo f = new Foo();<br /><br /><br />I'm pretty sure this restriction was *NOT* that the compiler couldn't otherwise figure out the type, but to be "explicitly explicit"; to MAKE the writer specify the type in order to minimize "mistakes". 'Say what you mean, mean what you say', and all that.<br /><br />Remember Java was written as a language for average programmers. A lot of Michael Campbellnoreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-90672199386130404002009-04-25T00:49:00.000-07:002009-04-25T00:49:00.000-07:00Saying that Java has refinement types is a stretch...Saying that Java has refinement types is a stretch (unless you call normal inheritance a refinement). In your example a new class is created which extends Object and adds a bar method. The type of the expression is simply this class, so the compiler doesn't have to have a concept of "Object + bar method".<br /><br />In Scala this is different, the expression really has the type "Object + bar Jesper Nordenberghttps://www.blogger.com/profile/07589508061874776093noreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-61331258760341089892009-04-24T19:25:00.000-07:002009-04-24T19:25:00.000-07:00Reinier,
Good point on composite types.
Your poi...Reinier,<br /><br />Good point on composite types.<br /><br />Your point on syntax for types might be valid in some language, but isn't in Scala. A refinement type looks like<br /><br />Type1 {def refinement : Type2}<br /><br />Which exactly mirrors how you construct instances of anonymous inner classes in Scala "new Type1 {def refinement : Type2}". In turn, that's not too different from James Iryhttps://www.blogger.com/profile/02835376424060382389noreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-24952213834093717382009-04-24T19:05:00.000-07:002009-04-24T19:05:00.000-07:00Java always infers the type of expressions, but ne...Java always infers the type of expressions, but never infers the type of variables, return types, or anything else. Seems perfectly consistent to me.<br /><br /><br />A few more instances of inconsistency between the typing of expressions and the typing of everything else:<br /><br />Composite Types. Expressions in java can be composite, for example:<br /><br />someBoolean ? new ArrayList() : newReinier Zwitserloothttp://zwitserloot.comnoreply@blogger.comtag:blogger.com,1999:blog-178174920347765771.post-10245789066579709732009-04-24T18:24:00.000-07:002009-04-24T18:24:00.000-07:00You didn't even mention generics! Yes, Java does ...You didn't even mention generics! Yes, Java does infer (or more correctly, *compute*) expression types as you said, but this is (as you said) a core part of any static type checker. However, that's not all Java can do in the area of type inference. By using generics in a very hairy way, it's actually possible to get a very crude form of type inference in vanilla Java. This comes out of the Daniel Spiewakhttps://www.blogger.com/profile/17323566514229790079noreply@blogger.com