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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 
>>> 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 [email protected].
>>> 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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to