Swift: I want to chain arrays

Isn't it special to treat only Optional?

There was something called Optional Chaining in Swift, but if the language specification supports such missiles, I would like you to support arrays and other similar (monamona) ones.

I think it's new, but as you know, optional chains

struct Person {
	let name: String
	let age: Int
	let friends: [Person]
}

let me: Person = .init(name: "Freddie", age: 30, friends: [])
let someone = me.friends.first?.friends.first?.friends.first // <- Person?

You can access properties continuously using?

But the question is, why doesn't this syntax support arrays and Result types?

The reason why we cite options and arrays to be treated equally is that they are very long, so I will omit them in the explanation that "these are common monads." Roughly speaking, both optional and array have member functions such as map and flatMap, and they are similar to each other, aren't they? That's it.

What you want to play

What I want to do is to write in an array like this dream.

let people: [Person] = [.init(name: "me", age: 32, friends: [.init(name: "Tom", age: 40, friends: [])]), .init(name: "you", age: 28, friends: [.init(name: "Nancy", age: 10, friends: []), .init(name: "Freddie", age: 20, friends: [])])]
let totalAge = people[].age.reduce(0, +) // 60
let ourFriends = people[].friends[].name // ["Tom", "Nancy", "Freddie"]

If you name it, it's called Array Chaining.

people[].age

Wouldn't it be short and beautiful if it could be written this way?

Good

people.map { $0.age }

Or at best

people.map(\.age)

Let's say goodbye to a masala town level code like this.

Let's implement it

This time I'm dealing with arrays, so I'm going to use [] instead of the signal to use the method chain.

public extension Collection {
	subscript() -> ArrayMemberLookupReference<Self> {
		.init(source: self)
	}
}

public extension Collection where Element: Collection {
	subscript() -> ArrayMemberLookupReference<[Element.Element]> {
		.init(source: lazy.flatMap { $0 })
	}
}

@dynamicMemberLookup
public struct ArrayMemberLookupReference<C: Collection> {
	fileprivate let source: C
}

extension ArrayMemberLookupReference {
	subscript<Property>(dynamicMember keyPath: KeyPath<C.Element, Property>) -> [Property] {
		source.map { t in t[keyPath: keyPath] }
	}
}

I'll try it

By the way, you may wonder if such a thing can really be used. Let me show you the sample code again.

struct Person {
	let name: String
	let age: Int
	let friends: [Person]
}

let people: [Person] = [.init(name: "me", age: 32, friends: [.init(name: "Tom", age: 40, friends: [])]), .init(name: "you", age: 28, friends: [.init(name: "Nancy", age: 10, friends: []), .init(name: "Freddie", age: 20, friends: [])])]
let totalAge = people[].age.reduce(0, +) // 60
let ourFriends = people[].friends[].name // ["Tom", "Nancy", "Freddie"]

Please give it a try.

If you suspect that it will actually work, try running it on Playground. It's actually implemented in the current Swift, but it looks as if a new language specification has been added.

Recommended Posts

Swift: I want to chain arrays
[Swift] I want to draw grid lines (squares)
I want to convert characters ...
[Swift] I want to do something like C's sprinftf
I want to use FormObject well
I want to convert InputStream to String
I want to docker-compose up Next.js!
I want to create a chat screen for the Swift chat app!
I want to remove the top margin in Grouped UITableView (swift)
I want to develop a web application!
I want to write a nice build.gradle
I want to eliminate duplicate error messages
I want to make an ios.android app
I want to display background-ground-image on heroku.
I want to use DBViewer with Eclipse 2018-12! !!
I want to RSpec even at Jest!
I want to write a unit test!
I want to install PHP 7.2 on Ubuntu 20.04.
I want to stop Java updates altogether
I want to use @Autowired in Servlet
I want to target static fields to @Autowired
I want to do team development remotely
Corresponds to 17 arrays
I want to test Action Cable with RSpec test
I want to sort by tab delimited by ruby
I want to output the day of the week
Run R from Java I want to run rJava
I want to send an email in Java.
I want to graduate from npm install properly [2020]
I want to use arrow notation in Ruby
[Ruby] I want to do a method jump!
I want to use java8 forEach with index
I want to var_dump the contents of the intent
I want to pass APP_HOME to logback in Gradle
I want to simply write a repeating string
I want to design a structured exception handling
rsync4j --I want to touch rsync in Java.
I want to play with Firestore from Rails
[Xcode] I want to manage images in folders
I want to be eventually even in kotlin
I want to write quickly from java to sqlite
I want to truncate after the decimal point
I want to reduce simple mistakes. To command yourself.
I want to perform aggregation processing with spring-batch
[Rails] I want to load CSS with webpacker
I want to delete files managed by Git
I want to get the value in Ruby
I want to use Combine in UIKit as well.
I want to use Clojure's convenient functions in Kotlin
I want to call a method of another class
I want to do something like "cls" in Java
[Java] I want to calculate the difference from the date
I want to use NetBeans on Mac → I can use it!
I want to embed any TraceId in the log
Pointcut Expression I want to specify more than one
I want to use fish shell in Laradock too! !!
I want to use ES2015 in Java too! → (´ ・ ω ・ `)
I learned stream (I want to convert List to Map <Integer, List>)
I want to judge the range using the monthly degree
I want to use a little icon in Rails
I want to know the answer of the rock-paper-scissors app