Arc Forumnew | comments | leaders | submitlogin
Improving "def" to support point free style
6 points by drcode 5953 days ago | 10 comments
For those who don't know, point free style is a technique common in languages like Haskell and can greatly increase code brevity, if combined with other higher-order function manipulations. I propose def should be modified to support point-free programming. In point-free style, instead of declaring all the parameters to your function, you can declare fewer and instead have your function return another function that accepts the remaining parameters. Here is a new version (I'm calling "defx" for now) that supports this:

  (mac defx (name args . rest) 
       (let wild [is _ '_] 
	    (let gens ()
	         (repeat (count wild args) (push (uniq) gens))
	         (if gens
		     (let g (copy gens)
			  (let args_nu (map [if (wild _) 
				                (pop g)
	  				   _]
		  		         args)
			       `(def ,name ,args_nu
	  			((do ,@rest) ,@gens))))
  		   `(def ,name ,args
  		      ,@rest)))))
To write a function in point-free style using my defx, simply replace any arguments you wish to leave undeclared by "_"- Note that they can be parameters located anywhere in the parameter list. If no "_" exist in the arguments, defx works exactly like the regular def.

Here is the splitn function in arc.arc:

  (def splitn (n xs)
    (let acc nil
      ((afn (n xs)
         (if (or (no xs) (<= n 0))
             (list (rev acc) xs)
             (do (push (car xs) acc)
                 (self (- n 1) (cdr xs)))))
       n xs)))
Here is the shorter version of the function modified to take advantage of a point-free style:

  (defx splitn (_ _)
    (let acc nil
         (afn (n xs)
	      (if (or (no xs) (<= n 0))
		  (list (rev acc) xs)
	  	(do (push (car xs) acc)
		      (self (- n 1) (cdr xs)))))))
(Note that there are bigger payoffs for pfs if combined with other techniques that I'm not getting into here)

-Conrad Barski



1 point by lojic 5953 days ago | link

Am I missing something here?

  arc> (splitn 2)
  Error: "procedure  splitn: expects 2 arguments, given 1: 2"
Shouldn't (splitn 2) evaluate to a function that accepts a list after creating the defx macro and using it to redefine splitn?

-----

1 point by drcode 5952 days ago | link

no- this does not support partial function application (yet) -only the function declarations are shorter.

-----

1 point by lojic 5952 days ago | link

I see. I didn't notice it was shorter.

-----

2 points by ryantmulligan 5953 days ago | link

While I don't doubt that this increases code brevity, an example of the effect of your macro on code size would be nice.

-----

1 point by drcode 5953 days ago | link

It would have zero effect on program size if there are no undeclared parameters, so in the default case the code remains identical to the previous behavior.

In terms of token count, by itself this feature might lead to a modest 2% token count decrease. It would probably go up to 5%-10% if combined with a partial application feature, such as described in http://arclanguage.org/item?id=645

I plan on creating an improved version of this that includes partial application and give more examples with more impressive decreases in token count.

-----

1 point by ryantmulligan 5952 days ago | link

I'd love to see even 1 example.

-----

1 point by drcode 5952 days ago | link

well, the splitn in the top level post showed a decreased token count (the very last line of the splitn function could be removed) but i'm working on something clearer...

-----

1 point by ehird 5953 days ago | link

thingy

  (mac defx (n x . b)
    (if (no b)
        `(= ,n ,x)
        `(def ,n ,x ,@b)))

-----

1 point by ehird 5953 days ago | link

silly:

  (defx accgen [let x _ [++ x _]])

-----

1 point by drcode 5952 days ago | link

I can tell I didn't communicate the intended purpose very well... let me put up another post that isn't as half-assed as my first one was (tonight)

-----