Similar, I believe, to an applicative, I would like to wrap a higher-order function in some context and apply it to a sequence.
protocol Foo { func a() -> Void }
class Bar: Foo { func a() { } }
let seq = [Bar(), Bar(), Bar()]
Concretely, Give the above three definitions, I'd like to be able to call dispatch(event) where dispatch wraps up a forEach over a sequence of protocol instances, and event is a function defined by that protocol.
private func dispatch(event: () -> Void) -> Void {
DispatchQueue.main.async { // context that the forEach mapping should happen inside of
seq.forEach($0.event())
}
}
let _ = dispatch(Foo.a)
Obviously, this doesn't work with Swift's type system (I'm used to Clojure's apply()). As a possible alternative, is there a way to wrap the sequence into a partial that I can forEach on?
let dispatch() -> [Foo] {
DispatchQueue.main.async {
seq.forEach // 🤷🏻♂️
}
}
let _ = dispatch { $0.a() }
Perhaps dispatch should be thought of as a constrained extension to Sequence?
extension Sequence where Iterator.Element == Foo {
func dispatch() -> [Foo] {
DispatchQueue.main.async {
return self.forEach // 🤷🏾♀️
}
}
}
While not as elegant as could have been with key paths to instance methods, you could also create a dispatch function that takes in a closure with each element as its parameter:
func dispatch(_ handler: #escaping (Foo) -> Void) {
DispatchQueue.main.async {
seq.forEach(handler)
}
}
And invoke it like so:
dispatch { $0.a() }
While you can't use KeyPath for instance methods, you can use it for properties, if it works for you.
You can change your protocol and implementation to something like this:
protocol Foo {
var a: () -> Void { get }
}
class Bar: Foo {
lazy var a = {
print("Bar")
}
}
Then you can define your dispatch function to take a KeyPath as parameter:
extension Sequence where Iterator.Element: Foo {
func dispatch(keyPath: KeyPath<Foo, () -> Void>) {
DispatchQueue.main.async {
forEach { $0[keyPath: keyPath]() }
}
}
}
and pass the properties KeyPath as parameter:
let seq = [Bar(), Bar(), Bar()]
seq.dispatch(keyPath: \Foo.a)
Related
So the title is a little weirdly worded, but here is the basis of what I am looking to do. I want to make a function that can determine if the generic type given extends from a specific protocol and then pass through the type to the more specific method for processing. This would be using the swift programming language to do so.
Psuedo code of what I want to achieve below:
func doStuff<T>(callback: Callback<T>) {
// Pseudo code of what I want to achieve as I'm not sure the syntax
// nor if it's even possible
if T extends Protocol {
let tExtendsProtocolType = T.Type as Protocol
mapStuffSpecific<tExtendsProtocolType>(callback: callback)
} else {
// Standard Use Case
}
}
func doStuffSpecific<T: Protocol>(callback: Callback<T> {
}
Thanks in advance
EDIT 1
typealias Callback<T> = (T) -> Void
protocol Protocol {}
struct A {}
struct B: Protocol {}
// I want to be able to use this to do some common set up then call into either doStuff<T> or doStuff<T: Protocol>
func tryDoStuff<T>(callback: Callback<T>) {
// Do some common setup then call this
doStuff(callback: callback)
}
func doStuff<T>(callback: Callback<T>) {
print("doStuff")
}
func doStuff<T: Protocol>(callback: Callback<T>) {
print("doStuffSpecific")
}
let callbackA: Callback<A> = { _ in } // Just an empty closure
let callbackB: Callback<B> = { _ in }
tryDoStuff(callback: callbackA) // prints doStuff
tryDoStuff(callback: callbackB) // prints doStuffSpecific
Swift's overload resolution algorithm already prioritizes the most specific overload available. Here's an example:
typealias Callback<T> = (T) -> Void
protocol Protocol {}
struct A {}
struct B: Protocol {}
func doStuff<T>(callback: Callback<T>) {
print("doStuff")
}
func doStuff<T: Protocol>(callback: Callback<T>) {
print("doStuffSpecific")
}
let callbackA: Callback<A> = { _ in } // Just an empty closure
let callbackB: Callback<B> = { _ in }
doStuff(callback: callbackA) // prints doStuff
doStuff(callback: callbackB) // prints doStuffSpecific
I have a case where I want to register either one argument or no argument closures with a service. There's always an argument available, but for brevity, I want to be able to register no arg closures as well, and then just dispatch the closure without the available argument in that case. Coming from a strong OO and dynamic types background where we love polymorphic dispatch and class inheritance trees and let the types figure themselves out, I can throw the following together:
class AbstractAction<T> {
func publish(value:T) {
fatalError("you should override this")
}
}
class NullaryAction<T>: AbstractAction<T> {
var closure:() -> ()
override func publish(_:T) {
closure()
}
init(closure:()->()) {
self.closure = closure
}
}
class UnaryAction<T>: AbstractAction<T> {
var closure:(T) -> ()
override func publish(value:T) {
closure(value)
}
init(closure:(T)->()) {
self.closure = closure
}
}
var action:AbstractAction = UnaryAction<Int>(closure: { print("\($0)") })
action.publish(42)
action = NullaryAction<Int>(closure: { print("something happened") } )
action.publish(42)
So I see 42 followed by something happened in my console. Great.
But I'd like to explore doing this with struct and/or enum. Value semantics are all the rage. The enum approach was relatively straightforward, I think:
enum Action<T> {
case Nullary( ()->() )
case Unary( (T)->() )
func publish(value:T) {
switch self {
case .Nullary(let closure):
closure()
case .Unary(let closure):
closure(value)
}
}
}
var action = Action.Unary({ (arg:Int) -> () in print("\(arg)") })
action.publish(42)
action = Action<Int>.Unary( { print("shorthand too \($0)") } )
action.publish(42)
action = Action<Int>.Nullary({ print("something happened") })
action.publish(42)
To do a struct approach, I it is my understanding that I should use a protocol to capture common interface of publish(value:T). But that's where things get confusing, because protocols apparently can't be mixed with generics? I tried:
struct NullaryAction<T> {
typealias ValueType = T
var closure:() -> ()
}
struct UnaryAction<T> {
typealias ValueType = T
var closure:(T) -> ()
}
protocol Action {
typealias ValueType
func publish(value:ValueType)
}
extension NullaryAction: Action {
func publish(_:ValueType) {
self.closure()
}
}
extension UnaryAction: Action {
func publish(value:ValueType) {
self.closure(value)
}
}
var action:Action = UnaryAction(closure: { (arg:Int) -> () in print("\(arg)") })
action.publish(42)
action = UnaryAction<Int>(closure: { print("shorthand too \($0)") } )
action.publish(42)
action = NullaryAction<Int>(closure:{ print("something happened") })
action.publish(42)
This just produces a lot of errors at the bottom. I had tried to do the extensions as generics (e.g. extension NullaryAction<T>:Action), but it told me that T was unused, even though I had placed the typealias expressions in the extensions.
Is it possible to do this with struct/protocol? I'm happy with the enum solution, but was disappointed I couldn't realize it with the struct/protocol approach.
Judging by the fact that you want to cast your structs to their protocols (by using var action: Action = UnaryAction {...}), I'm assuming you don't need the publish method to have the right signature upon evoking it.
In other words, by declaring your Action protocol with a typealias, the compiler is expecting to specialise the publish method for each instance of your structs.
This means that you have two options:
Remove the type casting:
Example:
var action /*removed the :Action type casting */ = UnaryAction<Int>(closure: { (arg:Int) -> () in print("\(arg)") })
action.publish(42)
action = UnaryAction<Int>(closure: { print("shorthand too \($0)") } )
action.publish(42)
var anotherAction = NullaryAction<Int>(closure:{ print("something happened") }) //need to use another variable for this last one
anotherAction.publish(42)
This solution makes your publish methods also have the same signature that your structs have. If your struct is specialised to work with Ints, then you'll have .publish(value: Int).
Make the protocol non-generic
Example:
protocol Action {
func publish(value:Any)
}
struct NullaryAction<T>: Action {
let closure: () -> ()
init(closure: () -> ()) {
self.closure = closure
}
func publish(value:Any) {
self.closure()
}
}
struct UnaryAction<T>: Action {
let closure: (T) -> ()
init(closure: (T) -> ()) {
self.closure = closure
}
func publish(value:Any) {
self.closure(value as! T) //Need to type cast here
}
}
var action: Action = UnaryAction<Int>(closure: { (arg:Int) -> () in print("\(arg)") })
action.publish(42)
action = UnaryAction<Int>(closure: { print("shorthand too \($0)") } )
action.publish(42)
action = NullaryAction<Int>(closure:{ print("something happened") })
action.publish(42)
This solution allows you to keep on type casting, but your publish methods will all have the same signature (.publish(value: Any)). You also need to account for that upon executing the closure.
I want to specify a protocol that manages some type objects that conform to another protocol. Like this:
// Specify protocol
protocol ElementGenerator {
func getElements() -> [Element]
}
protocol Element {
// ...
}
// Implement
class FooElementGenerator: ElementGenerator {
func getElements() -> [FooElement] {
// Generate elements here
return [FooElement()]
}
}
class FooElement {
// ...
}
When trying to compile this, I get an error:
Type 'FooElementGenerator' does not conform to protocol 'ElementGenerator'
hinting that candidate func getElements() -> [FooElement] has non-matching type of () -> [FooElement], but instead it expects () -> [Element].
How this kind of an error can be fixed?
UPDATE:
This solution seems to be working:
protocol ElementGenerator {
typealias T:Element
func getElements() -> [T]
}
protocol Element {
// ...
}
class FooElementGenerator: ElementGenerator {
typealias T = FooElement
func getElements() -> [T] {
return [T()]
}
}
class FooElement: Element {
// ...
}
But when I try to create a variable like this:
let a: ElementGenerator = FooElementGenerator()
a new error appears:
Protocol 'ElementGenerator' can only be used as a generic constraint because it has Self or associated type requirements
When implementing protocol methods, the return type must be same but you may return child class object like this;
protocol ElementGenerator {
func getElements() -> [Element]
}
//#objc for bridging in objective C
#objc protocol Element {
// ...
}
// Implement
class FooElementGenerator: NSObject,ElementGenerator {
override init() {
super.init();
//--
let fooElements:[FooElement] = self.getElements() as! [FooElement]
}
func getElements() -> [Element] {
// Generate elements here
return [FooElement()]
}
}
class FooElement:NSObject, Element {
// ...
override init() {
super.init();
//--
NSLog("FooElement init");
}
}
The error message in the second case is given since you have defined ElementGenerator with an “Associated Type”, and this means that you can only use it in giving constraints for types.
For instance, if you need to have a function defined for generic ElementGenerator values, you could write something like this:
func f<T1:ElementGenerator>(elemGenerator:T1) -> Element {
return elemGenerator.getElements()[0]
}
var a : Element = FooElementGenerator()
var b : Element = BarElementGenerator()
var x : Element = f(a)
var y : Element = f(b)
var z : FooElement = f(a) as! FooElement
I have a function that is only valid to call within the context of another function, so I want swift stop consumers from capturing the inner function:
protocol Foo {
func bar(onlyValidToCallInsideBar: () -> Void)
}
class GoodFooImpl {
func bar(onlyValidToCallInsideBar: () -> Void) {
// do some stuff
onlyValidToCallInsideBar()
// do some more stuff
}
}
class CapturingBadFooImpl {
var badCaptureOfOnlyValidToCallInsideBar: (() -> Void)?
func bar(onlyValidToCallInsideBar: () -> Void) {
badCaptureOfOnlyValidToCallInsideBar = onlyValidToCallInsideBar
}
func fizz() {
badCaptureOfOnlyValidToCallInsideBar!()
}
}
class AsyncBadFooImpl {
func bar(onlyValidToCallInsideBar: () -> Void) {
dispatch_async(dispatch_get_main_queue()) {
onlyValidToCallInsideBar()
}
}
}
class FooConsumer {
func buzz(foo: Foo) {
bar() {
// This should only be called inside bar
}
}
}
I want to prevent impls like CapturingBadFooImpl and AsyncBadFooImpl.
Swift has nested functions. It sounds like you want to make your function nested inside another. Or, if you are creating a framework, you can make your function private. That prevents it from being used outside of its module (the framework).
If you don't mean one of those things you're going to have to explain what you want more clearly.
Is there an equivalent syntax or technique for Anonymous class in Swift?
Just for clarification Anonymous class in Java example here - http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
Thanks!
There is no equivalent syntax, as far as I know.
Regarding equivalent techniques, theoretically you could use closures and define structs and classes inside them. Sadly, I can't get this to work in a playground or project without making it crash. Most likely this isn't ready to be used in the current beta.
Something like...
protocol SomeProtocol {
func hello()
}
let closure : () -> () = {
class NotSoAnonymousClass : SomeProtocol {
func hello() {
println("Hello")
}
}
let object = NotSoAnonymousClass()
object.hello()
}
...currently outputs this error:
invalid linkage type for global declaration
%swift.full_heapmetadata* #_TMdCFIv4Test7closureFT_T_iU_FT_T_L_19NotSoAnonymousClass
LLVM ERROR: Broken module found, compilation aborted!
Command /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 1
You can also create a basic empty class that acts like a bare protocol, and pass a closure to the init function that overrides anything you want, like this:
class EmptyClass {
var someFunc: () -> () = { }
init(overrides: EmptyClass -> EmptyClass) {
overrides(self)
}
}
// Now you initialize 'EmptyClass' with a closure that sets
// whatever variable properties you want to override:
let workingClass = EmptyClass { ec in
ec.someFunc = { println("It worked!") }
return ec
}
workingClass.someFunc() // Outputs: "It worked!"
It is not technically 'anonymous' but it works the same way. You are given an empty shell of a class, and then you fill it in or override whatever parameters you want when you initialize it with a closure.
It's basically the same, except instead of fulfilling the expectations of a protocol, it is overriding the properties of a class.
For example, Java listener/adapter pattern would be translated to Swift like this:
protocol EventListener {
func handleEvent(event: Int) -> ()
}
class Adapter : EventListener {
func handleEvent(event: Int) -> () {
}
}
var instance: EventListener = {
class NotSoAnonymous : Adapter {
override func handleEvent(event: Int) {
println("Event: \(event)")
}
}
return NotSoAnonymous()
}()
instance.handleEvent(10)
(Crashing the compiler on Beta 2)
The problem is, you always have to specify a name. I don't think Apple will ever introduce anonymous classes (and structs etc.) because it would be pretty difficult to come with a syntax that doesn't collide with the trailing closures.
Also in programming anonymous things are bad. Naming things help readers to understand the code.
No anonymous class syntax in Swift. But, you can create a class inside a class and class methods:
class ViewController: UIViewController {
class anonymousSwiftClass {
func add(number1:Int, number2:Int) -> Int {
return number1+number2;
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
class innerSwiftClass {
func sub(number1:Int, number2:Int) -> Int {
return number1-number2;
}
}
var inner = innerSwiftClass();
println(inner.sub(2, number2: 3));
var anonymous = anonymousSwiftClass();
println(anonymous.add(2, number2: 3));
}
}
This is what I ended up doing (Observer pattern). You can use closures in a similar way you would use anonymous classes in Java. With obvious limitations of course.
class Subject {
// array of closures
var observers: [() -> Void] = []
// #escaping says the closure will be called after the method returns
func register(observer: #escaping () -> Void) {
observers.append(observer)
}
func triggerEvent() {
observers.forEach { observer in
observer()
}
}
}
var subj = Subject()
// you can use a trailing closure
subj.register() {
print("observerd")
}
// or you can assign a closure to a variable so you can maybe use the reference to removeObserver() if you choose to implement that method
var namedObserver: () -> Void = {
print("named observer")
}
subj.register(observer: namedObserver)
subj.triggerEvent()
// output:
// observerd
// named observer
If you want to inline a click handler in Java style fashion, first define your closure as a variable in your button class:
var onButtonClick: () -> Void = {}
Then add a method to accept the closure as parameter and store it in the variable for later use:
func onClick(label: String, buttonClickHandler: #escaping () -> Void) {
button.label = label
onButtonClick = buttonClickHandler
}
Whenever the closure should be executed, call it in your button class:
onButtonClick()
And this is how to set the action that should occur on click:
newButton.onClick(label: "My button") { () in
print("button clicked")
}
You can also accept multiple parameters. For example, a toggle button may be handled like this:
var buttonClicked: (_ isOn: Bool) -> Void { set get }
Simply use a struct for defining the interface via function values and then anonymously implement it from a function, as is a very common way to write objects in JavaScript.
The function is only required for creating a private scope for the object returned.
import Foundation
struct Logger {
let info: (String) -> ()
let error: (String) -> ()
}
func createSimpleLogger() -> Logger {
var count = 0
func number() -> Int {
count += 1
return count
}
return Logger(
info: { message in
print("INFO - #\(number()) - \(message)")
},
error: { message in
print("ERROR - #\(number()) - \(message)")
}
)
}
let logger = createSimpleLogger()
logger.info("Example info log message")
logger.error("Example error log message")
Output:
INFO - #1 - Example info log message
ERROR - #2 - Example error log message