Skip to content

Instantly share code, notes, and snippets.

Last active July 22, 2016 00:59
Show Gist options
  • Save gsheld/542a57c1ca5efe87892a28759215283e to your computer and use it in GitHub Desktop.
Save gsheld/542a57c1ca5efe87892a28759215283e to your computer and use it in GitHub Desktop.
Example: Struct syntax for requesting a copy with an ivar set to an explicit value
struct Foo {
var bar = 0
var baz: String
let foo = Foo(bar: 1, baz: "baz") // Initial struct instance
let fooWithNewBar = foo.withBar(2) // Returns a new `Foo` with `bar` set to 2; `baz` remains set to "baz".
let fooWithNewBaz = foo.withBaz("BAZ") // Returns a new `Foo` with `baz` set to "BAZ"; `bar` remains set to 1.
let fooWithChaining = foo.withBar(3) // Example of method chaining using this approach. `bar` is set to 3 and
.withBaz("BaZ") // `baz` is set to "BaZ".
// Note that both `bar` and `baz` are var (mutable) properties. Although it is possible in certain situations to create
// a copy of an object with a let (constant) property** set to a certain value (e.g. when the value of the let property is
// directly injected into the initializer), it would be impossible to adapt the .withX() syntax to lets in all situations.
// The .withX() syntax proposed above is a simple syntactic sugar. The same affect can be achieved using
// already-available swift syntax:
struct Foo {
var bar = 0
var baz: String
func withBar(bar: Int) -> Foo {
var newFoo = self = bar
return newFoo
func withBaz(baz: String) -> Foo {
var newFoo = self
newFoo.baz = baz
return newFoo
// Of course, the downside of this approach is the additional boilerplate required to generate these immutable "setters".
// It would require the enterprising developer to write similar code for *all* structs for which they would like to use
// this syntax. It would also force developers to extend those Structs for which they do not have the source code (e.g.
// String).
// Given Swift's focus on immmutability as evidenced by the design of Struct (e.g. the keyword "mutating" is explicitly
// required to achieve mutability in any Struct property or method), I feel the syntax proposed above would reduce the
// burden of developers interested in transitioning to more immutable-APIs. Of course, there is always the danger of
// overuse and potential for confusion with actual "setters" that do change the state of a particular instance. That is why
// feedback would be most welcome!
// ** The same logic can be applied to "private(set)" properties.
Copy link

gsheld commented Jul 22, 2016

It's worth noting that there is another similar suggestion by Erica Sadun which involves syntax for method cascading.

A form of method cascading can also be achieved with vanilla Swift 2.2 --

// Here's an example using an overloaded operator.
infix operator ~> {}
func ~> <T>(lhs: T, rhs: (inout T) -> ()) -> T {
  var this = lhs
  return this

let cascadeFoo = foo ~> {
  $ = 2
  $0.baz = "BaZ"

For setting a single property, method cascading is not quite as elegant but is more general use than what I propose -- e.g. the syntax is valid with both methods and properties in addition to working on Class-based abstractions. Its an interesting alternative to the method chaining I briefly outline above, but their use cases do seem somewhat different.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment