Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

There isn’t a consistent single way to implement a red black tree with cons though, which I think is OP’s gripe.


Why does there need to be a single consistent way to implement something with cons? That's an odd complaint. What language would the OP be happy with if they want one singular, canonical way to implement everything?


To be clear, I'm steal manning his argument as I'm not sure I agree with it. But I think the point is summarized best with an example: "Here's an API that takes a red-black tree as an argument." Okaaay, what format is the red-black tree? How do I construct one?

In Lisp you'd pretty much have to ship your module with its own tree-construction logic, or use some common (but importantly, not technically standard) implementation, and document that's what you did, so people know how to structure the data they pass to you.

In C++, you simply take a std::map, which implements a red-black tree for you, and being part of the standard library it is accepted and commonly used nearly everywhere.

I think OP wishes Lisp had something like std::map.


Cons cells aren't the only data structures in Lisp. And there are libraries, packages, that you can use if you want a common structure across multiple projects.

> To be clear, I'm steal manning his argument as I'm not sure I agree with it. But I think the point is summarized best with an example: "Here's an API that takes a red-black tree as an argument." Okaaay, what format is the red-black tree? How do I construct one?

If the API calls for taking a red-black tree as an argument, it will also provide either the specific red-black tree implementation itself or it will refer you to an existing package to include as a dependency. This is not dissimilar from C++. In C++ if something takes a std::map, you use a std::map. If it takes another data structure that's not in the STL, then it will provide it or tell you how to obtain it as a dependency.

BTW: steel, not steal, manning.


The ergonomics of the language and ecosystem are so much better when there is a standard container implementation. See for example the annoyance of using a hashmap in C++ for the first few decades of its existence.


That's a poor example to use for criticizing Common Lisp, it has had hash tables for decades.


I don’t think I ever mentioned Common Lisp?


I mean, in Lisp your go-to structure will likely be unbalanced trees

Which like Quicksort (nearly the same analysis btw), has exceptional average case performance (even faster than RB trees on the average !!!!) but the downside of horrific O(n^2) performance on the worst case.

RBTrees or AVL trees all help at improving those worst cases (AVL strangely has its best case be the worst case of unbalanced trees lol).

In any case, there's a lot of tree flavors. Lisp is certainly sufficient and simple when it's exploring these different details.

Unbalanced trees, in any case, is actually a reasonably sane default. RB Tree or AVL is probably a better default but don't knock the unbalanced tree before you try it!!

------------

I've heard of highly optimized lisps where the typical list is turned into an array or at least a rope in the average case btw.


>In any case, there's a lot of tree flavors. Lisp is certainly sufficient and simple when it's exploring these different details.

I've become a fan of scapegoat trees¹ lately for (immutable) balanced trees. There are certainly a ton of other options besides RB and AVL trees that are fun to explore (in any language)

>I've heard of highly optimized lisps where the typical list is turned into an array...

Back in the lisp machine days there was CDR coding² to flatten out a list into a contiguous block, but I'm not sure if any modern common lisp or scheme implementations use it.

[1]: https://en.wikipedia.org/wiki/Scapegoat_tree

[2]: https://en.wikipedia.org/wiki/CDR_coding




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: