Arc Forumnew | comments | leaders | submitlogin
3 points by rocketnia 5509 days ago | link | parent

Whoops, at http://arclanguage.org/item?id=10788 aw brought up something I overlooked: adding new keys.

Here's an imperfect correction. It's the best I can think of without resorting to the power of hacking arc.arc and stuff.

  (mac aget (al (o key nil))
    (if key            (= al (list al key))
        (isa al 'sym)  (= al (ssexpand al)))
    ; At this point, "al" means "arg list" rather than "assoc list." ;)
    (if (~and (alist al) (is 2 len.al)) (err "Invalid arguments to aget"))
    (let (al key) al
      `(alref ,al ,key)))

  ; Because of technical difficulties (specifically, that al is already a value
  ; rather than a place at this point), this can't insert new entries at the
  ; beginning of al; they'd fall right back off, since the caller's variable (or
  ; other reference) is still bound to the "old" first spot, which is oblivious
  ; to anything before it. Instead, this works by inserting new entries at the
  ; *second* spot in al. On a related note, this can't modify anything about an
  ; empty assoc list, since an empty assoc list is nil, which is immutable.
  (defset alref (al key)
    (w/uniq (g-al g-key)
      `(,(list g-al al g-key key)
        (alref ,g-al ,g-key)
        (fn (val)
          (iflet entry (assoc ,g-key ,g-al)
            (= (cadr entry) val)
              ,g-al
            (push (list ,g-key val) (cdr ,g-al))
            (err "Can't set a value in an empty assoc list, sorry."))
          val))))