HNHacker News
TopNewBestAskShowJobs

gavinking

159 karma · joined December 20, 2011

submissionscomments
gavinking··on Ceylon 1.1.0 is now available
It's there now, I believe.
gavinking··on Ceylon 1.1.0 is now available
Yes, I understand. What I mean is a whole tutorial that shows a ceylon client in the browser calling a ceylon sever running on vert.x.
gavinking··on Ceylon 1.1.0 is now available
That's exactly right. Ceylon and Rust are both new languages, with, it seems to me, a fair amount of similarity in terms of overall philosophy, but they target quite distinct usecases. Ceylon -> VMs, Rust -> systems programming. And so quite fundamental differences between the languages arise out of that.
gavinking··on Ceylon 1.1.0 is now available
Oh yeah, we definitely need to write this now that vert.x's Ceylon integration just released it's 1.0 version!
gavinking··on Ceylon 1.1.0 is now available
As a further clarification, when I said: "there are a bunch of operations that I would love to add to ceylon.language, but can't, because they are simply unimplementable in JS", I don't mean that those operations aren't available. Just that they're exiled to a different module.

As a further sort of clarification: we're Java developers, not JavaScript guys. We recognize the importance of the JavaScript VM. But Java is where our hearts are at ;-)

gavinking··on Ceylon 1.1.0 is now available
I would say that Ceylon is heavily guided by the constraints of wanting to always do The Right And Elegant Thing, and not unduly compromise on that in light of the nature of the underlying VM. _Which_ VM doesn't quite enter into that question.

We're not crazy about this; of course compromises are necessary; hell, we just added use-site variance to the language purely to make Java interop better.

So to clarify: ceylon.language and ceylon.collection are designed the way they are because they're like way better and cleaner than java.lang and java.util. Not because they represent a "compromise" with JavaScript.

Likewise, the main reason that Ceylon only has 3 numeric types (Integer,Float, and Byte) is because that seems to me the Right Thing from the point of view of the goals of the Ceylon type system. It just so happens that this is also the right thing if you want cross-platform execution.

Hope that answers the question.

gavinking··on Ceylon 1.1.0 is now available
OK, sure, thanks for your comments :-)
gavinking··on Ceylon 1.1.0 is now available
>> but that it isn't one of the top two concerns of the language: i.e. it's possible and maybe kind of easy, but certainly not seamless. <<

Well it's certainly _a_ top concern, and one we've invested a huge amount of development effort in! Indeed, we could have delivered Ceylon literally a year or more earlier if we had not decided to jump through so many hoops to make the Ceylon compiler generate generic type info that the Java compiler understands.

>> This might be (and I don't know enough about it, so this is conjecture) one of the reasons why writing Kotlin on Android is pretty simple, while Ceylon not so much. <<

Well, no, I don't think so. It's not that _Ceylon_ doesn't have great Java interop; it's that _Android_ is not quite fully Java compatible! I can't just say to you: "oh, it's Java, so it will work". No; we can't depend on that.

But really the only reason that we don't have a welldefined story for running Ceylon on Android is simply that we haven't had time (yet) to invest the effort into trying it out and finding any sources of discomfort and fixing them and making it work, whereas perhaps the Kotlin team has done that already.

But we _will_ work on this, and I'm certain that we'll be able to make it work.

>> Kotlin also compiles to JavaScript, but it's much more a "hosted" language than one that tries to abstract away the host's native APIs. <<

Well the problem is that if you don't abstract away from the VM with your language module, and instead try to treat java.lang+java.util+whatever as providing your basic language types, or as dependencies of the module that provides your basic language types, then you simply _don't have a well-defined foundation for cross-platform development_.

* First, because the Java SDK itself is not modular, and the "boundaries" of what bit of the SDK is Java's "language module" is ill-defined. This is a real concrete problem for people who develop on GWT, so it's not some theoretical concern that I'm inventing! * Second, because even if you _could_ clearly discern the boundaries of java.base, there are plenty bits of it which _simply can't be implemented in JavaScript_. Seriously, there are a bunch of operations that I would love to add to ceylon.language, but can't, because they are simply unimplementable in JS. * Third, because _the basic types of the Java language_ are only meaningful on the JVM! You have types like long, and double whose semantics are 64-bit precision, and int and float whose semantics are 32-bit precision. But on a JavaScript VM, all numbers have 53 bits of precision! So the basic semantics of the type simply can't be satisfied. On the Dart VM, the situation is a lot better, since at least the two numeric types they have are both 64 bit, but that still leaves int, short, float as basically completely meaningless types.

So if you're truly serious about JavaScript VMs or the Dart VM or whatever as a real target platform for your language, you need to design your language and language module for that.

>> adopting Ceylon today, I think, is a much bigger risk than adopting Kotlin. <<

I'm not arguing, nor I would I ever argue, that there are no sources of discomfort that arise from having a cross-platform language module. There surely are, but they're minor, they're well-defined, and they're essentially very easy to work with. We've already written quite a lot of code that makes heavy use of Java libraries, and we've been identifying sources of discomfort and fixing them when/where necessary as we go along.

Nor would I suggest that there were no bugs/limitations in Ceylon 1.0. There were! And we fixed the ones we found. And surely we'll find a couple more in Ceylon 1.1. But we remain deeply committed to fixing such bugs.

Given that, calling it a "risk" is, I think, a bit of an unfair characterization. A "source of occasional discomfort", would be fairer.

gavinking··on Ceylon 1.1.0 is now available
Well it is somewhat better because it occurs immediately when the null value passes from Java code with unsafe null into Ceylon code with safe nulls.

Having the compiler produce an actual error in this case seems wrong and excessive, since the compiler does _not_ know better than you whether javaMethod() can return null. It simply doesn't have that information when calling Java code.

gavinking··on Ceylon 1.1.0 is now available
Well it all depends how you handle `null` at the boundary between the two languages. In Ceylon, we let you write either:

    String str = javaObject.javaMethod();
or:

    String? str = javaObject.javaMethod();
 
In the first case, we insert a runtime type check that throws an `AssertionError` if `javaMethod()` returns `null`. In the second case we don't.

That is to say, the Ceylon compiler recognizes that it's dealing with a Java library where information about null is simply missing from the method signature and adjusts accordingly.

gavinking··on Ceylon 1.1.0 is now available
FTR, Ceylon's Java interop is _excellent_, especially in this latest release, and Ceylon makes it absurdly easy to use the Java SDK directly from Ceylon.

Indeed, the Ceylon compiler's Java backend is actually built on Open JDK - that is, it is essentially `javac` itself that generates the bytecode - so we know that the bytecode we generate is extremely close to what Java itself would generate, including full information about generic types that the Java compiler can understand.

So, sure, we have the language module, and `ceylon.collection`, `ceylon.locale`, etc, which abstract away from the JVM, but that's necessary, since Ceylon also runs on JavaScript VMs. That _doesn't_ mean you can't easily use `java.lang`, `java.util`, and the rest of the Java SDK if you need it.

So it's not quite right to think that Ceylon is lacking in this area. It's actually a strong point of the language.

gavinking··on Ceylon 1.1.0 is now available
Yes, that's right, to confirm, it does run on Java 8, but we don't yet take advantage of any Java 8 features of the VM. (We first need to rebase the compiler backend on the Java 8 compiler, which could take some work.) FTR, we hope to move to a faster release cycle, 10 months between releases is really far too long.
gavinking··on Ceylon: Quick introduction
Exactly, thanks!
gavinking··on Ceylon: Quick introduction
Mutability is a great tool; it dramatically simplifies certain algorithms, and dramatically improves performance of others. But it comes at a cost, and there are situations in which it is inappropriate. So the language should force you to think before reaching for this tool. It shouldn't be the default tool for every problem.
gavinking··on Ceylon: Quick introduction
In Ceylon even local variables must be explicitly annotated `variable`.

The reason for that is that a local variable could be captured by an anonymous function or nested function, and escape from the local scope, so it's exactly the same situation with a local variable as for an instance variable of a class: both kinds of variable break referential transparency.

gavinking··on Ceylon: Quick introduction
FTR, the whole declaration section vs initialization section stuff really boils down to this:

    You can't declare mutually-recursive methods before 
    initialization logic in the body of a class. You have to 
    declare them _after_ the fields of the class are fully 
    initialized.
That's not so hard to understand.

To see why it's like this, you need to consider :

- Unlike most OO languages Ceylon statically _guarantees_ that a field of an object is initialized before it is accessed. (If we didn't, then we would have to have something conceptually equivalent to a NullPointerException when you access a field before initialization.) - We've always hated the amazingly repeaty syntax of constructors in C++/C#/Java.

What I mean is, in Java I have to write stuff like:

    class Point {
        final float x; 
        final float y;
        Point(float x, float y) {
            this.x = x;
            this.y = y;
        }
    }
In Ceylon, it would be:

    class Point(Float x, Float y) {}
And even with all that verbosity in the Java version, I _still_ don't get a static guarantee that `x` and `y` are initialized before they are used by a method. This code prints `0.0`:

    class Point {
        final float x; 
        final float y;
        Point(float x, float y) {
            fun();
            this.x = x;
            this.y = y;
        }
        void fun() { System.out.println(x); }
        public static final void main(String[] args) {
            new Point(1.0f,2.0f);
        }
    }
So Ceylon wants to solve _both_ these problems: eliminate the verbosity, and provide the static checking for initialization. Now, this is an _almost_ completely transparent process. I almost never find myself thinking about declaration section vs initialization section. I just write classes so that fields are initialized before the methods that use them are declared. Which is basically super-intuitive. In >95% of classes that's all you need to know. Very rarely, I mix this up, and the compiler complains and I need to move a member up or down. Which takes seconds to fix. Very, very rarely, I have a class with some kind of self-recursive initialization logic and then only in that case do I need to start holding the mental model of declaration-vs-initialization sections in my head. In practice, I think I've only run into this situation _once_, and it took me a few minutes to restructure the code. (FTR, it was `ArrayList` in `ceylon.collection`.)
gavinking··on Top Ceylon language features I wish we had in Java
> I was merely pointing out that although it is a user definable type, the language specification does mention its existence

Sure, the language spec _mentions_ Null, in order to define the syntax sugar X? and exists x. But that doesn't mean that Null has any special place _in the type system_.

> My main programming activities are using OCaml and Haskell, both of which have very few ad-hoc language features, if any.

OK, great, sorry for making assumptions. In my defense, I just didn't quite understand why you were having such a hard time believing that Ceylon could do things like this without adhoc special cases.

gavinking··on Top Ceylon language features I wish we had in Java
> But aren't you pretty much focusing on implementation details here?

No, not at all, I'm talking about the ability to abstract over things. Can I write a single higher-order function that operates over functions with any -arity? In most languages, no. In Ceylon, yes.

> Again, this discussion was very nice, resulted in learning a few new and interesting things and I'm taking nothing but good impressions with me!

In general, the quality of discussion here is better than in other places.

> I think if both communities took more care to explain the different reasoning, design decisions and philosophies behind the languages when giving talks or on conferences in the future

Sure, but when you have nasty and idiotic twitter stuff poisoning the air, it's hard to expect people to adopt a fair-minded and technical approach to the topic. People should just get off twitter. It's a community-wrecker. There's almost nothing you can say on twitter that rises above the level of insulting.

gavinking··on Top Ceylon language features I wish we had in Java
> Correct me if I am wrong, but there doesn't appear to be anything linking the nullability of the return value based on the possible emptiness of the input value.

Sure there is. The second type parameter of Iterable encodes that, see the definition of Iterable.

> does "Nothing" satisfy "Null"?

Of course. Nothing is the bottom type, it satisfies every type.

> If so then I would imagine that it becomes harder to enforce the constraint, likely because the return type can still be Null regardless of input restrictions.

I don't know what you mean by this. An Iterable<X,Nothing> cannot return Null from its first attribute. Check the declaration of Iterable.first.

> Does this use extra type inference on the expressions inside the function to do the enforcement, for instance using the "exists" operator to perform type set subtraction between {Value|Null} and {Null} on the true branch.

Approximately correct. But "exists" is not type subtraction, it's intersection with the class Object. Cool, huh?

> This implies that if I re-write the max function to have a single exit point (`ret = Null; if (exists values.first) { ...; ret = ...; } return ret;`) then I don't get the same guarantees?

I don't follow. You can't rewrite the function to do anything unsound because the compiler won't let you. Our type system is sound.

> Also the fact that Null is referenced by the "exists" operator also implies that it is part of the language specification, and not actually definable in any meaningful way as a user type.

That's not correct. Go and check the definition of Null. It's just a regular class, as advertised. There is no special behavior defined in the language spec. Sure, the exists operator is defined by the language spec to mean "is Object", but that's just trivial syntax sugar.

I guess the problem here is that you're used to languages full of weird special cases and ad hoc behavior. Ceylon is not like that. Ceylon's type system is very simple and these fancy constructs are layered over it as pure syntax sugar. It's a very different approach to other languages. But in the end it's much more satisfying. You'll just need a little mental adjustment to get used to it.

> If I read correctly, that means that I cannot implement the same behaviour/enforcement with completely user defined types.

Wha?! Nothing is the bottom type! The empty set. You want to define your own bottom types? That's not possible (nor desirable) in any language I know of. There's just no reason why you would want to write a class with no instances.

gavinking··on Top Ceylon language features I wish we had in Java
> The idea that the object graph I see in scala corresponds 1:1 to the object graph I see in java for the same object is comforting

Surely. Not merely comforting, but useful.

But it entails deep compromises in the design of the type system that we're just not willing to make, especially since Ceylon is primarily a cross-platform language, not just a JVM language.

> OTOH I have concrete cases where I need existential types for compatibility, much as I wish I didn't

Right. Whether we'll eventually have to throw in the towel on this one and add use-site variance to Ceylon, purely to get better interop with Java, is a very interesting and bothersome topic.

gavinking··on Top Ceylon language features I wish we had in Java
> Oh, now I'm a bit confused ... are you really saying that you think that the version with the unreadable and cryptic signature, which is non-extensible in any way and repeats all of Java's mistakes is a good solution (or the best solution available in Ceylon)?

I'm saying that it's cool as hell that the following is all well-typed:

    {Float*} zeroOrMore = ... ;
    {Float+} oneOrMore = ... ;
    Float? maybeNull = max(zeroOrMore);
    Float definitelyNotNull = max(oneOrMore);
    Null definitelyNull = max({});
And that this behavior makes the slightly cryptic signature of max() worthwhile.

Sure, sure, this is not the most general possible signature for max(), since it is only for types with a natural order. We could and should add some form of max() for comparator functions, which we already have for sorting.

P.S. By the way, there are examples of functions where type classes are nice, for example sum(), where the type class lets you correctly express the sum of zero elements. (But max() is not one of these functions.) So in fact, we would definitely like to experiment with type classes in a future version of Ceylon, especially since the idea probably meshes very nicely with our reified generics.

> What am I missing?

You're missing that the definition of compose() is abstracted over the arity of the second argument function in Ceylon. It's _one_ function, not a different method defined for each Fi type. Which means that I can write similarly-abstracted functions that use compose().

> Is there also stuff for filtering elements by type, mapping, grouping?

Sure. Tuple is a subtype of List, which is a subtype of Iterable, which defines all stream-processing functions. FTR, an [Integer,String,Float] is a List<Integer|String|Float>.

gavinking··on Top Ceylon language features I wish we had in Java
> Sounds like HList.

Maybe. I have never heard of HList until today.

> Do you avoid instantiating a JVM object for each entry?

Yes, a tuple, at the VM level is just a wrapped array. Our compiler backend does magic with certain language module types.

> Are you sacrificing Java compatibility, or is the tradeoff somewhere else?

Well, I dunno, a tuple looks like a regular Ceylon list to a Java client, but I don't think that really breaks _compatibility_ as such. Depends how you define "compatible".

> Having now paid attention to who you are, how do you handle ORM in what I presume is a more immutability-oriented language?

No clue. That's something we'll have to think about in 2014.

> hibernate seems to expect sessions to belong to a single thread, objects to belong to a single session, and updates to be performed by mutating an object rather than copying it.

Yes. That's definitely what Hibernate expects. It was never designed for copy-on-write. Because at the end of the day the database contains a bunch of mutable state and Hibernate reflects that in memory. I can't imagine that the solution to this problem is going to be straightforward.

> Anyway, to get back to the point, does Ceylon have a good story for this problem?

Not yet.

> Is it going to include a next-gen hibernate replacement?

I hope so, but I can't promise because I have not spent time thinking about it.

gavinking··on Top Ceylon language features I wish we had in Java
Oops, thanks. Appreciated. How I wish hn supported markdown :-/
gavinking··on Top Ceylon language features I wish we had in Java
Don't get me wrong, I don't mean to belittle scientific computing, which is after all, a big part of my background (I'm a mathematician by training).
gavinking··on Top Ceylon language features I wish we had in Java
> One of the next versions of Java will ship with a module system.

I certainly hope so, since we always planned to replace JBoss Modules with Jigsaw when that becomes possible. But we still don't know if the Jigsaw module system will be made available for all consumers or just for the JDK itself.

> If your type was written by someone who didn't care to implement Comparable, bad luck! - If the type has a Comparable implementation which differs from what you need, bad luck, too! - You need the type to be comparable in multiple ways? Again, bad luck!

Um, you've totally missed the point. Go and have another look.

And sure, since you bring it up, we can certainly add a version of max() that accepts a comparator function. It would be a method of Iterable, probably.

And sorry, but I can't imagine why I would want or need typeclasses to solve that problem. Sure, I could use typeclasses, if I were a solution in search of a problem ;)

> I'm not sure that there is a large difference.

You can't abstract over tuple and function -arity in Scala. So yes, there's a big difference. Look at the definition of compose() in Ceylon.

> and performance (no pointer chasing, all values are just a method call away).

At the VM level, tuples are represented as arrays. So there is no real performance penalty.

> Anyway, if one wanted tuples-as-linked-lists, one could just use Shapeless' HList library, which has a few benefits over Ceylon's tuples, too, as far as I see:

In Ceylon, without any macro library, you can write:

    value tuple = [1, "str", 42.31];
    String str = tuple[1]; //totally possible in Ceylon
Seriously dude, _just try it out_, you're desperately searching for reasons to not like this thing! But it really has cool stuff to offer you. Give it a fair chance!

Sure, _of course_ you're going to find stuff in Scala that you can't do in Ceylon. Scala is one of the most huge and complex and feature-rich languages _ever_! But you'll also find plenty of stuff you can do in Ceylon that you can't do in Scala, if you care to look.

gavinking··on Top Ceylon language features I wish we had in Java
> using maven

Brrrrr.

> What is the problem I'm supposed to be having that OSGi would be solving? Because I've never seen it.

The problem OSGi solves is having two versions of the same module as part of the same assembly. This is quite possible if you're using third-party libraries that in turn depend on another third-party library.

But I think you're missing something here. Ceylon's module system supplants both OSGi _and_ Maven. It's not just an alternative to OSGi, it's a whole architecture for modularity.

> I tried to do that, but it looks like you don't have an equivalent to javadoc/scaladoc with the standard library docs publicly available?

https://modules.ceylon-lang.org/modules/ceylon.language/1.0....

> I don't think you can do that without higher kinded types.

Correct, we don't have type constructor polymorphism in the official language, and even if we did, we wouldn't use it for this particular problem. Our equivalent APIs are based on (lazy, non-copying) stream-processing.

Now, I do have a working implementation of type constructor polymorphism in a branch of the Ceylon typechecker, but I probably won't merge it because:

1. we don't have a really convincing use for it, and

2. I see it as essentially useless without type constructor argument inference, and Ross and I doubt that a robust and decidable inference algorithm exists for a language with subtyping.

> Point, but I find it hard to care.

Speaking for myself, I don't like unnecessary distracting complexity, even trivial unnecessary distracting complexity.

> Shapeless 2 makes it painless to treat tuples as HLists (using implicit macros - a concept which admittedly would have utterly horrified me six months ago) which means you can work around it in practice

Brrrrr. And then you Scala folks tell the rest of us that Scala is not complex and that we're full of FUD or worse ;-)

FTR, the way Ceylon models this is the way this is the same way it is modeled in mathematics. That is to say, in mathematics, a function is a set of ordered pairs, where the first element of each ordered pair is a tuple. The notion of a tuple is itself defined by recursion. Therefore, in Ceylon, a function type is Callable<AType, ATupleType>, and Tuple is is a class with a recursive definition. Clean, intuitive, abstractable.

gavinking··on Top Ceylon language features I wish we had in Java
Ah, OK, fair enough, well, Bastien and Matija have recently been making very good progress on the IntelliJ plugin for Ceylon, and since we expect to be able to reuse quite a bit of underlying code from the Eclipse plugin, we hope to something useful quite soon. Stay tuned :)
gavinking··on Top Ceylon language features I wish we had in Java
> While this is interesting, is it enforced by the compiler?

Of course. That's the whole point. I really think you've missed the nature of Ceylon. Don't imagine, that just because it has a syntax that looks friendly and harmless and familiar, that it doesn't have a really killer type system under the hood.

> i.e. is the following a runtime, or compile time error?

A compile-time error, of course.

gavinking··on Top Ceylon language features I wish we had in Java
Don't know anything about it. But it's good that there's a revival of interest in languages for scientific computing. When I was in uni all we had was Fortran :-/
gavinking··on Top Ceylon language features I wish we had in Java
Cheers, Martin, thanks for the note, I appreciate it! Well, there's already a couple of things we learned from you guys: FTR, Scala was the first place I ever saw declaration-site variance, which rocks. It's also the language that influenced me and the others to take type inference seriously. Definitely hope it's a two-way street :-)
← PreviousPage 3 of 4Next →