It's not a huge deal but other strongly typed languages definitely allow 
arbitrary expressions in record update syntax.

# type t = { a : int ; b : float } ;;

type t = { a : int; b : float; }

# let emptyT () = { a = 1 ; b = 3.0 } ;;

val emptyT : unit -> t = <fun>

# let x = { (emptyT ()) with a = 7 } ;;

val x : t = {a = 7; b = 3.}

On Saturday, March 18, 2017 at 10:26:57 AM UTC-7, Mark Hamburg wrote:
>
> 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 <mhamb...@gmail.com <javascript:>> 
> 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 <mhamb...@gmail.com 
> <javascript:>> 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....@gmail.com 
>> <javascript:>> wrote:
>>
>> Re-posting the first example from Franscisco's thread 
>> <https://groups.google.com/forum/#!topic/elm-discuss/vzcrRdgY1-w>:
>>
>> 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...@googlegroups.com <javascript:>.
>> 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