6 ms·
Slowly but surely WASM is turning into Common Lisp! (: I kid, sort of. Greenspun and all that. (Common Lisp has support for multiple values built in. They’re
by reikonomusha 7y ago
Slowly but surely WASM is turning into Common Lisp! (:
I kid, sort of. Greenspun and all that.
(Common Lisp has support for multiple values built in. They’re not a “data structure” like a tuple, but rather an extension to data flow and control. Returning a tuple vs returning multiple values are different things, especially when the consumer of the values-produced only actually uses a single value, as is usually the case with e.g. multiple-value-returning functions like GETHASH or FLOOR. FLOOR returns the quotient of floor(x/y), as well as the remainder as a second value. Most of the time you don’t need the second value, and there’s no need to “opt-out”.)
- byron_fast 7y agoPlease don't tell anyone. WASM can be better, but they need to not think it's Lisp.
- skybrian 7y agoI was reminded of Go and Forth :-) It's not really Forth because in WASM, each block of code needs to have a statically determined stack effect. I wonder if there might be a nice Forth-like syntax for WASM, though?
- zozbot234 7y agoIt's kinda unrealistic to endow a Forth-like syntax with things like types and pre-determined stack effects. You end up with something not too different from the usual lambda syntax aside from postfix application, which in this context would simply be De Bruijn notation for lambda-like terms.
- brandonbloom 7y agoI think Factor is an existence proof that you're mistaken about this. Check out the section of the docs labeled "The stack": https://docs.factorcode.org/content/article-handbook-language-reference.html https://docs.factorcode.org/content/article-handbook-languag... Note that, in particular, there is full support for stack-effect declarations and that there is a static static-effect checker.
- abecedarius 7y agoAt https://github.com/darius/idel https://github.com/darius/idel is a Wasm-like VM I made in the early 2000s with a Forth-like source syntax and static stack effects. (Tail-call optimization too.) I regret making it a little too simple and then abandoning it -- it seemed too hard to try to get traction with such a thing.
- marcosdumay 7y ago"Turning into" is the wrong phrasing. It's enabling Lisp. And also Python, Go, Rust, Haskell...
- jhpriestley 7y agopretty hard to enable lisp without eval or garbage collection
- TomMarius 7y agoYou might find these interesting: - https://github.com/WebAssembly/gc https://github.com/WebAssembly/gc - https://github.com/WebAssembly/reference-types https://github.com/WebAssembly/reference-types - https://github.com/WebAssembly/funclets https://github.com/WebAssembly/funclets As for the eval thing, you surely can compile and execute code on the fly. Such features would be enabled by the aforementioned proposals, but should be possible today as well (through shared memory).
- jhpriestley 7y agoyou mean you can compile code into a separate module, right? Which could then access the original module only via marshaled calls through the javascript layer? I guess anything can be compiled into anything but I wouldn't prefer to target lisp to such an environment.
- TomMarius 7y agoYes, what you are saying, but that can be optimized very well after the proposals come through.
- pjmlp 7y agoMy Intel CPU also doesn't have garbage collection or eval opcodes and yet it runs Lisp...
- 7y ago
- mwcampbell 7y agoIIUC, Lua also handles multiple return values the way you're advocating. I like the way Lua does it.
- nixpulvis 7y agoI feel like you could do the same thing with tuples and "splats", like in Ruby. Just wrap your values in thunks, and call it the same.
- aidenn0 7y agoYou can't because in CL if you only want first return value, you can pretend that the function only returns one value. For example, the CL integer division functions (it has each of floor, truncate, and round) all return the remainder as a second value, but you can ignore that fact if all you wanted was division: (floor 5 3) -> 1 ; 2 (let ((x (floor 5 3)) x) -> 1 (setf (values x y) (floor 5 3)) (list x y) -> (1 2)
- nixpulvis 7y agoWell seeing as I can't find an optimization in CLISP for changing the underlying div instruction, I'm assuming this is going to run the same. Is this correct? My only point here is, I guess, that a thunk (0 argument function) acts a similar way. If we had need to call two instructions (or increase bitwidth) this might suffice: def floor(n, d = 1) [-> { n.div(d) }, -> { n.modulo(d) }] end p *floor(10.3) #<Proc:0x0000558aeacdbc00@s.rb:4 (lambda)> #<Proc:0x0000558aeacdbbd8@s.rb:4 (lambda)> p floor(10.3).first.call # 10 p *floor(10.3).map(&:call) # 10 # 0.3000000000000007
- aidenn0 7y agoI guess my point is that multiple values are transparent; lots of times there are functions for which it's sometimes useful to have auxiliary values, but most of the time the primary value is all that is needed. There are certainly arguments for why this might be a bad idea (if your the sort of person who likes rich type systems, you're unlikely to like this), but there is no way to do this in WASM efficiently, while there is for pretty much all real machines. FWIW, I'm not sure about CLISP; I haven't used it for almost 20 years. Sbcl and ccl will both omit the calculation of the modulo when it is not needed. The ergonomics of a thunk or a tuple are different.
- aidenn0 7y agoAFAICT this is very different from lisp's multiple values because, unlike lisp, you need to explicitly handle any extra values.