Arc Forumnew | comments | leaders | submitlogin
Help: filltbl
2 points by adm 5406 days ago | 8 comments
I need a routine which will create or update hastable using two lists for key & vals. e.g. if 'keys is the list containing keys like (k1, k2, k3) and 'vals is list containg vals: (v1, v2, v3). I want to build a hashtbl out of these two lists having: ((k1 v1) (k2 v3) (k3 v3)).

I was thinking of doing it by traversing the 'keys list by index and then fetching elements from both list using this index and then put this key/val into table.

thanks.



3 points by rntz 5406 days ago | link

Given a list 'keys of keys and 'vals of vals, this will produce a table of them:

    (listtab (map list keys vals))
If you need to update an existing table (which we'll call 'tbl) just use 'each:

    (each (k v) (map list keys vals)
      (= tbl.k v))
Alternatively:

    (map (fn (k v) (= tbl.k v)) keys vals)
All of these solutions rely on the fact that 'map is variadic. It takes any number of lists to map over, and the function is expected to take that number of arguments. For example:

    arc> (map + '(1 2 3) '(40 50 60))
    (41 52 63)

-----

1 point by adm 5406 days ago | link

I wanted something like perl hash slices to build the hashtable from lists.

  (def filltbl (tbl keys vals)
    (do
        (if (no tbl) (= tbl (table)))
        (map (fn (k v) (= tbl.k v)) keys vals)
        ))
this is what I will using. Thanks again.

-----

1 point by rntz 5406 days ago | link

That'll work fine, although the 'do in your function is unnecessary. Also, there is a macro 'or= that does precisely what your first line does (assigns a value to a place if it is nil):

    (def filltbl (tbl keys vals)
      (or= tbl (table))
      (map (fn (k v) (= tbl.k v)) keys vals))

-----

1 point by thaddeus 5406 days ago | link

I'm not sure how any of these can work for intializing a table that's not aleady a table...

  (= k* '("1" "2" "3"))
  (= v* '("One" "Two" "Three"))

  assuming t* has not been set - this is what I get: 

  arc> (filltbl t* k* v*)
  Error: "reference to undefined identifier: _t*"
  
  or even:

  arc> (filltbl 't* k* v*)
  Error: "Can't set reference  t* \"1\" \"One\""

  so what am I missing ?

-----

2 points by rntz 5405 days ago | link

filltbl isn't a macro, nor does it affect the global namespace. As written, it just creates a table if its first arg is nil. Of course, this is useless unless it returns that table... oops.

    (def filltbl (tbl keys vals)
      (or= tbl (table))
      (map (fn (k v) (= tbl.k v)) keys vals)
      tbl)
IMO, a more idiomatic way to represent this would be to use optional arguments, although that requires altering the argument order:

    (def filltbl (keys vals (o tbl (table)))
      (map (fn (k v) (= tbl.k v)) keys vals))
      tbl)

-----

1 point by thaddeus 5405 days ago | link

yeah I tried passing nil in, and got nothing back, so I figured it was supposed to create the table - I should have seen that too.

-----

1 point by adm 5405 days ago | link

Can this be part of arc.arc?

-----

1 point by shader 5405 days ago | link

You could push it onto Anarki. Other than that, there isn't much you can do to get it into a public arc.arc. It seems that if a function isn't used in the forum code, pg doesn't include it in the official release.

-----