(I'm noticing there's a bit of a brevity boost with infix syntax, though. It means you typically only have to add "1 + " to an expression, rather than "(+ 1 " on one side and ")" on the other, for a total of one edit versus two. I guess that makes it a way to boost brevity in a less customizable language.
With ssyntax, you usually only have to add "inc:" or "inc." to the left side of an expression (depending on whether it's already a function/macro call or just a symbol). This is why I love the hell out of ssyntax. It only doesn't work if the expression is already of the form "a.b", in which case you have to add some parentheses. Currently, "inc:inc.2" expands to "(compose inc inc.2)".
Recommendation: Have "a:b.c" expand to (a:b c); this will make it always, or nearly always (I haven't thought much about using it with quote or quasiquote), possible to tack an extra function/macro call onto an expression with a single edit. I think it's also more consistent: currently we have a.b.c -> (a.b c) [-> ((a b) c)], which is useful for referencing nested data structures; and it fits that pattern to have a:b.c -> (a:b c) [-> ((compose a b) c) -> (a (b c))]. I really think this would be a big improvement.
Anyway, this ssyntax stuff has the major advantage that it works to tack on any single-argument function/macro, rather than just the very few that are important enough to have their own special character. I find this extremely convenient: I can add "time:" and "prn:" to an expression when I want to debug it, and then remove it just as easily. Combined with my 'cp function (http://arclanguage.org/item?id=12873), this has in my past made for some very pleasant debugging.
Aesthetically, tacking "func:" onto "expr" is like adding an element to the tree (in fact, it literally does "expr -> (list func expr) = (cons func (cons expr nil))"), which is an O(1) operation, and it makes sense for it to always be a simple O(1) editing operation. (Adding something to the left side, then remembering to look for the right side so you can add a close-paren, is not O(1) to me.) In fact, it's a common O(1) operation, and it should be O(1); and the same should go for its opposite, removing an element previously tacked on.
Imma go figure out how to change ac.scm. ...And I've kludged it by making . and ! expand before : and ~ in the definition of "expand-ssyntax" in ac.scm.
This should work fine for the near future, as I don't have any reason to mix "." and ":" in expressions other than with "." as the last ssyntax character. I think it should ideally expand right-to-left no matter what the ssyntax characters are; note that, under this scheme, "a:b:c" would expand to (compose a:b c) -> (compose (compose a b) c), which is equivalent to the current expansion (compose a b c), and the Arc Compiler could transform the former into the latter.
Arc seems to load properly, and the ssyntax works the way I like it.
In Arc I sometimes like to say (a.b:c.d e f), which this change breaks. But I don't mind that. ^_^
Anyway, what you're talking about is already how Penknife works: Infix operators on the right are always handled first. An interesting result is that a!b ssyntax is a bit redundant under this setup. Here's an Arc demonstration:
; with ! ssyntax
a.b!c.d -> (a.b!c d)
-> ((a.b (quote c)) d)
; without ! ssyntax
a.b:quote.c.d -> (a.b:quote.c d)
-> ((a.b:quote c) d)
-> (((compose a.b quote) c) d)
-> ((a.b (quote c)) d)
So now the following ssyntaxes are all abbreviations for things that are a little more verbose but just as edit-efficient:
In Penknife, I've been thinking about having infix operator such that a`b.c is (b a c). Arc could do this if a`b expanded to something like (opcurry b a), where 'opcurry was a metafn such that ((opcurry a b c) d e f) expanded to (a b c d e f). Then the only essential ssyntaxes would be a`b and a.b:
Of course, at a certain point the verbosity is a bit silly. I've defined ` as a curry function in Penknife so that I can test it out a`foo.b with everyday functions foo, like 1`+.2 and so forth, and I've found it pretty cumbersome to actually type. Still, it's less cumbersome than 1.+(2), I suppose. :-p
Maybe it'll be useful in an axiomatic way. Perhaps a Penknife-like or Arc-like language can have ` and . as its only basic infix operators, with all other infix operators being abbreviations defined in terms of those two....
Hmm, an alternate axiomatic approach is to treat a`b.c as a single ternary operator a{b}c.
a&b -> a{andf}b
a:b -> a{compose}b
a.b -> a{call-op}b ; where (call-op a b) expands to (a b)
a!b -> a{compose}quote{call-op}b
.a -> get{call-op}a
!a -> get{compose}quote{call-op}a
~a -> no{compose}a
This is essentially equivalent to Penknife's approach, except that Penknife uses Haskell-style naming rules (infix identifier or alpha identifier) rather than delimiters. So it looks like the a`b.c approach is just a way to simulate this syntax system within itself. Pretty interesting. XD