Arc Forumnew | comments | leaders | submitlogin
cdr vs. nthcdr 1
1 point by evanrmurphy 5535 days ago | 2 comments
Given a list,

  arc> lst
  (a b c d)
its cdr and nthcdr 1 look the same:

  arc> (cdr lst)
  (b c d)
  arc> (nthcdr 1 lst)
  (b c d)
They think they're the same thing:

  arc> (is (cdr lst) (nthcdr 1 lst))
  t
But they don't pop the same:

  arc> (pop (cdr lst))
  b
  arc> (pop (nthcdr 1 lst))
  Error: "Can't set reference  #<procedure: nthcdr> 1 (d . nil)"
Does anyone have insight into why this is? I must admit I'm perplexed.


3 points by shader 5535 days ago | link

The answer is based on the fact that 'pop operates on a "place". In other words, it is expecting as input something that can be assigned to.

To see an example:

  arc> (= a '(1 2 3 4))
  (1 2 3 4)
  arc> (pop cdr.a)
  2
  arc> a
  (1 3 4)
You'll notice that not only did pop return 2, it also removed it from a. This functionality is provided to pop by using the macro 'setforms, which relies on a table 'setter that maps forms to functions that can assign to them.

So cdr has a setter defined by

  (defset cdr (x)
    (w/uniq g
      (list (list g x)
            `(cdr ,g)
            `(fn (val) (scdr ,g val)))))
but nthcdr doesn't currently have a setter defined for it.

So, if you want nthcdr to work with pop and similar destructive functions, you will need to define a setter for it.

-----

1 point by evanrmurphy 5535 days ago | link

Very helpful, thank you.

Edit: Rest of comment became post at http://arclanguage.org/item?id=11481

-----