Arc Forumnew | comments | leaders | submitlogin
1 point by drcode 5920 days ago | link | parent

Yes, you could of course use map for the simple example in the post. I didn't want to make it more complicated than necessary for a post- If you want a more complicated example that can't be done with map, here's a function that removes pairs of identical items from a list:

  (def rem-pairs ((a . (b . c)))
      (when a
           (if (is a b) (rem-pairs c)
              (cons a (rem-pairs:cons b c)))))

  arc> (rem-pairs '(d r b s d d e w))
  (d r b s e w)
This function, also, will work in every case but break when there are nils in the list)


1 point by almkglor 5920 days ago | link

For everything else, there's pattern matching (on nex-3's arc-wiki).

  (pat-match:def rem-pairs
    ( (a b . c) )
        (if (is a b)
          (rem-pairs c)
          `(,a ,@(rem-pairs `(,b ,@c))))
    ( (a) )
         `(,a)
    ( () )  ())
Possibly I can make it such that you can even say something like (a ,(b (is a b)) . c) in the pattern guard, but it seems a semi-hard problem.

  ;does not work in current version yet!!
  (pat-match:def rem-pairs
    ( (a ,(b (is a b)) . c) )
      (rem-pairs c)
    ( (a . as) )
      `(,a ,@(rem-pairs as))
    ( () )
      () )

-----

1 point by greatness 5920 days ago | link

I'm still not seeing the win of pattern matching here, I'm afraid. This is actually longer than the standard definition using car/cdr. Maybe it's better for more complicated things, I suppose, but that'll defeat the purpose because it wouldn't be legible at that point (as if it is now).

-----

1 point by almkglor 5920 days ago | link

The big win is that it's assuredly correct, and you don't have to mess around dealing with car and cdr. Crossref def varline in app.arc : arc1 had a bug there because it's ridiculously easy to make a mistake dealing with car and cdr. If you can't find the bug, try rewriting the code into pattern-matching form.

-----

1 point by greatness 5920 days ago | link

I'm not seeing the big win over something like this:

  (def print-list ((a . b))
    (when or.a.b
       prn.a
       print-list.b))

  (def rem-pairs ((a . (b . c)))
    (when or.a.b.c
      (if is.a.b rem-pairs.c
                 (cons a (rem-pairs:cons b c)))))

-----

1 point by drcode 5920 days ago | link

Well, I'd be happy with that, except it doesn't work- There's no way to know with or.a.b if you're at the end of the list or if there's just a nil as a last item in the list. Notice the missing item here:

  > (do (print-list '(nil nil nil)) 1)
  nil
  nil
  1

-----

1 point by greatness 5920 days ago | link

Ah, I see. When destructuring the arguments, if the last argument is nil it is equivalent to not being an item. ie:

  arc> (= a '(1 2 nil))
  (1 2 nil)
has a last destructuring bind of (nil . nil) so 'a would be nil and 'b would be nil, making my code not work and making it impossible to differentiate between the end of the list and the list with a last item of nil.

Even so, it's not that much of a problem:

  (def print-list (args)
    (unless no.args
       (prn:car args)
       (print-list:cdr args)))
This code shares almost the same amount of brevity, though I believe it defeats the purpose of what you were trying to do with the destructuring bind (make the calls to car/cdr disappear).

I don't believe your solution is the right thing to do because it wouldn't make sense for the car to be optional and then not force the cdr to be optional. I do not believe an optimal destructuring solution exists that could improve on the brevity of the original car/cdr solution.

-----