[Pitch] Nested if let and guard let

I like the idea of a syntax that is based on closure capture lists for destructuring properties (structs, classes). It would be great to see an actual pitch based on this. It has been brought up a few times, but never pitched. This is the biggest item on my wish list for Swift that isn't already in progress.

Although I like the symmetry that Javascript has on structuring/destructuring, it is might be too late to do that for Swift. It would be nice to see out how destructuring dictionaries and arrays could fit in to this... Possibly the same bracket syntax could be used, but with different matching syntax inside.

Using closure capture list syntax for destructuring was brought up here:

Just an idea based on above.

// Class / Struct properties
let [make, model, year] = car

if let [make, model, year] = car, year > 2014 {
  print("Make: \(make), Model: \(model)")
}

// Would carry a tuple type. Can override names like in a capture list.
let [carMake = make, model, year]: (String, String, Int) = car
// Nesting
let [
  policyHolder, 
  [make, model, year] = car
]: (String, (String, String, Int)) = autoPolicy 
// or maybe allow expressions
let [
  policyHolder, 
  make = car.make,
  model = car.model, 
  year = car.year,
]: (String, String, String, Int) = autoPolicy 

// Maybe extend for arrays with a slice-like ... syntax.
let [ a, b, c, ...theRest]: (Int?, Int?, Int?, ArraySlice<Int>) = [ 1, 2, 3, 4, 5]
let [ a, b, c, ...] = [ 1, 2, 3, 4, 5]
let [ a, b, c, ...]: (Int?, Int?, Int?) = [ 1, 2]
// Maybe destructure dictionaries
let [ "make": make, "model": model]: (String?, String?) = [ "make" : "Ford", "model": "Mach-E" ] 
// or subscript destructuring
let [ make = ["make"], model = ["model"]]: (String?, String?) = [ "make" : "Ford", "model": "Mach-E" ] 

Alternatively, maybe tuple destructuring could be extended for properties. That way square brackets could be reserved for Array/Dictionary destructuring and pattern matching. The slash is probably needed to avoid ambiguity during pattern matching and fits in with key path syntax.

let (\.make, \.model, \.year) = car

// allow renaming and nesting just like with tuples
if let (\.policyHolder, \.car: (\.make: carMake, \.model, \.year)) = autoPolicy, year > 2014 {
  print("\(policyHolder): \(carMake) \(model)")
}

// allow for named tuples with mismatched sizes
let (\.x, \.y) = (x: 1, y: 1, z: 1)

// a prefix character might be another option
let \(make, model, year) = car
let \{make, model, year} = car
2 Likes