Live data from Hacker News

Hurl, a terrible (but cute) idea for a language

ntietz.com

61–70 of 84 posts

Re: Hurl, a terrible (but cute) idea for a language

#61
post #23

While cute this is really close to call/cc and/or algebraic effects as an abstraction for control flow, which isn't as much "cute" as it is "a powerful way to express programs in as few expressions as possible"

The thing this appears to be missing is the ability to capture the part of the stack between the try and hurl as a first-class value and reify it later, although the toss/return is not too dissimilar as toss does capture the stack and return reifies it. It's close to multi-prompt due to multiple catch branches, so I would describe it as a one-shot, multi-prompt, second-class delimited continuation.

A bit more powerful are multi-shot, multi-prompt, first-class delimited continuations, which you can then use to implement exceptions themselves with multiple catch blocks.

Re: Hurl, a terrible (but cute) idea for a language

#62
If you extend the `catch` matching to compound values this isn’t even that bad.

   let fizzbuzz = func(fizzbuzz, x, max) {
     try {
       hurl [x % 3, x % 5];
     }
     catch ([ true,  true]) { print("FizzBuzz"); }
     catch ([false,  true]) { print("Buzz"); }
     catch ([ true, false]) { print("Fizz"); }
     catch ([false, false]) { print(x); }
     try { hurl x; }
     catch (max) {}
     catch (x) {
       fizzbuzz(fizzbuzz, x + 1, max);
     }
   }

Re: Hurl, a terrible (but cute) idea for a language

#63
> I guess this assumes the stack goes down, but this direction metaphor in stacks has always confused me. What's up and what's down?

The stack starts at the end of a process's memory space, so stack frame 0 has the highest possible memory address (ex 0xFFFF) and further stack frames have lower memory addresses (ex 0xFFF8). Now combine this with the fact that many visual representations of memory space have 0x0000 at the top and 0xFFFF at the bottom and the stack grows down by growing up and it all gets very confused

Re: Hurl, a terrible (but cute) idea for a language

#64

If you extend the `catch` matching to compound values this isn’t even that bad. let fizzbuzz = func(fizzbuzz, x, max) { try { hurl [x % 3, x % 5]; } catch ([ true, true]) { print("FizzBuzz"); } catch ([false, true]) { print("Buzz"); } catch ([ true, false]) { print("Fizz"); } catch ([false, false]) { print(x); } try { hurl x; } catch (max) {} catch (x) { fizzbuzz(fizzbuzz, x + 1, max); } }

and if you just renamed the `catch` to `case`, it almost looks like a regular language. Who cares how it does the jumps in the implementation! ;D

Re: Hurl, a terrible (but cute) idea for a language

#67
post #49

Earlier quoted context omitted.

loops are typed gotos, so are if statements, so, really are functions. Goto isn't bad, it's integral to programming. It's just too powerful, so we tame it in various ways. Algebraic effects are one of those ways.

The big difference here is to understand the program with Algebraic effects you now need to know _where the code was called from_. If you ask for an effect to come from higher up the call stack, does that mean part of the function signature needs to include that the call stack must be able to handle the effect? And if that's part of the call stack, why not just make that an explicit function?

> Does that mean part of the function signature needs to include that the call stack must be able to handle the effect?

Some people would argue that the effects a function may raise are indeed a part of a function's type and for it to type check it must be within scope of a handler for that effect. Think of it like function coloring, a function with the "async/await" effect means all callees must be invoked either within an "async" block (another function with the await effect) or within scope of a runtime that handles the effect.

But even that is a bit limiting.

> And if that's part of the call stack, why not just make that an explicit function?

This is kind of a meaningless question depending on how you formulate it, because the big thing about things like effects is that the callee both returns more than once and is called more than once - so the notion of a "call stack" is kind of meaningless.

For example if f calls g and g raises E1 and then E2, f can declare a handler for E1 which moves it into a different scope that has a handler for E2. From the perspective of g() there is no function to call to deal with E1 and E2, since it's the responsibility of the caller to determine that.

Re: Hurl, a terrible (but cute) idea for a language

#68
post #42

Earlier quoted context omitted.

