Lazy functions evaluation in swift

772 views Asked by At

Wondering is it possible to evaluate a simple if statement lazily. Below is an example that will print "this is foo" and "this is bar", but I really want to make it print only the first string:

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
}
3

There are 3 answers

0
Leo On BEST ANSWER

Do not know if this is what you want,you can use function as a type

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()
 }

Then if you callmaybeFooOrBar(true) will print first function,callmaybeFooOrBar(false)wii print second function

Also,this can be done in a clear way

func maybeFooOrBar(isFoo: Bool) {
    (isFoo ? foo : bar)()
}
0
Oleg Korban On

I have found a very simple solution following leo's answer

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()
}
5
James Webster On

I can't find canonical proof that Swift isn't a lazy evaluating language, but I'm sure the community will correct me if I'm wrong!

Since it isn't lazy, the method calls are simply executed in order rather than determining which methods will never need to be called.

To achieve the same effect, you need to implement the "lazy" behaviour yourself.

if isFoo
{
    foo()
}
else
{
    bar()
}

or more simply:

isFoo ? foo() : bar()

Swift does have lazy instantiation. That is, you can tell it that variables shouldn't be instantiated until they are used.

In Objective-C, this would require the developer to implement this behaviour manually:

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

In Swift, this is much simpler and achieved using the lazy keyword:

lazy var players = [String]()