In Ruby:

```
123.to_s[0].to_i # => 1
87.to_s[0].to_i # => 8
0.to_s[0].to_i # => 0
```

What’s the Crystal equivalent code?

In Ruby:

```
123.to_s[0].to_i # => 1
87.to_s[0].to_i # => 8
0.to_s[0].to_i # => 0
```

What’s the Crystal equivalent code?

123.to_s[0…0].to_i

Thanks @bcardiff.

Correction: `to_s[0..0]`

instead of `to_s[0...0]`

(2 dots, not 3).

I searched all over the docs for `to_s`

but couldn’t find this example.

Where is this shown/explained?

Let me say that the net result of the expressions is the same in Crystal.

`String#[0]`

returns the first character as a `Char`

, and if the char is a digit in base 10 `Char#to_i`

returns it as an integer, which is guaranteed to be the case because we start from non-negative integers:

```
% crystal eval '[123, 87, 0].each {|n| p n.to_s[0].to_i}'
1
8
0
```

The inner workings are different because `String#[0]`

returns a string in Ruby (nowadays), and because `String#to_i`

does not raise as `Char#to_i`

could do with an arbitrary receiver.

So, the given examples work the same in Crystal, but whether that really matters depends on the real usage of that idiom.

1 Like

I would reach for something like

```
struct Int
def first_digit
n = self
while n >= 10
n //= 10
end
n
end
end
pp 123.first_digit
pp 87.first_digit
pp 0.first_digit
```

Since version 2.4 Ruby has `Integer#digits`

, so idiomatic Ruby would be `123.digits.first`

.

Maybe Crystal could have such method too.

Note however `123.digits`

return `[3,2,1]`

, not `[1,2,3]`

. So it should be `123.digits.last`

to get `1`

as in the original example.

Good catch, thanks!

For the record: The Ruby code has exactly the same results in Crystal. You don’t need range literals to specify the first character, a simple integer index works.

1 Like

I’ve actually given coding exercises to candidates where finding arbitrary digits is a useful path to solving it. This was the most elegant solution one candidate submitted (translated to Crystal):

```
struct Int
def digit(place, base = 10)
digit_count = Math.log(self, base).floor.to_i + 1
if place > digit_count
raise "Can't find digit #{place} of #{self}"
end
self // (base ** place) % base
end
end
123.digit(2)
```

Also it looks like the Crystal parser for syntax highlighting doesn’t distinguish the `//`

integer-division operator from an empty regex.

If I remember correctly the Ruby discussion boiled down to this.

Since a decimal integer `123456789`

can be decomposed to its base 10 exponents: `9*10^0 + 8*10^1 +..+ 1*10^8`

, the exponents correspond to the array index, so you can do n.digits[d] to easily get the digit you want. The array is also easier to generate by just slicing off the LSD and shifting, as the algorithms show.

Thus, Ruby went with `123.digits => [3, 2, 1]`

as `43210.digits[0] => 0`

makes sense, as there’s always an LSD as `n[0] * 10^0`

.

Also in Ruby `digits`

doesn’t work for negative integers (which it shouldn’t conceptionally, because the negative sign is not a digit), so to get the digits of the number you just do `n.abs.digits`

, and go forward from there.