> I don't find this appealing on its face. Extreme terseness, even when done very elegantly, makes programs very hard to read and sometimes also hard to maintain. In that case, it's more about minimizing the language, rather than the programs. call/cc is a single instruction that is sufficiently expressive to implement e.g. exceptions, coroutines and lots of stuff for which people typically use monad-style embeddings…

I believe the point was you can say the same about goto. With goto you can replace if/else, for loops, while loops, functions, exceptions, etc, making for a very minimal language. Yet structured programming is superior. (I probably don’t know enough about call/cc to know if that’s a totally fair comparison, but languages being more restrictive/less flexible can be good overall in terms of aiding understanding/reducin…

I think people are misunderstanding that you can have a small core language and use that for static analysis (a smaller language means fewer typing rules which means a simpler type checker).

You can always define higher level sugar in terms of the small core language to make it easier for programmers which has the advantage of making a more ergonomic language without changing fundamentals like the type system or linkage.

Re: Hurl, a terrible (but cute) idea for a language

#69
post #32
post #23

While cute this is really close to call/cc and/or algebraic effects as an abstraction for control flow, which isn't as much "cute" as it is "a powerful way to express programs in as few expressions as possible"

> express programs in as few expressions as possible I don't find this appealing on its face. Extreme terseness, even when done very elegantly, makes programs very hard to read and sometimes also hard to maintain. I suspect that's one of the reasons Lisps (and functional languages in general) haven't caught up in popularity even as it becomes much easier to adopt one for any target and in any organization.

> Extreme terseness, even when done very elegantly, makes programs very hard to read and sometimes also hard to maintain.

I will definitely agree with you on this one. The tersness, which has many faces, is what I experience to be reason for "write-only" effect in Bash, Perl and now even C++. There, tersness come in form of trying to overload operators with lots of different meanings in different contects.

> I suspect that's one of the reasons Lisps (and functional languages in general) haven't caught up in popularity even as it becomes much easier to adopt one for any target and in any organization.

Here I believe you are perhaps wrong. I don't think Lisp is about tersness. In this case about control flow, on the contrary. Lisp was actually the language that introduced the 'if' and some other higher level constructs we take for granted today into the mainstream. Before McCarthy and Lisp there were no 'if' in any other programming language. Some Lisp(s) have do, while, cond, unless, when, and most importantly, the condition system, which is in a way, very close to the idea presented in the article.

Also note that some Lisp have rich facilities to extend the language itself, where the idea is that programmers should create abstractions to express progams in the problem domain, rather then use low-level language primitives. I am not so good at words, but I think Peter Norvig captures Lisp ideas very well in his Paradigms of AI book: https://norvig.github.io/paip-lisp/#/chapter3.

I wouldn't say that Lisp hasn't cought up. Lisp was very, very popular, at certain time, but has gone away. Perhaps Lisp was ahead of its time and had its own .COM crash. Or was it killed by big tech greed? I don't know, but many of Lisp ideas are in mainstream languages, it is just that they use different syntax and sometimes terminology.

Very similar could be said for functional languages too, Note as well that Lisp(s) are not necessarily functional programming languages. Many, if not all Lisps, do support functional paradigm, but they are (mostly?) procedural and some do support OOP too.

We are still early in our digital age as a civilization. If we think of the history of humanity, we have spent about 300 thousand years in the woods, and only last 10K years in urban settlements and for only about last 2.5K years do we seem to have developed science as a logical/mathematical discipline. Less than 100 years have we spend on programming languages theory.

I am quite sure we are still just testing our waters for the right direction. The only unfortunate thing with dying is to not be able to see how the civilization will look like in about a 1k or 10k years from now. Wonder how computers will look like and how programming languages would look like. The only thing I am sure about is that any guess I would make now would probably be wrong :).

Re: Hurl, a terrible (but cute) idea for a language

#70
post #23

While cute this is really close to call/cc and/or algebraic effects as an abstraction for control flow, which isn't as much "cute" as it is "a powerful way to express programs in as few expressions as possible"

Generalized exception-throwing is pretty much the Common Lisp condition system.

That was pretty much my first thought too when I was reading the article.
Post reply on HN