I'm asking to change assignment operator override behavior to require explicitly returning src if that's what you want the result of the operation to be.
If possible, this could be a non-breaking change if the assignment operator's . var defaulted to src.
To explain further, the assignment operator overrides let us turn procs like these:
thing
var
number
New(number)
src.number = number
proc
// operator+ : thingA(x) + thingB(y) + thingC(z) => thingD(x + y + z)
Sum(thing/other)
return new/thing(number + other.number)
// operator+= : thingA(x) += thingB(y) += thingC(z) => thingA(x + y + z)
Add(thing/other)
number += other.number
return src // Allows calling a.Add(b).Add(c) to add both b and c to a.
Into operators like these:
thing
var
number
New(number)
src.number = number
proc
// Sum : thingA(x).Sum(thingB(y)).Sum(thingC(z)) => thingD(x + y + z)
operator+(thing/other)
return new/thing(number + other.number)
// Add : thingA(x).Add(thingB(y)).Add(thingC(z)) => thingA(x + y + z)
operator+=(thing/other)
number += other.number
// return null => return src... But why?
I have a use case for being able to return null: events that don't require preprocessor macros to add/remove subscribers.
event
proc
Trigger()
operator+=(event/e)
return new/event/multiple(list(src, e))
operator-=(event/e)
if(e == src) return null // A single reduces to null.
return src
event/multiple
var/list/_events
New(list/events = new)
_events = events
Trigger()
for(var/event/event as anything in _events)
event.Trigger(arglist(args))
operator+=(event/e)
_events += e
return src
operator-=(event/e)
_events -= e
if(_events.len == 1) return _events[1] // A multiple reduces to a single.
return src
event/method
var
datum/_target
_callback
New(datum/target, callback)
_target = target
_callback = callback
Trigger()
call(target, callback)(arglist(args))
The above events can be used like so:
mob
var
event
Tested
method/TestedHandler
verb
// Trigger the event if anything is handling it.
test()
Tested?.Trigger()
// This initializes Tested=null to TestedHandler because null += thing returns thing.
// Also, a ||= b pls.
add_tested_handler()
Tested += (TestedHandler || (TestedHandler = new(src, .proc/Tested))
// This should set Tested to null because it no longer has any handlers.
// It currently doesn't, because -= can't return null on purpose.
remove_tested_handler()
Tested -= TestedHandler
// This works, but it's dumb and should already work like this.
actually_remove_tested_handler()
Tested = Tested.operator-=(TestedHandler)
proc
Tested()
src << "Tested!"
The only alternative here (besides wrapping the operations in macros) would be to del src, which is not really an option anyone should be forced into; or to use +/- instead of +=/-=.
*****************
Currently if you return null in an assignment operator override, it treats it as returning src. This doesn't allow us to do cases where returning null is intended.
I would like to request the ability to return null from these procs and have it be treated as null.
*****************
1: Start by explaining current behavior.
2: Keep it short and sweet.
3: Do not include unrelated or irrelevant details. A FR about changing minor behavior in operator overloading doesn't need a full blown refresher course on what operator overloading is.