基本类型的通用协议

时间:2014-06-13 17:21:02

标签: generics swift

我一直在思考swift的字符串格式化的可能实现,其中大多数归结为“使用NSString(格式:...)”这一切都很好,但我想要一个简洁易读的格式,所以我决定实现类似python的%格式化运算符:

@infix func % (value:Double, format:String) -> String {
    return NSString(format:format, value)
}

这适用于Double's,因为我可以使用:

println("PI = " + M_PI % "%.3f")

导致:

PI = 3.142

虽然我可以创造其中的5个,但我想把它变成一个通用函数:

@infix func %<T> (value:T, format:String) -> String {
    return NSString(format:format, value)
}

但这导致了消息:

Could not find an overload for 'init' that accepts the supplied arguments

合理的,我可以传入一个元组,或者同样非客观的东西-C。 (注意,为了真正做到这种Python风格,我希望传入一个元组,但这是另一个问题,超出了这个问题的范围)

我尝试声明我自己的空协议并在Double上实现它,但它根本没有帮助。

protocol NSStringFormattable {}
extension Double : NSStringFormattable {}

@infix func % <T:NSStringFormattable> (value:T, format:String) -> String {
    return NSString(format:format, value)
}

我显然可以做一些事情,例如为每个类添加一个格式函数,然后根据格式函数定义运算符,但在许多方面,这并不比定义5个不同的运算符重载更好。

protocol NSStringFormattable {
    func format(format:String) -> String
}

extension Double : NSStringFormattable {
    func format(format:String) -> String {
        return NSString(format:format, self)
    }
}

@infix func % <T:NSStringFormattable> (value:T, format:String) -> String {
    return value.format(format)
}

如何将T限制为只能传递给NSString(format:...)的那些类型?

2 个答案:

答案 0 :(得分:2)

发现它!

@infix func % (value:CVarArg, format:String) -> String {
    return NSString(format:format, value)
}

这个单一功能允许:

5 % "%04x"

3.4 % "%.3f"

M_PI % "%.3f"

Int64(32) % "%04X"

不幸的是,它还允许:

"String" % "%3.3s"

并生成垃圾,但欢迎使用printf而不进行参数类型检查

更进一步,通过定义一组函数:

@infix func % (values:(CVarArg, CVarArg), format:String) -> String {
    return NSString(format:format, values.0, values.1)
}

@infix func % (values:(CVarArg, CVarArg, CVarArg), format:String) -> String {
    return NSString(format:format, values.0, values.1, values.2)
}

我们可以实现类似python的影响:

(M_PI, 5) % "%.3f->%d"

每个元组长度必须定义一个丑陋,但我会继续攻击它:)

答案 1 :(得分:0)

据我所知(与你经历了相同的旅程),泛型不是这里的解决方案,而是多次重载(这不是很漂亮) -

operator infix % { }
@infix func % (format: String, value: Double) -> String {
    return NSString(format:format, value)
}
@infix func % (format: String, value: Float) -> String {
    return NSString(format:format, value)
}
@infix func % (format: String, value: Int) -> String {
    return NSString(format:format, value)
}
抱歉,从您的示例中反转参数顺序 - 允许

println("PI = %.3f" % M_PI)