Write a custom access operator in Swift - swift

I implemented a helper to have an array of unowned references:
class Unowned<T: AnyObject>
{
unowned var value : T
init (value: T) { self.value = value }
func get() -> T { return self.value }
}
Now, it is possible to do [ Unowned<Foo> ]. However, I'm not satisfied with having the additional get() method to retrieve the underlying object. So, I wanted to write a custom binary operator, e.g. --> for being able to do
for unownedFoo in ArrayOfUnownedFoos
{
var bar : Int = unownedFoo-->method()
}
My current approach is to define
infix operator --> { }
func --><T> (inout lhs: Unowned<T>, inout rhs: () -> Int) -> Int
{
}
The idea I had behind this is:
lhs is obvisouly the object I get out of the array, on which I want to perform the call on
rhs is the method I desire to call. In this case method() would not take no parameters and return an Int, and therefore
The return value is int.
However, the following problems / uncertainties arise:
Is this the correct approach?
Are my assumptions above correct?
How can I call the provided closure rhs on the instance of the extracted Unowned<T>, e.g. (pseudocode) lhs.value.rhs(). If method() was static, I could do T.method(lhs.value), but then I would have to extract the name of the method somehow to make it more generic.

Maybe, a postfix operator is rather simple.
postfix operator * {}
postfix func *<T>(v:Unowned<T>) -> T {
return v.value
}
// Usage:
for unownedFoo in ArrayOfUnownedFoos {
var bar : Int = unownedFoo*.method()
}

Use something like:
func --> <T:AnyObject, V> (lhs: Unowned<T>, rhs: (T) -> V) -> V
{
return rhs (lhs.get())
}
and then use it as:
for unownedFoo in ArrayOfUnownedFoos
{
var bar : Int = unownedFoo-->{ (val:Int) in return 2*val }
}
Specifically, you don't want to use method() as that itself is a function call - which you probably don't want unless method() is actually returning a closure.

Related

Reduce array of closures into single closure

Suppose I have an array of closures which can all be composed with one another (i.e., endomorphisms, their input and output types are the same). How can I compose these closures into a single closure?
For reference, I was trying to design something like the following.
struct MyType {
typealias MyClosure: (T) -> T
private var myClosures: [MyClosure] = [ ... ]
public var closure: MyClosure {
get {
return ? // somehow compose all of myClosures into a single closure here
}
}
}
My first thought was to use reduce, à la myClosures.reduce(STARTING) { a, b in b(a) },
but this requires a starting value to be supplied, and then successively applies the closures to it. I don't want to apply the closures to anything (yet), but just synthesize the private list of closures into a single, public closure which can be applied later. Given the way reduce is
defined, I expect this would look something like
myClosures.reduce(identity) { a, b in compose(a, b) }
func identity(_ input: T) { return input }
func compose(a: MyClosure, b: MyClosure) -> MyClosure { return b(a) }
but the type of b(a) is T, not (T) -> T. How can this be accomplished? Is this a better way of going about closure composition?
Edit: My original answer misunderstood what your problem was. But seeing as my original answer might be useful to future readers, I'll leave it at the bottom.
Your compose function is nearly there! b(a) does not compile because MyClosure does not take another MyClosure. b(a) is invoking the closure ("function application"). not composition. Since compose returns a closure, why not return a closure? A typical closure looks like this in Swift:
{ (param) in return doSomethingTo(param) }
So let's return that!
return { (x) in return b(a(x)) }
This can be simplified to:
{ b(a($0)) } // "return" can be omitted as well!
This page (among other things) tells you how and when you can simplify closure syntaxes.
Original answer:
Using reduce is the correct choice here. The reduction operation is composition, so let's write a compose function first:
func compose<T>(_ x: #escaping (T) -> T, _ y: #escaping (T) -> T) -> (T) -> T {
{ y(x($0)) } // or { x(y($0)) } if you want it the other way
}
Then, we reduce. What's the identity? The identity is something that has these properties:
compose(identity, anything) == anything
compose(anything, identity) == anything
What function does that? The identity function!
So we get:
func reduceClosures<T>(_ closures: [(T) -> T]) -> (T) -> T {
closures.reduce({ $0 }, compose)
}

understanding protocol extensions in swift

