Hacker News new | ask | show | jobs
by nickjj 1767 days ago
I wonder if they looked into using https://github.com/asaaki/cmark.ex which is an already made Markdown Elixir NIF written in C. No glue code needed since the package already exists.

Back when I was writing Elixir, it's what I used to process Markdown and it was also substantially faster than the native Elixir Markdown library (Earmark).

4 comments

Author here. I actually was not aware of cmark.ex - thanks for pointing it out.

In this case the code reuse was more important than pure native speed. We already had a Rust library that used pulldown-cmark [1] with some custom tweaks that we wanted to duplicate. Maybe this behavior could have been copied using cmark.ex too (we thought about doing this in pure Elixir, as mentioned in the post), but given how straightforward Rustler made integrating our existing code, this seems like the better choice.

[1] https://github.com/raphlinus/pulldown-cmark

Before Rust, it seemed there was a law that every sufficiently critical code path would eventually be rewritten in C or C++.

After Rust, giving up a bit of performance to not have to maintain the C code underneath seems preferred. And often you don't even sacrifice performance.

> After Rust, giving up a bit of performance to not have to maintain the C code underneath seems preferred

Yeah no doubt about it, although in this case the C implementation has been a long running project that's under the official commonmark GitHub repo at https://github.com/commonmark/cmark.

But I think the most important thing here is an Elixir NIF already exists to use it. The blog post as is leaves readers having to implement ~100 lines of Elixir code to use the Rust version because the author of the blog post didn't include that code in the article, or open source it as a library for others to use.

From a reader's POV if your goal is to get a highly stable, fast and safe Markdown parser running in Elixir, the Elixir cmark library I linked in a parent comment solves that problem out of the box.

Yeah; I think people responding are taking your response as "they did the wrong thing". It sounds more like "Hey, here's another option that I've used in the past to solve that problem", leaving the evaluation of the relevant tradeoffs as an exercise to the reader (where it should be since you'd wait them differently for different projects)
Yea, I'd probably of ended up using cmark too.

It is nice though to learn about NIFs and rustler, there are a lot of high quality crates out there that you can wrap and take advantage of from elixir code once you get comfortable with doing it.

So possibly a sub-optimal approach, but the author indicates in another comment they had customized the rust version and wanted to be able to share code, which seems legit. Always good to stock up that toolbox though with more neat stuff, and rustler NIFs are seriously neat.

I’ve seen a major preference toward Rust for NIFs in Elixir land because of the guarantees. People like their BEAM guarantees and exiting the BEAM without strong guarantees feels risky.
Even if they did they may have preferred Rust because parsing arbitrary user provided input is one of the more risky things you can do in C. This is a perfect use case for Rust's memory safety model.