I just had a senior engineer on my team ask me whether it was really the case 
that putting a qualified name or a field access into the beginning of a record 
update would fail to compile. His examples were much like the other examples 
from this thread, but I'm noting this here to make clear that this seems to be 
a routine stumbling block.

Mark

> On Mar 9, 2017, at 3:09 PM, Mark Hamburg <mhamburg...@gmail.com> wrote:
> 
> I got asked for non obfuscated/simplified examples, so let me run through 
> some more realistic code. I would pull from our own codebase but we've often 
> contorted ourselves away from these patterns because they are so ugly so I 
> can't just grab existing code.
> 
> Imagine having a style element that includes information about padding on 
> each side:
> 
> type Rect = { left : Int, top : Int, right : Int, bottom : Int }
> 
> type Style = { padding : Rect, ... }
> 
> Expressing it this way allows us to work with the padding as a whole when 
> useful and to avoid having to work with field names like leftPadding, 
> topPadding, etc (presumably along with leftMargin, topMargin, etc) 
> 
> But now say one wants to change just the left padding. The code has to build 
> a new padding object and then stick it back into the style. A little ugly 
> from the standpoint of repetition, but maybe just...
> 
> { style | padding = { style.padding | left = 10 } }
> 
> Nope. We can't use an expression for the record to be updated. So, instead we 
> have to write something more like:
> 
> let
>     oldPadding =
>         style.padding
>     newPadding =
>         { oldPadding | left = 10 }
> in
>     { style | padding = newPadding }
> 
> Or we can use the successive wrapping pattern if we have the necessary 
> utility functions:
> 
> 10 |> asLeftIn style.padding |> asPaddingIn style
> 
> And the inability to use an expression to derive the record also means that 
> we can't do something like:
> 
> { Style.default | color = "red" }
> 
> But rather have to write:
> 
> defaultStyle : Style.Style
> defaultStyle = Style.default
> 
> ...
> 
> { defaultStyle | color = "red" }
> 
> I don't have a good answer to the ugliness of the nested update though the 
> successive wrapping pattern would probably be pretty reasonable if we had 
> .field= in addition to .field. But the latter problem seems like the sort of 
> thing that should be very straightforward to solve and would also allow for 
> writing the first version of updating the left padding that I wrote above.
> 
> Mark
> 
>> On Fri, Mar 3, 2017 at 8:44 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:
>> Our codebase suffers from this as well. And unlike what one of the follow 
>> ups noted, this isn't an issue of wanting to add fields. Rather, it's an 
>> issue of not being able to use an expression in the first part of the record 
>> update. In this case, one doesn't even need a general expression but just an 
>> imported value. On the  their hand, members of my team have gotten bit by 
>> and complained about not being able to construct a nested update using what 
>> they thought were the language constructs:
>> 
>>     newFoo = { oldFoo | nested = { oldFoo.nested | field = 3 } }
>> 
>> The "best" syntax I've seen for that is something like:
>> 
>>     newFoo =
>>          3 |> asFieldIn oldFoo.nested |> asNestedIn oldFoo
>> 
>> But that's pretty obscure as well.
>> 
>> That said, I just added a utility module to our project that is filled with 
>> generic setFoo and asFooIn functions for every field name that seems at all 
>> likely to be used more than once. I would love to have support for .field= 
>> functions to parallel the .field functions. I would have them take the 
>> assigned value as a first parameter and the record as a second parameter to 
>> enable writing:
>> 
>>     Slides.defaultConfig
>>         |> .someAttribute= myCustomValue
>> 
>> The case where the parameters are reversed which helps with nesting could be 
>> handled using a utility function:
>> 
>>      3
>>         |> into oldFoo.nested .field=
>>         |> into oldFoo .nested=
>> 
>> Mark
>> 
>>> On Mar 2, 2017, at 10:16 PM, Richard Feldman <richard.t.feld...@gmail.com> 
>>> wrote:
>>> 
>>> Re-posting the first example from Franscisco's thread:
>>> 
>>> There is a common pattern where a library (ex, elm-markdown) will provide a 
>>> default config, to be extended by the user.
>>> 
>>> Here the two ways to do this right now, one painfully verbose and the other 
>>> relying on exposing values that would read better if fully qualified 
>>> instead of exposed:
>>> 
>>> import Slides
>>> 
>>> slidesDefaultConfig =
>>>   Slides.defaultConfig
>>> 
>>> myCustomSlidesConfig =
>>>  { slidesDefaultConfig | someAttribute = myCustomvalue }
>>> 
>>> or
>>> 
>>> import Slides exposing (slidesDefaultConfig)
>>> 
>>> myCustomSlidesConfig =
>>>  { slidesDefaultConfig | someAttribute = myCustomvalue }
>>> 
>>> Not a big deal TBH, but annoying.
>>> 
>>> 
>>> -- 
>>> You received this message because you are subscribed to the Google Groups 
>>> "Elm Discuss" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an 
>>> email to elm-discuss+unsubscr...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
> 

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to