I am trying to implement a basic protocol extension like so:
protocol Value {
func get() -> Float
mutating func set(to:Float)
}
extension Value {
static func min(of a:Value, and b:Value) -> Float {
if a < b { //Expression type 'Bool' is ambiguous without more context
return a.get()
}else{
return b.get()
}
}
static func < (a:Value, b:Value) -> Bool {
return a.get() < b.get()
}
}
At the if clause the compiler says:Expression type 'Bool' is ambiguous without more context. Why doesn't this work?
As touched on in this Q&A, there's a difference between operator overloads implemented as static members and operator overloads implemented as top-level functions. static members take an additional (implicit) self parameter, which the compiler needs to be able to infer.
So how is the value of self inferred? Well, it has to be done from either the operands or return type of the overload. For a protocol extension, this means one of those types needs to be Self. Bear in mind that you can't directly call an operator on a type (i.e you can't say (Self.<)(a, b)).
Consider the following example:
protocol Value {
func get() -> Float
}
extension Value {
static func < (a: Value, b: Value) -> Bool {
print("Being called on conforming type: \(self)")
return a.get() < b.get()
}
}
struct S : Value {
func get() -> Float { return 0 }
}
let value: Value = S()
print(value < value) // Ambiguous reference to member '<'
What's the value of self in the call to <? The compiler can't infer it (really I think it should error directly on the overload as it's un-callable). Bear in mind that self at static scope in a protocol extension must be a concrete conforming type; it can't just be Value.self (as static methods in protocol extensions are only available to call on concrete conforming types, not on the protocol type itself).
We can fix both the above example, and your example by defining the overload as a top-level function instead:
protocol Value {
func get() -> Float
}
func < (a: Value, b: Value) -> Bool {
return a.get() < b.get()
}
struct S : Value {
func get() -> Float { return 0 }
}
let value: Value = S()
print(value < value) // false
This works because now we don't need to infer a value for self.
We could have also given the compiler a way to infer the value of self, by making one or both of the parameters take Self:
protocol Value {
func get() -> Float
}
extension Value {
static func < (a: Self, b: Self) -> Bool {
print("Being called on conforming type: \(self)")
return a.get() < b.get()
}
}
struct S : Value {
func get() -> Float { return 0 }
}
let s = S()
print(s < s)
// Being called on conforming type: S
// false
The compiler can now infer self from the static type of operands. However, as said above, this needs to be a concrete type, so you can't deal with heterogenous Value operands (you could work with one operand taking a Value; but not both as then there'd be no way to infer self).
Although note that if you're providing a default implementation of <, you should probably also provide a default implementation of ==. Unless you have a good reason not to, I would also advise you make these overloads take homogenous concrete operands (i.e parameters of type Self), such that they can provide a default implementation for Comparable.
Also rather than having get() and set(to:) requirements, I would advise a settable property requirement instead:
// Not deriving from Comparable could be useful if you need to use the protocol as
// an actual type; however note that you won't be able to access Comparable stuff,
// such as the auto >, <=, >= overloads from a protocol extension.
protocol Value {
var floatValue: Double { get set }
}
extension Value {
static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.floatValue == rhs.floatValue
}
static func < (lhs: Self, rhs: Self) -> Bool {
return lhs.floatValue < rhs.floatValue
}
}
Finally, if Comparable conformance is essential for conformance to Value, you should make it derive from Comparable:
protocol Value : Comparable {
var floatValue: Double { get set }
}
You shouldn't need a min(of:and:) function in either case, as when the conforming type conforms to Comparable, it can use the top-level min(_:_:) function.
You can't write
if a < b {
because a and b have type Value which is NOT Comparable.
However you can compare the float value associated to a and b
if a.get() < b.get() {
If you want to be able to make types that can use operators such as >, <, ==, etc., they have to conform to the Comparable protocol:
protocol Value: Comparable {
func get() -> Float
mutating func set(to: Float)
}
This comes with more restrictions though. You will have to change all the Value types in the protocol extension to Self:
extension Value {
static func min(of a: Self, and b: Self) -> Float {
if a < b { //Expression type 'Bool' is ambiguous without more context
return a.get()
}else{
return b.get()
}
}
static func < (a: Self, b: Self) -> Bool {
return a.get() < b.get()
}
}
The Self types get replaced with the type that implements the protocol. So if I implemented Value on a type Container, the methods signatures would look like this:
class Container: Value {
static func min(of a: Container, and b: Container) -> Float
static func < (a: Container, b: Container) -> Bool
}
As a side note, if you want Value to conform to Comparable, you might want to also add the == operator to the Value extension:
static func <(lhs: Self, rhs: Self) -> Bool {
return lhs.get() < rhs.get()
}

is there a more elegant syntax for Swift Filter with 2 parameters

Is there a more elegant way to filter with an additional parameter (or map, reduce).
When I filter with a single parameter, we get a beautiful easy to ready syntax
let numbers = Array(1...10)
func isGreaterThan5(number:Int) -> Bool {
return number > 5
}
numbers.filter(isGreaterThan5)
However, if I need to pass an additional parameter to my function it turns out ugly
func isGreaterThanX(number:Int,x:Int) -> Bool {
return number > x
}
numbers.filter { (number) -> Bool in
isGreaterThanX(number: number, x: 8)
}
I would like to use something like
numbers.filter(isGreaterThanX(number: $0, x: 3))
but this gives a compile error annonymous closure argument not contained in a closure
You could change your function to return a closure which serves
as predicate for the filter method:
func isGreaterThan(_ lowerBound: Int) -> (Int) -> Bool {
return { $0 > lowerBound }
}
let filtered = numbers.filter(isGreaterThan(5))
isGreaterThan is a function taking an Int argument and returning
a closure of type (Int) -> Bool. The returned closure "captures"
the value of the given lower bound.
If you make the function generic then it can be used with
other comparable types as well:
func isGreaterThan<T: Comparable>(_ lowerBound: T) -> (T) -> Bool {
return { $0 > lowerBound }
}
print(["D", "C", "B", "A"].filter(isGreaterThan("B")))
In this particular case however, a literal closure is also easy to read:
let filtered = numbers.filter( { $0 > 5 })
And just for the sake of completeness: Using the fact that
Instance Methods are Curried Functions in Swift, this would work as well:
extension Comparable {
func greaterThanFilter(value: Self) -> Bool {
return value > self
}
}
let filtered = numbers.filter(5.greaterThanFilter)
but the "reversed logic" might be confusing.
Remark: In earlier Swift versions you could use a curried function
syntax:
func isGreaterThan(lowerBound: Int)(value: Int) -> Bool {
return value > lowerBound
}
but this feature has been removed in Swift 3.

How to use an Swift object method as a closure?

I'd like to use an object method as a closure because I need to reuse the same closure multiple times in different places in an object. Let's say I have the following:
class A {
func launch(code: Int) -> Bool { return false }
}
And I need a closure that is of type Int -> Bool in the same object. How would I be able to use the launch method as the closure? I'd rather not do something like { self.launch($0) } if I can just directly reference the method.
Instance methods are curried functions which take the instance
as the first argument. Therefore
class A {
func launch(code: Int) -> Bool { return false }
func foo() {
let cl = A.launch(self)
// Alternatively:
let cl = self.dynamicType.launch(self)
// ...
}
}
gives you a closure of the type Int -> Bool.

Swift Generic constraints in init

I have generic and I want to be able to initialize it with specific constrains. The constraints are only there for initialization. The rest of the class doesn't care. Here is a simplified example:
struct Generic<T> {
let compare: (T, T) -> Bool
init<T: Equatable>(data: [T]) {
let handler: (T, T) -> Bool = { $0 == $1 }
compare = handler
insert(data)
}
init(compareHandler: (T, T) -> Bool, data[T]) {
compare = self.compareHandler
insert(data)
}
}
You can see there's two initializers. The second one obviously works fine. However, in the first one the local type T is mismatched with the struct's generic Type. So, for example, attempting to insert data I get Cannot invoke 'insert' with an argument list of type '([T])'. Is it possible for me to specialize the Struct's generic type only for the initialization or a specific function?
Note, I've already tried init<T where T:Equatable>(data: [T]) to the same effect.
Update
I'm using the following workaround: I create a top level function and removing the specialized init:
func equatableHandler<T: Equatable>(left: T, right: T) -> Bool {
return left == right
}
Clients of the struct can initialize using: Generic(compareHandler: equatableHandler, data: data)
It's not quite the "convenience" of using a specialized init, but I suppose it works well enough for my purposes. I'm not a fan of creating top-level functions, but the generic is used so often for "Equatable" generics that it makes sense for me to define the handler once for clients to use.
The problem is that the first init method
init<T: Equatable>(data: [T])
introduces a local type placeholder T which hides (and is completely
unrelated to) the placeholder T of the Generic type, so it
is essentially the same problem as in Array extension to remove object by value.
As of Swift 2 you can solve that with a "restricted extension":
extension Generic where T : Equatable {
init(data: [T]) {
let handler: (T, T) -> Bool = { $0 == $1 }
compare = handler
// ...
}
}
For Swift 1.x the only solution is probably to define a global helper
function
func makeGeneric<T : Equatable>(data: [T]) -> Generic<T> {
return Generic(compareHandler: { $0 == $1 }, data: data)
}
(and I could not think of a sensible name for the function :).