Algebraic values for (in)identity//in)equality expressions

Say you have a function that takes several mullable arguments, and the first thing you do in tue function’s body is return early if one of the arguments is null. So you would have something like

fun someFun(a: A?, b:B?, c:C?, d:D?, e:E?, f:F?){
    if( a == null || b == null || c == null || d == null || e == null || f == null) return
    //do actual work here
}

Now, in english, this would read as 'if a is null, or b is null, or c is null, or d is null, or e is null, or f is null, then return". However in english we express in a more sccint way, by OR’ing the operands: “If a, b, c, d, e or f are null, then return”. I’d be nice if we could have a counterpart of this in syntax:

fun someFun(a: A?, b:B?, c:C?, d:D?, e:E?, f:F?){
    if( (a | b | c | d | e  f )== null) return
    //do actual work here
}

I use “|” instead of “||” to not make “||” polysemic, since “|” is unused in kotlin (weirdly so, IMHO), but using “||” would be just as good for me.
Of course for completion’s sake, I’d also propose having (a & b & c & d) == e with the intuitive meaning you would expect from it.

Why not do it functional way?

fun allNull(vararg args: Any?) = args.all{it == null}

fun anyNull(vararg args: Any?) = args.any{it == null}

if(anyNull(a, b, c, d, e, f)){...}
1 Like

Sure I can do that, and I by no means think the suggestion would be critical or anything. But just for the sake of the srgument, I would say my suggestion saves some allocations (varargs are translated to allocating an array, if I’m not mistaken).

Because new expression (a | b | c | d | e | f ) (I assume you missed last |) is used in super expression it should return the value.

What would be the type of that value? Probably some kind of collection.

Will be all expressions separated by | evaluated up front or each separated as needed?

I envisioning someFun(a | b) as being translated to someFun(a) || someFun(b). Not sure how to fit that in the type hierarchy though.

but your example doesn’t include someFun(…). instead (a | b | c | d | e | f ) == someExpression.

Converting this into your first example makes compiler unnecessarily complex. At the point it riches closing parentheses it doesn’t have enough info to complete handling it. This is what Kotlin syntax tries to avoid.

Oh, maybe this is something I took for grsnted, let me explain:

In the kotlin reference, it is stated that operators can be overloaded by overloading some specific functions (say, equals(…) ). Thus I was treating the == as any other function, just with syntax sugar.

So, my motivating example uses == by the idea is that the feature be appliable to any function.

Regarding the point of the compiler not having enough information when it reaches the closing paren, then forbid (b |c) ==a but at least a == ( b | c ), since that should give no problems.

Naturally operators like == are communicative which means that a==b is the same as b==a. This is especially true in Kotlin where operator handles null value gracefully. You suggesting to break this.

Also both sides of == operator are expressions. This is why I am asking what would be the type of the proposed expressions. What expression (a | b | c) == (d | e | f) means?

1 Like

Not saying it is better but this is possible in Kotlin:

if(a?.run{b}?.run{c}?.run{d}?.run{e}?.run{f} != null)

If you are OK with using a word instead of a symbol, you could also define an infix function:

infix fun Any?.OR(other: Any?) : Any? = this?.run{ other }

and then you can do:

if(a OR b OR c OR d OR e OR f != null)