这怎么可能是真的?

if a == 1 && a == 2 && a == 3 {
    print("All three match!")
}
复制代码

这本来是个 JavaScript 的面试题,但这并不能阻止我们在推特上研究 Swift 里的解法。先说一句,本文不讨论 Unicode 或藏代码这些方法,然后封面图是 pixiv 上 白夜ReKi 的 アクア

计算型变量

这可能是大家最容易想到的,只要每次自加一就好了:

var _a = 0
var a: Int {
    _a += 1
    return _a
}
复制代码

重载运算符

当然除了改变量之外,改运算符也是一种思路。参数名并不重要,所以本文采用统一的 lhsrhs

a = 1
func ==(lhs: inout Int, rhs: Int) -> Bool {
    // 不加 `inout` 那 `lhs` 就改为 `a`
    defer { lhs += 1 } // `a = 0` 就不用 `defer`
    return !(lhs != rhs) // 避免造成递归
}
复制代码

然后就出现了更简单粗暴的:

func &&(lhs: Bool, rhs: Bool) -> Bool { return true }
// 如果 T 已经是 Equatable,那必须得替换成更准确的类型
func ==<T>(lhs: T, rhs: Int) -> Bool { return true }
复制代码

遵循新协议

这个有点反着来的感觉,确实不容易想到。我们可以让某种 Equatable 遵循 ExpressibleByIntegerLiteral 协议,这样 1、2、3 就能被视为和 a 是同一个类型的,我们也就可以欺骗已经存在的 ==,让他们被视为相等的:

enum Foo: ExpressibleByIntegerLiteral {
    case bar
    public init(integerLiteral value: Int) {
        self = .bar
    }
}
复制代码

或者我这个有点重现 C 语系感觉的:

extension Bool: ExpressibleByIntegerLiteral {
    public init(integerLiteral value: Int) {
        self = value != 0
    }
}
复制代码

楼主中途又加了个限制,要求代码同时符合这个运行结果:

if b == 1 && b == 2 && b == 3 {
    print("All three match!") // 不执行这一条
} else {
    print("All three don't match!")
}
复制代码

但这只要 ab 不是同一个类型/实现就可以了,没啥影响。而且我们还可以用类似于这样的方法来掩人耳目:

let a: Bool = 1, b = 1
// 上面的 `b` 还是 `Int`
复制代码

如果你还有其他的姿势,不妨在下面,我的博客bilibili,或者 原提问者推特 上回复。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值