【问题标题】:What is the ~> (tilde greater than) operator used for in Swift?Swift 中使用的 ~>(波浪号大于)运算符是什么?
【发布时间】:2015-01-01 17:02:03
【问题描述】:

Swift 1.1 包含 ~> 运算符的声明:

infix operator ~> {
    associativity left
    precedence 255
}

这在 Swift 中是做什么用的?它似乎已声明,但没有定义利用它的函数。其他开发人员已经将它用于反应模式和队列之间的封送封包,但我想知道为什么它是在标准框架中定义的。我推测它的存在是为了“保留”一个自定义运算符供开发人员使用,因为它具有最高的优先级。

【问题讨论】:

  • 由于它是最高优先级,它将与对象/可选延迟相关。
  • 我不确定你能否做出这样的假设。没有为“.”、“!”或“?”声明后缀运算符而且我不确定您是否可以声明它们。这些是语言本身的一部分,充当其他函数调用的语法糖。

标签: swift


【解决方案1】:

由于 Swift 已经开源,我们可以看到在 stdlib 中包含 ~> 的实际原因:as a workaround for method specialization in a child protocol in Swift 1.x

// Workaround for <rdar://problem/14011860> SubTLF: Default
// implementations in protocols.  Library authors should ensure
// that this operator never needs to be seen by end-users.  See
// test/Prototypes/GenericDispatch.swift for a fully documented
// example of how this operator is used, and how its use can be hidden
// from users.
infix operator ~> { associativity left precedence 255 }

详细的例子可以在test/Prototypes/GenericDispatch.swift找到。

注意:不要在 Swift 2+ 中使用~&gt;。这是一个历史解决方法。它不再需要。继续阅读。


~&gt; 的工作原理

在 Swift 2 中,~&gt; 的唯一剩余实例是 abs 函数(它也可能会消失)。我们可以看到~&gt; 的实际工作原理。从stdlib/public/core/IntegerArithmetic.swift.gybSignedInteger 协议定义了一个~&gt; 运算符:

struct _Abs {}

protocol SignedNumber: Comparable {
    prefix func -(_: Self) -> Self

