Arc Forumnew | comments | leaders | submitlogin
Multiple-variable [] literal implementation
3 points by absz 6169 days ago | 15 comments
After reading the various discussions here (http://arclanguage.org/item?id=1227 and http://arclanguage.org/item?id=1329 come to mind), I wrote some code which alters the evaluation of brackets so that the following becomes legal:

  (maptable [prn _1 #\tab _2] (obj x 1 y 2 z 3))
    ; ==>
    ;     x	1
    ;     z	3
    ;     y	2
_# parameters are 1-based, and you can also use __ for the "rest" arguments (so that the function becomes variadic). As I'm working on the already-patched version of Arc for mzscheme 370+, I have a patchfile for that version as well as instructions for the original version. (The patchfile should be largely the same for the un-pre-patched version, but I can't guarantee it.) To apply the patch, run `patch -d . < bracket.patch` in the arc0 directory. You can find the instructions at http://asz.arc.googlepages.com/add-n-ary-brackets.txt and the patch at http://asz.arc.googlepages.com/bracket.patch .

The code works by macro-expanding the given expression and then finding which variables are used unbound. It then takes only the arguments of the form _# (as well as _, which is the same as _1, and __), finds the highest numbered, and constructs the argument list. Thus [... __ ...] expands to (fn __ (... __ ...)); [... _ ...] expands to (fn (_1) (let _ _1 (... _ ...))); [... _3 ... _5 ...] expands to (fn (_1 _2 _3 _4 _5) (let _ _1 (... _3 ... _5 ...))); [...] expands to (fn (_) (...)), and [... _ ... __ ...] expands to (fn (_1 . __) (let _ _1 (... _ ... __ ...))). I wouldn't be surprised if there's a much better way to write the code to make this happen, but it does seem to work.

I hope people find this useful.



3 points by okplus 6161 days ago | link

What if _ was a list in the event that the function was passed more than one argument? With the . syntax, you could use _.1, _.2 for an arbitrary number of arguments, and wouldn't have to introduce __ to access the list of arguments.

-----

1 point by absz 6161 days ago | link

Hmmm, I like that. The only problem is that then you can't just say _ to access the first argument, and one-argument functions are the most common case. So you'd either need a new name for _ or a different name for the list, it seems to me, and those break symmetry.

-----

1 point by okplus 6160 days ago | link

Easy, when one argument is passed, assign _ to the first argument of the arg list. It wouldn't change anything about current [] expressions.

-----

2 points by almkglor 6169 days ago | link

Looks interesting. I would take the liberty of adding it directly to the Arc wiki git at: http://git.nex-3.com/arc-wiki.git , unless you want to do that yourself^^.

-----

1 point by absz 6169 days ago | link

Ah, I'd forgotten about that. I'll add it once I build git.

EDIT: Pushed. (It was easier, actually: there was already a total-macro-expander.)

-----

1 point by almkglor 6169 days ago | link

I've noticed you've added a 'filter function which duplicates the functionality of 'keep, except that 'filter does not (testify ...) the predicate function. It doesn't seem to be used by make-br-fn, so I'm wondering if you would like it retained.

-----

1 point by absz 6169 days ago | link

Oops. If that's not used by make-br-fn, then it's probably from an earlier draft. Off with its head!

-----

1 point by almkglor 6169 days ago | link

I've been looking at it, and it looks like it's added quite a few functions to the global namespace. Either we need to implement namespaces (or modules) quite well, or we need to make local functions easier to create.

-----

1 point by absz 6169 days ago | link

Hmm, that's a good point. I think that andmap and ormap are generically useful; the rest should probably be hiding. I could wrap all of make-br-fns in (with (free? (rfn free? ...))), etc., but then it would have to recreate the procedures each time... prefixing the procedures with * mbf- might be one way to deal with it, so they don't overload a common name. I don't know what the best option is (until we actually have modules, in which case it's clear)--thoughts?

-----

2 points by almkglor 6169 days ago | link

Well, the lisplike we use in the office doesn't have modules either, so our convention (actually just my, since no one else takes that language seriously) is to put a prefix name like yours.

Btw there might be a bug in 'arglist-vars - it uses (is arglist 'cons), maybe you meant (isa ...) ?

-----

1 point by kennytilton 6169 days ago | link

I use CL with its pretty nice package mechanism and I still prefix all my names with a mnemonic abbreviation of the package name. FWIW.

-----

2 points by almkglor 6169 days ago | link

LOL. In my off-time in the office I'm building a package system for that lisplike, basing off a macro that must enclose all forms that need to use packages; basically what it does is add the package name to the symbols that have been imported from the package.

-----

1 point by almkglor 6169 days ago | link

Also, for 'arglist-frees - from what I can hack, it tries to extract used variables in argument lists for optional arguments. So for example, your intent is that: (arglist-frees '(x (o y (some-var)))) => (some-var)

However, to extract the subexpression, you use car:cdar. I don't understand why.

-----

1 point by absz 6169 days ago | link

You are correct on both counts: that's two bugs. car:cdar should be cddr. I'm adding the * mbf- prefix, and I'll repush then.

-----

1 point by almkglor 6169 days ago | link

Will be waiting, since I intend to do the docstrings for them; unless you wish to do the docstrings yourself ^^

-----