"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:
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 :)