Compiler can not parse integer with leading zero

No lines containing an integer literal with a leading zero will compile or execute in the REPL:

Linux> ./kotlinc/bin/kotlinc
Welcome to Kotlin version 1.2.40 (JRE 1.8.0_91-8u91-b14-1~bpo8+1-b14)
Type :help for help, :quit for quit

1
1
01
… ;
error: unexpected tokens (use ‘;’ to separate expressions on the same line)
01
^
error: expecting an element
;
^

I think a leading zero is not allowed because a lot of developers may think that the number is in octal then, and octal numbers are not supported: https://kotlinlang.org/docs/reference/basic-types.html#literal-constants

So a leading zero is used to indicate that you want to have another numeral system, and you have to specify which system you want: b for binary and x for hexadecimal.

Yes. I was just looking at the kotlin-spec (altough it is no longer up to date). It states

It is an error if a decimal literal other than 0 starts with digit 0. [Example: Literals 00, 007 are errors. End Example] [Rationale: Some programming languages use a leading zero to denote octal literals. Kotlin does not support octal literals, so without this rule there would be a possibility of difficult-to-catch mistakes when a user enters a literal starting with a leading zero and intends it to be interpreted as an octal literal, but the compiler simply drops leading zeros and interprets it as a decimal literal with a different numeric value than intended. End Rationale]

1 Like

var x = -01 also fails, and surely is harder to justify as an octal halucination deserving a parse failure.

If you look at the specs, this is explained as well. There are no negative number literals in kotlin. -1 is handled as a unary minus operator and a positive number one. Therefore the same rules with leading zeros apply. Also how would you write a negative number using octal if not as -01?

1 Like

Well, the answer is simple enough – when you enter octal digits on the control panel of your 8080 computer (typically to jump to the tape reader subroutine), there is no “minus” togle; the concept is missing in both reality and philosophy.

What I am trying to say is that the response to:

opt> echo “var x = 01;” > test.kts
opt> time ./kotlinc/bin/kotlinc test.kts

should not be:

test.kts:1:10: error: property getter or setter expected
var x = 01;
^
test.kts:1:10: error: unsupported [literal prefixes and suffixes]
var x = 01;
^
opt> time ./kotlinc/bin/kotlinc test.kts test.kts:1:10: error: property getter or setter expected
var x = 01;
^
test.kts:1:10: error: unsupported [literal prefixes and suffixes]
var x = 01;
^

real 0m56.445s
user 0m28.050s
sys 0m9.530s

is insufficiant to octal programmers and everyone else.

I hope the leading zero can be supported . As it make our code neater and cleaner :

截圖 2021-08-26 02.53.16

1 Like

Simple alternative: use numbers prefixed by _, and so you’ll need something like this:

const val _0 = 0
const val _1 = 1
const val _2 = 2
const val _3 = 3
const val _4 = 4
const val _5 = 5
const val _6 = 6
const val _7 = 7
const val _8 = 8
const val _9 = 9

and yeah it’ll do the job just fine.

1 Like

well , for 3-digit , I have to define :

const val __0 = 0

and for 4-digit :

const val ___0 = 0

It seems not so clever… :roll_eyes:

1 Like

If you’re at the point of using 3 or 4 digit numbers then I really don’t think readability matters anymore for single digits. But y’know what, sure:

inline val Int.i : Int get() = this

For readability, it basically looks like it is i for Int, I hope that that’s clear. Now, this can infinitely add 2 characters to any number, and so:

// 1 digit
0
// 2 digit
_0
// 3 digit
0.i
// 4 digit
_0.i
// 5 digit
0.i.i
// 6 digit
_0.i.i
// 7 digit
0.i.i.i
// 8 digit
_0.i.i.i
// 9 digit
0.i.i.i.i
// 10 digit
_0.i.i.i.i
// And so on...

// Lines up perfectly
println(6000000000)
println(_5.i.i.i.i)

The truth of the matter is that if you really really need ot squeeze that readability benefit from matching the line widths, then having those .i calls shouldn’t really hurt you that much.

Edit: and if you really care about seeing the digit in the last position instead of the first, then consider this implementation instead:


const val _0 = 0
const val _1 = 1
const val _2 = 2
const val _3 = 3
const val _4 = 4
const val _5 = 5
const val _6 = 6
const val _7 = 7
const val _8 = 8
const val _9 = 9

const val __0 = 0
const val __1 = 1
const val __2 = 2
const val __3 = 3
const val __4 = 4
const val __5 = 5
const val __6 = 6
const val __7 = 7
const val __8 = 8
const val __9 = 9

object I {
    const val _0 = 0
    const val _1 = 1
    const val _2 = 2
    const val _3 = 3
    const val _4 = 4
    const val _5 = 5
    const val _6 = 6
    const val _7 = 7
    const val _8 = 8
	const val _9 = 9
    
    const val __0 = 0
    const val __1 = 1
    const val __2 = 2
    const val __3 = 3
    const val __4 = 4
    const val __5 = 5
    const val __6 = 6
    const val __7 = 7
    const val __8 = 8
	const val __9 = 9
    
    val I: I get() = this
}

it works like this:

// 1 digit
0
// 2 digit
_0
// 3 digit
__0
// 4 digit
I._0
// 5 digit
I.__0
// 6 digit
I.I._0
// 7 digit
I.I.__0
// 8 digit
I.I.I._0
// 9 digit
I.I.I.__0
// 10 digit
I.I.I.I._0
// And so on...

// Lines up perfectly
println(6000000000)
println(I.I.I.I._0)

such tweaks are too bizarre…
I just hope kotlin compiler can support it. As java support this

Well… Java considers them octals, which is likely not what you want.

2 Likes