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

It's a convention, quite a nice one, but not all libraries are consistent and it does have different meanings too (! is sometimes used for "raise an error instead of returning a boolean").

In the Python case, `list.sort()` operates on the object, so you can kind of expect it to do mutation (but there's no convention / guarantee). Though it only makes sense as a function that the list object itself implements.

`sorted` is a general function that gives you a sorted list from any iterable, and because working with iterables is such a common thing in software, Python has a bunch of standard functions like that. It's nice because you learn them once and they apply absolutely everywhere.

Ultimately you learn the behaviours of a language and they become second nature. I find both Ruby and Python very clean and easy to read.



> it does have different meanings too

the meaning is the same high level: it has side effects, being it a destructive update, an in place operation or throwing an exception.

> `sorted` is a general function that gives you a sorted list from any iterable

iterable in Python is a very loose concept though.

And it's not very consistent too

    sorted("gheliabciou")
    ['a', 'b', 'c', 'e', 'g', 'h', 'i', 'i', 'l', 'o', 'u']
you give it a str it returns a list of char

in Ruby it makes much more sense

   "gheliabciou".chars.sort.join
   "abceghiilou"
You take out the chars from the string, sort them and then join them together again

because a string cannot be sorted, sorting a string makes no sense, you sort the chars composing it.

Also, Python could not do this for many years, while Ruby could no prob

  sorted("gheliabciouß⌚⌨⌛🆔🉑🈶🈚🈸🈺🈷🆚🉐㊙㊗🈴")

edit: Python also shows some very counterintuitive semantic

take the example above, to return a string you use

  ''.join(sorted("gheliabciou"))
  'abceghiilouß'
which is probably the last thing someone would think of.

sorting a list does not produce any output, because sort is _always_ in place, so you have to waste a variable to sort a list because you can't sort it inline

   list("fedcba")
   ['f', 'e', 'd', 'c', 'b', 'a']

   print(list("fedcba").sort())
   None # <-- where did the list go?

   # you have to do
   l = list("fedcba")
   l.sort()
   print(l)
   ['a', 'b', 'c', 'd', 'e', 'f']
again, highly unexpected

my favourite

  print([c for c in "bca"].sort())
  None # <- WTF? list comprehension is a functional concept!

  # this is how you "intuitively" do it
  print(''.join(sorted([c for c in "cba"])))
  abc


You can use emoji in HN comments? Emojis get automatically removed from mine.

Edit: ok, some do and some don’t. 🈶 is allowed but :laugh_with_tears: isn’t. I guess there’s a specific list of emojis that are getting stripped.



There are specific blocks that are filtered out.


Lots of objects don't have a natural way to return a sorted version of themselves, especially inplace (what's the reverse sort of a range, for example). You get the same in Ruby, as you've just demonstrated. Sorting into a list is the only thing that makes sense in all cases.

In that way `sorted` _is_ totally consistent - it always takes an iterable and returns a list of the elements. If we can't agree on that then I don't think there's much of a discussion to be had here.


> In that way `sorted` _is_ totally consistent - it always takes an iterable and returns a list of the elements

except Iterable is the wrong "interface"

in Python it is defined as

> An iterable is any Python object capable of returning its members one at a time, permitting it to be iterated over in a for-loop.

which is not always what you want for sorting

quicksort doesn't work one element at a time

so basically you have to extract all the elements before sorting them

what about infinite streams?

At least Ruby Enumerable mixins explicitly states that

> The Enumerable mixin provides collection classes with several traversal and searching methods, and with the ability to __sort__.

Another problem with sorted is that it accepts any iterable, true, returning a list of items, but it is not clear how you can tell if the object is an iterbale or not

  >>> sorted(123)
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  TypeError: 'int' object is not iterable
ok

  >>> isinstance(123, iterable)
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  NameError: name 'iterable' is not defined
mmmm

maybe it's because int is not iterable?

  >>> isinstace("abc", iterable)
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  NameError: name 'iterable' is not defined
so the solutions are

  # fails for strings in Python 2
  >>> try:
     _ = iter(some_object)
  except TypeError as te:
     print('is not iterable')
or

  # if 2.6 >= Python < 3.3
  from collections import Iterable
  # if Python >= 3.3
  from collections.abc import Iterable # <- personal note, abc stands for...? core maybe?
  # no idea on how to do it in Python < 2.6

  >>> isinstance("abc", Iterable)
  True
not only it's very ugly, but it can also fail in mysterious ways. As per documentation

Checking isinstance(obj, Iterable) detects classes that are registered as Iterable or that have an __iter__() method, but it does not detect classes that iterate with the __getitem__() method. The only reliable way to determine whether an object is iterable is to call iter(obj).

while in Ruby it's straightforward

  [3] pry(main)> [1, 2].is_a? Enumerable
  => true

  [4] pry(main)> "abc".is_a? Enumerable
  => false

  [5] pry(main)> "abc".chars.is_a? Enumerable
  => true




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

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

Search: