Re: [eclipse-clp-users] Dealing with ambiguity between empty arrays and empty lists

From: Alex Mahrer <>
Date: Mon, 09 Dec 2013 17:16:57 -0600
Thank you both for the prompt responses.

On 12/4/2013 8:30 PM, Sergii Dymchenko wrote:
> Hi,
> Is this a real practical issue?

The previous example using dim/2 demonstrated how the ambiguity of the
two representations manifests itself as an issue. As a practical example
of this issue, consider a predicate that calculates the total number of
integers contained in an integer array of arbitrary dimensions.

int_count(MultiArray, N) :-
  dim(MultiArray, Dims),
  (foreach(D, Dims), fromto(1, In, Out, N) do
    (Out is In * D)

The following query then results in an incorrect value for N.

?- int_count([]([], [], []), N).

N = 3

> Will the approach 2 solve the problem of not matching dimensions in the
> following case?
> ?- dim(Array2D, [3, 0, 777]), dim(Array2D, Dims).
> Array2D = []([], [], [])
> Dims = [3]
> Sergii.

The above query is semantically void. Compound terms with arity zero
contain no sub terms by definition. In this case, dim/2 should return an

On the other hand, the query below does have meaning - one that is
important in contexts where arbitrary arrays may be accepted as parameters.

?- dim(Array2D, [3, 0]), dim(Array2D, Dims).

I think it is important to consider '[]' as an empty array in this case
since empty arrays have been shown above to be useful in the degenerate
cases of multidimensional arrays. In other words, the output should

Array2D = []([], [], [])
Dims = [3,0]

Furthermore, as of version 6.1 #175, array-handling predicates including
do/2 (with foreachelem as its iter spec), array_list/2, array_flat/2,
and array_concat/3 treat the atom '[]' as an empty array. I think it
makes sense for dim/2 to follow suit, since what makes arrays distinct
from arbitrary compound terms is support from these built-in predicates.

On 12/5/2013 1:21 AM, Joachim Schimpf wrote:
> As for the remaining problems, I believe (correct me if I'm wrong) they
> only occur when you do more than one of these things at the same time:
> 1. the code is unaware of the dimensions of the arrays it works with,
>    or not all rows have the same length
> 2. the arrays can contain lists or other arrays as elements (the common
>    case of numeric arrays should be fine)
> To address (1), you could explicitly carry around the array dimensions
> in addition to the array itself.  To address (2), you could use type
> wrappers around the elements.
> That's as much as I can think of in general terms -- do you have a specific
> problem that you need to solve?
> -- Joachim

That looks correct to me. Those methods are sufficient to solve my
problem of handling degenerate cases of multidimensional arrays, though
built-in support from dim/2 would be nice. :)

Thank you,

On 12/4/2013 1:50 PM, Alex Mahrer wrote:
> Lists are defined in ECLiPSe as recursive data structures with root term
> '[]' so that an empty list is represented by the atom '[]'. Arrays are
> simply compound terms with functor '[]', thus empty arrays are also
> represented by the atom '[]'.
> This ambiguity leads to inconsistencies in instances where empty arrays
> must be distinguished from empty lists. As an example, consider the
> following query that uses dim/2 to both create a two-dimensional array
> and retrieve the dimensions of that array:
> ?- dim(Array2D, [3, 0]), dim(Array2D, Dims).
> Array2D = []([], [], [])
> Dims = [3]
> In this example, the dimensions provided to dim/2 in the first call do
> not match the dimensions that it derives from the array in the second call.
> Two approaches to dealing with this problem come to mind:
> 1) Avoid the use of empty arrays.
> 2) Represent arrays using a different functor, and rewrite all
> predicates that handle arrays to accommodate.
> Neither of these approaches is ideal. Are there any alternatives that
> I'm missing?
> Thanks,
> Alex
Received on Mon Dec 09 2013 - 23:17:04 CET

This archive was generated by hypermail 2.2.0 : Wed Dec 11 2013 - 18:13:17 CET