DM allows you to overload most of the operators it uses when working with datums and other objects. This means that A + B can call a proc defined under A instead, with B as an argument, and the return value of that proc would be the result.
The proc name for an overloaded operator is “operator” followed immediately by the operator itself, such as operator* to override the multiplication operator. A * B will call A.operator*(B) if the proc is available.
complex // complex number a+bi
var/a as num
var/b as num
New(_a,_b)
a = _a
b = _b
proc/operator+(complex/C)
if(istype(C)) return new/complex(a+C.a, b+C.b)
if(isnum(C)) return new/complex(a+C, b)
return src
proc/operator+=(complex/C)
if(istype(C))
a += C.a
b += C.b
else if(isnum(C)) a += CThe following operators may be overloaded:
If an overloaded proc is not available for an operator you try to use on a datum, a runtime error may result.
Operators without overloads
Fallback overloads
Comparison operators come in opposing pairs: ~= vs. ~!, < vs. >=, > vs. <=. You only need to override one operator from each pair; DM is smart enough to know that !(A ~= B) is the same as A ~! B.
By the same logic, you don’t have to define the assign-with-side-effect operators like += if you don’t want to. For instance if you override + but not +=, then A += B will be handled internally as A = A + B, which means the value of A after the statement may be a different datum than A was before. The value of A can also change if you do overload += but the proc returns a value other than null; its return value will be the new A.
List access
The list access operators have two different versions, because reading to a list and writing to it are different things. The [] overload is for reading, and []= is for writing.
Output
Output operations are given special treatment. If no overload is defined for the current left-hand-side value (the recipient), and the recipient isn’t a client, then the recipient is broken down into a list of clients who would ordinarily receive the output as a broadcast. E.g., outputting to world will output to each individual client instead. Each client is then checked for an overload before they receive output. Calling ..() will of course fall back on default output behavior.
// Send an effect to a player or list of players
proc/DoEffect(target, effect/E)
if(istype(target, /client))
... // do something here to show the effect
else
target << E // send as output overload
client/proc/operator<<(out, target)
if(target)
if(istype(out, /effect)) DoEffect(src, out)
else ..()Text operator
There is an overload for converting a datum to text. By having operator"" return a text string, that text will automatically appear anywhere that you embed the datum in a string, use json_encode() on the datum, or many other situations.
It won’t work for atoms being sent directly to output (e.g., world << obj) or other skin controls because the client has special handling for these situations, and the client isn’t given any info about the overloaded text. Likewise, the overloaded text won’t appear for objects in an input() prompt list, which is also handled mainly on the client and therefore can’t call any procs on the server. Despite these limitations, the text overload offers greater flexibility.