Arc Forumnew | comments | leaders | submit | rntz's commentslogin
2 points by rntz 5979 days ago | link | parent | on: Ask Arc: inst or filltbl?

Actually, there is already a function 'fill-table - I don't know how I missed it - that does most of what's wanted.

    (def filltbl (tbl keys vals)
      (fill-table (or tbl (table)) (mappend list keys vals))))
However, I honestly don't think this is a useful or general enough function to go in arc.arc, especially as we already have 'fill-table, 'listtab, etc.

As for "creating a named table", er:

    (= foo (table)) ; I'm unclear on what's difficult about creating a table.

-----

1 point by thaddeus 5979 days ago | link

I think the difficult part is passing in an arbitrary name to a function, for which the tables 'name' becomes set to, but I am just guessing that's what he wants...

and I agree I don't see a whole lot of need for the function to be part of the arc release..., since there are probably better ways to accomplish the same end result.... a good example of which is news.arc's storage of story records.

-----

1 point by fallintothis 5979 days ago | link

I think the difficult part is passing in an arbitrary name to a function, for which the tables 'name' becomes set to, but I am just guessing that's what he wants...

I rather doubt that's the issue, as it's easy to do with a macro.

  arc> (mac filltbl (tbl keys vals)
         `(= ,tbl (fill-table (table) (mappend list ,keys ,vals))))
  #3(tagged mac #<procedure: filltbl>)
  arc> (filltbl blah '(a b c) '(1 2 3))
  #hash((c . 3) (a . 1) (b . 2))
  arc> blah
  #hash((c . 3) (a . 1) (b . 2))

I think it's just a request for a convenience function to zip together a list of keys with a list of values into a table, since the existing methods for creating tables center around having alternating key/value pairs.

-----

1 point by thaddeus 5979 days ago | link

Agreed, it was only a wild guess given he was already given a good solution, yet...

   "Am I missing anything here?"
So I don't know what the deal is, but I don't plan to spend any time thinking about it :)

-----

1 point by adm 5968 days ago | link

only difficulty was creating a list of pairs which can be used an an arg for fill-table or listtab.

  (mappend list keys vals)
is precisely what I wanted. Sorry for the caused confusion.

-----

3 points by rntz 5980 days ago | link | parent | on: Help: filltbl

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 5980 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 5980 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 5980 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 5980 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 5980 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 5980 days ago | link

Can this be part of arc.arc?

-----

1 point by shader 5979 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.

-----


If you use the latest arc3.tar (unfortunately I haven't gotten around to merging these changes into the arc3.master branch on anarki), 'string will concatenate lists of strings (or indeed anything coercable to string) into one string, with no spaces, recursively:

    arc> (string '("foo" bar (2 3) "baz")
    "foobar23baz"
Also, 'rem is capable of removing characters from strings.

    arc> (rem #\  "foo bar")
    "foobar"

-----

1 point by rntz 5986 days ago | link | parent | on: Why is 'copylist necessary?

Ah, I just realized why.

    arc> (def terminator (l) (if acons.l (terminator cdr.l) l))
    #<procedure: terminator>
    arc> (terminator (list 1 2 3 4 5 6))
    nil
    arc> (terminator (mylist 1 2 3 4 5 6))
    ()

-----

1 point by CatDancer 5986 days ago | link

Ah yes, that's a simpler way to get an observable difference ^_^

-----

1 point by conanite 5986 days ago | link

What's the difference between nil and () ?

They both appear to have the same behaviour for car and cdr (return nil), and for scar and scdr (not allowed), and on top of that

  arc> (is () nil)
  t
Couldn't we drop one of these?

-----

1 point by CatDancer 5986 days ago | link

What's the difference between nil and ()

Arc lists are terminated by 'nil, Scheme lists by '(). Because Scheme lists sometimes appear in Arc, the Arc runtime (such as 'is) treats '() like 'nil.

Couldn't we drop one of these?

http://hacks.catdancer.ws/nil-impl-by-null.html ^_^

-----

1 point by conanite 5985 days ago | link

sounds like an onion to me :)

-----


The only thing that bothers me about this is the same thing that bothers me about 'o for optional arguments: that it messes with destructuring.

    arc> (let (o x) '(1 2) x)
    2     ;expected result
    (1 2) ;actual result
The reason for this is that `(let ,var ,exp ,@body) translates into `((fn (,var) ,@body) ,exp)), and so if var is a list beginning with 'o, it gets interpreted as an optional argument. Likewise:

    arc> (let (c d e) '(1 2 3) e)
    3 ; current result
    Error: "reference to undefined identifier: _e" ; result with argument conversion

-----

2 points by CatDancer 5986 days ago | link

I agree, I'd like to have some syntax for hacking function arguments that doesn't interfere with destructuring.

-----

2 points by rntz 5986 days ago | link

There are at least two options here which don't interfere with existing syntax; I'll demonstrate using optional arguments rather than argument conversion for simplicity:

    (def foo (x y ('o z)) ...)
This doesn't interfere because binding 'quote is more or less illegitimate in arc. (The reason for this lies in the underlying scheme - if 'quote is lexically bound as an identifier, it doesn't function as a special form.)

    (def foo (x y (:o z)) ...)
This doesn't interfere because binding to ':o in arc is more-or-less useless, because ssyntax expands away ':o to 'o. The same is true of '+o.

-----

2 points by shader 5985 days ago | link

I personally like the :o, maybe just because it reminds me of CL. Anyway, it shouldn't be too hard to add a special case for ': in ssyntax if it is the first character.

After all, wouldn't that be an error anyway? Therefore redefining it would not interfere with normal usage of ':. In fact, it makes sense to have different versions for each ssyntax if it is at the beginning, end or middle.

-----

1 point by rntz 5988 days ago | link | parent | on: New ppr function

It also doesn't handle long '[]s correctly.

    arc> (ppr '[+ 2 _ a very long bracket fn causes extra parens])
    [(+ 2 _ a very long bracket fn causes extra parens)]t
Your ppr has a rather significant number of bugs it seems.

-----

1 point by shader 5987 days ago | link

well, it is a complicated function. At the very least, it is better than the old version.

That bug must have creeped in because it calls ppr again on the body if it needs to wrap. I'm not 100% sure how to fix it though. Maybe print the first and then map ppr over the rest?

The question is, how to get br-fns to properly indent their bodies. Maybe ppr needs an option to avoid printing the parens.

-----

1 point by shader 5982 days ago | link

I've fixed the bug, and it has been pushed to github but not to arc master. I'm going to try and port it to arc3 first.

-----

1 point by rntz 5988 days ago | link | parent | on: New ppr function

It doesn't handle large arguments to macros correctly.

    arc> (ppr '(let ex (afn (args)
                         (if (no (cdr args)) (car args)
                             `(if (is ,var ,(car args)) ,(cadr args) 
                                  ,(self (cddr args)))))))
    (let ex (afn (args) (if (no (cdr args)) (car args) `(if (is ,var ,(car args)) ,(cadr args) ,(self (cddr args))))))t
This example is lifted from the source of 'caselet.

-----

2 points by rntz 5988 days ago | link | parent | on: Update: clearer +, inverse trig functions

There's a bug in your updated '+. It uses scheme's 'list? to check whether a given argument is a list to be converted - but 'list? only returns #t on proper lists (those that end with ()), and arc lists end with 'nil. So, for example:

    arc> (+ "" '(foo))
    Error: "Can't coerce to string (foo . nil)"
A simple solution is to change the use of list? to pair?, since 'nil and '() are both handled earlier in the cond expression.

Also, having a 'coerce-string function for coercing arguments to '+ to strings and not using it in 'coerce seems odd - if (+ "" x) and (coerce x 'string) behave differently, that's just unintuitive complexity, and if they behave the same, then some common code should be factored out.

-----

1 point by pg 5987 days ago | link

Thanks, both fixed in the latest arc3.tar.

-----

1 point by rntz 5989 days ago | link | parent | on: Update: clearer +, inverse trig functions

"Soon I'll start to put the latest version at arc4.tar"

Wait, does this mean you're planning on releasing arc4.tar soon? Or just that, if you at some point have more changes to make, you'll release them as arc4.tar?

-----

1 point by pg 5989 days ago | link

The latter.

-----

3 points by tc-rucho 5988 days ago | link

Hg/Git FTW ;)

-----


It encapsulates the notion of only evaluating a given set of expressions once. It's used for writing macros. An example is probably best:

    arc> (with (x '(x-expr) y '(y-expr)) (once-only (x y) `(+ ,x ,y ,y)))
    (with (g1838 (x-expr) g1839 (y-expr)) (+ g1838 g1839 g1839))
This is the equivalent of the handwritten:

    arc> (with (x '(x-expr) y '(y-expr))
           (w/uniq (gx gy) 
             `(with (,gx ,x ,gy ,y) (+ ,gx ,gy ,gy))))
    (with (g1840 (x-expr) g1841 (y-expr)) (+ g1840 g1841 g1841))

-----

More