Add a `new()` primitive to the `uri` package.
Inspired by the request.new() and response.new() functions from the gleam_http package, and while working with Uris, I thought that it would also be a good idea to be able to do the same with Uri.
Provisionally, the implementation of the function would look as follows:
pub fn new() -> Uri {
Uri(
scheme: None,
userinfo: None,
host: None,
port: None,
path: "",
query: None,
fragment: None,
)
}
This would create a completely bare Uri object that the developer could then go ahead and build on top of. I have created a related issue here that would implement 'builder' primitives to set fields on the Uri object. Coupled, these primitives would create a really nice pattern for building out a Uri, but even without those 'setter' primitives being present yet, the developer could still utilise this implementation of new() as follows:
let uri = Uri(..uri.new(), scheme: "http", host: "localhost")
This primitive would make cases like the following taken from uri_test.gleam more concise:
uri.Uri(Some("ftp"), None, None, None, "", None, None)
|> uri.to_string
|> should.equal("ftp:")
allowing them to be switched out for:
uri.Uri(..uri.new(), scheme: Some("ftp"))
|> uri.to_string
|> should.equal("ftp:")
and coupled with the 'setter' primitive proposal mentioned earlier (here), if that proposal were to be implemented:
uri.new()
|> uri.set_scheme("ftp")
|> uri.to_string
|> should.equal("ftp:")
If okay'd, I'd be happy to go ahead and implement this myself.
If I'm reading the URI syntax description correctly, it seems that at a minimum scheme and path are required in order to have a minimally valid URI. If that is indeed correct, then I would think that new might arguably be a bit better implemented as follows, as I don't imagine it would make sense to not specify a scheme:
pub fn new(scheme: String) -> Uri {
Uri(
scheme: Option(scheme),
userinfo: None,
host: None,
port: None,
path: "",
query: None,
fragment: None,
)
}
Your examples might then become slightly simpler. For example:
uri.new("ftp")
|> uri.to_string
|> should.equal("ftp:")
Arguably, defaulting path to an empty string likely doesn't make sense either since that's equivalent to no path at all, which, again, seems to be invalid, but URI validation is a big can of worms to deal with, so perhaps better left for a separate discussion.
That sounds sensible to me!
That said, given we're unlikely to get the builder API is there still a use case for this function?
That sounds sensible to me!
That said, given we're unlikely to get the builder API is there still a use case for this function?
Probably not.
Even if we do not have builders, would it not be valuable to still have a function (or perhaps even a constant Uri.empty) that would eliminate the boilerplate needed to create a complete Uri?
Referring back to this usage:
let uri = Uri(..uri.new(), scheme: "http", host: "localhost")
OK, sounds good.
So, the issue can be closed because of #798, I suppose?
Thank you