On Wed, May 29, 2019 at 08:56:58AM -0400, Ricky Teachey wrote:
For the understanding of all, it would help tremendously for you to implement a WORKING TOY example showing exactly the behavior you want in real (not theoretical) python, maybe something like this as a starting point:
I don't think the precise hardware signal behaviour is important. We can simplify the whole thing down to a toy example:
I want to print "Surprise!" whenever I assign a value to a variable.
Or perhaps log the value and target. Whatever the behaviour, we can assume Yanghao Hua knows how to implement it, he just needs a hook:
Addition operator + hooks into __add__ and __radd__
Equality operator == hooks into __eq__
When the assignment target is a dotted name, obj.x, the assignment pseudo-operator = hooks into the descriptor protocol and __setattr__
But when the assignment target is a bare name, not an attribute, the assignment "operator" hooks into ... nothing.
So if we cannot hook into assignment, perhaps we could have another operator which looks kinda-sorta like assignment. The walrus operator := is already taken (as of Python 3.8) but we can invent a new arrow operator:
target <== value
which calls target.__arrow__(value). Yanghao Hua can write his own __arrow__ method; he just needs the interpreter to call it.
The obvious solution to customising assignment is to use a dotted target:
obj.x = value
but that doesn't really work. I know in my previous message I said the problem was the aesthetics, but on further thought there are more problems with it. Suppose you want to pass x to some function:
# initialise the value obj.x = 0 # pass it to a function function( .... what goes here??? ... )
If you write this:
what the function receives is not the special object "obj" with an attached "x" attribute, but the current value of obj.x alone (in the example shown, that would be the plain old int 0). The link to obj is lost. But if you write this instead:
now function needs to know that it has to operate on obj.x rather than obj.y or obj.spam or obj.foo. The function is now tightly coupled to the name of the attribute. If you have multiple objects with differently named attributes, you can only pass one to the function:
a.x = 0 b.spam = 0 function(a) # hard-codes the attribute name "x" function(b) # fails with AttributeError
We can "fix" this problem by telling function what name to use as a seperate argument:
function(a, "x") # operates on a.x function(b, "spam") # operates on b.spam
but I'd have to be really, really desperate to write code that inelegant.
As far as I can tell, there is no straight forward way in Python to pass a dotted reference to a function and have the function see the dotted reference itself rather than the value of the dotted reference.
I think that some variation on Call-By-Reference or Call-By-Name semantics, as used by Pascal or Algol, might solve this, but we're even less likely to get that than we are to get a new operator.