Swift中的惰性函数求值

3

想知道是否可能对简单的if语句进行惰性求值。以下是一个示例,将打印“this is foo”和“this is bar”,但我真的希望它只打印第一个字符串:

func foo() {
  println("this is foo")
}

func bar() {
  println("this is bar")
}

func maybeFooOrBar(isFoo: Bool) {
  let myFoo = foo()
  let myBar = bar()
  isFoo ? myFoo : myBar
}

我不理解为什么会被踩。这是一个很好的问题。我猜测可能是因为这根本不可能实现。(如果我确定了,我会把它作为答案发布的)。 - James Webster
3个回答

4

我不知道这是否是您想要的,您可以将函数用作类型

func foo() {
    println("this is foo")
}

func bar() {
    println("this is bar")
}

func maybeFooOrBar(isFoo: Bool) {
    let myFoo = foo
    let myBar = bar
    let result = isFoo ? myFoo : myBar
    result()
 }

如果你调用callmaybeFooOrBar(true),将会打印第一个函数;callmaybeFooOrBar(false)将会打印第二个函数。

此外,这可以以清晰的方式完成。

func maybeFooOrBar(isFoo: Bool) {
    (isFoo ? foo : bar)()
}

1
我无法找到确切证据证明Swift不是一种惰性求值语言,但如果我错了,我相信社区会纠正我!由于它不是惰性的,方法调用只是按顺序执行,而不是确定哪些方法永远不需要被调用。要实现相同的效果,您需要自己实现“惰性”行为。
if isFoo
{
    foo()
}
else
{
    bar()
}

或更简单地说:
isFoo ? foo() : bar()

Swift 确实惰性实例化。也就是说,你可以告诉它在使用变量之前不要实例化。

在Objective-C中,这需要开发者手动实现此行为:

@property (nonatomic, strong) NSMutableArray *players;
- (NSMutableArray *)players 
{
    if (!_players) 
    {
        _players = [[NSMutableArray alloc] init];
    }
    return _players;
}

在Swift中,这变得更加简单,可以使用lazy关键字实现:

lazy var players = [String]()

是的,我知道这样可以正常运行。但是让它像我的示例那样工作确实很有趣。 - Oleg Korban
2
你问题中的例子存在一个问题,它忽略了函数调用的影响。仅仅因为结果变量没有被使用,并不意味着函数调用没有做其他事情——理论上编译器可以尝试确定函数调用是否可以被优化掉,但是foo()或bar()可能会导致许多额外的函数调用,这很快就变得非常困难——如果不必要,程序员最好不要调用该函数,这样会简单得多。 - Paulw11
James,你不能将参数传递给懒惰变量初始化。如果你要使大多数函数引用透明化,这样是不行的。 - Oleg Korban
是的,我明白了。但问题是关于惰性函数而非惰性变量。打开谷歌或者 Swift 文档来查找如何实例化惰性变量相当简单。 - Oleg Korban
@RudraFury,我只是包含了那个因为我认为你可能读过关于延迟初始化,并且忘记了它的确切含义,然后把它和惰性求值混淆了...我也这么做了;) - James Webster

0

我已经找到了一个非常简单的解决方案,遵循了Leo的答案

func foo(a: Int)() {
  println("this is foo")
}

func bar(b: Int)() {
  println("this is bar")
}

func maybeFooOrBar(isFoo: Bool) {
  let myFoo = foo(1)
  let myBar = bar(2)
  isFoo ? myFoo() : myBar()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接