是否可以在swift中以编程方式添加函数定义

时间:2021-01-14 20:27:39

I'm creating a struct that holds 3 float values,

我正在创建一个包含3个浮点值的结构,

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

我想添加一堆与内置数学函数等效的函数定义,但它对我的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:

我想要做的是创建一个函数将原始数学函数转换为我的Col版本,这样我就可以这样调用它:

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?

在Swift中有什么办法吗?

Thanks

谢谢

3 个解决方案

#1


5  

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 Floats 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.

两个重载函数toCol在Floats上采用一元/二元函数并返回一个新函数,它在Col类型上执行相同的操作。有了这两个,您可以轻松地为您的Col类型创建一个pow功能。

#2


3  

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:

无法以编程方式在Swift等静态语言中定义新函数。但是,你可以做的是提高一个更高的功能:

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) }

#3


0  

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) }

#1


5  

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 Floats 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.

两个重载函数toCol在Floats上采用一元/二元函数并返回一个新函数,它在Col类型上执行相同的操作。有了这两个,您可以轻松地为您的Col类型创建一个pow功能。

#2


3  

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:

无法以编程方式在Swift等静态语言中定义新函数。但是,你可以做的是提高一个更高的功能:

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) }

#3


0  

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) }