tl;dr: allow .info.age
as a derived form/syntactic sugar for (\r -> r.info.age)
in the same way that already works for simply .age
.
I find an accessor function a pretty useful shortcut, obviously not because it’s fewer characters but just because it gets rid of noise that isn’t helpful to comprehension:
combinedAge =
List.map .age people
Seems nicer to me than
combinedAge =
List.map (\p -> p.age) people
Unfortunately if the value required is nested this doesn’t work, you have to write the noisy lambda way:
combinedAge =
List.map (\p -> p.info.age) people
or
getAge person =
person.info.age
combinedAge =
List.map getAge people
So I suggest that this shortcut should just be allowed regardless of how long the chain is:
combinedAge =
List.map .info.age people
I realise that Elm tends to discourage nested records in favour of just having larger records and using extensible record type syntax to restrict/hide information where necessary. But this seems still a reasonable extension of the shortcut nonetheless.
Obviously it’s probably something of a code smell if you saw something like List.map .one.two.three.four.five
, I’d respond with
- I’m not sure this proposed syntax really encourages deeply nested record structures rather than just makes them slightly less unpleasant to work with.
- If the alternative is
List.map (\r -> r.one.two.three.four.five)
at least the shortcut makes it clearer at first glance that the function really does nothing other than accessing a nested record. - If you’re really worried about that you could restrict it to whatever length you wanted, but I believe 1 is not the correct length to restrict it to.
However, if you suggest that forcing someone to name the getAge
function is better that’s a much more convincing argument (to me anyway). In fact I’m not sure I haven’t just talked myself out of this altogether. I suppose it isn’t forcing you to write the getAge
because you can write the lambda (am I now proposing to ban lambdas? I at least think lambdas are useful in teaching to demonstrate that functions are values just as ints and strings are)
Mostly irrelevant side issue
Currently if you try to write this, the error message you get is:
> .info.age
-- TYPE MISMATCH ---------------------------------------------------------- REPL
The 1st argument to this function is not what I expect:
3| .info.age
^^^^
This .age field access function has type:
{ b | age : a } -> a
But this function needs the 1st argument to be:
{ b | info : a }
So it’s basically saying that you’re trying to apply the function .info
to the value (which happens to be a function) .age
, which of course does not have the correct type. But I guess that’s almost certainly not what the user was trying to do, they where either assuming .info.age
would work in the way I propose or they have simply mis-typed something like person.info.age
as person .info.age