Specify operator precedence for infix functions


#1

I’m thinking of adding some Kotlin extensions to the jOOQ library. One interesting thing might be to make use of infix functions, e.g.

infix fun Condition.and(other: Condition): Condition {
    return this.and(other);
}

infix fun Condition.or(other: Condition): Condition {
    return this.or(other);
}

This would allow for expressions like:

(A eq 1) or ((B eq 2) and (C eq 3))

However, note the need for explicit parentheses around all sorts of expressions, specifically to give and an explicitly higher precedence than or, which is the expected behaviour in most languages (e.g. SQL). I guess I’d rather not use infix functions this way, it would be rather confusing for users.

Is there a way to specify operator precedence for infix functions in Kotlin or are there any plans to support this in the future?


#2

No, there is no way to do that, and we don’t currently have plans to support this in the future.


#3

OK, thanks.


#4

However, overloadable &, |, ^ are on the table: https://youtrack.jetbrains.com/issue/KT-1440
The were present in the most recent community feature survey, but were not quite popular.


#5

Thanks for the pointer. Interesting. I’ll comment directly on there as well.

I suspect that overloading pre-existing operators will mean that precedence is inherited. Yet, when people “rename” && as and, || as or, yet the readable versions do not inherit the expected precedence, things get a bit weird…


#6

Hi @lukas.eder - since this thread is dead or on its last breath I would like to use the opportunity to digress a little.

  1. A really big thanks for considering JOOQ port for Kotlin. Operator overload would have been nice here - but I hope you will still see that Kotlin gives the opportunity for better syntactical representation of JOOQ.
  2. I have done a smallish but complicated project using JOOQ with Kotlin and really want to tell you -

WELL DONE! The learning curve was tiny, the constructs felt as natural as Java permits, all aspects were extremely well thought out; the utilities were easy, assistance and documentation was forthcoming when needed - and best of all - the Kotlin calls to the Java generated code didn’t feel too alien; even multi-tennant with Spring in no time. Your feedback on listening to suggestions is also heartwarming and appreciated.

Again - WELL Done and thanks.

Regards,
Gawie


#7

@Gawie_Kellerman thanks for your nice words. Well, I don’t think we’ll port jOOQ to Kotlin :slight_smile: but there’s a low hanging fruit with these inline / infix / operator functions in Kotlin, which work out of the box with existing Java API, which is a really nice Kotlin feature (the same is true with Scala’s implicit functions). Of course, any help in the right direction would be great, too! Perhaps, this doesn’t work for actual operators (which rely on precedence), but it might work with ordinary SQL syntax.

So, I’m currently gathering information on what could potentially be done in a new jOOQ-kotlin-extensions module. One thing is adding component1…N functions to Record[N] for type safe auto-unstructuring records to local variables: https://github.com/jOOQ/jOOQ/issues/6245


#8

Any changes?

We’re building a query DSL and not having precedences is problematic. If you read

Before(date) or After(date) and Before(msg)

you expect

Before(date) or (After(date) and Before(msg))

but get

(Before(date) or After(date)) and Before(msg)

#9

Still no plans, sorry.


#10

I suspect that overloading &, | and ^ might have been more popular if it had been better explained in the survey what they were supposed to be overloading in the first place.

Whilst it would arguably have been better if Kotlin had implemented the ‘traditional’ bitwise operators (&, |, ^, ~, <<, >>) in the first place, it seems to me that this ship has now sailed and we should therefore concentrate on improving the corresponding infix operators so that they have an assignment form (x and= y, or whatever) and that there is some way of controlling the priority.

It is sometimes forgotten that and, or and xor can also take boolean operands as well as integer operands even though they are rarely used. The only reason I can think of why the first two would be preferred to && and || is because you always wanted the second operand (perhaps a function call) to be evaluated because of some side effect. However, even in C programming, this is considered bad practice nowadays and so they are virtually useless in Kotlin itself.

I could therefore see the sense in the boolean versions of these infix operators being replaced by &, | and ^ as it would break very little code and make these operators available for overloading in DSLs etc. An assignment form would then be no problem and the priority would be what (most of us) would expect


#11

This ship hasn’t sailed; overloading &, | and ^ is still on the table and far more likely to be implemented than the possibility to specify priorities for infix functions or to call them as part of an augmented assignment.