infix operatorが他のファイルから参照できない

投稿者: Anonymous

以下のように新たな演算子を定義し、そして処理を書きました。
これをMaybe.swiftとしてxcodeプロジェクトに追加します。

infix operator >>= { associativity left }

public func >>=<T, U>(optional: T?, f: T -> U?) -> U? {
    if let x = optional {
        return f(x)
    } else {
        return nil
    }
}

この状態で、Maybe.swift以外のSwiftコード、例えばViewController.swiftで、

let input: String? = "10"
let output = input >>= { value -> Int? in
    Int((value as NSString).intValue)
} >>= { value -> Int? in
    if value >= 0 {
        return value
    }
    return nil
}

のように使おうと試みますが、これだけではコンパイルに失敗します。

エラー> […省略]/ViewController.swift:17:28: Cannot invoke ‘>>=’ with an argument list of type ‘(String?, $T9)’

トライ&エラーにより、わかった原因は、演算子の定義が見えていないことです。

なので、この場合、ViewController.swiftのグローバルスコープに、

infix operator >>= { associativity left }

を足してやることによって、コンパイルに成功し、動作も正常になりました。
しかしこの解決方法では、
この演算子を使いたいファイルには全て

infix operator >>= { associativity left }

を毎回コピペしなくてはなりません。
これをコピペしなくて済む方法はありませんでしょうか?

解決

次のように括弧を足すとエラーが解消されました。

    let input: String? = "10"
    let output = (input >>= { value -> Int? in
        Int((value as NSString).intValue)
        }) >>= { value -> Int? in
            if value >= 0 {
                return value
            }
            return nil
    }

必ずしもファイルごとに演算子定義を書かないと使えないというわけではないようです。

(input >>= {}) >>= {}

このように括弧を足すとコンパイルが通りますが、associativity left で定義してるので本来は括弧を書かなくても左から処理されるべきだと思います。
findall さんがおっしゃるように >>== に変更するとコンパイルエラーが解消するので、既存の演算子とぶつかって悪さしてるんじゃないかと思います。

ここらへんはよく分かりませんがXCodeのバグかもしれません。

findall さんと同じ結論ですが、とりあえず >>= は既存の演算子と被るので避けた方が無難かなと思います。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *