For vs forEach

In the classic iterative factorial function you can do:

var total = one
(two rangeTo x).forEach{i -> total *= i}

or

var total = one
for (i in two rangeTo x) { total *= i }

(Seemingly a bit weird code due to using BigInteger – Integer and Long are simply not up to the task of calculating factorials.)

Which of these Kotlin statements is deemed more idiomatic?

(Is the Kotlin equivalent of Python’s Pythonic, Kotlinic?)

This was discussed here: for vs forEach · Issue #33 · Kotlin/kotlin-style-guide · GitHub
In this case, I’d definitely go for for.

(Also, you don’t need to invoke rangeTo as a method; you should use the .. operator instead.)

1 Like

You are folding the collection. The example below uses integers:

val total = (2..x).fold(1) { total, value -> total * value }
1 Like

Any way, if I do more than one thing, I will choose for; forEach is just a method reference or side effect change

I am not convinced myself about not using forEach, but if using for is the preferred style, I have no problem.

I believe I do need the rangeTo since … is not defined for BigInteger and I therefore have to define a rangeTo operator.

I actually have that solution as well. This is a collection of different algorithms achieving the same goal I have the fold version, my question was the most idiomatic representation of the iterative version.

Defining the rangeTo operator is what allows you to use ..

Using rangeTo works, but if I use … I get a “For-loop range must have an iterator() method”. So I guess my support code is missing something.

I generally prefer to use ‘for’ unless I don’t need a control variable in the body when I use forEach instead.

On your last point, ‘Pythonic’ is already an English word whereas ‘Kotlinic’ is not and so the former ‘sounds right’ to me but the latter does not.

As a portmanteau word, I think I prefer ‘Kotlinesque’ to ‘Kotlinic’.

The downside of Kotlinesque would be that Pythonesque is a very negative description: Pythonic – your code is in harmony with the Python infrastructure; Pythonesque – your code has the look and feel of a series of Monty Python’s Flying Circus.

I think I’m right in saying that Guido van Rossum named his language after Monty Python’s Flying Circus so Pythonistas might not necessarily object to ‘Pythonesque’ to describe the language’s idioms. In fact, according to this link the word is sometimes used in this sense.

Perhaps we don’t really need an adjective for Kotlin in any case. Running through a list of the most popular languages (Java, C, C++, C#, JavaScript etc.) I can’t think of a suitable adjective for any of them.

During my Python workshops I used Pythonic as good and Pythonesque as bad to instil in people a sense of being idiomatic and in sympathy with the language and underlying runtime. Maybe I was abusing the term Pythonesque, but it worked for the audience.

The languages you mentioned are all old languages and suffer from style wars and thus doubt and uncertainty. Also a lot of poor code. Languages such as Go, Rust, Ceylon, etc. try to encourage (well Go totally enforces) a single style of code that everyone will use. This avoids style wars. Also as a side effect it makes it a lot harder to write non-idiomatic code. This I think is a good thing. Whilst I have lots of disagreements with the one-and-only Go format style, that there is only one removes a whole collection of decisions a programmer has to consider. So Go removes a whole dimension of style, and thus a whole dimension of idiomatic.

Anyway, in one sense you are totally right “idiomatic” serves for all languages. It is nice though that “idiomatic Python” can be shortened to Pythonic.

Might also want to consider tail recursion as an alternative:

val BigInteger.factorial : BigInteger
    get()
    {
        tailrec fun factorial(n: BigInteger, total:BigInteger) : BigInteger
            = if(n > BigInteger.ONE)
            	factorial(n - BigInteger.ONE, total * n)
            else
                 total
        
        return factorial(this, BigInteger.ONE)
    }

Apologies for seeming to disappear for over a year.

Tail recursion clearly beats recursion in this situation, but iterative with reduce/fold or for loop still wins performance wise – at least with the slightly unscientific measures I have.

You example is though really helpful since I should always have done the examples as extension methods on BigInteger!

Took a look at what gets generated and it looks like what is hurting it performance wise is that it keeps checking for nulls because it doesn’t realize that BigInteger subtraction and multiplication calls will not return null. Don’t know if the new contracts stuff will help with that. It is even checking BigInteger.ONE to make sure it is not null each time.

Seems like some work here might be useful. BigInteger and BigDecimal are critical a lot of calculations in bioinformatics, finance, etc. Python, R, and Julia are the incumbents in this space and without performance Kotlin will not compete.

JVM compiler can remove null checks and dead code, JVM bytecode is really far to C2 output.

It CAN, but would be much better to not have to put them there in the first place.

1 Like

There is a compiler option to disable all the null checks. Perhaps it would be worthwhile to have an annotation that can disable it on a smaller scale. Of course in some cases the explicit null checks can actually speed things up as the jit doesn’t need to be as careful afterwards.