Re: table.sort: invalid order function for sorting

Francisco Olarte <[email protected]> Fri, 24 Apr 2026 19:38:15 +0200
Newsgroups gmane.comp.lang.lua.general
Message-ID <CA+bJJbwyfD5Q2xGeNsz+cYrX2mWpU361kU0U5CvxBEy8PXnySA@mail.gmail.com>
On Fri, 24 Apr 2026 at 16:52, 'Martin Eden' via lua-l <
[email protected]> wrote:

>
> I've thought about current Lua's approach. Requiring strict ordering
> (with inherited irreflection) makes some sense if we want to minimize
> number of calls of comparison function.
>
> But for me it's schizophrenic: trying to fit tertiary value into binary.
> For me linear order comparison has three values: less, equal, greater.
> You can't fit them into boolean and build sorting algorithm on that
> without discovered side effects.
>

When you implemented sorting stuff, you learn the hard way using binary
less-than is better.


> If someone wants to use boolean comparators - he still needs two of them.
> For example is_less() and is_equal(). Of course I won't be happy
> to provide two almost identical blocks of code for them.
>

No, you do not. a==b can be done by ~((a<b) or (b<a))

But unless you are doing weird stuff you do not normally need it, as when
you do a sorter you do not target a[i]<=a[i+1], you just target
not(a[i+1]<a[i]). Testing too much makes a lot algorithms slower.

i.e., when you do quicksort you choose a pivot, but you do not split the
array in <pivot, ==pivot and >pivot, you just split in <pivot, pivot,
not(<pivot). Sure, in arrays with zillions of dupes "fattening" the pivot
may be a win, but normally it is a looser.

In bubble sort ( unused but known sweep-swap sorter ) you do not test three
way, you just swap neighbours if out of order ( IIRC this also makes it
stable, which may make it a good candidate for microsorts ). Similar things
can be done with insertion or selection sort, which you should always use
in place of bubble, that is for dydactic purposes only. And merge sort can
also be done with one less-than usage per loop.

And in similar problems, like bsearch, you do similar things. A naive
algorithm for bsearch may do start with l=1, h=#t, m=(l+h)//2, if m==x then
return m, if m<x then l=m+1, else h=m-1, rinse and repeat.

But faster algorithms normally find the insertion point. They start with
l=0, h=#t+1 ( so you know the possible position is after l before h ), get
m, and then do if(m<x) then l=m else h=m, faster in the loop, and then,
when l-h<2 you know the insertion point, if present, is at m. Then, if you
wanted to find it you check if the insertion point is in the array and if
the element there is equal.

Sorting and searching algorithms are full of this kind of things.


> For me requirement of comparison function to return one of three values
> is more natural and acceptable than providing fragile sorting algorithm
> for binary comparator.
>

It is initially easier to grok, been there. Once you implement some dozens
you normally find boolean comparators lead to shorter, simpler and more
robust code ( well, once debugged all sorting algorithms are robust ).


> You can't even easily invert sorting like:
>
> -- Ascending sort
> table.sort(Orders, function(a, b) return DateIsLess(a, b) end)
>
> -- Descending sort? Nah! Wandering runtime error!
> table.sort(Orders, function(a, b) return not DateIsLess(a, b) end)
>
> You can not do it that way, but you are falling in a trap:

table.sort(Orders, function(a, b) return DateIsLess(b,a) end)

is shorter and works. Lua reference is terse, but this example is found in
lots of places.


Francisco Olarte.

-- 
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/lua-l/CA%2BbJJbwyfD5Q2xGeNsz%2BcYrX2mWpU361kU0U5CvxBEy8PXnySA%40mail.gmail.com.