In Go, I can pass a bound function as a parameter, which is a great feature. But is it possible to do sort of the opposite: having a bound parameter, extract the receiver? An example is below: the purpose is to call shmoo() having a bound pointer to foo(). How can I do it?
type S struct {}
func (s* S) foo() {}
func (s* S) shmoo() {}
func bar(fn func ()) {
fn() // foo
magic(fn).shmoo() // this is what I want
}
func caller() {
s := &S{}
bar(s.foo)
}
Related
I am new to Swift Combine and re-writing the code for my functionality in Swift Combine where the function is returning AnyPublisher<Person, Error>.
public func newPublisherFunction() -> AnyPublisher<Person, Error> {
.....
}
However, the callers of my code are still on Obj-C (even Swift too but not using Combine) and the function which they are invoking, in my code presently, returns a direct object type Person as shown below
// this is the function being used by different callers
public func existingFunction() -> Person {
....
}
Is there a way possible to create a bridging function which can take value (of type Person) emitted by someFunction1() and just return that value.
Specifically asking, I want to implement something like below
public func newPublisherFunction() -> AnyPublisher<Person, Error> {
.....
}
func bridgingFunction() -> Person {
var person: Person
// logic to consume value from newPublisherFunction()
// and assign it to 'person'
return person
}
public func existingFunction() -> Person {
return self.bridgingFunction()
}
I would like to change following code
let views: [UIView] = []
views.forEach {
$0.removeFromSuperview()
}
to some other way, in which I pass function UIView.removeFromSuperview as an argument to the forEach function.
Something similar to
let views: [UIView] = []
views.map { /* transform views to be passed further */ }
.forEach(UIView.removeFromSuperview)
Is it possible somehow?
UPDATE
Based on the answer below and some comments, I can sum up feedback for this question for myself a bit.
Instance Methods are “Curried” Functions in Swift (By Ole Begemann)
Flattening the function type of unapplied method references (Swift Evolution)
Based on the latter, Chris Lattner has mentioned some flip function in a paragraph Impact on existing code.
My assumption about its implementation is something following
func flip<T>(_ function: #escaping (T) -> () -> Void) -> (T) -> Void {
return { object in function(object)() }
}
Thus, we can rewrite initial code like
views.forEach(flip(UIView.removeFromSuperview))
It's easy enough to just call the method on $0:
views.forEach {
$0.removeFromSuperview()
}
(And you can name the argument if you like.)
But you could also wrap it into a method:
extension Sequence {
func onEach(_ invoke: (Iterator.Element) -> () -> Void) {
self.forEach { invoke($0)() }
}
}
This works because instance methods can be represented as functions that take an instance of their type and return a function that has their "top-level" signature.
One downside here is that you can't include the rethrows annotation that's present on forEach, because rethrows only applies if the function argument itself is throwing.
Here's the simplified code that I have:
class MyClass {
func returnSomething(argument: Protocol2) {}
}
protocol Protocol2: Protocol1 where E == Int {
}
protocol Protocol1 {
associatedtype E
func doSomething(_ value: E)
}
Compiler gives me the following error: Protocol 'Protocol2' can only be used as a generic constraint because it has Self or associated type requirements.
I understand that associated type E needs to be resolved before the protocol can be used as an argument in a function, but given that Protocol2 provides that information, why I still cannot compile that code?
Since I am learning about Swift generics , so I want to give it a go:
If you want to use Protocol2 as the type of argument in the function returnSomething
As suggested by #Nicolas Miari
class MyClass {
func returnSomething<T: Protocol2>(argument: T) {}
}
Now as the name suggests this function should return something
so
class MyClass {
func returnSomething<T: Protocol2>(argument: T) -> T {
return argument
}
}
Another issue that I see in the original problem is the use of where clause
I think you want to say the associated type of Protocol1 is Int
you should do it like this
protocol Protocol2: Protocol1 {
typealias E = Int
}
"How to use associated type protocol as argument's type to a function?"
I might not be following what you're asking here, but if a protocol of yours have an associated type, e.g.
protocol DummyNumericTypeWrapper {
associatedtype U: Numeric
static func magic(_ bar: U) -> U
}
You can access this type e.g. in a generic context where the generic placeholder has been constrained to your protocol. To follow up the dummy wrapper above with an entirely dummy example, e.g.:
extension StupidNumericTypeWrapper where U == Int {
static func magic(_ bar: Int) -> Int {
return bar + 42
}
}
func foo<T: StupidNumericTypeWrapper>(_ bar: T.U, _ _ : T.Type) -> T.U {
return T.magic(bar) * T.magic(bar)
}
struct DefaultMagic: StupidNumericTypeWrapper { }
let num = foo(1, DefaultMagic.self)
print(num) // 1849 (43*43)
Swift compiler converted my typealias to the where clause. (Typealias overriding associated type 'E' from protocol 'Protocol1' is better expressed as same-type constraint on the protocol)
Passing argument indeed works with aforementioned syntax, thank you all!
But how would you return an instance that conforms to Protocol2?
class ClassConformsToProto2: Protocol2 {
func doSomething(_ value: Int) {
}
}
class MyClass {
func returnSomething<T: Protocol2>() -> T {
return ClassConformsToProto2()
}
}
This code doesn't work.
Cannot convert return expression of type 'ClasConformsToProto2' to return type 'T'
Consider type Foo:
class Foo {
var isBaz: Bool {
return false
}
func bar() {
print("some boring print")
}
}
Now let's say I want to iterate through a collection of class instances and call some function on each of them:
let someFoos: [Foo] = [Foo(), Foo(), Foo()]
someFoos.forEach { $0.bar() }
This syntax is quite compact, but it feels a bit awkward. Also, it cannot be used everywhere. For example, in an if statement condition:
if someFoos.contains { $0.isBaz } {
// compiler error: statement cannot begin with a closure expression
}
if someFoos.contains($0.isBaz) {
// compiler error: anonymous closure argument not contained in a closure
}
if someFoos.contains({ $0.isBaz }) {
// this is correct, but requires extra pair of parentheses
}
Ideally, it would be nice to write something like
someFoos.forEach(Foo.bar)
but as of Swift 2.1 this is not a correct syntax. Such way of referencing the function would be similar to the following:
func bar2(foo: Foo) -> Void {
print("some boring print")
}
someFoos.forEach(bar2)
Is there a better way to reference instance function? How do you prefer to write such expressions?
There are two different problems here. The trailing closure syntax
can be used when calling a function and the last parameter is a closure,
so
let b1 = someFoos.contains({ $0.isBaz })
let b2 = someFoos.contains { $0.isBaz }
are fully equivalent. However, the trailing closure syntax can be problematic in the condition of an if-statement:
if someFoos.contains({ $0.isBaz }) { } // OK
if someFoos.contains { $0.isBaz } { } // Compiler error
if (someFoos.contains { $0.isBaz }) { } // OK, as noted by R Menke
We can only speculate why the second one does not work. It could be that the compiler
takes the first { as the start of the if-body. Perhaps this will
change in a future version of Swift but probably it is not worth
the effort.
The other problem is about curried functions.
someFoos.forEach(bar2)
compiles because bar2 has the type Foo -> Void, and that is exactly
what the forEach() method expects. Foo.bar, on the other hand,
is a curried function (see http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/) which takes the instance as the first
argument. It has the type Foo -> () -> (). So
Foo.bar(someFoo)
is a closure with type () -> (), and
Foo.bar(someFoo)()
calls the bar method on the someFoo instance.
(Note: The following is not meant as an actual recommendation,
but only as a demonstration about curried functions and fun
with closures!)
To pass Foo.bar directly as an argument to forEach() we need to
"swap" the order of the parameters. Haskell has a "flip" function for that purpose,
and it is also possible in Swift (see e.g. How to write a flip method in Swift?):
func flip<A, B, C>(f: A -> B ->C) -> B -> A ->C {
return { b in { a in f(a)(b) } }
}
Then flip(Foo.bar) has the type () -> Foo -> (), so
the void argument of the bar method can be applied
flip(Foo.bar)()
to get a Foo -> () closure, and
flip(Foo.bar)()(someFoo)
calls the bar method on the someFoo instance.
And now we can call
someFoos.forEach (flip(Foo.bar)())
without using a closure expression { .. } !!
If isBaz were a method instead of a property
func isBaz() -> Bool { return false }
then you
could do the same in the if-expression:
if someFoos.contains(flip(Foo.isBaz)()) {
// ...
}
Again, this is only meant as a demonstration. Also properties
are not curried functions, so this cannot be done with
your isBaz property.
The $0 syntax is there to help you create a shortcut, but if you don't like it you can use the more complete form:
someFoos.forEach { thisFoo in thisFoo.bar() }
I tried to write an "editor" class that could retain a reference to a property on a different object for later mutation. I first wrote the editor class to receive a closure for reading, and a closure for writing. This worked. I then tried to pass the parameter in question by (inout) reference, and then generate the getter / setter pair from that. This did not work. The Swift docs does say (paraphrasing) that Swift figures out when to copy, and when to not. I think I am up against unpredictability of that limitation, but thought I'd pose the question just the same.
Alternatively, is it possible to get a curried function for the individual getter and setter?
My code is:
class SomeModel : Printable {
var a:String
init(a:String) {
self.a = a
}
var description:String {
return "\(self.a)"
}
}
class Editor {
var getter:()-> String
var setter:(String)->()
init(getter:()-> String, setter:(String)->()) {
self.getter = getter
self.setter = setter
}
convenience init(inout bindTo:String) {
self.init(
getter:{ return bindTo },
setter: { v in bindTo = v })
}
func read() -> String {
return self.getter()
}
func write(value:String) {
self.setter(value)
}
}
func testBindTo() {
var readModel = SomeModel(a:"Did not capture by reference");
var bindForReading = Editor(bindTo: &readModel.a)
readModel.a = "captured by reference!"
println(bindForReading.read())
var writeModel = SomeModel(a:"Did not capture by reference");
var bindForWriting = Editor(bindTo: &writeModel.a)
bindForWriting.write("captured by reference")
println(writeModel)
}
testBindTo()
func testExplicitGetterSetter() {
var readModel = SomeModel(a:"Did not capture by reference");
var bindForReading = Editor(
getter: { readModel.a },
setter: { v in readModel.a = v })
readModel.a = "captured by reference!"
println(bindForReading.read())
var writeModel = SomeModel(a:"Did not capture by reference");
var bindForWriting = Editor(
getter: { writeModel.a },
setter: { v in writeModel.a = v })
bindForWriting.write("captured by reference")
println(writeModel)
}
testExplicitGetterSetter()
The results are:
Did not capture by reference
Did not capture by reference
captured by reference!
captured by reference
Thanks!
I don't think this is possible. And it shouldn't be possible, if you think about it, because it would be super unsafe.
Because closures can outlive the scope they were created in, captured variables must be stored with the block. But in order to be able to assign to the captured variable and share the state of that variable between the (one or more) block(s) that captured it and the original scope, the blocks cannot just capture the value of the variable (which would create independent copies of the variable), but capture a kind of "reference" to a shared copy. This means that assignable variables that are captured by blocks must be stored specially. In Objective-C, this is declared with __block. In Swift, this __block behavior is implicit.
However, in order for the block to modify an inout variable (potentially at a later time) as it is seen in the function caller's scope, that would mean that the passed variable in the caller's scope would also need to be stored in a way that can outlive the stack frame. But the caller function doesn't know this. All it knows from the type of the called function is that one of its parameters is inout; it doesn't know that the function plans to capture that inout variable in a block. So it doesn't know to prepare this __block storage for this passed variable.
It can be done as follows. )Notice that the closure and the inout param have the same lifespan.)
/// A class providing access to a resource with an inout parameter in an escaping closure.
class ProtectedResource<ValueType> {
private var protectedResourceArray = [ValueType]()
private var protectedResourceArrayLock = NSRecursiveLock()
private let opq = OperationQueue()
func performWithResource(block: #escaping (inout [ValueType]) -> ()) {
opq.addOperation { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.protectedResourceArrayLock.lock()
block(&strongSelf.protectedResourceArray)
strongSelf.protectedResourceArrayLock.unlock()
}
}
}
/// Some other class using that in out parameter.
func run() {
func updateArray(array: inout [String]) {
print("Performing on \(array)")
array.append("test")
}
protectedResource.performWithResource(block: updateArray)
protectedResource.performWithResource {
print("Performing on \($0)")
}
}