o is a keyword. No different from assign or tagged or if. Your suggestion is to match a 'keyphrase': (tagged optional _) or even having to detect then evaluate things like (annotate 'optional 'a) at compile-time. Maybe even read time. Does that ever happen right now?
I'm having trouble articulating myself, but it definitely seems like another whacky rocketnia idea :)
"o is a keyword. No different from assign or tagged or if."
You might already know this (search for "AST" at http://arclanguage.org/item?id=13079), but I'm irked by special forms like 'assign or 'if too. I like reducing the places where some message almost always has one meaning, unless it's some particular message which has a completely different meaning. I'm just fine when language designers make knowing sacrifices, but whenever possible, I want to be able to say "the eagle has left the nest" to talk about actual eagles--or at least to be sure I won't ever want to talk about actual eagles.
I think 'o is a place where neither sacrifice is necessary (neither giving up (o b c) destructuring nor giving up 'o as a variable name).
As for 'tagged, that's a symbol you can't observe from Arc unless you drop to Racket, whereas macros see the symbol 'o all the time.
---
"Your suggestion is to match a 'keyphrase': (tagged optional _) or even having to detect then evaluate things like (annotate 'optional 'a) at compile-time. Maybe even read time. Does that ever happen right now?"
Eh? O_o You're all over the map in misinterpreting me (which isn't something I blame you for).
Some parts of what you're talking about "happen right now" in PyArc, as far as I understand: Under default options, there's no distinction between compile time and read time, and macros are expanded in that one step, just like ssyntax is. This isn't necessarily the final reader design, since it causes problems with things like (afn ((= a b)) ...). Keep in mind that I'm talking about solutions for PyArc in this turbulent time, so suggestions I make may be more generalized, more wacky, and more misinterpretable than the same suggestions applied to any given concrete version of PyArc. ^^;
The solution I'm talking about does apply to official Arc too, except that official Arc doesn't have ssyntax in the reader, so the approach isn't as practical. Official Arc does save ssexpansion until surrounding macros have done their work (post-read-time), so we can use an easier solution like '.o instead.
Here's exactly how the tagged value approach would look in official Arc:
(def foo (a b #(tagged optional (c d)) e)
(+ a b c e))
Note that #(tagged a b) is read as a tagged value:
arc> (type '#(tagged a b))
a
arc> (mac stx-types args `',(map type args))
#(tagged mac #<procedure: stx-types>)
arc> (stx-types 4 a (b) () "c" #\d #(tagged e f))
(int sym cons sym string char e)
However, I've never seen anyone write a literal tagged value this way, and I think we oughta consider it to be mostly an implementation detail, since it piggybacks on Racket vector literal syntax. The most useful thing we'd do with it is serializing a tagged value to a file and reading it back in. Still, it does "happen right now."
By the way, if the #(...) syntax didn't exist, we could still define functions with optional arguments this way:
(eval `(def foo (a b ,(annotate 'optional '(c d)) e)
(+ a b c e)))
I'm not saying it's a good idea. Like I said, this idea is targeted at PyArc, where a read-time a=b syntax would easily be the most attractive way to stuff values of type 'optional into the code.
"You might already know this (search for "AST" at http://arclanguage.org/item?id=13079), but I'm irked by special forms like 'assign or 'if too."
Yeah, I don't like those either. In fact, I was thinking about making `fn` a macro in PyArc. Also, if I can, I plan to allow programs to shadow things like `assign` and other special forms:
(def foo (bar assign)
(= bar "something"))
(foo) -> error, because = uses assign, but assign is nil
I've also tried to keep the number of special forms in PyArc to an absolute minimum. Right now, there's quote, quasiquote, if, fn, assign, and apply. I hope to get rid of apply, and possibly fn.
The only way I can see to get rid of if, assign, quote, and quasiquote would be to create a third "function" type: it behaves like a function, so it's evaluated at run time, but it doesn't evaluate it's arguments, so it's basically a function/macro hybrid.
Haha, I just had a crazy idea. Make (fn) desugar into the special hybrid form, but have it evaluate all it's arguments. Then there would only be two function types, and (fn) would be a thin wrapper around one of them. I should be able to get rid of all the special forms then, leaving only functions and macros (which are just annotated functions anyways).
---
"I think 'o is a place where neither sacrifice is necessary (neither giving up (o b c) destructuring nor giving up 'o as a variable name)."
But you do give up (o a b) destructuring:
(def foo ((o a 1) (o b a)) (list a b))
(foo '(1 2 3) '(4 5 6)) -> ((1 2 3) (4 5 6))
Unless of course you're talking about ab/using ssyntax like .o, in which case you're not really using (o a b) anymore, nor would it work if ssyntax is expanded at read time.
Thus, it has the same gotcha as (= a b), which is that you can't use o as the first element when destructuring. By the way, I mentioned earlier that I could treat escaped symbols differently:
(def foo ((|=| a b)) (list = a b))
(foo '(1 2 3)) -> (1 2 3)
I think this approach would be better than using ssyntax, because || already means "escape this thing", so we don't need to invent new syntax for it. Not sure if I'll go that route, but it is an option.
You have 'apply as a special form? In most Schemes it's a function. :)
You can definitely implement 'quasiquote and 'if as macros.
That leaves 'quote, 'fn, and 'assign. Those are all pretty fundamental. While you could make them macros, there's pretty much nothing to turn them into, unless you go for the tagged type route.
---
"The only way I can see to get rid of if, assign, quote, and quasiquote would be to create a third "function" type: it behaves like a function, so it's evaluated at run time, but it doesn't evaluate it's arguments, so it's basically a function/macro hybrid."
Hey, look, fexprs. XD Every sufficiently long Arc Forum topic seems to get around to them at some point. :-p
Since you're writing an interpreter, fexprs are a natural thing to do. They have certain elegance advantages over classical macros, since you can avoid special forms altogether, and programmers can (re)define their fexprs after the places they use them. The main disadvantage is that they're much harder to efficiently compile--not an issue for an interpreter.
---
"Haha, I just had a crazy idea. Make (fn) desugar into the special hybrid form, but have it evaluate all it's arguments. Then there would only be two function types, and (fn) would be a thin wrapper around one of them. I should be able to get rid of all the special forms then, leaving only functions and macros (which are just annotated functions anyways)."
Kernel, the most promising design I've seen for an efficient fexpr language (er, with lexical scope; sorry, PicoLisp) does the opposite: Functions are annotated fexprs. All forms are applied in exactly the same way, but functions take the extra step of evaluating their arguments. (FYI, Kernel calls functions "applicatives" and fexprs "operatives.") The one thing about Kernel is that it's kinda vaporware....
Eight's another fexpr language with lexical scope. Like Kernel, it isn't quite complete, but at least it's developed in the open on GitHub. (Hi diiq!) There's a very old topic on Eight here: http://arclanguage.org/item?id=10719
Recently, like a few months ago, diiq came back to Eight and reimplemented it in JavaScript. I've been too busy to bother with it yet, but it oughta be awesome if it's both similar to Arc and runnable in a browser.
---
"Unless of course you're talking about ab/using ssyntax like .o, in which case you're not really using (o a b) anymore, nor would it work if ssyntax is expanded at read time."
That's exactly the kind of thing I'm talking about. :) That's a solution I'm satisfied with for official Arc, but I'm confident there'd be at least some solution for PyArc that I liked better than 'o. It may just be too early to identify it.
---
"By the way, I mentioned earlier that I could treat escaped symbols differently: [...] I think this approach would be better than using ssyntax, because || already means "escape this thing", so we don't need to invent new syntax for it. Not sure if I'll go that route, but it is an option."
Well, I'm not sure what s-expressions you consider the 'def macro to see as input. If you manage to be consistent about that, and if you don't actually need to use the || in practice too much, then it's an idea I could get behind.
It's both a function and a special form. Yes, it's weird. Yes, I hope to change it.
I don't see how `if` could be implemented as a macro. Consider this case:
(def foo (a) (if a 1 2))
The `if` form needs to be evaluated every time the foo function is run, and then return either 1 or 2, depending on what 'a is. Keep in mind this is Python, so I can't have `if` desugar to `cond`. :P
---
Yeah, that's what I was talking about: have `fn` be a fexpr that returns functions that are annotated with type 'fn. And since macros are just functions with type 'fn, that would mean that everything in PyArc boils down to fexprs.
I didn't realize that what I described was fexprs, but in hindsight I probably should have. I actually messed around with NewLisp for a bit; they use fexprs. I prefer Arc's macro system, since I don't think NewLisp has quasiquote/unquote, which made certain things more verbose than they should have been.
However, the ability to have everything desugar to fexprs is appealing, especially since I no longer need special forms hardcoded into eval. PyArc will still have normal functions and macros, of course. They'll just be fexprs underneath. :P
"Eight's another fexpr language with lexical scope. Like Kernel, it isn't quite complete, but at least it's developed in the open on GitHub. (Hi diiq!) There's a very old topic on Eight here: http://arclanguage.org/item?id=10719 "