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…
Tell HN: We are trying to get tail calls into the WebAssembly standard
201–210 of 300 posts
Re: Tell HN: We are trying to get tail calls into the WebAssembly standard
#202Earlier quoted context omitted.
> In languages like Scala, Java, C#, and Swift, it basically never happens. Scalaz and cats use tail calls extensively and wouldn't be possible without them.
How does that work on the JVM?
Re: Tell HN: We are trying to get tail calls into the WebAssembly standard
#203Earlier quoted context omitted.
> But, as Scheme has demonstrated, once the virtual machine supports tail calls, a compiler can implement exceptions and cooperative multithreading by way of compiling to continuation-passing style. So this is not the beginning of a long series of extensions; it's Lambda the Ultimate Goto. Well to an extent. CPS can be extremely slow. Scheme shows that continuations will also be needed down the road. But yes, that's…
IIRC, one shot continuations can be made pretty efficient, effectively folding back into a single stack. If there's a simple way to safely express this in wasm that might be the right balance. If you want multishot continuations you'd need to explicitly clone the one-shot continuation.
Re: Tell HN: We are trying to get tail calls into the WebAssembly standard
#204Earlier quoted context omitted.
> Implementations are required to have every call consume some abstract resource towards exhausting some abstract finite limit If an implementation really wanted to, they could get around this by incrementing a "function call counter" that traps at, say, 2^64, rendering it effectively moot. I feel like these kinds of situations are where being practical might make more sense than being mathematically precise. Somethi…
> each function call must consume at least N bits of memory This is going to be a problem for any long-running recursive program. Why would we mandate this?
The nightmare scenario is that you spend months writing a program that works great in browsers A and B, but when you roll it out to prod it immediately fails in browser C, which doesn't perform TCO.
You only want to write code that depends on TCO if you can get a guarantee that TCO will be performed. This is the motivation for the clang:musttail attribute in C/C++ (I implemented musttail in Clang): https://clang.llvm.org/docs/AttributeReference.html#musttail
Re: Tell HN: We are trying to get tail calls into the WebAssembly standard
#205Earlier quoted context omitted.
Tail-calls is fundamentally something that the compiler _cannot_ solve. Trust me, if there was a way we would have avoided ourselves all this work. The issue is that to avoid stack blow-up you need the engine to recycle stack frames. You might argue that this could happen implicitly in the VM, with all the calls in tail position being automatically converted to tail-calls. The problem with this is that in WebAssembly…
> Tail-calls is fundamentally something that the compiler _cannot_ solve. I don't see why. Compilers are how tail calls are literally always implemented. It's not like there's hardware support. What makes this impossible? . > The issue is that to avoid stack blow-up you need the engine to recycle stack frames. I mean, what's stopping you from just implementing a trampoline? . > The problem with this is that in WebAss…
Re: Tell HN: We are trying to get tail calls into the WebAssembly standard
#206Earlier quoted context omitted.
My comment is about ES6 proper tail calls. WASM is another story
Graaagh, sorry.
Re: Tell HN: We are trying to get tail calls into the WebAssembly standard
#207Earlier 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).
Re: Tell HN: We are trying to get tail calls into the WebAssembly standard
#208Earlier quoted context omitted.
Understood, but in practice how often does that really happen? (I'm aware of the contrived 'odd'/'even' example always given, but in the real world, I never had anything like that). Even when I wrote more functional code I rarely (if ever?) did that. 98-99% of the time it was the same function calling itself. Is your experience different?
Iteratees are immensely useful in practice and they involve doing this all the time (basically you do stream processing with a source and a sink that are mutually recursive - the source emits an element by calling the sink to process it, the sink processes it and then recurses into the source for the next element. It feels a bit forced if you describe it like that, but it gives you a model wiht lots of natural struct…
I think I understood that concept but it still seems a bit strange to me. Doesn't that imply a potentially infinite stack of function calls?
I've seen this idea in other functional program examples as well. Instead of having a sequence of instructions, they have a sequence of function calls. Instead of a function returning to the caller, it calls the next function in the program which is analogous to the virtual machine moving on to the next line of code in the sequence. It implies the program's structure and state is actually expressed within the function call stack and its frames. I admit I'm not sure what the purpose of this is.
Re: Tell HN: We are trying to get tail calls into the WebAssembly standard
#209You can use F# with WASM. I know F# convert recursive tail calls to loops but I understand this is another case. But shouldn't F# have the same problem?
Re: Tell HN: We are trying to get tail calls into the WebAssembly standard
#210Earlier quoted context omitted.
Tail-calls is fundamentally something that the compiler _cannot_ solve. Trust me, if there was a way we would have avoided ourselves all this work. The issue is that to avoid stack blow-up you need the engine to recycle stack frames. You might argue that this could happen implicitly in the VM, with all the calls in tail position being automatically converted to tail-calls. The problem with this is that in WebAssembly…
Heya, (1) Thank you for implementing this in JSC!! I hope they take it, it makes it into Safari, and the tail-call proposal advances. (2) I don't think you are exactly right about the call stack being observable via thrown exceptions. There's no formal spec for the v3 exceptions proposal yet, but in the documents and tests, there's nothing that would change in WebAssembly core to make the call stack observable. (Ther…
It's a nice detail for you to highlight, but surely that exists in the test spec specifically because the opcode spec doesn't mandate tail-call handling. If the latter did (a la Scheme), then the test spec would be updated to no longer have this note...?