Arc Forumnew | comments | leaders | submitlogin
Suggestion: partial application by default
7 points by Zak 6140 days ago | 9 comments
When a function expecting n arguments is given n-x arguments, it should return a closure that takes x arguments, like Haskell does. There should also be a partial application function (maybe with optional syntax) for use with functions that have optional arguments.


3 points by Zak 6139 days ago | link

Note also that I don't want to have to call par when the function takes a fixed number of arguments. I want to be able to do this:

  (= foo (cons 'bar))
  => #<procedure: foo>
  (foo 'baz)
  => (bar . baz)

-----

1 point by sjs 6139 days ago | link

I think this would be great, but it'll take some work. For example right now Arc compiles s-exps to mzscheme, so it would need to change mzscheme's semantics (not sure if this is even practical or possible). Arc most likely needs to stand on its own a little more before this will be feasible.

-----

2 points by rkts 6139 days ago | link

  (mac par (f . args1)
    (w/uniq (gf gargs1 gargs2)
      `(with (,gf ,f ,gargs1 (list ,@args1))
         (fn ,gargs2 (apply ,gf (join ,gargs1 ,gargs2))))))
Partial application probably isn't as useful in Arc as it is in Haskell since many functions take an arbitrary number of arguments. E.g. you couldn't do (map (+ 10) xs) because (+ 10) just evaluates to 10.

Edit: why is there a gap at the top of my comment?

-----

1 point by Zak 6139 days ago | link

Probably not, but it's still useful as a generic way to write generator functions. Your par macro isn't working as expected for me. Is this a bug, or am I using it wrong?

  (def accgen (n) (par ++ n))
  #<procedure: accgen>
  arc> (= foo (accgen 5))
  #<procedure>
  arc> (foo 8)
  Error: "Function call on inappropriate object #3(tagged mac #<procedure>) (5 8)"

-----

1 point by rkts 6139 days ago | link

Well, I was thinking par would be call-by-value. So your accumulator would have to be something like

  (def ref (x) (obj contents x))

  (def ++ref (x (o by 1)) (++ (x 'contents) by))

  (def accgen (n) (par ++ref (ref n)))
I don't know if a call-by-reference par could be implemented using macros. I also don't know that that's a good idea, since it could lead to bugs when mutation is involved.

  (= fns nil)

  (= x 1)
  (push (par + x) fns)

  (= x 2)
  (push (par + x) fns)

  (= x 3)
  (push (par + x) fns)

  (map [_ 1] fns) => (4 4 4)  ; probably not what you want
Edit: I think the issue is that we have slightly different definitions of partial application. You are thinking of it as a sort of syntactic sugar on top of closures, whereas I (being primarily an ML programmer) am used to thinking of partial application as a function call. So that's why we have different intuitions about how it should work.

-----

1 point by rkts 6139 days ago | link

By the way, why are you bothering with generators? Arc being an exploratory language, the idea seems to be to use lists for everything, at least at first. Iterators/generators are often a premature optimization.

-----

1 point by sjs 6139 days ago | link

Did you mean to write (def accgen (n) (par + n))?

-----

3 points by Zak 6139 days ago | link

I did not: an accumulator increments. See http://paulgraham.com/accgen.html

-----

1 point by greatness 6136 days ago | link

I was thinking more like this:

  (def curry (f . args)
    (fn args2 (apply f (join args args2))))
which is pretty much the same thing except without it being a macro. I've found that with the [] syntax, currying doesn't really improve code brevity.

-----