I agree that this use case doesn’t provide a compelling reason for a language change, since it is rare to need to recover self types. But would supporting these features really be harmful to the type system? I’ve thought of these proposals as
a sort of meta programming rather than a more fundamental type system change, but perhaps I’m missing something.
More generally, I think they would help make meta programming safer with improved clarity, which I think is very relevant for Ceylon for things like web and persistence frameworks.
Keeping with the Comparable them, an apples-to-apples, uh, comparison:
Current:
shared [Object*]
sortObjects([Object+]
objects) {
value
comparableType = comparableTypeFor(objects.collect(type));
// no discards, since we trust comparableTypeFor()
value
comparables =
`function
Iterable.narrow`.memberInvoke(
objects, [comparableType]);
value
result = `function
sort`.invoke([comparableType],
comparables);
assert (is [Object*]
result);
return result;
}
Proposed:
shared [Object*]
sortObjects([Object+]
objects) {
alias
T =
comparableTypeFor(objects.collect(type));
// safe since we trust comparableTypeFor()
assert (T
satisfies
Comparable<T>);
// safe with no discards, since we trust comparableTypeFor()
value
comparables = objects.narrow<T>();
return
sort(comparables);
}
I think the static type checking and code clarity in the second example is far superior.
For completeness, the implementation for `comparableTypeFor` that seems to work:
Type<Anything>
comparableTypeFor([Type<Anything>+]
types) {
value t =
types.fold<Type<Anything>?>(null)((a,b)
{
if (!exists
a) {
if (!b.subtypeOf(`Comparable<Nothing>`))
{
throw
Exception("oops,
``b`` does not satisfy Comparable");
}
return
b;
}
else {
// evidence of existence and prior checks ensure `apply<>(a)` is valid
if (!b.subtypeOf(`interface
Comparable`.apply<>(a))) {
throw
Exception("oops,
``b`` cannot be compared to
``a``");
}
return
a.union(b);
}
});
assert (exists
t);
return t;
}
John
Don't screw up your type system to satisfy this use case. This use case is exactly what gradual typing is designed for. Since you don't have gradual typing, then the first solution given is totally the correct one: you should just reflect on each
object to get the compare method for that object and then supply that method with the appropriate object. If you really want to check that the compare method has Comparable's contract, then in each iteration you should grab the dynamic type of the second object
and then check if the first object satisfies Comparable of that type.
I'm working from my phone for a while, so sorry if this is rudely terse!
On Friday, July 17, 2015, John Vasileff <
jo...@vasileff.com> wrote:
Yeah, I cheated a bit by saying “homogeneous sequence” :)
> On Jul 17, 2015, at 12:50 PM, Gavin King <gavin...@gmail.com> wrote:
>
> Not quite right, since the runtime type of objects.first is not
> necessarily a supertype of the runtime type of the other objects. You
> would need to iterate the objects and form a union of their types
> somehow. (That's possible in principle if we provided the right APIs.)
>
> On Fri, Jul 17, 2015 at 4:30 AM, John Vasileff <jo...@vasileff.com> wrote:
>> I just realized that this problem raises an interesting use case for a
>> couple proposed enhancements.
>>
>>
https://github.com/ceylon/ceylon-spec/issues/1359
>>
https://github.com/ceylon/ceylon-spec/issues/560
>>
>> The idea is that we would create a type alias for the unknown type of the
>> objects, check to see if the type is Comparable, and then perform operations
>> that require Comparables on instances of this type without using the
>> metamodel api:
>>
>> shared void printSorted(objects) {
>> "Must be a homogeneous sequence"
>> [Object+] objects;
>>
>> // Create a type reference for the element type of `objects`
>> alias T = type(objects.first);
>>
>> // Test to see if `T` really is `Comparable`
>> if (!T satisfies Comparable<T>) {
>> throw Exception("oops, we expected Comparables");
>> }
>> else {
>> // In this block, `T satisfies Comparable<T>`
>>
>> "A correctly type container of our Comparables (discarding non-Ts)"
>> {T*} ourComparables = objects.narrow<T>();
>>
>>
>>
>> // Sort (because we can!), and print
>> print(sort(ourComparables));
>> }
>> }
>>
>> John
>>
>> On Jul 16, 2015, at 4:04 PM, Dietmar Höhmann <d...@it-con.biz> wrote:
>>
>> Thanks John, your solution works perfectly.
>>
>> BUT only on JVM :-( on JS it throws:
>>
>> /home/dietmar/Software/eclipse/plugins/com.redhat.ceylon.dist.repo_1.1.0.v20141013-1416/repo/ceylon/language/1.1.0/ceylon.language-1.1.0.js:5498
>> if (a[i]!==undefined && !is$(a[i],val_t))throw
>> IncompatibleTypeException$meta$
>> ^
>> ceylon.language.meta.model::IncompatibleTypeException "Wrong type for
>> argument 0, expected ceylon.language::Integer got ceylon.language::Integer"
>>
>> This is most likely a bug in the language module.
>>
>> The background for all this is: I have a nice little script interpreter I'm
>> porting from C# to Ceylon. And I don't have any chance to predict the types
>> the script will later use. In general I'm absolutely with you: Make
>> applications as type safe as possible. But this is a special case. I guess I
>> need to put all the dynamic parts in a separate module that uses the meta
>> model on JVM and dynamic blocks on JS.
>>
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "ceylon-users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to
ceylon-users...@googlegroups.com.
>> To post to this group, send email to
ceylon...@googlegroups.com.
>> Visit this group at
http://groups.google.com/group/ceylon-users.
>> To view this discussion on the web visit
>>
https://groups.google.com/d/msgid/ceylon-users/1725155c-b37e-4693-8b44-8021ba37e148%40googlegroups.com.
>> For more options, visit
https://groups.google.com/d/optout.
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "ceylon-users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to
ceylon-users...@googlegroups.com.
>> To post to this group, send email to
ceylon...@googlegroups.com.
>> Visit this group at
http://groups.google.com/group/ceylon-users.
>> To view this discussion on the web visit
>>
https://groups.google.com/d/msgid/ceylon-users/B061CF78-A690-40BE-8B5C-0121C93494D9%40vasileff.com.
>>
>> For more options, visit
https://groups.google.com/d/optout.
>
>
>
> --
> Gavin King
>
ga...@ceylon-lang.org
> http://profiles.google.com/gavin.king
> http://ceylon-lang.org
> http://hibernate.org
> http://seamframework.org
>
> --
> You received this message because you are subscribed to the Google Groups "ceylon-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to
ceylon-users...@googlegroups.com.
> To post to this group, send email to
ceylon...@googlegroups.com.
> Visit this group at
http://groups.google.com/group/ceylon-users.
> To view this discussion on the web visit
https://groups.google.com/d/msgid/ceylon-users/CAP7PoCe2G0w7D%2Bwsd%3DVrewCjY%3Dntr9TiCwa3AoWOVFQ4mzcD9A%40mail.gmail.com.
> For more options, visit
https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "ceylon-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
ceylon-users...@googlegroups.com.
To post to this group, send email to
ceylon...@googlegroups.com.
Visit this group at
http://groups.google.com/group/ceylon-users.
To view this discussion on the web visit
https://groups.google.com/d/msgid/ceylon-users/50F57CBC-AC7C-49FB-97AF-388222942D2C%40vasileff.com.
For more options, visit
https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "ceylon-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
ceylon-users...@googlegroups.com.
To post to this group, send email to
ceylon...@googlegroups.com.
Visit this group at
http://groups.google.com/group/ceylon-users.
To view this discussion on the web visit
https://groups.google.com/d/msgid/ceylon-users/CABnofR5g1m5qz1YLUfEopM%2BkJ3VKftdugD9XXK3NqQ20WBZzCQ%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.