On 05/02/2017 11:58 AM, oldk1331 wrote:
> I saw this in an old email from Martin Rubey in 2008,
> titled "Bug in ALIST?":
> 
> (90) -> A := construct([[1, 10], [2, 20]]$List Record(key: INT, entry:
> INT))$ALIST(INT, INT)
> 
>    (90) table(2= 20,1= 10)
>                                        Type: AssociationList(Integer,Integer)
> (91) -> map(x +-> x+1, A)
> 
>    (91) table(2= 21,1= 11)
>                                        Type: AssociationList(Integer,Integer)
> (92) -> A
> 
>    (92) table(2= 21,1= 11)
>                                        Type: AssociationList(Integer,Integer)
> 
> 
> That's because 'map' uses 'copy', but AssociationList
> is a List of Records, so it only does "shallow" copy.

If the function map (without ! at the end of its name) modifies one of
its arguments, that's a bug in my eyes.

I would accept map(foo!, L) with a destructive function foo! to modify L
in-place, but + isn't such a function.

I think that is not a problem of the representation of AssociationList,
but rather a problem with the implementation of map.

> 'copy' of Table works as intended.
> 
> Current 'copy' of AssociationList is implemented in LSAGG:
> 
>    copy x ==
>        y := empty()
>        for k in 0.. while not empty? x repeat
>            k = cycleMax and cyclic? x => error "cyclic list"
>            y := concat(first x, y)
>            x := rest x
>        reverse! y
> 
> I assume cyclic structure is not expected for AssociationList?
> Then add this version to AssociationListAggregate is good enough:
> 
>    copy x ==
>        y := empty()
>        while not empty? x repeat
>            y := concat(copy first x, y)
>            x := rest x
>        reverse! y

Well, I don't think that is right (but see below).

Aside from your problem, since we have Rep := Reference List Pair, maybe
it makes sense to add

  copy x == ref copy deref x

to ALIST to avoide an extra layer of ref/deref inside the copy loop.

Anyway...

When I program, I take on the following convention:

  If c := copy x, then for any (destructive) operation f of the
  domain %, after d := f(c), x should be exactly as it was before
  the copy happened.

So in other words that convention doesn't ever say what the depth of the
copy is, it only says that destructive functions don't modify the origin
of a copy.

What I have seen in FriCAS and Aldor libraries seems to follow another
convention. (Unfortunately, I cannot remember that I have ever seen that
written down.) In general, it is only a copy of the toplevel structure,
i.e., a copy of the list structure of association list.

I somehow think that the problem is not in "copy" of LSAGG. The problem
is that setelt! in ALIST does not respect my "convention" from above.

        setelt!(t : %, k : Key, e : Entry) ==
          (r := assoc(k, t)) case Pair => (r::Pair).entry := e
          setref(t, concat([k, e], deref t))
          e

Now the question actually is, should we put another layer of copy into
the copy function of ALIST, i.e., Qian's proposal or change setelt! to
respect the convention.

In fact, I'm unsure which one is better, but in any case, there must be
another layer of copy, either in copy$ALIST or in setelt!$ALIST.

Just my 2 cents.
Ralf

-- 
You received this message because you are subscribed to the Google Groups 
"FriCAS - computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/fricas-devel.
For more options, visit https://groups.google.com/d/optout.

Reply via email to