Hacker News new | comments | ask | show | jobs | submit login

Somehow, it looks a lot more like lua with a bunch of type-checks and tests added then like python. No named parameters, no generators, no comprehensions that I can see, no focus on iteration in general, no significant indentation, etc.

Instead: "end" syntax, unified number type, all blocks produce new scopes (not just functions), local variables are explicit instead of default, etc.

That's a useful comparison, thanks. While we were certainly inspired by Pythonic syntax, we have ended up somewhere slightly different.

The note about local variables is particularly important; we actively don't want Python's model of variables and scope.

Note: this wasn't a criticism of your language: I rather prefer lua's way of doing numbers, co-routines, and even scoping to some degree. I was more criticizing your comparison.

The language itself looks pretty slick, and I am a sucker for gradual/optional typing. Do the type annotations result in performance/compiler optimization, as in Julia?

> Do the type annotations result in performance/compiler optimization, as in Julia?

We've been designing the static system with exactly this in mind. The current implementation doesn't do anything fancy yet, but that's just because we've been getting off the ground and focusing on ergonomics and curriculum first. Getting performance in return for types is absolutely where we're going.

Its shocking to me that so many languages designed after Scheme get variable scoping wrong.

Indeed, but apparently, it doesn't have multiple return values, and I don't know if there is an equivalent to metamethods.

It's easy to obtain the equivalent of multiple return values by using a literal object.

I've been burned by multiple return values numerous times in Scheme and Racket. They're very subtle and hard to make performant. It's one of those language features that very much does _not_ pay its own way, so you have to really, really need it to want to put it in your language. My view is that its uses are not many, and most (all?) can easily be achieved with literal objects. That's why Pyret doesn't have them and is unlikely to get them.

Can you say more about how multiple return is "very subtle and hard to make performant" and leads to getting burned?

As far as I can tell the main advantage of multiple-return over literal objects is that callers who only care about the primary value can call the function the normal way, whereas if it's wrapped in an object they have to "pay" for it by explicitly extracting it. That's a nice-to-have but you seem to be saying that it isn't worth the trouble because the trouble is considerable. I'd like to hear more about why. (A friend is working on a language where this is an issue.)

p.s. This thread is just awesome. Thank you for engaging so extensively here.

1. Designing a performant multiple return values mechanism is very subtle. For instance, see J. Michael Ashley, R. Kent Dybvig: An Efficient Implementation of Multiple Return Values in Scheme. LISP and Functional Programming 1994: 140-149.

2. Write me the identity function. (No, really. Stop. Try. Then read on.)






I hope you didn't say it's

fun id(x): x;

because if F returns multiple values and G consumes them, I can't refactor G(F(...)) into G(id(F(...))), which is pretty much the definition of an identity function. You should see the true identity function in R5+RS Scheme....

3. The way to make simple functions like that continue to work is to make the return values not be multiple values but a single one (i.e., some kind of tuple). At which point...

4. Pyret's objects are very lightweight. They don't carry baggage à la those in JavaScript, etc.

5. If you have multiple values, every single library function has to be rewritten to work with them. What should map do? filter? fold? And the hundred other library functions? It's also really hard to remember this when writing every line of library code (see #2).

6. We'd need a new binding construct in the language to bind the multiple return values. That's yet more syntax design, but also, it's yet more opportunity for typos to turn into indecipherable error messages ("Expected two values, got one" is a horrible thing to read for someone who doesn't even know a function can return two values!).

So, I claim this is simply not worth the frequency with which you actually need precisely this, as opposed to just returning some sort of tuple or object. Also, once I've bound the return value (say to r), saying r.x and r.y instead of just x and y is really not a big deal.

> 2. Write me the identity function. (No, really. Stop. Try. Then read on.)

In Lua:

    function id(...) return ... end
    a, b = id(1, 2) --> a == 1, b == 2
    c, d = id(3)    --> c == 3, d == nil
    e = id(4, 5, 6) --> e == 4, the rest is discarded.
I use it all the time :-)

The vararg system is built on a stack mechanism, and it is efficient.

Regarding map and other higher level functions, I'd only take the first return value.

If you have tuples it is indeed less of a concern. Better still if you have destructuring assignement, à la Julia.

I hope you didn't say it's fun id(x): x;

Well, I did. :)

That's an interesting example. My first reaction was that one might be able to construct a similar anomaly by abusing optional arguments, but perhaps not: optional arguments to F don't get magically passed on to G. Still, I feel like I've seen function-signature constructs that would break the identity function similarly to how multiple-return does in your example. Maybe some twisted aspect of Common Lisp...

No doubt. Things with optional arguments, keyword arguments, all sorts of contraptions like that. That's why we've studiously avoided such things.

Still, there's an asymmetry, at least to our minds, between calls and returns, so the argument put forth for multiple values ("a function can take multiple arguments, why can't it return multiple answers?" -- made especially compelling in a CPS context, because returns turn into calls) doesn't quite play out in practice.

Ergo, no multiple return values.

PS: Fun exchange for me, too!

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact