泛型函数中的Swift可选绑定

泛型函数中的Swift可选绑定,swift,binding,functor,optional,applicative,Swift,Binding,Functor,Optional,Applicative,可爱的马车斯威夫特再一次让我惊讶。 在我的新项目中,我使用了带有运算符的可选应用程序函子,如下所述 中缀运算符{结合性左优先150} 功能(左:(A->B)?,右:A->B?{ 如果让lhs1=lhs{ 如果设rhs1=rhs{ 返回lhs1(rhs1) } } 归零 } 这真的很酷,直到我遇到了一次奇怪的碰撞。我将用一个简化的版本来展示它 let常量:任何对象?=无 func someFnc(对象:AnyObject!){ println(“lol,wat?”) } someFnc常数 那

可爱的马车斯威夫特再一次让我惊讶。 在我的新项目中,我使用了带有
运算符的可选应用程序函子,如下所述

中缀运算符{结合性左优先150}
功能(左:(A->B)?,右:A->B?{
如果让lhs1=lhs{
如果设rhs1=rhs{
返回lhs1(rhs1)
}
}
归零
}
这真的很酷,直到我遇到了一次奇怪的碰撞。我将用一个简化的版本来展示它

let常量:任何对象?=无
func someFnc(对象:AnyObject!){
println(“lol,wat?”)
}
someFnc常数
那么,输出是什么呢?当然没什么,你会期待什么? 如果我们传递一个变量呢

var变量:AnyObject?=无
someFnc变量
你告诉我的这个也一样,但我的控制台说:

哈哈,怎么了? 是的,这是正确的,如果我们通过var,它很高兴通过可选的绑定检查。 我在
NSObject
和一些Swift结构/类中尝试了这个方法,如果我传递常量,一切正常,如果它是一个变量,一些神奇的事情正在发生

更新

描述正在进行的魔术时,
var
内部的
函数变成嵌套的
可选的
,而
不要

这种含蓄的行为有什么合理的解释吗

解决方法

对于解决方法,您可以将变量包装在一些函数中,如:

var变量:AnyObject?=无
func getVar()->AnyObject?{
返回变量
}
someFnc getVar()
或在计算属性中:

var变量:AnyObject?=无
var getVariable:AnyObject?{
返回变量
}
someFnc getVariable
以下是发生的情况:

infix operator <*> { associativity left precedence 150 }

func <*> <A, B>(wrappedFunction: (A -> B)?, optional: A?) -> B? {
    println(optional)
    if let f = wrappedFunction {
        if let value = optional {
            return f(value)
        }
    }
    return nil
}

func someFnc(obj: AnyObject!) {
    println("lol, wat?")
}

let constant: AnyObject? = nil
let result1: ()? = someFnc <*> constant
var variable: AnyObject? = nil
let result2: ()? = someFnc <*> variable
因此,我们的
var变量:AnyObject?
一旦进入
函数,就成为一个嵌套的可选
AnyObject??
。然后它的值是可选的(nil),而不是nil,因此对它调用包装函数。另一个解决方法是展平嵌套的可选对象:

let result2: ()? = someFnc <*> variable?

如果我们使用
map
方法而不是全局函数,那么在所有情况下都是
nil
,并且没有调用
大写[N]
函数。常规和隐式展开选项之间的行为没有区别。变量和常量的行为不同并不是这里最糟糕的事情。最糟糕的是编译器允许我们调用
upperCase1
upperCase2
。在这种情况下,只有两个函数是
upperCase3
upperCase4
,好消息是这两个函数可以正确地处理变量。

问题可以简化为:

func foo<A>(v: A?, f:(A) -> Void) {
    println(v)
}

let constant: Int? = nil
var variable: Int? = nil
func someFunc(x: Int!) {}

foo(constant, someFunc)
foo(variable, someFunc)
因此,根据我的假设:

  • foo(常量,someFunc)
    被解释为
    foo(常量为Int?,someFunc为(Int)->Void)
  • foo(变量,someFunc)
    被解释为
    foo(变量为Int!?,someFunc为(Int!)->Void)
这里有些含糊不清:

// `(Int!) -> Void` can be cast to `(Int) -> Void`
func f(Int!) {}
let f2 = f as (Int) -> ()

// `Int?` can be cast to `Int!?`
let i:Int? = 1
let i2 = i as Int!?
在这种情况下,我认为

  • 常数比参数强
  • 参数比变量强

我不确定这是不是一个bug。至少让人很困惑。

我试过上面的一点。
someFnc常量
(不是videoInput)返回nil,而
someFnc变量
返回{(0个元素)},这已经够奇怪了。我的最佳猜测是:放弃它,等待半年:-/这种混乱的主要问题是为什么
var
成为嵌套的
可选
,而
不要这样做。这种含蓄的行为确实令人沮丧。我以前在玩RAC 3.0的时候捕捉到过一次,不知怎的,我用一些
信号获得了
Optional(Optional)(Optional(something))
。我希望尽可能避免隐式展开选项,但几乎所有的ObjC SDK都是用
swift
包装的,所以我没有太大的选择余地,但编写自己的包装可能会很困难。好的,谢谢你的回答,特别是你的解决方法
someFnc变量?
。我刚刚报告了一个bug。刚刚发现添加了一个函子实现-
(lhs:(a!->B)?,rhs:a?->B?{/*相同的*/}
-使示例代码使用这个新的实现,并与
var
s配合使用。由于在Objective C API中很难避免隐式展开选项,也许这种解决方法比记住在每个变量参数中添加
更安全。现在这肯定更干净了,我认为这正是编译器应该自动执行的操作,但它没有。
func foo<A>(v: A?, f:(A) -> Void) {
    println(v)
}

let constant: Int? = nil
var variable: Int? = nil
func someFunc(x: Int!) {}

foo(constant, someFunc)
foo(variable, someFunc)
nil
Optional(nil)
// `(Int!) -> Void` can be cast to `(Int) -> Void`
func f(Int!) {}
let f2 = f as (Int) -> ()

// `Int?` can be cast to `Int!?`
let i:Int? = 1
let i2 = i as Int!?