    func ~> (_: Self, _: (_Abs, ()) -> Self
}

func ~> <T: SignedNumber>(x: T, _: (_Abs, ()) -> T {
    return x < 0 ? -x : x
}

这里,箭头~&gt; 的RHS 指定可以向对象发送什么命令。将p~&gt;(cmd, args) 想象成p.cmd(args)

然后,当给定SignedNumber 时,我们提供_Abs默认实现

protocol AbsoluteValuable : SignedNumber {
    static func abs(_: Self) -> Self
}

func ~> <T: AbsoluteValuable>(x: T, _: (_Abs, ())) -> T {
    return T.abs(x)
}

接下来,我们有一个子协议AbsoluteValuable,它计算绝对值的方法可能比x &lt; 0 ? -x : x 更有效。然后,我们将 ~&gt; 运算符特化为 AbsoluteValuable

func abs<T: SignedNumber>(_ x: T) -> T {
    return x ~> (_Abs(), ())
}

最后,我们将~&gt; 调用隐藏在公共包装方法中。如果T 实际上是AbsoluteValuable,则将选择更专业、更高效的~&gt;

这也是我们得到42 ~&gt; _advance(12)42 ~&gt; _distanceTo(23) 的原因,如@rintaro's answer 所示,因为.advanceBy.distanceTo 方法对于一般ForwardIndexType 来说是O(n),但可以在O(1) 如果类型是RandomAccessIndexType


你不需要~&gt;

此模式也可以在调用~&gt; 操作符的情况下使用协议扩展来完成:

protocol SignedInteger: Comparable {
    prefix func -(_: Self) -> Self

    func genericAbs() -> Self
}

extension SignedInteger {
    func genericAbs() -> Self {
        return self < 0 ? -self : self
    }
}

protocol AbsoluteValueable: SignedInteger {
    static func abs(_: Self) -> Self
}

extension AbsoluteValueable {
    func genericAbs() -> Self {
        return Self.abs(self)
    }
    // normally you would allow subtypes to override
    // genericAbs() directly, instead of overriding 
    // static abs().
}

func abs<T: SignedInteger>(x: T) -> T {
    return x.genericAbs()
}

这就是为什么除了 abs 之外的所有其他 ~&gt; 实现在 Swift 2 中都消失了:使用这种技术的所有专业化都已更改为使用更明显的协议扩展,例如


注意:雷达问题 14011860 未公开,但我们可以通过 OpenRadar 上的重复项看到该错误的范围:

【讨论】:

    【解决方案2】:

    看来,是相关的集合/序列/索引类型

    根据Defines-Swift

    protocol SequenceType : _Sequence_Type {
      typealias Generator : GeneratorType
      func generate() -> Generator
      func ~>(_: Self, _: (_UnderestimateCount, ())) -> Int
      func ~><R>(_: Self, _: (_PreprocessingPass, ((Self) -> R))) -> R?
      func ~>(_: Self, _: (_CopyToNativeArrayBuffer, ())) -> _ContiguousArrayBuffer<Self.Generator.Element>
    }
    
    protocol CollectionType : _CollectionType, SequenceType {
      subscript (position: Self.Index) -> Self.Generator.Element { get }
      func ~>(_: Self, _: (_CountElements, ())) -> Self.Index.Distance
    }
    
    protocol ForwardIndexType : _ForwardIndexType {
      func ~>(start: Self, _: (_Distance, Self)) -> Self.Distance
      func ~>(start: Self, _: (_Advance, Self.Distance)) -> Self
      func ~>(start: Self, _: (_Advance, (Self.Distance, Self))) -> Self
    }
    
    protocol SignedNumberType : _SignedNumberType {
      prefix func -(x: Self) -> Self
      func ~>(_: Self, _: (_Abs, ())) -> Self
    }
    
    func ~><T : _CollectionType>(x: T, _: (_CountElements, ())) -> T.Index.Distance
    func ~><T : _CollectionType>(x: T, _: (_UnderestimateCount, ())) -> Int
    func ~><T : _CollectionType, R>(s: T, args: (_PreprocessingPass, ((T) -> R))) -> R?
    func ~><T : _SequenceType>(s: T, _: (_UnderestimateCount, ())) -> Int
    func ~><T : _SequenceType, R>(s: T, _: (_PreprocessingPass, ((T) -> R))) -> R?
    func ~><S : _Sequence_Type>(source: S, _: (_CopyToNativeArrayBuffer, ())) -> _ContiguousArrayBuffer<S.Generator.Element>
    func ~><C : CollectionType where C._Element == C._Element>(source: C, _: (_CopyToNativeArrayBuffer, ())) -> _ContiguousArrayBuffer<C._Element>
    func ~><T>(x: EmptyCollection<T>, _: (_CountElements, ())) -> Int
    func ~><T : _ForwardIndexType>(start: T, rest: (_Distance, T)) -> T.Distance
    func ~><T : _ForwardIndexType>(start: T, rest: (_Advance, T.Distance)) -> T
    func ~><T : _ForwardIndexType>(start: T, rest: (_Advance, (T.Distance, T))) -> T
    func ~><T : _BidirectionalIndexType>(start: T, rest: (_Advance, T.Distance)) -> T
    func ~><T : _BidirectionalIndexType>(start: T, rest: (_Advance, (T.Distance, T))) -> T
    func ~><T : _RandomAccessIndexType>(start: T, rest: (_Distance, (T))) -> T.Distance
    func ~><T : _RandomAccessIndexType>(start: T, rest: (_Advance, (T.Distance))) -> T
    func ~><T : _RandomAccessIndexType>(start: T, rest: (_Advance, (T.Distance, T))) -> T
    func ~><T : _SignedNumberType>(x: T, _: (_Abs, ())) -> T
    func ~><T : AbsoluteValuable>(x: T, _: (_Abs, ())) -> T
    func ~><T>(x: CollectionOfOne<T>, _: (_CountElements, ())) -> Int
    

    例如,

    42 ~> _advance(12) // -> 54
    42 ~> _distanceTo(23) // -> -19
    

    不过,我不知道这些是如何使用的:-/

    【讨论】:

      【解决方案3】:

      SwiftDoc 上,此运算符已从 Swift 3.0 的运算符章节中删除。

      【讨论】:

        猜你喜欢
        • 2012-04-22
        • 2011-04-26
        • 2011-08-23
        • 1970-01-01
        • 1970-01-01
        • 2012-02-26
        • 2016-11-16
        相关资源
        最近更新 更多