Arc Forumnew | comments | leaders | submitlogin
1 point by waterhouse 5392 days ago | link | parent

You can use lists of the 2 indices as keys to a hash-table. Thus, to make an "array" where the element at (i, j) is i^j, we could go:

  (= x (table))
  (for i 1 10
    (for j 1 10
      (= (x (list i j)) (expt i j))))
Optionally, you could define an array-lookup procedure thus:

  (def aref (a . indices)
    (a indices))
I haven't learned how to use 'defset yet, so I may be wrong, but I think you could then use it to make

  (= (aref a i j ...) value)
macroexpand into:

  (= (a (list i j ...)) value)


3 points by waterhouse 5392 days ago | link

I learned to use 'defset by looking at the documentation and demonstration in arc.arc.

  (defset aref (x . indices)
   (w/uniq (gx gi)
           (list `(,gx ,x ,gi (list ,@indices))
                 `(,gx ,gi)
                 `(fn (val) (= (,gx ,gi) val)))))
And this works fine:

  arc> (= x (table))
  #hash()
  arc> (= (aref x 1 2) 3)
  3
  arc> x
  #hash(((1 2 . nil) . 3))
  arc> (x '(1 2))
  3
However, strangely, my definition of aref, as:

  (def aref (x . indices)
    (x indices))
does not work as intended. If x, a table, has a value for the key (list 1 2), then (aref x 1 2) will not find that value. I investigated and, basically, it seems that the list created by (list 1 2) is nil-terminated, while the list constructed from a rest parameter is ()-terminated:

  arc> (def ach (x . rest) rest)
  #<procedure: ach>
  arc> (ach x 1 2)
  (1 2)
  arc> (list 1 2)
  (1 2)
  arc> (cddr (ach x 1 2))
  ()
  arc> (cddr (list 1 2))
  nil
I imagine that's why the hash-table doesn't recognize the 'indices rest parameter as the key (1 2 . nil). Oh well, here's a stupid hack that makes 'aref work properly by constructing an Arc nil-terminated list:

  (def aref (x . indices)
    (x (apply list indices)))

-----