1
$\begingroup$

Assume that you are writing sorting algorithms, and that you want the ability to select between ascending and descending order. The only change required to do this for comparison sorts is to use the inverse of the comparison operator (for example: > becomes <). This begs the question, why is it not possible to change operators on the fly?

A simple bubble sort for ascending order:

private T[] BubbleAscending(T[] sortMe)
    {

        bool stopMe = true;
        int stopRecurse = sortMe.Length - 1;
        int optimizeMe = stopRecurse;

        for (int i = 0; i < stopRecurse && stopMe; i++)
        {
            stopMe = false;

            for (int j = 0; j < optimizeMe; j++)
            {
                if (sortMe[j].CompareTo(sortMe[j + 1]) > 0)
                {
                    Swap(sortMe, j, j + 1);
                    stopMe = true;
                }
            }

            optimizeMe--;
        }

        return sortMe;
    }

Now we have to have a Bubble sort for descending order:

private T[] BubbleDescending(T[] sortMe)
    {

        bool stopMe = true;
        int stopRecurse = sortMe.Length - 1;
        int optimizeMe = stopRecurse;

        for (int i = 0; i < stopRecurse && stopMe; i++)
        {
            stopMe = false;

            for (int j = 0; j < optimizeMe; j++)
            {
                if (sortMe[j].CompareTo(sortMe[j + 1]) < 0)
                {
                    Swap(sortMe, j, j + 1);
                    stopMe = true;
                }
            }

            optimizeMe--;
        }

        return sortMe;
    }

Now we have to have some logic to allow the user to easily select between them:

public T[] BubbleSort(T[] sortMe, bool descending)
    {
        if (!descending)
            return BubbleAscending(CopyArray(sortMe));

        else
            return BubbleDescending(CopyArray(sortMe));
    }

Wouldn't it be much simpler if we could do this?

public T[] BubbleSort(T[] sortMe, bool descending)
    {
        if (!descending)
            operator comparison = >;

        else if (descending)
            operator comparison = <;

        bool stopMe = true;
        int stopRecurse = sortMe.Length - 1;
        int optimizeMe = stopRecurse;

        for (int i = 0; i < stopRecurse && stopMe; i++)
        {
            stopMe = false;

            for (int j = 0; j < optimizeMe; j++)
            {
                if (sortMe[j].CompareTo(sortMe[j + 1]) comparison 0)
                {
                    Swap(sortMe, j, j + 1);
                    stopMe = true;
                }
            }

            optimizeMe--;
        }

        return sortMe;
    }
$\endgroup$
4
  • 3
    $\begingroup$ It's possibile and it's a common approach in many standard libraries. E.g. std::sort (C++ <algorithm> library) accepts a user defined comparison function object. Even qsort (<stdlib.h>) accepts a comparison function. $\endgroup$
    – manlio
    Commented Jun 11, 2016 at 7:24
  • 1
    $\begingroup$ I don't see an actual question here. In any case, this much code is off-topic. This is very likely to be closed but, if you can clarify what your actual question is, and express the ideas in a generic way, such as with pseudocode, the question will be considered for re-opening. $\endgroup$ Commented Jun 11, 2016 at 10:40
  • $\begingroup$ It is a generic question about why it isn't easy to manipulate operators on the fly as an object. Interpret the code as C-like psuedo code, it's much easier to read and understand than standard Basic like psuedo code. I used this language as an example because that's the language I'm most familiar with and allowed me to easily express my question with an example. All code was written on site and isn't copy pasta-ed over. $\endgroup$ Commented Jun 12, 2016 at 17:45
  • $\begingroup$ You want to treat functions as values, which is a feature in many languages. $\endgroup$
    – Raphael
    Commented Jun 18, 2016 at 23:10

1 Answer 1

1
$\begingroup$

Welcome to the wonderful world of functional programming and the lambda calculus!

The answer is, there is no reason that you can't do this, and most sufficiently modern programming language (and some ancient ones i.e. LISP) will let you do this.

In a language with first-class functions, functions are data. You can treat them as variables, pass them as parameters, define them as lambda expressions (i.e. a nameless function). So in most languages, you can do something like this:

if (descending)
  comparison = lambda x y -> x < y
else 
  comparison = lambda x y -> x > y

The lambda is just a way of saying "comparison a function which takes two arguments and returns the value after the ->".

Treating functions as data is an idea as old as computer science itself: lambda calculus was developed by Alan Turing's supervisor, Alonzo Church, in the 1930s.

Not being able to do this is a restriction of C and Java (although new versions are introducing lambdas), and a few other languages.

What you've shown is probably not possible because it's hard to parse (most parsers rely on the fact that < and > are special characters), but if you treat comparison as a normal function instead of an infix operator, and use a language that allows for higher-order functions, you can indeed do this, and in many cases it is preferable.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.