Wojtek previously suggested a ~URI sigil 
<https://groups.google.com/g/elixir-lang-core/c/CjY7W9xvu80/m/M9FlA7JnAQAJ>, 
and while there was some initial excitement around it, the thread somewhat 
died without explicit approval or dismissal.

I bring it up because, if that proposal were to be accepted, I think that 
using ~URI"https://example.com"; as the inspect representation would be my 
preferred approach. If the URI is valid, it would inspect using the sigil 
(which itself is compile-time validated when used); if it is invalid, it 
inspects using the struct.

To be clear, I don't want to derail this thread, and if there's interest in 
resurrecting the ~URI discussion, I think that should be done on the other 
thread, but I wanted to bring it up here because it would be suboptimal to 
change the inspect representation twice, were ~URI to be implemented.
On Friday, May 31, 2024 at 6:58:22 AM UTC-4 woj...@wojtekmach.pl wrote:

> On 31 May 2024, at 12:32, José Valim <jose....@dashbit.co> wrote:
>
> I have reviewed the pull request and I noticed that it does validate the 
> URL before generating URI.new!, but it now has the unfortunate side-effect 
> that you may have 2 (or 3) distinct representations when inspecting, which 
> is another downside of the proposal. I don't think the cons (multiple 
> representations, hiding of structures) justify the pro of a more succinct 
> representation.
>
>
> I agree, 3 representations is probably too much, I think having just 2, 
> URI.new! and %URI{}, is more palatable. This reminds me that we used to 
> print `%{~D[2024-01-01] | calendar: Calendar.Holocene}` as `%Date{year: 
> 2024, month: 1, day: 1, calendar: Calendar.Holocene}` so FWIW there was 
> some precedent for this. (It has been improved since, though, and nowadays 
> it would have printed: `~D[2024-01-01 Calendar.Holocene]`.)
>
> If discoverability is more important than verbosity then that’s that. I 
> personally don’t think it matters that much, we have good error messages 
> when mistyping field names and we have the |> inspect(structs: false) and 
> IEx.Info “fallbacks”. Here’s somewhat contrived example so take it for what 
> it is but the difference is pretty stark:
>
> ```
> iex> Enum.map(1..5, &URI.new!("https://example.com/foo?x=#{&1}";))
> [URI.new!("https://example.com/foo?x=1";),
>  URI.new!("https://example.com/foo?x=2";),
>  URI.new!("https://example.com/foo?x=3";),
>  URI.new!("https://example.com/foo?x=4";),
>  URI.new!("https://example.com/foo?x=5";)]
> ```
>
> ```
> iex> Enum.map(1..5, &URI.new!("https://example.com/foo?x=#{&1}";))
> [
>   %URI{
>     scheme: "https",
>     userinfo: nil,
>     host: "example.com",
>     port: 443,
>     path: "/foo",
>     query: "x=1",
>     fragment: nil
>   },
>   %URI{
>     scheme: "https",
>     userinfo: nil,
>     host: "example.com",
>     port: 443,
>     path: "/foo",
>     query: "x=2",
>     fragment: nil
>   },
>   %URI{
>     scheme: "https",
>     userinfo: nil,
>     host: "example.com",
>     port: 443,
>     path: "/foo",
>     query: "x=3",
>     fragment: nil
>   },
>   %URI{
>     scheme: "https",
>     userinfo: nil,
>     host: "example.com",
>     port: 443,
>     path: "/foo",
>     query: "x=4",
>     fragment: nil
>   },
>   %URI{
>     scheme: "https",
>     userinfo: nil,
>     host: "example.com",
>     port: 443,
>     path: "/foo",
>     query: "x=5",
>     fragment: nil
>   }
> ]
> ```
>
> Can’t say I run into stuff like this very often but on the rare occasion I 
> wouldn’t mind something way more compact so I could focus on what matters 
> (i.e. not the internal structure)
>
> Anyway, thanks for considering this!
>
>
> On Fri, May 31, 2024 at 12:20 PM José Valim <jose....@dashbit.co> wrote:
>
>> There are some issues with this proposal:
>>
>> 1. URI parse does not validate, it only parses the components, which 
>> means inspecting with URI.new! after URI.parse! does not guarantee it will 
>> be parseable and return the same result back.
>>
>> 2. URI.new! (and similar) hide the underlying fields of the URI, making 
>> them harder to discover. I believe URI.new! (and similar) are almost always 
>> justified when the structs fields are private, which is not the case here, 
>> so there is more space for debate
>>
>> If the main goal is to reduce verbosity, then maybe we should consider 
>> tagging all fields as optional, so we have this instead:
>>
>> iex> URI.new!("https://elixir-lang.org";)
>> %URI{
>>   scheme: "https",
>>   host: "elixir-lang.org",
>>   port: 443
>> }
>>
>> It may be an acceptable trade-off between hiding fields and keeping it 
>> more compact.
>>
>> On Fri, May 31, 2024 at 12:13 PM Wojtek Mach <woj...@wojtekmach.pl> 
>> wrote:
>>
>>> The current inspect implementation is pretty verbose:
>>>
>>> ```elixir
>>> iex> URI.new!("https://elixir-lang.org";)
>>> %URI{
>>>   scheme: "https",
>>>   userinfo: nil,
>>>   host: "elixir-lang.org",
>>>   port: 443,
>>>   path: nil,
>>>   query: nil,
>>>   fragment: nil
>>> }
>>> ```
>>>
>>> I'd like to propose a more concise one along the lines of "Expression-based 
>>> inspection" from ELixir v1.14 
>>> <https://github.com/elixir-lang/elixir/blob/v1.14/CHANGELOG.md#expression-based-inspection-and-inspect-improvements>
>>> :
>>>
>>> ```elixir
>>> iex> URI.new!("https://elixir-lang.org";)
>>> URI.new!("https://elixir-lang.org";)
>>> ```
>>>
>>> There is a subtle difference between `URI.new!/1` and `URI.parse/1`, the 
>>> former sets the deprecated `authority` field to `nil` so this proposal 
>>> takes that into consideration, returns `URI.parse` "as is":
>>>
>>> ```elixir
>>> iex> URI.parse("https://elixir-lang.org";)
>>> URI.parse("https://elixir-lang.org";)
>>> ```
>>>
>>> `URI.new!/1` is stricter than `URI.parse/1` and in particular it does 
>>> not allow non-escaped characters, notably `"` and `(` and `)` which would 
>>> conflict with the inspect representation so for these I propose to return 
>>> `%URL{}`:
>>>
>>> ```elixir
>>> iex> URI.parse("https://elixir-lang.org/\"";)
>>> %URI{
>>>   scheme: "https",
>>>   authority: "elixir-lang.org",
>>>   userinfo: nil,
>>>   host: "elixir-lang.org",
>>>   port: 443,
>>>   path: "/\"",
>>>   query: nil,
>>>   fragment: nil
>>> }
>>> ```
>>>
>>> I vaguely remember previous discussions about this and I believe the 
>>> biggest concern was "hiding" the internal structure. For example, what is 
>>> the `:scheme`, `:host` and `:path` in intentionally mistyped URL 
>>> `http:/foo`? We would not get the answer from Inspect:
>>>
>>> ```elixir
>>> iex> URI.new!("http:/foo")
>>> URI.new!("http:/foo")
>>> ```
>>>
>>> but I'd like to propose to additionally implement `IEx.Info`:
>>>
>>> ```
>>> iex> i URI.new!("http:/foo")
>>> Term
>>>   URI.new!("http:/foo")
>>> Data type
>>>   URI
>>> Description
>>>   This is a struct representing a URI.
>>> Raw representation
>>>   %URI{scheme: "http", authority: nil, userinfo: nil, host: nil, port: 
>>> 80, path: "/foo", query: nil, fragment: nil}
>>> Reference modules
>>>   URI
>>> Implemented protocols
>>>   IEx.Info, Inspect, String.Chars
>>> ```
>>>
>>> PR: https://github.com/elixir-lang/elixir/pull/13623
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "elixir-lang-core" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to elixir-lang-co...@googlegroups.com.
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msgid/elixir-lang-core/e36197aa-1b77-4000-a3b2-55f022e20ce1n%40googlegroups.com
>>>  
>>> <https://groups.google.com/d/msgid/elixir-lang-core/e36197aa-1b77-4000-a3b2-55f022e20ce1n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>
> -- 
> You received this message because you are subscribed to the Google Groups 
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to elixir-lang-co...@googlegroups.com.
>
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J2z%2B4LmR49nehE_GD8qeZye%3D867PfGuvTcf%2BSzWcyPtg%40mail.gmail.com
>  
> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J2z%2B4LmR49nehE_GD8qeZye%3D867PfGuvTcf%2BSzWcyPtg%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/e37c34ce-2c9f-49b8-a9e4-d1a551071d9cn%40googlegroups.com.

Reply via email to