Arc Forumnew | comments | leaders | submitlogin
1 point by CatDancer 5921 days ago | link | parent

Sorry, I wasn't clear: I meant I wanted the two sides of the bitable to be separate: setting side a would automatically set side b and vis. versa., but I would still be choosing to do a look up in side a or side b, and I'd still be choosing to set side a or side b (though with the bidirectional table setting side a X Y would be the same as setting side b Y X).


1 point by almkglor 5921 days ago | link

Can do, you could just build something like this:

  (def bidir-table-sided ()
    (with (a-to-b (table)
           b-to-a (table)
           erase-link
           (fn (k-to-v v-to-k k)
             (let v (k-to-v k)
               (= (v-to-k v) nil
                  (k-to-v k) nil)))
           report-error (fn (side) (err:string "bidir-table-sided: not side a or b - " side)))
      (add-attachment
        '= (fn (v side k)
             (let (k-to-v v-to-k)
               (case side
                 a (list a-to-b b-to-a)
                 b (list b-to-a a-to-b)
                   (report-error side))
               (if
                 (no k)
                   (err "bidir-table-sided: can't assign nil key")
                 v
                   (do
                      ;first erase
                      (erase-link k-to-v v-to-k k)
                      (erase-link v-to-k k-to-v v)
                      ;now link them
                      (= (v-to-k v) k)
                      (= (k-to-v k) v))
                 ; else delete
                   (erase-link k-to-v v-to-k k))))
        ; no keys attachment: not a real table, since
        ; we specify a side
        (fn (side k)
          (case side
            a (a-to-b k)
            b (b-to-a k)
              (report-error side))))))
To use:

  (= (foo 'a 42) 1)
  (foo 'b 1)
Can obviously be extended so that the user can specify the sides, for example you can just specify 'user and 'cookie as the side, this is just proof-of-concept.

-----