{"action":"created","issue":{"url":"https://api.github.com/repos/ceylon/ceylon/issues/6189","repository_url":"https://api.github.com/repos/ceylon/ceylon","labels_url":"https://api.github.com/repos/ceylon/ceylon/issues/6189/labels{/name}","comments_url":"https://api.github.com/repos/ceylon/ceylon/issues/6189/comments","events_url":"https://api.github.com/repos/ceylon/ceylon/issues/6189/events","html_url":"https://github.com/ceylon/ceylon/issues/6189","id":147132481,"number":6189,"title":"implicit conversions for Java types","user":{"login":"gavinking","id":579974,"avatar_url":"https://avatars.githubusercontent.com/u/579974?v=3","gravatar_id":"","url":"https://api.github.com/users/gavinking","html_url":"https://github.com/gavinking","followers_url":"https://api.github.com/users/gavinking/followers","following_url":"https://api.github.com/users/gavinking/following{/other_user}","gists_url":"https://api.github.com/users/gavinking/gists{/gist_id}","starred_url":"https://api.github.com/users/gavinking/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gavinking/subscriptions","organizations_url":"https://api.github.com/users/gavinking/orgs","repos_url":"https://api.github.com/users/gavinking/repos","events_url":"https://api.github.com/users/gavinking/events{/privacy}","received_events_url":"https://api.github.com/users/gavinking/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ceylon/ceylon/labels/m-compiler-java","name":"m-compiler-java","color":"00aa00"},{"url":"https://api.github.com/repos/ceylon/ceylon/labels/m-typechecker","name":"m-typechecker","color":"00aa00"},{"url":"https://api.github.com/repos/ceylon/ceylon/labels/prio-high","name":"prio-high","color":"fbca04"},{"url":"https://api.github.com/repos/ceylon/ceylon/labels/s-request%20for%20feedback","name":"s-request for feedback","color":"eb6420"},{"url":"https://api.github.com/repos/ceylon/ceylon/labels/t-feature","name":"t-feature","color":"02e10c"}],"state":"open","locked":false,"assignee":{"login":"gavinking","id":579974,"avatar_url":"https://avatars.githubusercontent.com/u/579974?v=3","gravatar_id":"","url":"https://api.github.com/users/gavinking","html_url":"https://github.com/gavinking","followers_url":"https://api.github.com/users/gavinking/followers","following_url":"https://api.github.com/users/gavinking/following{/other_user}","gists_url":"https://api.github.com/users/gavinking/gists{/gist_id}","starred_url":"https://api.github.com/users/gavinking/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gavinking/subscriptions","organizations_url":"https://api.github.com/users/gavinking/orgs","repos_url":"https://api.github.com/users/gavinking/repos","events_url":"https://api.github.com/users/gavinking/events{/privacy}","received_events_url":"https://api.github.com/users/gavinking/received_events","type":"User","site_admin":false},"assignees":[{"login":"gavinking","id":579974,"avatar_url":"https://avatars.githubusercontent.com/u/579974?v=3","gravatar_id":"","url":"https://api.github.com/users/gavinking","html_url":"https://github.com/gavinking","followers_url":"https://api.github.com/users/gavinking/followers","following_url":"https://api.github.com/users/gavinking/following{/other_user}","gists_url":"https://api.github.com/users/gavinking/gists{/gist_id}","starred_url":"https://api.github.com/users/gavinking/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gavinking/subscriptions","organizations_url":"https://api.github.com/users/gavinking/orgs","repos_url":"https://api.github.com/users/gavinking/repos","events_url":"https://api.github.com/users/gavinking/events{/privacy}","received_events_url":"https://api.github.com/users/gavinking/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/ceylon/ceylon/milestones/5","html_url":"https://github.com/ceylon/ceylon/milestones/1.3","labels_url":"https://api.github.com/repos/ceylon/ceylon/milestones/5/labels","id":1411356,"number":5,"title":"1.3","description":null,"creator":{"login":"CeylonMigrationBot","id":6583436,"avatar_url":"https://avatars.githubusercontent.com/u/6583436?v=3","gravatar_id":"","url":"https://api.github.com/users/CeylonMigrationBot","html_url":"https://github.com/CeylonMigrationBot","followers_url":"https://api.github.com/users/CeylonMigrationBot/followers","following_url":"https://api.github.com/users/CeylonMigrationBot/following{/other_user}","gists_url":"https://api.github.com/users/CeylonMigrationBot/gists{/gist_id}","starred_url":"https://api.github.com/users/CeylonMigrationBot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CeylonMigrationBot/subscriptions","organizations_url":"https://api.github.com/users/CeylonMigrationBot/orgs","repos_url":"https://api.github.com/users/CeylonMigrationBot/repos","events_url":"https://api.github.com/users/CeylonMigrationBot/events{/privacy}","received_events_url":"https://api.github.com/users/CeylonMigrationBot/received_events","type":"User","site_admin":false},"open_issues":450,"closed_issues":38,"state":"open","created_at":"2015-11-14T01:13:20Z","updated_at":"2016-07-01T07:02:00Z","due_on":null,"closed_at":null},"comments":24,"created_at":"2016-04-09T14:25:23Z","updated_at":"2016-07-04T15:37:19Z","closed_at":null,"body":"I have long opposed defining any implicit type conversions in the language, because of the ambiguities and confusing behavior that can result. For example, consider what happens if we define an implicit type conversion from Java `List` to Ceylon `MutableList`, and write:\r\n\r\n```ceylon\r\njavaObject.someList.size\r\n```\r\n\r\nThe programmer might expect `size` to refer to the attribute `MutableList.size` of type `Integer`, but in fact it actually refers to the *method* `size()` of `List`. Even worse ambiguities arise if implicit conversions are transitive.\r\n\r\nAs we've seen, however, confusion and inconvenience can also arise from _not_ having any sort of implicit type conversions, for example, when Java's `String` type leaks into Ceylon code, or when strings aren't assignable to Java parameters that accept `CharSequence`.\r\n\r\nYesterday, I realized that there is an approach to implicit conversions that *doesn't* lead to the ambiguities I've always been bothered by. Traditional implicit type conversions are only applied when the original type is not assignable to the declared type of something. They are thus, in some sense, \"lazy\", and the original type always has the chance to \"leak out\".\r\n\r\nBut for the specific case of inter-language interop, that's actually _not_ what we need. What if we defined some type conversions that were *always* applied, as soon as possible? That is, as soon as we have an expression of type `java.lang.String`, the conversion to `ceylon.language::String` is *immediately* applied, and no operations of `java.lang.String` are *ever* visible. Then, essentially, no Ceylon code would ever be able to interact with the type `java.lang.String` except to the extent that it can occur as a type argument in a generic type.\r\n\r\nLikewise, no Ceylon code would ever interact directly with a `java.util.function.Predicate<T>`, since any expression of that type would immediately be converted to `Boolean(T)`.\r\n\r\nIt seems to me that this solution is perfect for protecting Ceylon code from Java types, including `String`, primitive wrapper classes, `@FunctionalInterface`s, `Iterable`, `List`, `Set`, `Map`, and perhaps even primitive arrays (which could be converted to `Array`). I think and hope it would also work for the special transformation `CharSequence <-> List<Character>`, which I admit is a slightly tricky case.\r\n\r\nSo the next problem that arises is how to pass a value to a Java parameter declared with one of these \"hidden\" types. Since we can no longer form an expression of type `java.lang.Integer`, we can't call any Java method that accepts a `java.lang.Integer`.\r\n\r\nWell, the solution is quite similar: the typechecker, when it comes to assign a type to parameter of one of the \"hidden\" types, actually applies the same conversions, and arrives at a type to which we *can* assign!\r\n\r\nObviously, this implies a mathematical property of the transformation, namely that it is a _bijection_. Fortunately, I _think_ we can shoehorn our transformations into a bijective function. However, I still need to verify that.\r\n\r\nFor this to really work correctly and transparently, there's one big caveat: the set of transformations and reverse transformations would need to be applied every time we assign a supertype like `Object` or `Number` to or from Java! Actually `CharSequence` also counts as one of these \"supertypes\", so it's not *that* special. As is `Iterable` I guess.\r\n\r\nAnyway, I think this is a very strong way forward, and just requires thinking through the details. I believe it can be made to work.\r\n\r\nWDYT?"},"comment":{"url":"https://api.github.com/repos/ceylon/ceylon/issues/comments/230315745","html_url":"https://github.com/ceylon/ceylon/issues/6189#issuecomment-230315745","issue_url":"https://api.github.com/repos/ceylon/ceylon/issues/6189","id":230315745,"user":{"login":"gavinking","id":579974,"avatar_url":"https://avatars.githubusercontent.com/u/579974?v=3","gravatar_id":"","url":"https://api.github.com/users/gavinking","html_url":"https://github.com/gavinking","followers_url":"https://api.github.com/users/gavinking/followers","following_url":"https://api.github.com/users/gavinking/following{/other_user}","gists_url":"https://api.github.com/users/gavinking/gists{/gist_id}","starred_url":"https://api.github.com/users/gavinking/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gavinking/subscriptions","organizations_url":"https://api.github.com/users/gavinking/orgs","repos_url":"https://api.github.com/users/gavinking/repos","events_url":"https://api.github.com/users/gavinking/events{/privacy}","received_events_url":"https://api.github.com/users/gavinking/received_events","type":"User","site_admin":false},"created_at":"2016-07-04T15:37:19Z","updated_at":"2016-07-04T15:37:19Z","body":"@FroMage you can still explicitly instantiate a `FooFunction` if you need, and you can still explicitly assign a `FooFunction` to a `Callable` type by just writing `FooFunction.theMethod`."}}
{"actor":{"display_login":"gavinking"}}