Hmm. Maybe post the original source of the post? I mean the input string to markdown ^^. Kinda hard to parse through markdown without seeing the data it's supposed to be working on.
However, I'm not 100% sure why you're using global variables in inst-entity1 in the first place - is there some special reason?
3. docstrings would be nice ^^.
4. The actual code seems to use addtemscaff (not addscaff) and rname (not ename). Or am I looking at the wrong code?
Edit:
5. You seem to be storing the code added by addtemscaff as lists of expressions. Why not store them in a function? That way we can capture variables into an environment instead of forcing the user to always use globals.
6. The (each v tablist.scaffold ...) could probably be transformed to (ontable k v scaffold ...)
> 1. scaffold.arc / inst-entity1 uses global variables. Is this deliberate? Why?
The arc eval doesn't seem to support local environments or passing of environments, so this is the only way to pass in anaphoric variables I could find on my first pass. This function could probably be rewritten without eval and with proper scoped anaphoric variables, but given what is happening in the code this requires serious macro-fu. I do sort of know what I'm doing here- The evals and global vars don't make me feel good either... I will clean this up eventually, but won't complain if someone else figures out how to do it first :)
> 2. Personally I would recommend using the following interface to inst-entity1:
> 5. You seem to be storing the code added by addtemscaff as lists of expressions. Why not store them in a function? That way we can capture variables into an environment instead of forcing the user to always use globals.
I am planning on adding a command for debugging scaffolds, where the instances of the scaffold are instantiated and pretty-printed to make writing scaffolds less uber-meta. Having functions would prevent this- But you are right that using functions might be the Right Thing. I'll give it some thought.
> 6. The (each v tablist.scaffold ...) could probably be transformed to (ontable k v scaffold ...)
Yes I think you're right. This is definetely "release early, release often" type code, so there's lots of room for improvement.
> a command for debugging scaffolds, where the instances of the scaffold are instantiated and pretty-printed ... Having functions would prevent this
Looks like we should really be solving the correct problem: make function code pretty-printable ^^. Yes, I think I'll solve this using attachments again... ^^ Go attachments! http://arclanguage.com/item?id=3698
Edit: Which reminds me, I haven't actully grokked this scaffolding thing at all yet. I'll be home in maybe 3-4 hours, hopefully I can get the weekend for this, unless I do something stupid, like track down where the girl I'm trying to see is hiding ^^.
arc> (help prall)
(from "arc.arc")
[fn] (prall elts (o init ) (o sep , ))
Prints several arguments with an initial header and separated by a
given separator.
Above function also exists in Arc2.
Instead of (point return ...(return ...)) try using (catch ...(throw ...)).
Final nitpick: I think it's rtm, not rm, although, well, I dunno. ^^
(mac point (name . body)
" Creates a form which may be exited by calling `name' from within `body'. "
(w/uniq g
`(ccc (fn (,g)
(let ,name [,g _]
,@body)))))
breakable: works on any expression, not just loops and other control structures. Basically, if you need something to suddenly return a value without continuing, just add breakable: to the point you want to do so and use (break ...) to break out.
Maybe should have called it 'brittle or 'fire-extinguisher ^^
I wonder how ccc in Arc/Scheme compares to return in Ruby with respect to efficiency. Hopefully ccc is very lightweight. It really does make me question why return wasn't defined to be part of the language.
Basically the most important realization is that the return address on the stack may be modeled as the address for a different procedure, which by a staggering coincidence just so happens to point to the code after the function call. So basically a return is itself equivalent to a function call.
ccc is one of the strangest things in Scheme (and Arc now). Hard to get everything behind it, but it can be used to implement return statements, try-catch à la C++/Java, coroutines à la Lua, generators à la Python and of course continuation-based web apps à la Arc...
A very strange beast, and as far as I know the thing Scheme has that CL hasn't (and cannot trivially implement).
Actually, the form of closure used by Arc is highly similar to a continuation passing style, so although it doesn't use 'ccc, it does use continuations.
cl-cont is a library that implements closures and runs on many CL implementations. So it's not a matter of CL can't do it, CL just has to use a library to do it.
I think there are conceptual problems mixing unwind-protect-like constructs and call/cc.
The cl-cont lib appears to only support a subset of CL (in particular unwind-protect is not supported).
So cl-cont doesn't demonstrate that CL can support it, only that a restricted subset of CL can.
I don't know if it is possible to sensibly accommodate unwind-protect and call/cc in the same language, it seems smarter people than I have avoided doing so.
Scheme's dynamic-wind serves the same purpose as unwind-protect (except with entry conditions as well, since a continuation could suddenly return into your protected code), and plays nicely with continuations. I'm not sure about the details, though.
Thanks for that, pretty interesting. I guess that makes writing entry and exit conditions a little more interesting, since they could end up being invoked multiple times.
i am learning how to write scheme compilers now it it looks like you just jump around your CCC's like GOTO labels - very fascinating and lower over head then functions calls (if you compile to machine level)
Thanks. And from your comment ( http://arclanguage.com/item?id=4432 ) on the 8 Queens thread, the Ruby snippet in the OP above could be implemented as:
That said catch-throw is in ArcN, although they do have different intended usages. breakable: is supposed to be used as a modifier for existing control structures, while (catch ...) is supposed to be a control structure in its own right.
Supposedly you can use the "git rebase -i origin/master" command as described in the CONVENTIONS file. It doesn't seem to work on me, however; I get the message "Usage: /usr/bin/git-rebase [-v] [--onto <newbase>] <upstream> [<branch>]"; looking at my online documentation does not reveal a -i option. ^^
You probably need a newer git. People recommend using git HEAD and I haven't had problems with it so far.
cd ~/src
git clone git://git.kernel.org/pub/scm/git/git.git
cd git
make prefix=$HOME/apps all doc info
make prefix=$HOME/apps install install-doc install-info
It might have been easier to just do something like this for default values of optional arguments:
(dsb (&o (p 100)) foo
(body))
=>
; put default values here
(with (p 100
,tree foo)
; do the checking here
(if ,tree
(= p (car tree)))
(body))
Edit: Personally I'd do a recursive expansion of the optional/keyword part, successively deciding at each sublist whether it should go to an optional or a keyword argument, or if the sublist is empty, to stop parsing. This would probably reduce significantly the overhead of nth, which I think needs to measure the length of the argument list each time. Will think of an alternative method of expressing dsb in a recursive manner which would hopefully just significantly increase the apparent complexity of the generated code while gaining a minor boost in efficiency.
"Personally I'd do a recursive expansion of the optional/keyword part"
I'll be honest, I am just a simple application programmer, I was stunned for example by the expansion of withs.
And I am just a muddy Common Lisper, I am not smart like the Lisp-1 guys, I do not know how to express the number 3 as a half-dozen nested lambda forms. So...
...that's a long way of saying I think you are right, there is almost definitely a nicer lambda-based solution out there. I would say I would love to see it except I doubt I would understand, I have been to Lisp-1 talks and never understood a word, I've stopped going.
But I would enjoy seeing a recursive solution, your approach sounds promising and even easy to read, more than I can say for mine.
Turns out that 'withs is recursive enough for this ^^.
(mac dsb (params data . body)
(let (reqs keys opts) (dsb-params-parse params)
(w/uniq (tree kvs)
(withs (optfn
(afn (l)
`()))
; turn reqs into the argument list, adding
; the ,tree as a rest argument
(if (no reqs)
(= reqs tree)
((afn (l)
(aif (cdr l)
(self it)
(= (cdr l) tree)))
reqs))
`(withs (,reqs ,data
,@(mappend [list (carif _)
`(do1 (if ,tree
(car ,tree)
,(cadrif _))
(= ,tree (cdr ,tree)))]
opts)
,kvs (pair ,tree)
,@(mappend [list (carif _)
; don't use aif - dsb might be
; used itself in an aif context
(w/uniq it
`(let ,it (assoc ',(carif _) ,kvs)
(if ,it
(cadr ,it)
,(cadrif _))))]
keys))
,@body)))))
Yep, I concede. The recursive solution won't easily handle the cases in http://arclanguage.org/item?id=4423 . So this is really the best way to do it ^^.
Ha, ha, yeah right, I don't even use any lisplike programming languages in an application I've ever passed to a client (using a lisplike to generate an application in a non-lisplike is another statement).
...that's a long way of saying no, I'm not even a simple application programmer, I bet you've built more Lisp code that actually reached application level.
Anyway I'll be doing my hacking now, will come back in a few dozen minutes.
It's problematic for a recursive solution. ^^ So is the second. ^^ In the end I decided that the sketch up of your solution is better, since 'withs is, after all, recursive ^^