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

是否可以在swift中以编程方式添加函数定义,swift,Swift,我正在创建一个包含3个浮点值的结构 struct Col { var r: Float var g: Float var b: Float } 我想添加一组函数定义,这些函数定义与内置的数学函数等价,但在我的结构的成员上逐段操作 我能用手做这件事(如用手) 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)) } 但这是乏味和容

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

struct Col {
  var r: Float
  var g: Float
  var b: Float
}
我想添加一组函数定义,这些函数定义与内置的数学函数等价,但在我的结构的成员上逐段操作

我能用手做这件事(如用手)

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))
}
但这是乏味和容易出错的

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

defineColVersion(pow, noArgs: 2)
它定义了新版本,而不覆盖在double上运行的内置函数

在Swift中有什么方法可以做到这一点吗

谢谢

我没有能力编译它,所以它可能有一些错误,但希望它会有用。您可以这样使用它:

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

无法用静态语言(如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) }

我实际上认为这正是你想要的:

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)

两个重载函数
toCol
Float
s上获取一个一元/二元函数,并返回一个新函数,该函数在
Col
类型上执行相同的操作。使用这两个函数,您可以轻松地为
Col
类型创建
pow
函数

如果我理解正确的话,实例方法或类型方法应该足以解决您的问题。您不能用泛型来实现这一点,泛型也不是解决类似问题的方法。Swift是一种类型安全语言,如果这是Javascript,它可以在一秒钟内解决,但是当您想在编译时获取结构/类的任何成员的引用时,Swift会进行类型检查,您可能很容易理解类型T(实际上是占位符)没有(应该)成员
r
g
b
。这就是我要做的,只是对Swift结构初始值设定项语法做一点修改:
init(ua:Col,b:Col,uu.function:(Float,Float)->Float){
self.init(r:function(a.r,b.r),g:function(a.g,b.g),b:function(a.b,b.b))
是的。这正是我想要的。我甚至没有尝试它,因为我假设let pow=toCol(Darwin.pow)会覆盖接受double的版本,但它实际上重载了它:)
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)