3

I want to multiply two lists, where I take the left list and multiply it by each element of the right list.

For example:

?- multLists([3,4,2], [4,7,8], R).
R = [[12,16,8],[21,28,14],[24,32,16]].

For that I wrote a helper predicate that takes a list and multiplies it by a single scalar:

multListElem([], _, _).
multListElem([H|T], Result, Elem) :- 
    multListElem(T, W, Elem),
    Z is H*Elem,
    Result = [Z|W].

But now, when I run ?- multListElem([1,2,3], X, 3). I get:

1 ?- multListElem([1,2,3], X, 3).
X = [3, 6, 9|_G1840].

What is that weird tail _G1840?

repeat
  • 18,496
  • 4
  • 54
  • 166
JAN
  • 21,236
  • 66
  • 181
  • 318

2 Answers2

5

The bug is here: multListElem([],_,_). When the first list is empty, the result is empty, so you must write multListElem([],[],_).

When you work with lists, you can use functional idioms like maplist:

multLists(L1, L2, R) :-
    maplist(mult_one_list(L1), L2, R).

mult_one_list(L1, Elem, R) :-
    maplist(mult_2_numbers(Elem), L1, R).

mult_2_numbers(V1, V2, R) :-
    R is V1 * V2.

maplist applies the first argument to each element of each list (passed to it as an argument).

Community
  • 1
  • 1
joel76
  • 5,565
  • 1
  • 18
  • 22
3

your base case leave uninstantiated the tail: change to

multListElem([],[],_).

and it will work.

@Joel76 already addressed your problem, and exposed a better approach using maplist. If you have lambda.pl available here is a compact formula solving the problem

?- maplist(\A^B^maplist(\X^Y^(Y is X*A), [3,4,2], B), [4,7,8], R).
R = [[12, 16, 8], [21, 28, 14], [24, 32, 16]].

edit of course the proper interface would be

multLists(L1, L2, R) :-
    maplist(\A^B^maplist(\X^Y^(Y is X*A), L1, B), L2, R).

The second bug that @false pointed it's difficult to understand but easy to fix:

multLists(L1, L2, R) :-
    maplist(\A^maplist(\X^Y^(Y is X*A), L1), L2, R).

The first bug I would call a feature: it's very useful that lambda works with the closure, and A is declared then... Just my 2 cents...

CapelliC
  • 59,646
  • 5
  • 47
  • 90