【问题标题】:Can you create names for tuple elements inside a closure's parameter list?你可以在闭包的参数列表中为元组元素创建名称吗?
【发布时间】:2014-08-27 01:34:22
【问题描述】:

该属性为由UInt8s 组成的颜色提供了足够好的亮度表示,用于redgreenblue

var luma: UInt8 {
    return UInt8(
        [(red, 54), (green, 183), (blue, 19)].reduce(0){
            let (color, eightBitWeight) = $1
            return $0 + Int(color) * eightBitWeight
        } >> 8
    )
}

我希望它看起来像这样,但它无法编译:

[(red, 54), (green, 183), (blue, 19)].reduce(0){ luma, (color, eightBitWeight) in
    luma + Int(color) * eightBitWeight
} >> 8

我们能更接近一点,没有比前者更多的代码吗?

【问题讨论】:

  • 你为什么不直接使用Int(red)*54 + Int(green)*183 + Int(blue)*19
  • 代码不会自行记录权重的范围。

标签: swift tuples


【解决方案1】:

我期待

[(red, 54), (green, 183), (blue, 19)].reduce(0) {
    (luma, let (color, eightBitWeight)) in
    return luma + Int(color) * eightBitWeight
}

但是我遇到了编译器错误……

这是我得到的最接近的地方。

[(red, 54), (green, 183), (blue, 19)].reduce(0) {
    (luma, item: (color: Int, eightBitWeight: Int)) in
    return luma + Int(item.color) * item.eightBitWeight
}

我不确定redgreenblue 是什么类型,所以我将它们设为Int

【讨论】:

  • 干得好。我想知道为什么需要外部括号。然而,“回归”不是。另外,我说颜色是 UInt8s,但我没有像你那样对变量名进行代码高亮;现在修复。
【解决方案2】:

我认为你原来的解决方案:

let red = 1, green = 2, blue = 3
var luma: UInt8 {
    return UInt8(
        [(red, 54), (green, 183), (blue, 19)].reduce(0){
            let (color, eightBitWeight) = $1
            return $0 + Int(color) * eightBitWeight
            } >> 8
    )
}

非常好,因为它是最小化和显式的(尽管我同意元组解包语法可能更简单),但是如果你想要简洁而不是显式键入,那么你可以只使用默认参数名称:

let red = 1, green = 2, blue = 3
[(red, 54), (green, 183), (blue, 19)].reduce(0) {
    $0 + Int($1.0) * $1.1
}

但这更难阅读。如果是我的代码,我会使用较短的变量名,并调整您的原始形式:

let r = 1, g = 2, b = 3
return reduce([(r, 54), (g, 183), (b, 19)], 0) { let v = $0, (color, weight) = $1
    return v + color * weight
}

【讨论】:

    【解决方案3】:

    作为元组的替代方案,您是否考虑过枚举?

    enum RGBColor {
        case Red(UInt32)
        case Green(UInt32)
        case Blue(UInt32)
        func toLumaComponent() -> UInt32 {
            switch self {
            case let .Red(weight):   return weight << 16
            case let .Green(weight): return weight << 8
            case let .Blue(weight):  return weight
            }
        }
    }
    
    [RGBColor.Red(54), .Green(183), .Blue(19)].reduce(UInt32(0)) {
        luma, color in
        return luma | color.toLumaComponent()
    }
    

    甚至是一个简单的函数?

    func RGBColorToLuma(# red: UInt32, # green: UInt32, # blue: UInt32) -> UInt32 {
        return red << 16 | green << 8 | blue
    }
    
    RGBColorToLuma(red: 54, green: 183, blue: 19)
    

    【讨论】:

    • 我正在为组件使用私有枚举,例如get { return self[.Red] },用于 red 的 getter。整个颜色存储为 UInt32。 ChannelBitOffset.Red 为 24。您的函数执行我的 setter 和 getter 的操作,但它们实际上并未计算 luma 值。
    猜你喜欢
    • 1970-01-01
    • 2014-04-09
    • 2010-10-08
    • 2023-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    • 2013-09-17
    相关资源
    最近更新 更多