nPn
nPn

Reputation: 16748

Is there an equivalent of Ruby's instance_eval in Swift?

In ruby I can pass a block into a method and have the block evaluated in the context of the receiving object.

class Receiver

    def method_a
        puts "hello from method_a"
    end

    def method_b
        puts "hello from method_b"
    end

    def define_something &action
        method_a 
        instance_eval &action
    end

end

thing = Receiver.new 
thing.define_something { method_b }

which produces the following output:

hello from method_a
hello from method_b

Whats the right way to implement something like this in Swift?

Here is what I have, but of course Xcode complains that methodB is an unresolved identifier.

class Receiver {

    func methodA() {
        print("hello from method A")
    }

    func methodB() {
        print("hello from method B")
    }

    func defineSomething( action: () -> Void ) {
        methodA()
        action()
    }
}

let thing = Receiver()
thing.defineSomething { methodB() }

BTW, this can also be done in Kotlin which has the idea of a function type with a receiver.

for example the following produces similar output to what the ruby example produces.

class Receiver {
   fun methodA() = println("hello from methodA")
   fun methodB() = println("hello from methodB")
   fun defineSomething( action: Receiver.() -> Unit) {
       methodA()
       action()
   }
}

fun main(args: Array<String>) {
   val thing = Receiver()
   thing.defineSomething { methodB() }
}

hello from methodA
hello from methodB

Upvotes: 0

Views: 106

Answers (1)

vacawama
vacawama

Reputation: 154631

I don't know of a way to do that in the language. You can do it manually by having action take a Receiver instance as input, and then call action(self) inside of defineSomething(action:).

class Receiver {

    func methodA() {
        print("hello from method A")
    }

    func methodB() {
        print("hello from method B")
    }

    func defineSomething(action: (_: Receiver) -> Void ) {
        methodA()
        action(self)
    }
}

let thing = Receiver()
thing.defineSomething { $0.methodB() }
 hello from method A
 hello from method B

Upvotes: 1

Related Questions