Make integer conversion initializers failable

It appears that the current integer conversion initializers will either always work, possibly trap, or truncate:

init(_: Int)
init(_: Int8)
init(_: Int16)
init(_: Int32)
init(_: Int64)
init(_: UInt)
init(_: UInt8)
init(_: UInt16)
init(_: UInt32)
init(_: UInt64)
init(truncatingBitPattern: Int)
init(truncatingBitPattern: Int16)
init(truncatingBitPattern: Int32)
init(truncatingBitPattern: Int64)
init(truncatingBitPattern: UInt)
init(truncatingBitPattern: UInt16)
init(truncatingBitPattern: UInt32)
init(truncatingBitPattern: UInt64)

I suggest that we change trapping initializers to failable initializers. Initializers that can't fail (identity, unsigned -> bigger signed/unsigned, signed -> bigger signed) should keep a non-Optional type.

This could extend to changing SignedIntegerType's and UnsignedIntegerType's (U)IntMax to failable initializers as well.

I think I remember someone on the core team saying that someone's working on integer types at the moment. Is that right?

Félix

It appears that the current integer conversion initializers will either always work, possibly trap, or truncate:

init(_: Int)
init(_: Int8)
init(_: Int16)
init(_: Int32)
init(_: Int64)
init(_: UInt)
init(_: UInt8)
init(_: UInt16)
init(_: UInt32)
init(_: UInt64)
init(truncatingBitPattern: Int)
init(truncatingBitPattern: Int16)
init(truncatingBitPattern: Int32)
init(truncatingBitPattern: Int64)
init(truncatingBitPattern: UInt)
init(truncatingBitPattern: UInt16)
init(truncatingBitPattern: UInt32)
init(truncatingBitPattern: UInt64)

I suggest that we change trapping initializers to failable initializers. Initializers that can't fail (identity, unsigned -> bigger signed/unsigned, signed -> bigger signed) should keep a non-Optional type.

Personally, I would want to see any proposal along these lines also address arithmetic. I've asked for optional arithmetic before and the response has basically been that the case is too uncommon to be worth supporting with additional operators and they would prefer to see some way of modifying the behavior of arithmetic operations in a statement. I think these initializers are exactly analogous.

···

--
Brent Royal-Gordon
Architechies

I'm curious: how would you use the failable initializers? I feel like, more
often than not, you would end up force-unwrapping the return value, which
would produce the same result as trapping inside. But I guess in that case
you would make it clearer on the caller site that that can fail?

···

On Fri, Feb 12, 2016 at 9:23 AM Félix Cloutier <swift-evolution@swift.org> wrote:

It appears that the current integer conversion initializers will either
always work, possibly trap, or truncate:

init(_: Int)
init(_: Int8)
init(_: Int16)
init(_: Int32)
init(_: Int64)
init(_: UInt)
init(_: UInt8)
init(_: UInt16)
init(_: UInt32)
init(_: UInt64)
init(truncatingBitPattern: Int)
init(truncatingBitPattern: Int16)
init(truncatingBitPattern: Int32)
init(truncatingBitPattern: Int64)
init(truncatingBitPattern: UInt)
init(truncatingBitPattern: UInt16)
init(truncatingBitPattern: UInt32)
init(truncatingBitPattern: UInt64)

I suggest that we change trapping initializers to failable initializers.
Initializers that can't fail (identity, unsigned -> bigger signed/unsigned,
signed -> bigger signed) should keep a non-Optional type.

This could extend to changing SignedIntegerType's and
UnsignedIntegerType's (U)IntMax to failable initializers as well.

I think I remember someone on the core team saying that someone's working
on integer types at the moment. Is that right?

Félix

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Javier Soto

Are you thinking of something along the lines of is proposal?

It has been sitting as a PR for quite a while and not been merged yet.

-Matthew

···

On Feb 12, 2016, at 11:21 AM, Félix Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

It appears that the current integer conversion initializers will either always work, possibly trap, or truncate:

init(_: Int)
init(_: Int8)
init(_: Int16)
init(_: Int32)
init(_: Int64)
init(_: UInt)
init(_: UInt8)
init(_: UInt16)
init(_: UInt32)
init(_: UInt64)
init(truncatingBitPattern: Int)
init(truncatingBitPattern: Int16)
init(truncatingBitPattern: Int32)
init(truncatingBitPattern: Int64)
init(truncatingBitPattern: UInt)
init(truncatingBitPattern: UInt16)
init(truncatingBitPattern: UInt32)
init(truncatingBitPattern: UInt64)

I suggest that we change trapping initializers to failable initializers. Initializers that can't fail (identity, unsigned -> bigger signed/unsigned, signed -> bigger signed) should keep a non-Optional type.

This could extend to changing SignedIntegerType's and UnsignedIntegerType's (U)IntMax to failable initializers as well.

I think I remember someone on the core team saying that someone's working on integer types at the moment. Is that right?

Félix

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I could get behind this iff there's no performance impact. Otherwise,
I'd rather have the option to write a function than not have the
option of a performant conversion.

···

On Fri, Feb 12, 2016 at 12:10 PM, Félix Cloutier <swift-evolution@swift.org> wrote:

My use case is a small chess game where my Board class has a Location
indexer, and any Location object has a guaranteed value on the Board. The
Location struct handles adding signed deltas to coordinates and returns nil
when that location wouldn't exist. My coordinates are UInt8 values and the
"casting" code looks like:

private func intToU8(int: Int) -> UInt8? {
if int >= 0 && int <= Int(UInt8.max) {
return UInt8(int)
}
return nil
}

