Alex Moore-Niemi
Alex Moore-Niemi

Reputation: 3372

Swift equivalent of Ruby's "yield"

I'm new to Swift, and have a Ruby background. I'm wondering if there's a way I can do something like this:

def completion_handler response, &block
  yield response
end

extracted = proc {|r| puts r}

completion_handler "response", &extracted
response
=> nil

I'm having a little trouble searching as yield mostly brings up sequence generators and I don't think that's what I'm looking for right now. I mostly want to know if this is possible because there's times I like to be able to extract a block to a proc object. In Swift, a closure looks like a block to me. Is there a similar extraction to a proc object?

Upvotes: 1

Views: 3742

Answers (2)

Jokester
Jokester

Reputation: 5617

It's possible to save block (or 'closure' as in swift programming guide) in variables or pass them around. A big difference to ruby is that some types have to specified to compile.

Example code (only tested with swift 2.2-dev linux):

func foo(arg1: Int, block: ((Int)->(String))? = nil) {
    if let block = block {
        // ruby's yield (call the block with argument and get its return value)
        // is not part of swift grammar, so we have to call it manually.
        print(block(arg1))
    }
}

// named closure
let block1 = {(a: Int)->String in
    print("yielded", a)
    return "returned from block1"
}

foo(1, block: block1)

// unnamed closure
foo(2, block: {
    print("yielded", $0)
    return "returned from block2"
})

// unnamed closure in another syntax. usable only when the closure is the last argument.
foo(3) {
    print("yielded", $0)
    return "returned from block3"
}

Output:

yielded 1
returned from block1
yielded 2
returned from block2
yielded 3
returned from block3    

Upvotes: 4

Jonah
Jonah

Reputation: 17958

Swift closures mostly closely resemble Ruby Lambdas. They are objects with a defined set of arguments which return to their calling scope (unlike non-object Ruby Blocks or Ruby Procs which do not check argument count and where a return can escape the calling scope).

As such there's no real yield equivalent. Swift functions which accept a closure argument call the closure explicitly with a parenthetical argument list.

Upvotes: 5

Related Questions