@Valim yea, you're right.
And I think `from_naive/*` wasn't a good example there, you have a fair 
point there for having a "neutral" result (not success, not failure, just 
neutral).

At Turtle, we do have several cases where we need to figure out a 
success/failure from a result without knowing its shape (at least on some 
tooling, such as Derive). It might sound like a very small thing and that 
Elixir should have to care about it, but we can't control Built-In types 
nor Remote types from dependencies. For Turtle, that leads to either:

   - Implementing a `*normalize_result*/1` function, with a bunch of 
   hardcoded transformations from known result shapes (from deps and built-in 
   fns) to our normalized shape (the one suggested);
   - Making users (teammate devs) care about those inconsistencies, what 
   often leads them to implement anonymous inline functions within pipelines 
   just to get around the inconsistent result shape.

Neither seem ideal IMO, because the later kinda kills the DX intended.

To be clear, with this suggestion I'm exploring a possible solution that 
we'd only see its benefits in the long-run. It's supposed to be a way of 
smoothly leading people towards a convention for `result` values (`result` 
as in the Operation Result Pattern). Nothing would be enforced there, it 
would be just a built-in type.

Maybe something like 

```
@type result(t) :: {:ok, t} | {:error, term}
```

```
# DateTime
@spec from_naive(
  Calendar.naive_datetime,
  Calendar.time_zone,
  Calendar.time_zone_database
) ::
  result(t)
  | {:ambiguous, first_datetime :: t, second_datetime :: t}
  | {:gap, t, t}
  | {:error, :incompatible_calendars | :time_zone_not_found | 
:utc_only_time_zone_database}
```
Downside is that the union for this return typespec contains an `{:error, 
term}` type, but the shape is correct at least and if you don't care about 
what error happened then `term` would be just fine.

Anyway, not a huge deal for me, personally and for Turtle, but I'd love to 
see more consistency on result types across the ecosystem. 

On Thursday, March 30, 2023 at 2:30:02 AM UTC-3 José Valim wrote:

> The point of returning gap or ambiguous is exactly that they may or may 
> not be errors and it is up to you to handle them. For example, some 
> application may choose to surface those to the user and ask more 
> information to resolve the ambiguity. In a statically typed language would 
> have to handle those as well.
>
> The “with” special form provides all flexibility to handle those cases 
> without tying the ecosystem to a shape which may not be sufficient.
>
> On Thu, Mar 30, 2023 at 06:21 Rafael Willians Moraes <m...@rwillians.com> 
> wrote:
>
>> I agree 
>>
>> Although one could simple define their own `@type result(t) :: {:ok, t} | 
>> {:error, term}`, having this built-it IMO would be great for the ecosystem.
>> Maybe biggest problem with :ok|:error tuples right now is that lib 
>> (including standard Elixir libs) are inconsistent on that from. Therefore, 
>> having this type built-in could be a way of encourage people to use it 
>> throughout the ecosystem.
>>
>> Take returns from modules *DateTime* and *Integer* for example:
>>
>>    - `DateTime.*convert/2*`
>>    ```
>>    {:ok, t} 
>>    | {:error, :incompatible_calendars}
>>    ```
>>    - `DateTime.*from_naive*/1` returns
>>    ```
>>    {:ok, t}
>>    | {:ambiguous, first_datetime :: t, second_datetime :: t}
>>    | {:gap, t, t}
>>    | {:error, :incompatible_calendars | :time_zone_not_found | 
>>    :utc_only_time_zone_database}
>>    ```
>>    - `DateTime.*from_iso8601*/1`
>>    ```
>>    {:ok, t, Calendar.utc_offset} 
>>    | {:error, atom}
>>    ```
>>    - `Integer.*parse*/1`
>>    ```
>>    {integer, remainder_of_binary :: binary} 
>>    | :error
>>    ```
>>
>> If one just wants to assert if the result is a success or failure, they 
>> have to know implementation detail of the given result value (not to 
>> mention that I'm not even sure if those `ambiguous` and `gap` from 
>> `from_naive` are success or failure).
>>
>> Therefore, IMO, having a result type is a starting point to have some 
>> consistency across the ecosystem.
>>
>> I'd suggest the following types
>> ```
>> @type result(t, s) :: {:ok, t} | {:error, s}
>> @type result(t) :: {:ok, t} | :error
>> ```
>> On Saturday, March 3, 2018 at 8:31:54 PM UTC-3 yordis...@gmail.com wrote:
>>
>>> Ben it is not about the boilerplace and less typing or more typing, 
>>>
>>> but I found myself having a hard time parsing those | for reading 
>>> different types, because of that, having something like this, when you 
>>> brain sees this automatically understands 
>>> what is that type about, the parsing becomes easier.
>>>
>>> Also from language perspective, I like to embrace this as type, like 
>>> Haskell or Swift those with those Optional types (I dont need a optional 
>>> type itself on elixir btw, just the typespec)
>>>
>>> but, that is just me, I can't speak for others.
>>>
>>>
>>> On Tuesday, February 27, 2018 at 4:11:39 AM UTC-8, Yordis Prieto wrote:
>>>
>>>> Introducing `maybe(t)` it will reduce the boilerplate code for `nil | 
>>>> something` 
>>>>
>>>> It is more convenience to write it this way, at least for me.
>>>>
>>>> What are your thoughts about it?  
>>>>
>>> -- 
>>
> 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/c839c36e-300d-4ba0-b460-8427121b600fn%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/elixir-lang-core/c839c36e-300d-4ba0-b460-8427121b600fn%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-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/9ad043e7-42dd-4c1e-abc6-a9f86931d45fn%40googlegroups.com.

Reply via email to