Arc Forumnew | comments | leaders | submitlogin
Functional vs non-functional destructive operations
2 points by akkartik 4449 days ago | 4 comments
There was a discussion on the optional param default arg gotcha in python at https://news.ycombinator.com/item?id=6033546, and I ended up posting a comment connecting it up to lisp (https://news.ycombinator.com/item?id=6036472) that y'all might find interesting.


2 points by rocketnia 4443 days ago | link

"But there's a reason lisp does seemingly the wrong thing. According to the spec, nconc skips empty arguments (http://www.lispworks.com/documentation/HyperSpec/Body/f_ncon...) Reading between the lines, I'm assuming this makes sense from a perspective in lisp where we communicate even with 'destructive' operations through their return value."

This isn't just an idiomatic thing. Since nil is immutable, (nconc a '(34)) couldn't change a if it tried.

And whereas Python's list.append() mutates a single object, Lisp operations like 'nconc and 'nreverse destructively create a whole tree of objects. Particularly in the case of 'nreverse, the new tree's root isn't specified to be any particular object the caller has seen before, so the caller has to get a reference to it somehow: as the return value.

Incidentally, the spec for 'nconc leaves less unspecified, so the programmer doesn't actually need to use the return value. Given a non-returning version, they can reconstruct a returning version like so:

  ; Arc code
  (def nconc args
    (do1 (find idfn args)
         (apply nconc-with-no-return-value args)))
So the return value of 'nconc probably is an idiomatic thing, for consistency with 'append and 'nreverse.

-----

1 point by akkartik 4443 days ago | link

Yes, I was phrasing it poorly. I meant that since just reusing the binding sometimes doesn't work, the idiom has evolved to always rebind. Even for non-nil lists, and even for destructive operations that are safe to just operate on like nconc. But I'm not a huge expert on what the idioms are :)

-----

2 points by zck 4446 days ago | link

Ooh, cool discussion. I really like the connection you made to nconc.

At least Arc does the default properly:

  arc> (def f (n (o tbl (obj))) (= tbl.n (* n 2)) tbl)
  #<procedure:zz>
  arc> (f 1)
  #hash((1 . 2))
  arc> (f 2)
  #hash((2 . 4))

-----

1 point by akkartik 4443 days ago | link

Thanks!

Arc does have similar gotchas with quote: http://arclanguage.org/item?id=10248 (one of my earliest posts on this forum)

-----