[Review] SF-0020: URI Templating

Hello community,

The review of URI Templating begins now and runs through March 21, 2025.

Reviews are an important part of the Swift-Foundation evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager by email or DM. When contacting the review manager directly, please include proposal name in the subject line.

What goes into a review?

The goal of the review process is to improve the proposal under review
through constructive criticism and, eventually, determine the direction of
Swift-Foundation. When writing your review, here are some questions you might want to
answer in your review:

  • What is your evaluation of the proposal?
  • Does this proposal fit well with the feel and direction of Swift-Foundation?
  • If you have used other languages or libraries with a similar
    feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick
    reading, or an in-depth study?

More information about Swift-Foundation review process is available here.

Thank you,

Tina L
Review Manager

6 Likes

The URL.init?(template:variables:) initializer looks misplaced to me. I think this operation would be more naturally expressed as something like a render method on URI.Template.

Proposed (using ! for brevity):

let template = URL.Template("http://www.example.com/foo{?query,number}")!
let url = URL(template: template, variables: ["a": "b"])!

Suggestion:

let template = URL.Template("http://www.example.com/foo{?query,number}")!
let url = template.render(with: ["a": "b"])!

According to the proposal this was mentioned as a considered alternative, and in my opinion the initializer is the better choice given the context.

I didn't think so. Like the proposal says, this seems consistent with other APIs, e.g.: String(format:). At least to my mind, this makes more sense, for in general templates don't really render or do anything; they're something you render or act with. In this case, the URL initialises itself with a template and variables.

Oh sorry, I totally forgot to check the alternatives section.

String(format:) seems like an odd comparison. It's quite a niche API in Swift (unlike its counterparts in C and ObjC, where format-based string creation is the norm).

More generally, initializer overloads feel overused and hard to discover. URL already has 18 documented initializers, and even more privateish undocumented ones (go in a repl, type URL.init and press tab).

They also compose poorly in fluent-style method chains, though I guess that's less relevant here, where a template is less likely to be used in that style.

+1, looks great, thanks @deggert!

Generally a +1.

Any reason why URL.Template itself isn't ExpressibleByStringLiteral, so we could directly use:

let url = URL(template: "http://www.example.com/foo{?query,number}", variables: ["a": "b"])!

Any reason why URL.Template itself isn't ExpressibleByStringLiteral , so we could directly use […]

That’s an interesting thought.

The general idea with URL.Template is that a server sends you a template. You fill in the variables and use that to send requests to the server.

In your example

let url = URL(template: "http://www.example.com/foo{?query,number}", variables: ["a": "b"])!

you could have done

let url = URL(string: "http://www.example.com/foo")!

and gotten the same result. ;)

Maybe the documentation needs to be updated to more clearly state what this is intended to be used for?

But I’m not opposed to adding ExpressibleByStringLiteral. But it might be promoting usage other than what’s (originally) intended. The question is thus: should we discourage such usage or encourage it.

There’s also the question of: Why isn’t URL itself ExpressibleByStringLiteral?