Of course, if UInt8's initializer returned an Optional instead of trapping,
I wouldn't need that function at all.

In general, I would also say that it's a good idea to make dangerous
behavior explicit. I think that Swift's model for converting integers is
already punishing enough that we might as well add the exclamation mark.

Félix

Le 12 févr. 2016 à 12:27:55, Javier Soto <javier.api@gmail.com> a écrit :

I'm curious: how would you use the failable initializers? I feel like, more
often than not, you would end up force-unwrapping the return value, which
would produce the same result as trapping inside. But I guess in that case
you would make it clearer on the caller site that that can fail?
On Fri, Feb 12, 2016 at 9:23 AM Félix Cloutier <swift-evolution@swift.org> > wrote:

It appears that the current integer conversion initializers will either
always work, possibly trap, or truncate:

init(_: Int)
init(_: Int8)
init(_: Int16)
init(_: Int32)
init(_: Int64)
init(_: UInt)
init(_: UInt8)
init(_: UInt16)
init(_: UInt32)
init(_: UInt64)
init(truncatingBitPattern: Int)
init(truncatingBitPattern: Int16)
init(truncatingBitPattern: Int32)
init(truncatingBitPattern: Int64)
init(truncatingBitPattern: UInt)
init(truncatingBitPattern: UInt16)
init(truncatingBitPattern: UInt32)
init(truncatingBitPattern: UInt64)

I suggest that we change trapping initializers to failable initializers.
Initializers that can't fail (identity, unsigned -> bigger signed/unsigned,
signed -> bigger signed) should keep a non-Optional type.

This could extend to changing SignedIntegerType's and
UnsignedIntegerType's (U)IntMax to failable initializers as well.

I think I remember someone on the core team saying that someone's working
on integer types at the moment. Is that right?

Félix

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Javier Soto

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

My use case is a small chess game where my Board class has a Location indexer, and any Location object has a guaranteed value on the Board. The Location struct handles adding signed deltas to coordinates and returns nil when that location wouldn't exist. My coordinates are UInt8 values and the "casting" code looks like:

private func intToU8(int: Int) -> UInt8? {
  if int >= 0 && int <= Int(UInt8.max) {
    return UInt8(int)
  }
  return nil
}

Of course, if UInt8's initializer returned an Optional instead of trapping, I wouldn't need that function at all.

In general, I would also say that it's a good idea to make dangerous behavior explicit. I think that Swift's model for converting integers is already punishing enough that we might as well add the exclamation mark.

Félix

···

Le 12 févr. 2016 à 12:27:55, Javier Soto <javier.api@gmail.com> a écrit :

I'm curious: how would you use the failable initializers? I feel like, more often than not, you would end up force-unwrapping the return value, which would produce the same result as trapping inside. But I guess in that case you would make it clearer on the caller site that that can fail?
On Fri, Feb 12, 2016 at 9:23 AM Félix Cloutier <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
It appears that the current integer conversion initializers will either always work, possibly trap, or truncate:

init(_: Int)
init(_: Int8)
init(_: Int16)
init(_: Int32)
init(_: Int64)
init(_: UInt)
init(_: UInt8)
init(_: UInt16)
init(_: UInt32)
init(_: UInt64)
init(truncatingBitPattern: Int)
init(truncatingBitPattern: Int16)
init(truncatingBitPattern: Int32)
init(truncatingBitPattern: Int64)
init(truncatingBitPattern: UInt)
init(truncatingBitPattern: UInt16)
init(truncatingBitPattern: UInt32)
init(truncatingBitPattern: UInt64)

I suggest that we change trapping initializers to failable initializers. Initializers that can't fail (identity, unsigned -> bigger signed/unsigned, signed -> bigger signed) should keep a non-Optional type.

This could extend to changing SignedIntegerType's and UnsignedIntegerType's (U)IntMax to failable initializers as well.

I think I remember someone on the core team saying that someone's working on integer types at the moment. Is that right?

Félix

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
--
Javier Soto

Yes, with the same intent. What would it throw, though?

Félix

···

Le 13 févr. 2016 à 09:32:52, Matthew Johnson <matthew@anandabits.com> a écrit :

Are you thinking of something along the lines of is proposal?

Failable numeric conversion initializers by anandabits · Pull Request #58 · apple/swift-evolution · GitHub

It has been sitting as a PR for quite a while and not been merged yet.

-Matthew

On Feb 12, 2016, at 11:21 AM, Félix Cloutier via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It appears that the current integer conversion initializers will either always work, possibly trap, or truncate:

init(_: Int)
init(_: Int8)
init(_: Int16)
init(_: Int32)
init(_: Int64)
init(_: UInt)
init(_: UInt8)
init(_: UInt16)
init(_: UInt32)
init(_: UInt64)
init(truncatingBitPattern: Int)
init(truncatingBitPattern: Int16)
init(truncatingBitPattern: Int32)
init(truncatingBitPattern: Int64)
init(truncatingBitPattern: UInt)
init(truncatingBitPattern: UInt16)
init(truncatingBitPattern: UInt32)
init(truncatingBitPattern: UInt64)

I suggest that we change trapping initializers to failable initializers. Initializers that can't fail (identity, unsigned -> bigger signed/unsigned, signed -> bigger signed) should keep a non-Optional type.

This could extend to changing SignedIntegerType's and UnsignedIntegerType's (U)IntMax to failable initializers as well.

I think I remember someone on the core team saying that someone's working on integer types at the moment. Is that right?

Félix

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution