Hacker News new | ask | show | jobs
by cryptonector 2308 days ago

  > But in python, it works perfectly (even for
  > user-defined types). How? Simple. Python's parser
  > has a little hack in it - which I'm sure must hurt
  > the python people a lot, so much do they hate
  > hacks - that makes m[5]= parse differently than
  > just plain m[5].
  > 
  > The python parser converts o[x]=y directly into
  > o.setitem(x,y).
The name for this is "generalized variables", at least in Lisp land. The idea is to allow complex assignment left-hand side (LHS) expressions and turn assignments into calls to setter functions, including whatever complex data structure traversals might be needed.

Lisp has generalized variables via "setf macros", which turn assignments into the right set of calls to setter functions. Setf macros do this at compile time and generically for any getter/setter functions that have been registered with a bit of ceremony.

(Lisp also has destructuring-bind, which lets you write a data structure with variable symbols in it such that the corresponding variables will be bound to the data find in the corresponding places of a real data structure value. The two features, destructuring and generalized variables, are similarly magical.)

jq can do crazy generalized variable assignments like '.a[].b[0] = 1', but this is a run-time thing. (The LHS is evaluated in a context that allows only "path expressions", and in a reduction, while the RHS expression is run in the body of the reduction to update the input value at each path matched by the LHS.)

Icon implements generalized variables by letting procedures return "places" -- references to assignable locations --, so you can assign to the return value of procedures. This may seem quite surprising when you see it, but it works beautifully.