So write defun the Arc macro, the symbol seems to be available. Have it accept (= <??>) as the first param and expand into the defset boilerplate. And it is boilerplate, I simplified arccells client code by cutting/pasting the defset I found for car. Don't forget optional and keyword args. :)
The larger point is that it is exceedingly rare to code a (setf ???) form in CL, tho of course when you want it it totally rocks. But in Arc or CL when I need to get the hood up to do some brown belt coding I expect some unusual wiring to appear.
Oh, it is not just CLOS. defstruct also defines setters and many an apparent reader function is also a writer, (so we call them accessors). That means one does not fire up (defun (setf foo)...) unless there is an usual case of abstraction where there is some function on an object (not just reading a slot) and where there is some state change intelligibly viewed as being transitive aka share the name with the reader.
In re writing a defun, I probably just talked you out of it, but here is what I did (warning, old nooby Arc code) for optional and keyword args:
(mac defun (name params . body)
(w/uniq (rtargs)
`(def ,name ,rtargs
(withs ,(with (reqs nil key? nil opt? nil keys nil opts nil without)
(each p params
(if (is p '&o) (do (assert (no opt?) "Duplicate &o:" ',params)
(assert (no key?) "&k cannot precede &o:" ',params)
(= opt? t))
(is p '&k) (do (assert (no key?) "Duplicate &k:" ',params)
(= key? t))
key? (push-end p keys)
opt? (push-end p opts)
(do (assert (~acons p) "Reqd parameters need not be defaulted:" p)
(push-end p reqs))))
(with (n -1 kvs (uniq))
(+ (mappend [list _ `(nth ,(++ n) ,rtargs)] reqs)
(mappend [list (carif _) `(or (nth ,(++ n) ,rtargs)
,(cadrif _))] opts)
(list kvs `(pair (nthcdr ,(++ n) ,rtargs)))
(mappend [list (carif _)
`(or (alref ,kvs ',(carif _))
,(cadrif _))] keys)
)))
,@body))))
also, i find myself not using clos or defstruct all that much in my cl code. i tend to use ordinary data structures like lists and arrays.
my recent example (an excerpt from which i already showed) was a sudoku solver. i wrote one version in CL, then thought i'd do it in arc for fun. in CL, the puzzles were simply arrays (in Arc, they were lists do to the lack of an array type).
However, i didn't want my code to use the array (or list) accessors built into the language to access values in the puzzle, because that is not abstract enough. so i defined a function called pval that takes the puzzle and an x and y, giving the value in that square. that way, my code deals with puzzles, not arrays.
Then I wanted to be able to set the value in a square using the same pval accessor. Trivial in CL, but Arc made it a little difficult. This comes up rather often for me.
That point might not have justified such a long explanation. Whoops.
all i really intend to do is a simple def= macro that will transform (def= pval (val puz x y) (= ((puz y) x) val)) into the previously given defset form. shouldn't be too bad. i have no intentions of mimicing CL's defun. i honestly like arc's def as it is.
It varies. Req3 can be a second, then Req4 another twenty, or Req4 and Req5 can be a second and then a killer.
And now I have a meta-concern: Arc's poster boy is the web thingy and in going on a day yours (thx!) is the only response on it being effectively unusable. Whassup with that? I was looking forward to doing a kickass integration of Cells and Arc's webbery. :(
I gave up (temporarily) on running Arc's web server under Windows, due to various problems (http://arclanguage.org/item?id=1531). My impression is that Windows support is "immature", based on the (system "some Unix command") scattered through the code.
See my point? Even in this incredibly simple iterative task you are forced into a clever trick leveraging how append works and then totally artificially taking each thing you want to collect and wrapping it in a list of one.
Looked at another way, you are not really going out and getting lists of variable length and then appending them, you are just using this trick to avoid collecting nils.
In this case the issue is not efficiency, it is that the loop DSL provides a more natural way for the developer to express themself. Now scale this to a loop that does three things at once, perhaps partitioning a list into several while counting or summing something else and the non-loop version explodes in complexity exponentially while the loop version gracefully grows linearally. (Say that three times fast.)
I got a little carried away with being clever in that version. But look at the canonical Arc version:
(rev:accum collect
(each y whatever
(awhen (pfft y) (collect (yo-mama (cons y it))))))
This version is pretty straightforward in expressing my intent.
As for the scaling issue, I'm still thinking about your other example. I'm not sure it's a good thing that Loop allows more and more to be tacked on. Subroutines in imperative-style languages like C++ have the same agglutinative property, and we're all familiar with the results of that.
Where on earth in your intent was reversal? Either the semantic or the run-time cost (ie, now you have introduced an efficiency issue that was not there with mappend/list.
You cannot win this fight, find a white flag, run it up. Why can you not win? Because loop the DSL was written with the most common iterative design patterns in mind, and hard-coded to make them both more succinct, more efficient, and to play well with other iterative patterns we occasionally want to run merged as one iteration.
This is what DSLs are for! Read On Lisp. We build the language up to our requirements. Loop is about iteration, and Lisp stands for list-processing. 2+2 left as an exercise. :)
2. "Arc lists are terminated with nil, rather than '()." is odd, because nil and '() are the same. Maybe modify the preceding remark to be "Arc uses t and '()/nil for true and false..." and lose this altogether.
But Arc is an exercise in minimalism...hang on. pg is being pounded for Arc being too close to Lisp to be hundred-yeary, maybe we should pad the numbers. :)
"Is the use of this type of pattern language something required to make hygienic macros work or is it just a design choice that the Scheme implementors made?"
Great minds wonder alike. Check out the "What's up with Scheme macros?" thread I kicked off on comp.lang.lisp. I do believe you will like I be sorry you asked. :)
I think somewhere in the dozens of treatises is the response "design choice", but I also think that response was challenged (surprise! surprise!). But I am just a working application programmer and I could not understand very much of what they were saying.
I did get a kick out of one shocked Schemer insisting something was trivial and then posting a twenty-line solution which at one point had a form beginning with four (!) left parens.
Pattern matching is completely orthogonal to hygiene.
You could add in another operator, %, that performs exactly the same as ` but hygienically.
Personally I'd settle for just being able embed procedures in code trees like you can in common lisp. Being able to write.
Hygienic macros do not require pattern-matching, as proven by the example of MIT scheme. Basically, macros in their system take three arguments - an s-expression, the environment the s-expression is being evaluated in, and the environment the macro is written in - and return syntax, which is an s-expression where you've chosen explicitly for each variable what environment it should be evaluated in. (More or less. If you're interested, it's called syntactic closures and you can probably find stuff about it online, or I can just write more here if people want.) I don't remember any way to insert a free identifier, but it might be there.
By the way, arc can already do half of that if you put (procedure? x) into literal.scm. The harder part is making variable references to things that aren't procedures, and I'm not quite sure how you'd do that (except the really annoying way, by wrapping everything in a procedure application).
SRFI-72 is another proof, as someone posted below, and might be better than syntactic closures (I don't know).
That reminds me, I ended up reinventing Cells over the table in Arc because the real deal was so big it would have been a heckuva project, but I started on the actual code and... whoa! I have one chunk I found easiest to express as a very simple state machine using Common Lisp's tagbody/go and I had very little confidence in my conversion to a functional solution.
I chose not to submit anything, because it would just turn into a silly game. If I wanted to make my point, I would simply itemize all the capabilities of loop, but that would be too big a task.
Delete everything but the "Pfft!" and you have my contribution.
New contribution?! That was a joke, a painful transliteration of a couple of pages of graph paper formulas and diagrams working out the parameterized construction of a 3-dimensional button out of insanely small OpenGL atoms, including the torturous calculation of normals to support lighting.
I steered this thread to the Common Lisp Hyperspec entry on loop. By reading that and examining your own use of Arc iterators you can deduce how it can express them all more briefly and with fewer parens. That immediately helps the hacker over one bump... when it is time to iterate I type "(loop " without thinking and just take it from there -- no worrying about whether it is a sequence, list, or hash table, or whether I will need temp variable to be defined in a let/with statement, loop includes a mechanism for that, etc etc etc...
I think the suggestion was just phrased a little awkwardly.
Lisp is so easy to program that it is commonplace to reinvent builtins -- they are as easy to write as they are to find (especially in an, er, mildly documented language).
I went proactive on reinvention thang and invited people to let me know of things I had reinvented. Somewhat tangentially, I also make an effort to use things like [... _ ...] and func.arg to give pg's ideas a fair test and so my Arc code can help other noobs get up to speed on the language. If I stay as close as I can to my preferred Common Lisp, like someone writing C in Common Lisp neither I nor anyone else gets a feel for Arc. But I digress.
I do not see any problem with sharing word of another Lisp option in this space as long as it does not turn into a drumbeat. But what do you mean by "goodbye Arc"? It does not sound like you tried it. As for newLISP:
newLISP does not support sharing of subobjects among objects, cyclic structures, nor multiple variables pointing to the same object. Objects are (physically) copied when stored in data structures or passed to functions
The only times I've seen folks here talk bad (or really even talk at all) about NewLISP is when someone specifically asks about it. I don't think anyone here is out to destroy NewLISP, or to stop people from using it. If it works for you, then go for it!