Maplist using a lambda on a lists of dicts doesn't work as expected

Given this:

:- use_module(library(yall)).
:- use_module(library(apply)).
:- use_module(library(apply_macros)).
works(L) :- maplist([A,B]>>(get_dict(b, A, B)), [#{a:1,b:2},#{a:3,b:4}], L).
doesnt(L) :- maplist([A,B]>>(B = A.b), [#{a:1,b:2},#{a:3,b:4}], L).

This works as I expect:

works(L).
L = [2, 4]

But this doesn’t:

doesnt(L).
Arguments are not sufficiently instantiated
In:
   [4] throw(error(instantiation_error,_1920))
   [1] doesnt(_1974) at  line 4

I though the two are supposed to be equivalent, clearly not?

1 Like

This has come up before and actually just bit me the other day! You can see what’s happening if you try doing listing(doesnt/1):

doesnt(L) :-
    '.'(A, b, C),
    maplist([A, B]>>(B=C),
            [#{a:1, b:2}, #{a:3, b:4}],
            L).

What’s happening here is that the expansion of the dot-syntax to look up the dictionary gets hoisted outside of the lambda, so it happens once at the beginning of the predicate, not each iteration through the lambda.

1 Like

Ah, thanks! So I’m not losing my marbles then :laughing: The listing hint is useful as well, thank you.

I thought it was pilot error on my part but it looks like it’s is a long-standing issue:

In my case the lambda is more complex than a simple dict value selection, so it is probably better off in a separate predicate anyway.

1 Like