I think the alist conversion procedures are important since they allow bags to be defined in program text and serialized with read and write.

I guess the pertinent question is: does ((a . 1) (1 . 2)) mean (1) "1 copy of a, and then *an additional* 2 copies of a"; or (2) "currently the count of a's is 1; in the past the count for a was 2." The semantics of assoc make it seem that conventionally, (2) is how alists with duplicate entries are interpreted. Which I think is consistent with your first definition for how alist->bag and alist->bag! should work.

Kevin Wortman



On Tue, Aug 19, 2014 at 3:20 PM, John Cowan <xxxxxx@mercury.ccil.org> wrote:
Kevin Wortman scripsit:

> How about something like this (untested pseudocode) for alist->bag!:
>
> (define (alist->bag! bag alist)
>   (bag-delete-all! bag (map car alist))

Bag-delete-all doesn't remove all instances of the objects in the list,
only one instance: it means "all in list", not "all copies".  Maybe the
name should be changed?  And by the same token, maybe there should be
bag operations to delete all copies of some object(s)?

>   (for-each (lambda (pair)
>                   (unless (bag-contains? bag (car pair))
>                     (bag-increment! bag (car pair) (cdr pair))))
>                 alist))

That's what I said it should do, but on reflection it's not quite right.
If the bag is {a, a, a} and the a-list says ((a . 1) (a . 2)), I think
we should end up with {a, a, a, a} as a result of the (a . 1), and the
(a . 2) should be ignored.

Maybe this means that alist->bag! doesn't really make sense.  Thoughts?

--
John Cowan          http://www.ccil.org/~cowan        xxxxxx@ccil.org
Principles.  You can't say A is made of B or vice versa.
All mass is interaction.  --Richard Feynman