Reputation: 497
I'm creating a struct that holds 3 float values,
struct Col {
var r: Float
var g: Float
var b: Float
}
and I'd like to add a bunch of function definitions that are equivalent to the built in math functions, but that operate piecewise on the members of my struct
I can do it by hand, eg
func pow(a: Col, b: Col) -> Col {
return Col(r: pow(a.r, b.r), g: pow(a.g, b.g), b: pow(a.b, b.b))
}
but this is tedious and error prone.
What I'd like to do is create a function to turn the original math function into my Col version, so that I could call it like this:
defineColVersion(pow, noArgs: 2)
and it defines the new version, without overwriting the built in function that operates on Doubles
Is there any way to do this in Swift?
Thanks
Upvotes: 3
Views: 217
Reputation: 14983
I actually think this is exactly what you want:
func toCol(f: (Float, Float) -> Float) -> (Col, Col) -> Col {
return { a, b in
Col(r: f(a.r, b.r), g: f(a.g, b.g), b: f(a.b, b.b))
}
}
func toCol(f: Float -> Float) -> Col -> Col {
return { c in
Col(r: f(c.r), g: f(c.g), b: f(c.b))
}
}
let pow = toCol(Darwin.pow)
let sin = toCol(Darwin.sin)
let log = toCol(Darwin.log)
let a = Col(r: 0.4, g: 0.2, b: 0.7)
let b = Col(r: 0.3, g: 0.9, b: 0.3)
pow(a, b)
sin(a)
log(b)
The two overloaded functions toCol
take a unary/binary function on Float
s and returns a new function which does the same on your Col
type. With those two, you can easily create a pow
function for your Col
type.
Upvotes: 5
Reputation: 2372
func init(first: Col, second: Col, function: (Float, Float) -> Float ) {
newR = function(first.r,second.r)
newG = function(first.g,second.g)
newB = function(first.b,second.b)
return self.init(r:newR,g:newG,b:newB)
}
I'm not in a position to compile this so it probably has some errors but hopefully it will be useful. You would use it like so:
first = Col(r:1,g:2,b:3)
second = Col(r:1,g:2,b:3)
combined = Col(first:first,second:second) { pow($0,$1) }
Upvotes: 0
Reputation: 11882
It is not possible to programmatically define new functions in a static language like Swift. What you can do, however, is to make a higher-kinded function:
func init(a: Col, b: Col, function: (Float, Float) -> Float) -> Col {
return self.init(r: function(a.r, b.r), g: function(a.g, b.g), b: function(a.b, b.b))
}
Col(Col(1, 2, 3), Col(3, 4, 5)) { $0 * $1 }
Col(Col(1, 2, 3), Col(3, 4, 5)) { pow($0, $1) }
Upvotes: 3