[swift-users] Implementing signum

Dave Abrahams dabrahams at apple.com
Mon Nov 28 20:53:21 CST 2016


on Sun Nov 20 2016, Hooman Mehr <swift-users-AT-swift.org> wrote:

> Let me explain this a bit further:
>
> Swift generic programming is very different from C++ template programming. Swift compiler needs to
> type-check generic code on spot, not while instantiating the template (because in Swift,
> instantiation can occur at runtime if the generic code is from a different module).
>
> This means that it should know what operations will be supported on the type being extended. Your
> `Signumable` defines only a single function. IF you extend `Signumable` to provide an
> implementation, you can’t refer to any function other than `sgn()`, but you need more to be able to
> implement sin(). This is don though generic constraints. You need to constrain the type to which
> your extension applies. The minimal contains that you need are: `ExpressibleByIntegerLiteral` and
> `Comparable` so that you can write the algorithm as follow:
>
> The way you wrote it, would require more defined operations (subtraction):
>
> protocol Signumable
> {
>     func sgn() -> Self
> }
>
> extension Signumable where Self: ExpressibleByIntegerLiteral & Comparable
> {
>     func
>         sgn()
>         -> Self
>     {
>         if 0 < self { return 1 }
>         if self < 0 { return -1 }
>         return 0
>     }
> }
>
> This can potentially work on any integer (including unsigned) and floating point type and any other
> type that happens to support those two protocols. But it does not work yet, because those types do
> not automatically conform to `Signumable`. To make them conform you need a bit of boilerplate:
>
> extension Int: Signumable {}
> extension Int8: Signumable {}
> extension Int16: Signumable {}
> extension Int32: Signumable {}
> extension Int64: Signumable {}
> extension UInt: Signumable {}
> extension UInt8: Signumable {}
> extension UInt16: Signumable {}
> extension UInt32: Signumable {}
> extension UInt64: Signumable {}
> extension Float32: Signumable {}
> extension Float64: Signumable {}
> extension Float80: Signumable {}
>
> The problem is, if a new numeric type is defined say a rational number type
> <https://gist.github.com/hooman/6e08c48e1e06ee19e06e5b09f664f9be>, it won’t conform automatically
> and you will have to declare its conformance as above. For this reason, it is better to try to find
> an existing standard protocol to extend instead of introducing your own protocol for such things.
>
> So, as others suggested, it is better to extend the existing `SignedNumber` protocol instead of
> introducing your own `Signumable`, unless if you need to write other generic algorithms that need
> your protocol as their constraints.

The deeper generic programming principle here has to do with how
requirements are clustered into protocols and whether that limits what
you can express.  Are there any Signumables that can't also efficiently
implement the requirements of SignedNumber (and vice-versa)?  If not,
these two things are fundamentally, in some sense, the same protocol and
should be merged.  If so, there may be a reason to have a distinct
protocol, so that you can write algorithms constrained to that protocol
that give protocols that depend on the operation.

-- 
-Dave



More information about the swift-users mailing list