News for hackers. Stuff that matters.
Re:Lily Programming Language by alkonaut on Friday July 01, 2016 @08:46AM (#12015533)
Love it. It's like someone used C# a lot and got fed up with how much cermony goes into making a simple sum type and exhaustive handling of the variants.

A pet peeve of mine is the sloppyness by which .NET allocates things like iterators etc. I'd very much like to see zero-cost abstractions in a new language, so that there is no surprise differences between various ways of iterating over collections. I read it only quickly but couldn't find anything related to how enumeration/iteration works under the hood.

Re:Lily Programming Language by jesserayadkins2 on Friday July 01, 2016 @09:07AM (#12015667)
Actually, no, I've never used C# except for a few minutes and only one time. I have more experience with the syntax of Scala and Rust. Between the two, I found Rust's more appealing. I like that enums serve a single purpose and can't be inherited.

Currently, the best you can get for iteration of Lists and Hashes is to do each-ing the way you'd go about it in Ruby, except that the language currently lacks iterators.

That's not to say I don't want iterators. But I've spent a huge amount of time of this release in making sure that all of the built-in classes get dynaloaded so that memory usage stays low. Now that everything's getting dynaloaded properly, I've less of a problem with doing iterators.

Re:Lily Programming Language by stevedonovan on Friday July 01, 2016 @09:30AM (#12015831)
Very cool - haven't come across a fun new language for a while. When thinking about iterators, think about coroutines a la Lua. Otherwise you're going to get yield-with-serious-restrictions.
Re:Lily Programming Language by DanWaterworth on Friday July 01, 2016 @09:55AM (#12016012)
When I was adding for each style loops to my language, plastic [1], I just opted for 'you can iterate over any expression that produces a coroutine'. It shouldn't cause any problems a tracing jit can't fix and it's super convenient.

[1] https://github.com/DanielWaterworth/plastic

Re:Lily Programming Language by MichaelGG on Friday July 01, 2016 @11:46AM (#12017081)
Lack of escape analysis or manual alternatives really kills perf on .NET. It feels like they got "good enough" vs Java and left it there.
Re:Lily Programming Language by alkonaut on Friday July 01, 2016 @01:26PM (#12018013)
There is so much good stuff going on in projects like Midori that a new systems language (or a massive overhaul of C#) has to come out of Microsoft soon.

The biggest design mistake in Java was the omission of stack allocated value types, and the same for C# was the distinction between value and object types. If something can be done on the stack it should be done on the stack - the biggest lie we were told was that "short lived objects are cheap".

Re:Lily Programming Language by MichaelGG on Friday July 01, 2016 @03:47PM (#12019141)
Dunno - MS seems to be doubling down on C++. They've essentially abandoned the F# team it seems. They haven't updated the CLR format since adding generics in v2. C# dev seems like they are sort of satisfied and just focusing on tooling. This many years, and not even tuples or pattern matching? Come on.

Or maybe I'm in a total echo chamber. Working with a client today, they were astonished to find out that:

  var x = new List() { 1 , 2 };
  var y = x;
  x.Clear(); // This affects y.
Absolutely astounded. They also had no concept of local variable scope, thinking they had to manually clear out the List so the next invocation of the function wouldn't have the old data. They aren't fresh devs. They've had professional programming jobs. They've built a successful company based on their code. It does non-trivial work (not just a web UI on a DB) and processes many $/sec. In fact, I'm impressed how successful they are.

So who knows, maybe MS's overwhelming feedback is from people that fundamentally don't understand what's going on, and they're the ones with money?

To be fair, I've seen successful C projects with lines like: buffer = malloc(....); // gets memory

Re:Lily Programming Language by agumonkey on Saturday July 02, 2016 @05:26AM (#12021948)
Even though it appears as ridiculous, I hope it means the guy did ensure that things worked correctly no matter how ignorant they were on some aspects, which if true is a good quality. No matter the tools, it's the properties of the system built that counts.
Re:Lily Programming Language by hugoestr2 on Sunday July 03, 2016 @01:00PM (#12026683)
Tupples and pattern matching are meant to come in C# 7.
Re:Lily Programming Language by neutronicus on Friday July 01, 2016 @04:54PM (#12019574)
The C line is bad because it isn't checking for NULL?
Re:Lily Programming Language by scott_s on Friday July 01, 2016 @05:01PM (#12019618)
A "gets memory" comment is unnecessary next to a call to malloc.
Re:Lily Programming Language by nomel on Saturday July 02, 2016 @03:22AM (#12021739)
The complete omission of "free" is strictly necessary after a "gets memory" comment, though.
Re:Lily Programming Language by eropple on Friday July 01, 2016 @01:52PM (#12018225)
I think a divide between value and reference types in C# is inevitable. There are semantic differences between value and reference types in C# that I don't think you can elide in a way that's both reasonable for the tooling author and conceptually clear to the end user.
Re:Lily Programming Language by alkonaut on Friday July 01, 2016 @03:47PM (#12019139)
It's mostly an issue with poor escape analysis and the tendency to use heap allocation for data that could go on the stack. This isn't a requirement of the language/runtime though (I believe) so this could be improved, but maybe some property or feature of the language is what makes escape analysis hard?
Re:Lily Programming Language by eropple on Friday July 01, 2016 @03:53PM (#12019183)
I think it's more than that, though, much as it is in something like C++. A struct in C# can be considered a class in C++ with no virtual methods (where interfaces are handled either through static linkage in a local scope or via boxing, I forget the exact method), and this does have different implications with regard to dereferencing and that sort of thing. Think about an array of structs, which is represented internally as an array of n * sizeof(SomeStruct) versus an array of classes (which is an array of references).

(n.b.: when I write C#, it's for game development, and I am constantly thinking about structs versus classes and I'm very careful about them, so my perspective is probably not the same as your average C# developer.)

Re:Lily Programming Language by dcohenp on Friday July 01, 2016 @04:15PM (#12019329)
It looks like they're definitely working on bolting on some of that stuff onto C# and the Runtime in the near term: https://qconnewyork.com/system/files/presentation-slides/csy...
Re:Lily Programming Language by kenko on Friday July 01, 2016 @06:57PM (#12020299)
Wasn't Midori killed?
Re:Lily Programming Language by alkonaut on Saturday July 02, 2016 @03:20AM (#12021734)
I think it was a research project only so simply a project from which features would be ported into production tech. I'm sure something found its way into C#, but I'm hoping for more. C++ isn't the horse to bet on...
Re:Lily Programming Language by cbHXBY1D on Friday July 01, 2016 @08:57PM (#12020878)
Yep and M# :'(
Re:Lily Programming Language by noblethrasher on Friday July 01, 2016 @04:08PM (#12019279)
I can’t tell if you’re referring to iterators (abstracted by `yield return`) or enumerators (abstracted by `foreach`).

In case it’s the latter, I’ll just point out that you can have zero-cost abstraction because, in C#, `foreach` is pattern-based: An object is enumerable with respect to `foreach` whenever:

1. It has a public method named “GetEnumerator” of type ‘E

2. 'E has a method named “MoveNext” of type () -> bool and a property named “Current” of type () -> ’T (where ’T can be any class (including those that inherit from System.ValueType.. i.e. a struct)).

While it is the case that `yield return` does result in allocation for a reference type, it’s also true that this is easily remedied should it become a problem: In my experience, it only takes about 5-10 minutes to implement a zero-cost iterator as I described above.

Many of the BSL collection classes (e.g. System.String (as an IEnumerable<char>) and System.Collections.Generic.List<T>) use the zero-cost abstraction.

Re:Lily Programming Language by munificent on Friday July 01, 2016 @01:00PM (#12017805)
> I'd very much like to see zero-cost abstractions in a new language, so that there is no surprise differences between various ways of iterating over collections.

I never got around to writing in detail about it, but I have that goal with iteration in Wren, and came up with a little iteration protocol[1] that I think accomplishes it.

In most languages a loop structure like:

    for (i in sequence) {
      print(i);
    }
Desugars to something like:

    {
      var __iterator = sequence.getIterator()
      while (__iterator.moveNext()) {
        var i = __iterator.getValue()
        print(i)
      }
    }
You've got one fundamental piece of state: a cursor that tracks where you currently are in the sequence. This is separate from the sequence itself because you can iterate over the same sequence multiple times, sometimes even simultaneously.

And you have three fundamental operations you need to perform:

1. Produce a new cursor pointing to the beginning of the sequence.

2. Advance the cursor and determine if we've reached the end.

3. Get the value at the current cursor position.

In most languages, the last two operations are defined as methods on the cursor itself. That means for any given sequence, it needs to define a cursor type specific to that sequence (and storing a reference to it), and you have to allocate that object at runtime, mainly so that you can use it as a dispatch token to find its implementations of those two operations.

That's kind of lame. In Wren, it desugars a little differently:

    {
      var __iterator = null 
      while (__iterator = sequence.iterate(__iterator)) { 
        var i = sequence.iteratorValue(__iterator) 
        print(i) 
      }
    }
The first two operations are combined into a single iterate() method that uses a "null" parameter to mean "produce a new cursor" and any other parameter to mean "advance". If it returns null or false, we're done with the sequence. Otherwise, it returns a cursor pointing to the next element in the sequence.

To get the value at the current cursor position, we call iteratorValue() on the sequence passing the cursor in.

This means the cursor object is pure state—it's just a bit of data that gets passed repeatedly to the sequence. The sequence itself has the dynamic dispatch of the methods for its own iteration protocol.

What this means in practice is that for simple things like lists, you can use a dead simple cursor type: a number.

The implementation of the protocol for lists looks pretty much like this (except its actually in C in Wren):

    class List {
      iterate(iterator) {
        // Start the at first element.
        if (iterator == null) return 0

        // Stop at the end.
        if (iterator >= count) return null

        // Advance.
        return iterator + 1
      }

      iteratorValue(iterator) {
        return this[iterator]
      }
    }
Since numbers are unboxed in Wren, it means many sequences can be iterated without any dynamic allocation at all. It makes it easier to implement the iteration protocol because you don't always have to define a class that stores a reference back to your sequence.

[1]: http://wren.io/control-flow.html#the-iterator-protocol

Re:Lily Programming Language by DanWaterworth on Friday July 01, 2016 @02:35PM (#12018595)
How do you unbox something that could be null? Why not have a separate method on the sequence to define the initial value?
Re:Lily Programming Language by munificent on Friday July 01, 2016 @03:42PM (#12019106)
> How do you unbox something that could be null?

Wren is dynamically typed, so you don't really have to think about explicit boxing or unboxing.

> Why not have a separate method on the sequence to define the initial value?

Yes, I am definitely considering that. There's no real reason why that needs to be combined with the method to advance, and I'm honestly not even sure why I originally designed it that way.