Arc Forumnew | comments | leaders | submitlogin
Does Arc have (2-dim) arrays?
1 point by icarus 5387 days ago | 7 comments
I just can't find them in pg's official tutorial? Why?


2 points by fallintothis 5386 days ago | link

Arc doesn't really have arrays, so it doesn't have 2-dimensional arrays. One approach is to use a list of lists.

  arc> (= plane '((a b c) (d e f) (g h i)))
  ((a b c) (d e f) (g h i))
  arc> ((plane 0) 0)
  a
  arc> ((plane 0) 1)
  b
  arc> ((plane 0) 2)
  c
  arc> ((plane 1) 2)
  f
But indexing linked lists is inefficient, so you could similarly nest hash tables.

Granted, neither solution is pretty. I suspect they aren't there because (as with many things) pg hasn't needed them yet himself.

-----

1 point by akkartik 5386 days ago | link

Prettier syntax: arr.i.j

-----

2 points by fallintothis 5386 days ago | link

D'oh. My fingers were in pre-Arc3 mode, where that would've expanded into

  (arr i j)
But yeah, good point, that works now: http://arclanguage.org/item?id=9163. Thanks for spotting it.

-----

1 point by waterhouse 5382 days ago | link

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 5382 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)))

-----

1 point by meric 5384 days ago | link

Currently hash table -> (tab key key2) returns tab.key . It'd be cool if (tab key1 key2) returns ((tab key1) key2)

-----

1 point by rocketnia 5384 days ago | link

Actually, (hash key default) behaves more like (or hash.key default), except that default is evaluated either way (since hash isn't a macro).

-----