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

Developers in other languages know the performance characteristics of list.delete because there is only one implementation throughout 99% of their codebase. Go you have to look at the implementation every single time to make sure its doing the right thing.


Haskell documentation uses the Big O notation everywhere which I really love. I wish Go and many other languages did the same.

An example would be https://hackage.haskell.org/package/containers-0.4.0.0/docs/....

  size :: Map k a -> IntSource
  O(1). The number of elements in the map.

  member :: Ord k => k -> Map k a -> BoolSource
  O(log n). Is the key a member of the map? See also notMember.

  lookup :: Ord k => k -> Map k a -> Maybe aSource
  O(log n). Lookup the value at a key in the map.
And so forth...


Redis does the same; e.g. [1]:

> Time complexity: O(N) where N is the number of elements to traverse to get to the element at index. This makes asking for the first or the last element of the list O(1).

I agree this is something more documentations should do when possible; it doesn't even have to be big-O notation as far as I'm concerned, just a "this will iterate over all keys" will be fine.

Ruby's delete() doesn't mention any of this, although you can easily see the (C) implementation in the documentation[2]. In principle at least, this doesn't have to be O(n) if the underlying implementation would be a hash for example, which of course has its own downsides but something like PHP may actually do this with their arrays as they're kind of a mixed data structure? Not sure.

[1]: from https://redis.io/commands/lindex

[2]: https://ruby-doc.org/core-3.0.0/Array.html#method-i-delete


Redis's documentation is wonderful, I wish every system I use were documented even half as well.


In the C++ standard the complexity of algorithms is a requirement for a compliant implementation. Many text books skip it, but better documentation references it. Taking the "delete element from list" example from this thread https://en.cppreference.com/w/cpp/container/list/remove states that there is a linear search.


Andrei Alexandrescu has a scheme to encode these in the D typesystem on his website. It didn't get merged into the standard library in the end but you can happily do it in your own code


My experience is that developers in other languages have no idea of the performance characteristics of list.delete. It seems low-level and therefore obviously fast.


"Fancy algorithms are slow when n is small, and n is usually small." Rob Pike, creator of Go.


Not at the scale of his employer.


You don't need to be Google scale. Google scale is just "medium large startup" scale replicated across a zillion regions. Gmail has an enormous amount of data behind it, but it's not like calling foo.sort() is going to be iterating over billions of accounts.


But isn't usually when using lists performance is dead anyway (due to cache misses).


"List" is usually a generic term for any data structure that can hold many items, and that has an API for adding or removing items. This can be implemented using an array, a linked-list, a hasthable, or a more advanced data structure.

Also, in languages with GCs, linked lists do not necessarily cause more cache misses than arrays, due to the way allocation works (this is especially true if you have a compacting GC, but bump-pointer allocation often makes it work even when you don't).


Linked-lists, maybe, but `list`s in Python are just resizable arrays.


resizable arrays of pointers to objects stored elsewhere, which is going to blow through your cache anyway, especially when you start accessing those objects' attributes. so it's more a memory management strategy than a performance optimization.


But when removing an item it’s not necessary to visit every element, just re-arrange the pointers (and in CPython, modify the reference count of the item that was removed).


When removing an item by value (being the use case in this thread), you do need to visit the elements to check the value.


Yes but the problem there is not that your list is backed by a linked list or an array, it's that every single value is boxed and needs dereferencing. The difference between no hops and one hop totally trumps one hop vs two hops.


You can write a list data structure with performant 'delete' properties if you're willing to maintain a sort or a hash table. There would be people here bitching about memory usage if the stdlib did that natively. Here's a solution: don't use list.delete. You're using the wrong data structure if that's your solution to whatever collection you're maintaining.


Downvotes on comp sci 102. Nice.


We have this saying in my country "if grandma had a mustache she'd be a grandpa".


I like my country's version better: "if grandma had wheels she'd be a bicycle".


Which language/country is this?

I will use this in English regardless. I like it.


Mexican Spanish. I don't know if they also use that saying in other Spanish speaking countries besides Mexico. In Spanish it goes: "Si mi abuelita tuviera ruedas, sería bicicleta".


If your aunt had nuts she'd be your uncle


That has the same basic idea as the mustache version, but is pithier. I still prefer the surrealism of the bicycle.


You'd probably do better on HN to substitute 'decrying' for 'bitching'.


Noted, thanks. Didn't realize that was the issue.


Yes!

Perfect example: Datetimes. In Golang, if you want to convert a string to a datetime (or vice versa), you _need_ to look at the godoc for datetime because it uses very specific permutations of "Jan 2, 2006" that you _have_ to include in your code. This is much more confusing than how this would be done in Python (provide the format of the date using ISO8601 notation) or Ruby (provide the string, get a Datetime, done).




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

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

Search: