Arc Forumnew | comments | leaders | submit | rincewind's commentslogin
1 point by rincewind 6072 days ago | link | parent | on: M-Expression Syntax

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)).

-----

1 point by rincewind 6072 days ago | link | parent | on: Interesting macro 'focus

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*)
without an intermediate list

-----

1 point by drcode 6072 days ago | link

Yup, looks like 'w/res is very close to 'focus.

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.

-----

1 point by rincewind 6072 days ago | link

sorry, I hadn't had access to an Arc then.

  (best (fn (a b) (and odd.a (or even.b (> a b)))) '(6 2 4 5))
as mexpr:

  best[[a;b]-> odd[a] and (even[b] or a > b); list[6;2;4;5]];

-----

1 point by drcode 6072 days ago | link

yes, still a pretty good solution.

-----

2 points by rincewind 6073 days ago | link | parent | on: Howto: windows + command line arc?

IIRC, you can run arc inside DrScheme.

-----

1 point by bOR_ 6073 days ago | link

Sounds interesting.. I've seen a friend work with DrScheme. Any shreds of memory how to hook it up to arc?

Ah. Step three here: http://arcfn.com/2008/05/using-opengl-with-arc.html

-----

1 point by bOR_ 6072 days ago | link

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.

  > (require mzscheme)
  > (require "ac.scm")
  > (require "brackets.scm")
  > (use-bracket-readtable)
  > (require "bitops.scm")
  > (load "ffi.scm")
  procedure application: expected procedure, given: #f; arguments were: #<struct:fun-syntax> #<syntax:C:\Program Files\anarki\ffi.scm:18:14>
  >

-----

1 point by bOR_ 6064 days ago | link

Never fixed the snag.. but there also seems to be the problem that you open as.scm in the edit window, whilst I want my arc file in there.

-----

1 point by rincewind 6073 days ago | link | parent | on: Referential transparency

how do you know that a variable is free at macro expansion time?

-----

1 point by stefano 6073 days ago | link

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:

  (mac my-mac (non-free-var-list my-arg1 ...)
    ...)
instead of:

  (mac my-mac (my-arg1 ...)
    ...)

-----

2 points by almkglor 6073 days ago | link

Why not just mod 'mac to something like (docstring extraction and name redefinition elided):

  (mac mac (name args . body)
    `(set ,name
       (annotate 'mac
         (fn ,(cons 'expansion-context args)
           ,@body))))
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 ^^

-----

1 point by rincewind 6073 days ago | link

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)

and what about list in

  (let list (list 1 2 3) list)

-----

1 point by rincewind 6073 days ago | link | parent | on: M-Expression Syntax

clickable links:

The reader http://placebo.hpi.uni-potsdam.de/~robert.pfeiffer/arc/mexpr...

test case and examples http://placebo.hpi.uni-potsdam.de/~robert.pfeiffer/arc/test....

-----

2 points by rincewind 6074 days ago | link | parent | on: Referential transparency

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.

-----

1 point by almkglor 6073 days ago | link

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. ^^

-----

1 point by rincewind 6077 days ago | link | parent | on: Pipe operator

someting similar as a macro: http://arclanguage.org/item?id=5987

-----

4 points by rincewind 6077 days ago | link | parent | on: Pipe operator

Avoiding re-inventing rreduce:

  (def >> args
     (rreduce (fn (a b) a.b) rev.args))

-----

3 points by almkglor 6077 days ago | link

Avoiding rev:

  (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))

-----

1 point by rincewind 6084 days ago | link | parent | on: Half Hygienic Macros

If I write this into the foo-package-file:

   (let list '(this is a test case)
       (all is-a-foo (map make-a-foo list)))
   
would list be read as <foo>list or <arc>list? Should the expression

   (sym "make-a-foo")
evaluate to <foo>make-a-foo?

-----

2 points by almkglor 6084 days ago | link

> If I write this into the foo-package-file: ....

Assuming you mean in the same file with the example foo package:

  (<arc>let <arc>list (<axiom>quote (<arc>this <arc>is <foo>a <foo>test <arc>case))
    (<arc>all <foo>is-a-foo (<arc>map <foo>make-a-foo <arc>list)))
> Should the expression ....

No, it evaluates to the unpackaged symbol 'make-a-foo.

-----

1 point by rincewind 6084 days ago | link | parent | on: Implicit Currying Support For Arc

clickable link: http://arclanguage.org/item?id=7788

I wrapped the currying and arity with a macro in my code:

  (mac defc (name args . body)
    `(do (def ,name ,args ,@body)
         ,(errsafe:let arity (len args)
                 `(zap [curry ,arity _] ,name))))
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.

-----

1 point by almkglor 6084 days ago | link

> 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.

-----

1 point by rincewind 6083 days ago | link

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

  (map (my-curried-fun (annotate 'foo val)) my-large-list)
This may be difficult to implement without a change in the interpreter or in p-m and curry/defc.

-----

More