Live data from Hacker News

Tell HN: We are trying to get tail calls into the WebAssembly standard

news.ycombinator.com

71–80 of 300 posts

Re: Tell HN: We are trying to get tail calls into the WebAssembly standard

#71
post #10

Sorry if I miss something obvious, but how is this not solvable by the compiler? I'm a huge functional programming evangelist, but high-level stuff like this does not belong in a low level language bytecode like WASM. Wasm should only care about two things: Security and Performance. With the standard blowing up like crazy we'll get neither. Worse, we'll cemenent the current duopoly of browser engines, because we'll m…

We shouldn't have GC, Exceptions or Tail calls in WASM, as long as the compiler can provide them.

I’m not a compiler guy, but spent my time with runtimes closely, and can say that befriending GCs/RCs, exceptions, continuations, etc between them was my least favorite part.

That said, wasm is already a potential target for different runtimes built with no common vm in mind, so interop headaches are imminent either way.

Re: Tell HN: We are trying to get tail calls into the WebAssembly standard

#72
post #7

I'm using Blazor (C#) WebAssembly and I'm really wishing it could do DOM manipulation. My favorite tool for that is Dart, so I'm working on marrying C# and Dart for my client solutions.

What's wrong with JS bindings? Surely DOM manipulation is slow enough for WASM/JS overhead not being noticeable.

Re: Tell HN: We are trying to get tail calls into the WebAssembly standard

#74
post #47
post #10

Sorry if I miss something obvious, but how is this not solvable by the compiler? I'm a huge functional programming evangelist, but high-level stuff like this does not belong in a low level language bytecode like WASM. Wasm should only care about two things: Security and Performance. With the standard blowing up like crazy we'll get neither. Worse, we'll cemenent the current duopoly of browser engines, because we'll m…

I think its Rich Hickey who said something to the effect that tail calls are so fundamental that the underlying platform should be providing them.

tail calls are so fundamental that its trivial to build a call-push, return-pop stack calling protocol on top of them, but not the converse

Re: Tell HN: We are trying to get tail calls into the WebAssembly standard

#75

Earlier quoted context omitted.

I highly recommend TypeScript. I don't really like the JS runtime, but, purely from a language point of view, TS is my favorite. Some cool features: 1) Type unions interface A { a: string; } interface B { b: string; } type C = A | B; const c: C = { a: 'a' }; 2) Type assertions if ('a' in c) { /* compiler knows c is of type A here */ } function isA(c: A): c is A { return 'a' in C } // compiler knows c is A if this ret…

TBH, TypeScript's type system really impressed me. It's the strongest type system of any language I regularly use (I haven't had time to unpack Rust yet, and I learned enough Haskell to decide Haskell didn't help me solve problems I had).

It’s an expressive type system, but ime it allows developers to go crazy on type interdependencies and general entanglement, so you can’t just go to the “header” and quickly figure out what your method or a return value really is, despite TS has structural typing.

E.g. look at this: https://github.com/telegraf/telegraf/blob/v4/src/telegram-ty...

Re: Tell HN: We are trying to get tail calls into the WebAssembly standard

#76
post #7

I'm using Blazor (C#) WebAssembly and I'm really wishing it could do DOM manipulation. My favorite tool for that is Dart, so I'm working on marrying C# and Dart for my client solutions.

What's wrong with JS bindings? Surely DOM manipulation is slow enough for WASM/JS overhead not being noticeable.

You still need to go through a port with Blazor, but you can minimize those calls for the most part. DOM manipulation was slow as recently as a few years ago, but improvements to Blink have made it blazingly fast. I agree with Svelte that we no longer need a virtual DOM

https://svelte.dev/blog/virtual-dom-is-pure-overhead

Edit: I didn't answer your question. There's nothing wrong with JS bindings. Both Blazor and Dart use them, which could get awkward going from Blazor -> Dart (as JS) -> JavaScript lib. I'm considering TypeScript again because no port is needed to call JS libs.

Re: Tell HN: We are trying to get tail calls into the WebAssembly standard

#77
post #14

Earlier quoted context omitted.

Edit: this is wrong. For posterity my original comment was: “From what I understand, tail calls can always (?) be lowered to while loops[1], which are expressible in WASM. 1. https://en.wikipedia.org/wiki/Tail_call#Relation_to_the_whil...

This is possible, and trivial, when self-recursing: A -> A If you have an A -> B, or A -> [indirect] call, that is not the case.

I am genuinely asking, is your position that a compiler cannot convert:

g(): a = 1+1; b = 2+a; print(b); return f()

into code that does not allocate stack space and just reuses the frame allocated for g()?

Re: Tell HN: We are trying to get tail calls into the WebAssembly standard

#78

Earlier quoted context omitted.

Genuine question: is the goal to get something that is not achievable with JS/TS, or is the goal to simply avoid JS/TS?

I really dislike JavaScript for a number of reasons. Dart gives me more distance from it than TypeScript. Of course, I can't avoid it, but I don't have to deal with many annoyances such as which 'this' is this? Should I put 'this' into a var called 'self' to be safe? That's just one example of how JavaScript and I don't get along. I understand some people have brains that think this way, but mine doesn't

The comment reads like you used JavaScript 10 years ago. For instance, just use arrow functions and this remains untouched.

Re: Tell HN: We are trying to get tail calls into the WebAssembly standard

#79

ELI5: Tail-calls?

A tail call is a function call occurring in the final position of a function:

  void foo(...) {
    ...
    bar(x,y,z); // 
If the function has a return value (vice void like above):

  int foo(...) {
    ...
    return bar(x,y,z); // 
In the way most languages are compiled, function calls generate a new entry in the call stack (a stack frame). This is necessary for all non-tail calls in order to handle the bookkeeping around what to do when the call finishes, how does the caller resume.

With tail calls, that additional stack frame has no real value (outside, maybe, debugging information to give you a stack trace but traces can be collected other ways). Tail call elimination (or tail call optimization) will reuse the current stack frame rather than construct a new one. This reduces the memory overhead (you aren't constructing unnecessary stack frames) and gives some performance improvement (less bookkeeping overhead, and the function call becomes a simple jump). These two functions can, in principle, get compiled to the same thing if you have TCE:

  uint factorial(uint n) {
    uint acc = 1;
    for(; n > 0; n--) {
      acc *= n;
    }
    return acc;
  }
  uint factorial(uint n, uint acc = 1) {
    if (n == 0) return acc;
    return factorial(n - 1, acc * n);
  }
But while that's a recursive example, tail calls and tail call elimination (TCE) aren't just for recursive cases. My first two examples, though they are just sketches, show a non-recursive example of tail calls. With full TCE (it isn't uncommon to have TCE only apply to self-recursive cases) those examples would also have tail call elimination performed.

Re: Tell HN: We are trying to get tail calls into the WebAssembly standard

#80
post #38

Tangential but what's the status of garbage collection and DOM manipulation in WASM? Are we ever getting those? I understand it's a high-value technology without them, but I'm interested in writing full apps in say, OCaml (so I'm glad to hear that WASM is getting TCE!).

While I'm also looking forward to TCE and GC for WASM, you can build full apps in OCaml now via js_of_ocaml.
Post reply on HN