1. It is implemented as its own reader, but it uses arc/mzscheme-read for symbols and quotation syntax (the version at http://placebo.hpi.uni-potsdam.de/~robert.pfeiffer/arc/mexpr... also handles quasiquotation-syntax on its own, but is less well tested)
You can load a file in m-expression format with "(load-m filename)" (or "load-m[filename];").
2.Yes I have. The M-Expr reader converts into prefix form at read time, so the read forms look like arc code. M-Expressions are just a skin for S-Expressions, therefor I tried not to break anything by changing the run-time semantics of Arc (unlike infix.arc, which makes numbers callable, which my break drcodes currying (or my idea for automatically converting numbers in functional position into Church Numerals)).
I used this in my m-expr reader, as a generalisation of do1:
(mac w/res body
" Define the result of this expression by calling the 'result' (captured!)
function inside. Calling result does not change the control flow, like in
Delphi/Pascal."
(w/uniq return
`(withs (,return nil result [= ,return _])
,@body
,return)))
(def call-reader-w/delimiters (port start end fun)
" Reads from port with fun, ensures that given delimiters are read before and
after, otherwise an error is raised"
(w/res (expect port start 'delim)
(result (fun port))
(expect port end 'delim)))
Your odd-number example could be written:
(best (fn (a b) (and odd.a (> a b))) *list-of-numbers*)
Your 'best alternative for my example is extremely clever, but doesn't work:
> (= *list-of-numbers* (6 2 4 5))
> (best (fn (a b) (and odd.a (> a b))) *list-of-numbers*)
6
I knew something was wrong with it, but it took me like half an hour to realize the flaw :)
...it can of course be fixed with extra flagging (well, it'll still fail on only lists of even numbers by not returning nil) but then you'll lose the brevity advantage over my solution.
Small snag. I used drscheme 372 and anarki. opened as.scm as per instructions and ran it, but it error'd out on loading ffi.scm. I'll try and install drscheme 352 to see of that helps.
You would need help from the compiler. Basically a macro would be called with a list of bound variables as an extra argument. For a compiler, this would be quite easy. Now a macro would look like:
Then insert stuff in Scheme-side 'ac to use (apply macro the-free-list-or-whatever (cdr ex)) instead of (apply macro (cdr ex))
That way macros that need it can get it, while macros which don't need it can ignore it.
We can potentially define 'expansion-context as a table or function, and potentially we could allow an implementation to have expansion-context!line, say provide line number etc. information so that the macro can give decent error messages. Of course if we have a dorky backend (like mzscheme) then we can just have it return expansion-context!line as nil, because it can't somehow extract line numbers, but for implementations that can, then good.
edit: Oh and ye: the 'ac compiler on scheme-side really does keep a list of bound variables ^^
This is a solution, but I consider this cheating, because it is nearly as tedious as manually inserting symeval around global functions.
w/var:do in my mexpr.arc is an example of a macro/dsl which can not take a free-var list as 1st arg (it could be changed, but that would make it useless)
I tried that. It doesn't work without knowing which variables are local and arc currently has no way of finding out, what the binding forms are, because all macros are unhygienic.
example:
(let list '(foo bar) (do (prn list)))
| | unbound | | |
mac | mac | function
function function
=>(let (global list) '(foo bar) (do ((global prn) (global list))))
We know that let binds its first argument and aif binds self, but since macros are turing-complete, this cannot be automatically inferred.
expand any macros in sub-expressions, then look at them. That's the advantage of avoiding "first-class macros", whatever their imagined advantages might be. ^^
(def >> args
; throw an error here so that user won't get
; mysterious errors in the 'reduce part
(if (no args)
(err "'>> requires at least one argument"))
(reduce (fn (a b) b.a) args))
Having to specify which functions are curried is not a problem for me, because I mostly use it for combinators, but this simple macro does not integrate with defm or pat-m (yet).
(defc flip (fun a b)
(fun b a))
(defc times (n f)
[do (repeat n (zap f _)) _])
((flip times cdr) 4 '(a b c d e))
=> (e)
;(flip times cdr) is nthcdr
these examples should work with drcodes currying too, just use def instead of defc.
> but this simple macro does not integrate with defm or pat-m (yet).
It doesn't have to: the 'p-m modifier will adapt to it. All it needs is an args . body somewhere at the end of your macro's arg list - which you do have. p-m will then be able to adapt.
All patterns would have to be of the same length, and ideally they should be ll(1) patterns, so they could dispatch on the first arg. Or should the pattern matching occur after the function got all of its arguments?
What I would really like to see is currying with partial function application and dispatch on every function argument, so that (my-curried-fun (annotate 'foo val)) is evaluated to a curried function for the type foo. Otherwise the (types|patterns) would have to be compared everytime this function is applied, which may be inefficient, e.g in