Arc Forumnew | comments | leaders | submitlogin
Pattern-matching for function definitions in Arc
11 points by almkglor 5913 days ago | 7 comments
I've built a pattern-matching macro for function definitions in Arc, currently pushed on http://git.nex-3.com/arc-wiki.git in lib/defpat.arc .

Among other things, it supports fixed-arity functions, docstrings, symbol-matching (you just have to put symbols in a 'symbol form, otherwise they are treated as variables), and list destructuring. Like most Arc conditional structures, it uses a <pattern> <clause> <pattern> <clause> <clause> style.

This is just a test of how to do stuff in Arc ^^. Whether you like or dislike pattern-matching in functions is up to you.



2 points by nex3 5913 days ago | link

It would be really nice if this could be built into the standard def. Not with this syntax, naturally, but perhaps detecting if any pattern-like parameters showed up:

  (def factorial (0) 1)
  (def factorial (1) 1)
  (def factorial (n) (* n (factorial (- n 1))))

  (def pair ((x . y . zs)) `((,x ,y) ,@(pair zs)))
  (def pair ((x)) (list x))
  (def pair (nil) nil)
Although now that I look at it,

  (defpat factorial
    (0) 1
    (1) 1
    (n) (* n (factorial (- n 1))))

  (defpat pair
    ((x . y . zs)) `((,x ,y) ,@(pair zs))
    ((x)) (list x)
    (nil) nil)
Is more concise.

-----

1 point by almkglor 5913 days ago | link

Some nitpicks - (x . y . zs) should be (x y . zs) - note that this was buggy at the time you wrote your post, but I have just posted a bugfix on your arc-wiki.git. Also, the builtin pair uses (list (list (car xs))) for the ((x)) case.

Also, the definition of factorial above will crash on (factorial -1) but then so does Haskell if you defined it like that ^^.

-----

2 points by eds 5913 days ago | link

Is (x . y . zs) a valid list? Shouldn't it be (x y . zs)? Not that it really changes anything above... I just wanted to point it out.

-----

2 points by sjs 5911 days ago | link

If you think of the . here as Haskell's cons (:) then it makes sense. All the same, (x y . zs) can mean the exact same thing, not to mention it is shorter and familiar.

-----

2 points by almkglor 5911 days ago | link

Weird....

  arc> '(x . y . z)
  (y x z)

-----

5 points by soegaard 5909 days ago | link

Arc uses the PLT Scheme reader. The PLT Scheme reader has a non-standard (as compared to RnRS) extension, namely the double-dot notation. The double-dot notation is used to write "infix expressions".

Consider:

  (x . < . y)  is turned into  (< x y)
  (integer? boolean? . -> . void?) is turned into (-> integer? boolean? void?)
This reader extension can be turned off, but setting the appropriate parameter.

-----

1 point by sjs 5910 days ago | link

That is strange, and probably a bug. You can use up to 2 dots and the last dot is handled first, consing x and (z . nil) then consing y and (x (z . nil)). '(w x . y . z) gives (y w x z).

I can almost see how this bug appeared. Searching for the first part of a dotted expression yields (w x), and then searching for the 2nd part yields z. For some reason the expression becomes '(y . (w x z)); that I cannot explain without looking at the code.

-----