I find the compositional syntax of SwiftUI very intuitive and would like to use a similar approach for composing/modifying URLs. Here’s what I have in mind:
struct URLTemplate {
let url: String
}
A template url might look something like this:
https://myserver.com/resource.jpg?width={width}
Now I might want to modify this URL as follows:
urlTemplate
.width(400) // replace the stencil → https://myserver.com/resource.jpg?width=400
.format(.portrait) // append a parameter: &format=portrait
.withWatermark() // append a parameter: &watermark=true
To accomplish this, I would add extension functions on URLTemplate as follows:
extensions URLTemplate {
func width(_ width: Int) -> URLTemplate { ... }
func format(_ format: Format) -> URLTemplate { ... }
func withWatermark() -> URLTemplate { ... }
}
Each of these functions would modify the url and wrap it in a new URLTemplate instance. Works.
The problem is on the caller side:
In the end, I want to have a URL, not a URLTemplate, because that’s what I use to make requests. Then why not just use a URL instance in the first place instead of this custom type? Well, because I need some other information for making these URL modifications that each modifier needs to know.
I could of course just extract the modified URL in the end like this:
urlTemplate
.width(400)
.format(.portrait)
.withWatermark()
.url // ← here
but this is super annoying as it leads to redundant boilerplate code as I would need to do this every time I want to use a URL to make some request.
So what I would wish for is some kind of automagic type inference whenever a URL is expected. When the compiler cannot infer a concrete type, the following expression would return a URLTemplate:
let urlTemplate = urlTemplate
.width(400)
.format(.portrait)
.withWatermark() // → returns self (type: URLTemplate)
However, when the compiler infers a URL type from the context, it should automatically understand that a URL is expected and implicitly return the url instead:
let url: URL = urlTemplate // notice the explicit type annotation
.width(400)
.format(.portrait)
.withWatermark() // → implicitly returns self.url (type: URL)
Is there a feature like this in Swift and if not, can I somehow build this kind of behavior on my own using existing Swift language features?
Note: It should be obvious that I want to be able to use an arbitrary number of modifiers, for example, just omit the withWatermark() modifier above. So in this case, urlTemplate.width(400).format(.portrait) should also be interpreted as a URL when a URL type is inferred.




