[erlang-questions] Tried this... Thought it interesting... But it didn't work.
zxq9
zxq9@REDACTED
Tue Sep 1 20:55:37 CEST 2015
On 2015年9月1日 火曜日 20:01:38 Jesper Louis Andersen wrote:
> On Tue, Sep 1, 2015 at 6:43 PM, zxq9 <zxq9@REDACTED> wrote:
>
> > Honestly, I don't really think this is the best use of list comprehension
> > syntax. I can easily imagine people being confused at that, or at least
> > requiring a few moments thought to figure out wtf is going on in that line.
> > The fact this confounded you (and the example was unclear in the blog post,
> > imo) is a good reason why you shouldn't do this in your code.
> >
>
> I must admit I sometimes do this. Consider:
>
> f(X) ->
> E = case X > 5 of
> true -> [7];
> false -> []
> end,
> [1,2,3] ++ E ++ [4,5].
>
> This is easier written as
>
> f(X) ->
> [1,2,3] ++ [7 || X > 5] ++ [4,5].
>
> but as a way to get the list comprehension to append like this is the only
> way I tend to use the construction. For real-world use, consider the
> following snippet from my Maps R18 tests:
>
> https://github.com/jlouis/maps_eqc/blob/96d06da56053e87dd33c830b293dface525be17d/src/maps_eqc.erl#L693-L696
>
> remove_args(#state { contents = C } = State) ->
> frequency(
> [{5, ?LET(Pair, elements(C), [element(1, Pair)])} || C /= [] ] ++
> [{1, ?SUCHTHAT([K], [map_key(State)], find(K, 1, C) == false)}]).
>
> The idea here is that we want to generate arguments for removing an element
> from a map, and C contains the current contents of the map. If the map is
> non-empty, C /= [], and we can pick elements from C. Otherwise, we generate
> a map key such that it is really not an element of the map in question
> (which is trivially true if C = []). The neat part is that the first
> variant with frequency 5 is never generated for the empty map.
>
> A case analysis in this case would tend to repeat code, so I find this
> somewhat more nimble. But these situations are probably the only situations
> on which I use this way of writing.
I sort of see your point, but I tend to write far less exciting code. I would probably do something more like:
remove_args(#state { contents = C } = State) ->
frequency(prefix_on_empty(C) ++
[{1, ?SUCHTHAT([K], [map_key(State)], find(K, 1, C) == false)}]).
prefix_on_empty([]) -> [];
prefix_on_empty(C) -> [{5, ?LET(Pair, elements(C), [element(1, Pair)])}].
Note, I have no idea what a fitting name for prefix_on_empty/1 should be, but you get the idea.
Anyway, interesting technique.
-Craig
More information about the erlang-questions
mailing list