That looks pretty good. The implementation seems relatively straightforward and short, and the value is pretty high. I recommend however that you look at SXML for the syntax, as opposed to reinventing the wheel. http://en.wikipedia.org/wiki/SXML
For the (html (html issue, I would consider instead making a more general 'sxml macro, and then several helper macros such as 'html which automatically generate boilerplate doctypes, etc.
Also, why are some of your expressions wrapped in an extra layer of parens? i.e. ((script src "arc.js")). Is this so that you can differentiate the body vs attributes? If it is, I would recommend sxml syntax for attributes instead.
> Also, why are some of your expressions wrapped in an extra layer of parens? i.e. ((script src "arc.js")). Is this so that you can differentiate the body vs attributes?
Yes, exactly. I can see now that they're using the @ symbol to differentiate attribute lists, but it's interesting to note that they actually end up using more parens. Unless I've misunderstood, where my program would have
In light of this, could you elaborate on your recommendation to adopt SXML's syntax? Do you find it somehow superior or does it have more to do with adopting a standard?
> For the (html (html issue, I would consider instead making a more general 'sxml macro, and then several helper macros such as 'html which automatically generate boilerplate doctypes, etc.
Sounds like a wise path of generalization to carry out over the long run.
You're right, I hadn't noticed how many parens SXML actually uses. I guess I just preferred more of a tree style "tag owns attributes" than the idea of applying a tag to its body.
I originally like the idea of the standard, but SXML probably supports far more than we need for now. How about a compromise?
This uses arc's style of "leave out parens for grouping pairs" like you were doing, but also doesn't require the attribute parens if you don't have attributes. This seems to make the tag style more homogeneous.
The body can be distinguished from the attribute-value pairs thanks to either the fact that it doesn't begin with a symbol or the fact that there's nothing to pair it with.
It does save a single pair of parentheses every once in a while, but it takes half a page of comments to explain comprehensively. :-p Then again, it's meant for Arc macros in general, so some of the idiosyncracies might disappear if it's modified for a specific purpose like this one.
Do y'all like the x:a?
I thought the "x:a" was just an abbreviation for things like "w/html:a", "html:a", "tohtml:a", and "sml:a", substituting whatever you decided the macro name would be. What alternative are you thinking about?
> I thought the "x:a" was just an abbreviation for things like "w/html:a", "html:a", "tohtml:a", and "sml:a", substituting whatever you decided the macro name would be.
The "x:a" originally came from the example at http://en.wikipedia.org/wiki/SXML#Example, where I think it had another meaning - maybe something to do with XHTML... anyway, it's probably not important. You clarified that I wasn't missing something in the conversation (unless we both are ;).
> This uses arc's style of "leave out parens for grouping pairs" like you were doing, but also doesn't require the attribute parens if you don't have attributes.
I like that compromise and will definitely consider it. To be sure though, my current implementation doesn't require the attribute parens for nil attributes either:
On these cases, my html.arc and the compromise converge. It's for the non-nil attributes case that they differ, and I think it comes down which you dislike less: the tag name in the caar position or the @ symbols.
Yes, but your current method seems to lack consistency (at least to me).
In some cases, (script fn "somefn();") means script with attributes, in others it means that it has a body. The difference is where the (script ...) is located; at the car of a list or not. Personally, I like the consistency provided by "anything that's not an @ list is body" which means that you don't have to pay as much attention to the number and layering of parens.
Yeah, I frequently see people hacking together their own namespace systems, and either trying to go for the most complete and cumbersome system possible (handling dependencies, versions, etc.) or something that isn't general enough to be used more than once.
Maybe we should try and design a set of very basic namespace handling tools, and then allow users to extend off of them. Basic as in "See namespace. See namespace hold names. See namespace export names for use" If we make them simple enough, and generic enough, it should be possible to add whatever other features are necessary later.
Right now the only hard part about implementing namespaces seems to me to be support for macros. Anyone have any ideas on how to allow macro indirection via namespaces without having first class macros? Or maybe just a good way to handle first class macros themselves?
Anyone have any ideas on how to allow macro indirection via namespaces without having first class macros?
Lathe's approach (where namespaces are friendly-name-to-unfriendly-global-name tables encapsulated by macros):
arc> (use-rels-as ut (+ lathe-dir* "utils.arc"))
#(tagged mac #<procedure: nspace-indirect>)
arc> (macex1 '(ut (xloop a list.7 b 0 a.b)))
(gs2012-xloop a list.7 b 0 a.b)
arc> (macex '(ut (xloop a list.7 b 0 a.b)))
((rfn next (a b) a.b) list.7 0)
arc> (ut:xloop a list.7 b 0 a.b)
7
Maybe we should try and design a set of very basic namespace handling tools, and then allow users to extend off of them.
Funny, that's part of what I had in mind as I made Lathe's module system. :-p Is there some aspect of Lathe's namespace handling that's inconsistent with what you have in mind? The point of the Lathe module system is mainly to keep the rest of the Lathe utilities safe from name conflicts, so I'll gladly swap it out if we can come up with a better approach.
I wish we weren't so dependent on Scheme's reader, so that ssyntaxes could be "first class".
I.e., what if instead of being forced to use foo!bar, you could use foo.'bar .
Right now, you can't do that, because scheme's reader turns it into two expressions "foo." and 'bar, before it even gets sent to the ssyntax parser. If we had our own reader, we could use syntax in more situations, like foo."bar", foo.(bar), etc.
I wonder if aw's parser combinator library would be good for that, or do we need to write something specifically for this?
That's precisely the purpose of my Scheme/Arc parser (scheme-parser0.arc at http://awwx.ws/hundred-year-parser) -- use that as a starting point, and implement whatever parser you want. It doesn't handle incremental parsing yet though, so it isn't a drop in replacement for "read" now.
Yes, arc is still under development. PG doesn't really tell us that much about what he's working on, but periodically a new version will be posted on the website.
There's also the community version hosted on github, Anarki, which is under fairly constant development, and adds a few nice features over vanilla arc. However, PG is designing his language to only include what he actually uses, so most of the changes are unlikely to be copied over to the official version.
As for specification, since the source code is extremely short (only 2500 lines) and most of that is basic library function definitions of 5 lines or less, PG claims that the source code is the spec. There are some community created documentation sources, but the source code is pretty clear.
But if you made the changes as you suggested to ssyntax, then it would be easy enough to define a (w/o-ssynatax body) macro to temporarily disable ssyntax for a particular call.
Well, since it's a scheme library function I should think that you'd be accessing it with '$ or 'mz, both of which (if I remember correctly) send all of the symbols in their arglist directly to scheme without any arc transformations first.
So ($.exn:srclocs args) should work, or maybe just
(($ exn:srclocs) args) presuming of course that you've loaded the requisite lib files.
There are a lot of reasons that we use arc over CL or Scheme.
Brevity is a major one; a lot of arc code is shorter or cleaner than equivalent scheme or CL code. Fewer parenthesis, more logical names, a few bits of syntactic sugar that go a long way, etc. Just compare the code in ac.scm to arc.arc, and decide which you would rather write, or read. (not quite fair, since ac.scm is mostly compiler stuff, and arc.arc is just the basic library of functions, but there is still a noticeable difference in readability and brevity)
I also like arc because it's really easy to change to be the way I want it. Since the whole language definition is less than 2500 lines long, half of that in arc code, and very few functions more than 10 lines long, it's easy to figure out how it works, and easy to change.
Libraries aren't really a strong point of arc, but using Anarki (the community version on github) it's pretty easy to just use PLT's libraries, which are quite extensive. Speed is the only other real "con" to using arc, and I haven't really found it to be much of an issue.
As for tutorials, PG wrote an arc tutorial that is on the main arclanguage.com page. Other than that I don't know of much that has been written specifically about arc. arcfn.com has a lot of nice tips and a decent documentation section, though there isn't a link to that on his front page.
Other than that, SICP and On Lisp will go a long way towards understanding arc. If you have any questions about the differences between arc and CL or scheme, or just questions in general, feel free to ask.
Most of us here are somewhat disappointed by the current lack of activity on the arc forum, and would gladly welcome and answer whatever questions you may have ;)
I am having a TON of Fun! I am using anarki now and going thru the tutorials and docs available. Got it running on my server, I hope to have something interesting running soon!
Yeah, I normally check comments first and then new, since comments change the most, and new second most. This forum doesn't have enough traffic right now to need to sort by popularity.
It's funny, I never would've used the comments page on HN, but its utility is clear here. Traffic is a significant variable in usability on these sites, even though they're clones of one another.
So, does anyone know what happened to the hack of macexing (or something like that) the car of a list before evaluating it? Unless it's obviously a macro of course.
Or any other ideas on how to add first class macros to arc?
That didn't seem to be about first-class macros, except for a very narrow special case (granted, it's about modules, which you seem most interested in). If you think about it, macro-expanding the car of a list won't really first-class anything -- you'd still need to do
because macro-expanding the car above doesn't get rid of the macro literals push and pull, which will cause an error on application. vincenz tried to make ac recognize macro literals, but it still amounted to evaling (at least of macros), which he didn't get working. http://arclanguage.org/item?id=804
The most obvious way to handle this is to straight-out interpret. As the most obvious way, I'd guess that's why first-class macros have the reputation of being difficult to compile, since there will be some cases that need run-time expansion.
Yes, that was the discussion I was talking about, and I suppose you're correct; it wouldn't really help in most cases.
"As I said, to the best of my knowledge it's still an unsolved problem."
Then let's see if we can't solve it ;)
Personally, I think that the advantages in terseness of being able to use first class macros would probably outweigh the slight decrease in performance for edge cases.
Couldn't you use the current system, but if the car is a list, eval it, since you don't know what it is yet? That would only add a performance penalty for complex cars.
Maybe the complex car structures could start with a symbol that signifies that it returns a macro, and otherwise it isn't evaled and the performance penalty isn't incurred.
I.e. add a special form that transforms a function call into a macro call, such as (callmac fn). Then functions and macros could be the same, but you just call them differently. ssyntax could then be used to make it look nicer.
When read in, it should produce an identical closure. The problem is knowing under what variables the function is closed in the first place.
It would be nice if there was more information about objects and source code in arc. I.e. the source codes of functions, the current namespace, the variables captured in a closure, the stack trace, etc.