[swift-evolution] Draft proposal: multi-property assignment .= operator
Jacob Bandes-Storch
jtbandes at gmail.com
Mon Jan 11 02:32:00 CST 2016
I would much prefer to see something like a "with" construct, which has
been discussed previously in other threads. It would afford
property-setting and also method calls, allowing people to build DSLs
pretty easily. I don't feel that a multi-setter is particularly valuable as
a special case.
object.{ // or "with object {"
property1 = 1
property2 = "a"
method()
...
}
Jacob Bandes-Storch
On Sun, Jan 10, 2016 at 12:21 PM, Michel Fortin via swift-evolution <
swift-evolution at swift.org> wrote:
> (This proposal came from thinking about the memberwise initializer
> proposal as well as older proposals for "cascading" and creating scopes
> making some members act like local variables.)
>
> I'd like to propose a syntax to set multiple properties at once. It would
> look like this:
>
> var object = MyObject()
> object .= (
> property1: 1,
> property2: "a"
> )
>
> and be equivalent to this:
>
> var object = MyObject()
> object.property1 = 1
> object.property2 = "a"
>
> What the `.=` operator does is take each value in the tuple on the right
> and assign them to the property of the same name on the variable on the
> left. Assignments are performed in the same order as they're defined in the
> tuple.
>
> The tuple on the left of the `.=` operator can be written on the spot (as
> above) or be the result of an arbitrary expression, like here:
>
> var object = MyObject()
>
> var values = (property1: 1, property2: "b")
> object .= values
>
> func makeValuesFor(value: Int) -> (property1: Int, property2:
> String) {
> return (value, "\(value)")
> }
> object .= makeValuesFor(4)
>
> If the tuple contains property names that do not exist in the assigned
> variable, or if there is a mismatch in type or visibility and the
> assignment cannot happen, this is a compile-time error.
>
> This syntax is particularly beneficial when assigning to properties of a
> deeply nested value:
>
> object.subpart.detail.numberPad .= (
> radix: 9
> position: .Top
> font: .System
> )
>
>
> ## Tentative Implementation
>
> It's almost possible already to implement this with reflection. Here's an
> attempt (using a different operator name because `.=` doesn't work as a
> custom operator):
>
> infix operator ~= { }
>
> func ~= <T>(inout target: T, values: (a: Int, b: String)) {
> let valuesMirror = Mirror(reflecting: values)
> let targetMirror = Mirror(reflecting: target)
> valueLoop: for valueField in valuesMirror.children {
> guard let label = valueField.label else {
> fatalError("Missing label in value tuple.")
> }
> for targetField in targetMirror.children {
> print(targetField)
> if targetField.label == label {
> targetField.value =
> valueField.value
> continue valueLoop
> }
> }
> }
> }
>
> This fails because you can't assign to fields using the Mirror API. If
> this line could be replaced by something that works:
>
> targetField.value = valueField.value
>
> then we could have a library implementation.
>
>
> --
> Michel Fortin
> https://michelf.ca
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160111/236f66df/attachment.html>
More information about the swift-evolution
mailing list