goparametersparameter-passinginfix-operator

How to Use Infix (Comparison) operators as parameters in Go


In GoLang, it is possible to use functions as parameters, such as in this simple example that compares two numbers based on either the less than or equal to (<=) or greater than or equal to operator (>=)

package main

func leq(x, y int) bool {
    return x <= y
}

func geq(x, y int) bool {
    return x >= y
}

func compare(x, y int, comparator func(int, int) bool) bool {
    return comparator(x, y)
}

func main() {
    println(compare(3, 5, leq)) //true
    println(compare(5, 3, leq)) //false
    println(compare(3, 5, geq)) //false
    println(compare(5, 3, geq)) //true
}

Is there a way to have infix operator, rather than a function, as a function parameter?

Such as:

func compare(x, y int, comparator <something here>) bool {
    return comparator(x, y)
}

func main() {
    println(compare(3, 5, <=)) //true
    println(compare(5, 3, <=)) //false
    println(compare(3, 5, >=)) //false
    println(compare(5, 3, >=)) //true
}

Or is my best bet just writing the wrappers for the operators as in the first example?

Additionally, if the above is possible, is it possible to use the infix operator parameter with infix syntax? Such as

func compare(x, y int, c <something here>) bool {
    return x c y
}

Solution

  • No, this is not a correct program according to the Go language specification.


    The function type is defined to contain, among other terms, a list of parameters which each consist of a parameter declaration: [ IdentifierList ] [ "..." ] Type.

    This requires that all parameters to functions have types, specified as the production Type, thus:

    TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
              SliceType | MapType | ChannelType
    

    The built-in operands (such as equality and comparison operators) are language-internal and not exposed here as possible type literals.

    Moreover, the specification for function calls requires that arguments in a call are single-valued expressions. Binary operators are not themselves expressions.

    Accordingly, you may not pass "infix" Operators as arguments to a function call. You should define your own interface or function type which wraps the operator, and pass this to your comparison function.