123 karma · joined July 12, 2010
There are online tools to help visualize regex's. Here is a recent tweet including a visualization of mal's tokenizer regex: https://twitter.com/Mehulwastaken/status/1382292764834996230
- Do you have some specific examples? The test cases are marked as either deferrable or optional. You shouldn't ever have to implement optional (and if so that's a bug in the tests or the guide). I think the deferrable items are marked pretty clearly in the guide where they become mandatory in later steps. If it's not clear, then that's a bug.
- This is one of the tensions that exists with trying to make the guide incremental; later features may require re-work of earlier functionality. I do try and minimize that as much as possible although I've found it can really vary depending on the nature of the target language. Note that the primary goal of mal/make-a-lisp is pedagogical (as opposed to say "the easiest way to make your own Lisp"). So sometimes the need to go back and re-work something is in line with that goal.
If you have any concrete guide text or test driver improvements (especially that further the pedagogic goals of mal), I'm always happy to review pull requests! :-)
make stats
or for more condensed form: make stats | egrep "Running|total|comments"It then grew into a personal learning tool for me for learning new languages. As I implemented more languages, I refactored the structure to make it more portable and incremental. At some point I realized that it might be an interesting learning tool for others so I wrote an early version of the guide and had a friend work through it and give feedback. He liked it enough that he immediately did a second implementation.
At some point the project got some twitter/HN attention and other people began contributing implementations and feedback for the guide.
Mal also serves as programming language "Rosetta Stone". A bit like rosettacode.org but using a full working project.
However, that being said, the following implementations are "smallish" (in both lines of code and bytes): mal itself (self-hosted), Clojure, factor, Perl 6, Ruby. The following are "largish": Awk, PL-pgSQL, C, PL-SQL, Chuck, Swift 2, Ada.
OCaml is in the "smallest" third of the implementations.
Note that this should obviously be taken with a grain of salt: the implementations were created by many different people each with their own style and differing experience levels with the target language. That being said, from my own experience, I think the concision (size) of the implementation often reflects how "Lispy" a language is. Most of the Lisps are in the top half of the list (fewest LOCs). Ruby is often described as very Lisp-like. Factor is one that stands out for me (second after mal itself). Factor also happens to be one of the fastest implementations (for certain microbenchmarks).
for i in $(make print-IMPLS); do \
s=$(make stats^$i | grep total); \
printf "%-9s %s\n" "$i" "$s"; \
done | sort -n -k2
I made a gist with the current results: https://gist.github.com/kanaka/fdef20f5d0c2e04b97d9106b2f2f2...But if you want to take another pass through the code now that it's not based on an ancient Rust version, I'm always happy to take any advice from the master. :-)
Lua does seem to be an odd one in that the short tests run quickly but this does not translate into iterations for the longer 10 second test. Perhaps the mal implementation is triggering bad GC behavior or something and that drags down the longer running tests. That's just speculation though. Again, please take the numbers with a mountain size grain of salt.
UPDATE: I will point out that the README is pretty clear that this is rust 0.13. Doesn't mean it's a good representation of rust 0.13 either of course, but it clearly isn't based on a recent version of Rust.
That did seem rather inefficient at the time but I wasn't able to discern the more efficient method at the time. I've kind of been waiting for Rust 1 to cycle back around. But I'll see if I might be able to address some of those and bump to Rust 1.0 alpha in the next few days.
Note the conversation about performance is kind of unfortunate. Those numbers should be considered VERY rough (they were just a personal notes file of mine). Also, with --release, the numbers place rust in the same range as other compiled languages.
The reason it still uses the alternate pcre is because this still hasn't been fixed: https://github.com/rust-lang/regex/issues/28 I would love to get rid of that nastiness.
- forth
- mal itself (e.g. self-hosting: all implementations can run this)
- miniMAL (Lisp interpreter in < 1024 bytes of JS)
- PostScript
- R
- Racket
Caveat, no GC. Although that could probably be added easily using the Boehm GC. I plan to do so at some point assuming nobody beats me to it.
I'm happy to take pull requests that make an implementation shorter and/or more idiomatic as long as it doesn't change the overall order/flow (and doesn't break any of the tests of course).
With noVNC the protocol decode/encode is done in the browser (modern browsers are plenty fast enough to do this easily), whereas with Guacamole the burden of decode/encode for every client happens on the server where the proxy/client part is running. Even if you need to run websockify to proxy/bridge noVNC, the only thing it is doing is shuttling network traffic and the python implementation of websockify can easily handle lots of simultaneous clients without breaking a sweat.
noVNC was designed with Infrastructure as a Server (IaaS) providers in mind so minimizing server CPU, memory and bandwidth was a goal in the design.
Also, guacamole does use websockets when it is available.
I just pushed type/record/protocol/reify support. Next big thing is to fix runtime namespace creation. Then file I/O. Then all the bugs discovered while try to compile the compiler using the compiled compiler (i.e. self-hosting).