Antra

Standardbibliothek

Antra::Ops

import Antra::Ops

Operator and access protocols: one protocol per capability.

Each protocol names the method behind one operator, so a type takes only what it supports. A 2D vector adds and scales, but has no %:

import Antra::Ops.*

impl Add for %V[..] {
    fn __add__(%V[a, b], %V[c, d]) -> %V[a + c, b + d]
}
impl Mul for %V[..] {
    fn __mul__(%V[a, b], k) -> %V[a * k, b * k]
}

println(%V[1, 2] + %V[3, 4] * 2)   # %V[7, 10]

In a package header several combine: package Money with Add, Eq, Ord { … }. The operators dispatch on the left operand's tag (%T{..}, %T[..], %T<..>); any protocol with a method of that name works the same, these just give the names a home. len(x) uses __count__ from Antra::Enumerable, so it has no protocol here.

Überblick#

Kleine Protokolle fuer die Operatoren und Zugriffe, eines pro Faehigkeit. Ein Typ nimmt nur, was er kann: ein 2D-Vektor addiert und skaliert, hat aber kein %.

ProtokollMethodeWirkt auf
Add, Sub, Mul, Div, Mod__add__, __sub__, __mul__, __div__, __mod__+ - * / %
Neg__neg__(a)-a
Eq__eq__==, !=
Ord__cmp__ (:lt/:eq/:gt)< <= > >= <=>, Array.sort/min/max
Index__get__(self, k)x[k], x?[k]
Contains__contains__(self, v)v in x
Hash__hash__(self)Gleichheit in Sets (%<…>, in, Set.*)
import Antra::Ops.*

impl Add for %V[..] {
    fn __add__(%V[a, b], %V[c, d]) -> %V[a + c, b + d]
}
impl Mul for %V[..] {
    fn __mul__(%V[a, b], k) -> %V[a * k, b * k]
}

println(%V[1, 2] + %V[3, 4] * 2)      # %V[7, 10]

package Money with Add, Eq, Ord {
    pub field cents = 0
    pub fn new(c) -> bless(%{cents: c}, Money)
    fn __add__(a, b) -> Money.new(a.cents + b.cents)
    fn __eq__(a, b) -> a.cents == b.cents
    fn __cmp__(a, b) -> a.cents <=> b.cents
}

println(Money.new(5) + Money.new(7) > Money.new(10))   # true

Wie bei Antra::Display ist der Import nicht noetig: die Operatoren schauen nur nach dem Methodennamen, jedes eigene Protokoll mit __add__ wirkt genauso. len(x) nutzt __count__ aus Antra::Enumerable und hat deshalb hier kein eigenes Protokoll. Die Regeln im Einzelnen stehen in 15-protokolle.md.

Protokolle#

Addprotocol</>
protocol Add {
    fn __add__(a :- Self, b :- Self) :- Self
}

a + b

Subprotocol</>
protocol Sub {
    fn __sub__(a :- Self, b :- Self) :- Self
}

a - b

Mulprotocol</>
protocol Mul {
    fn __mul__(a :- Self, b)
}

a * b

Divprotocol</>
protocol Div {
    fn __div__(a :- Self, b)
}

a / b

Modprotocol</>
protocol Mod {
    fn __mod__(a :- Self, b)
}

a % b

Negprotocol</>
protocol Neg {
    fn __neg__(a :- Self) :- Self
}

-a

Eqprotocol</>
protocol Eq {
    fn __eq__(a :- Self, b) :- Bool
}

a == b and a != b (without it: deep equality)

Ordprotocol</>
protocol Ord {
    fn __cmp__(a :- Self, b :- Self) :- :lt | :eq | :gt
}

<, <=, >, >=, <=>, Array.sort/min/max. __cmp__ returns :lt, :eq or :gt.

Indexprotocol</>
protocol Index {
    fn __get__(self :- Self, k)
}

x[k] and x?[k] (ranges and slices read the data)

Containsprotocol</>
protocol Contains {
    fn __contains__(self :- Self, v) :- Bool
}

v in x

Hashprotocol</>
protocol Hash {
    fn __hash__(self :- Self)
}

Set membership: two values are one element when their __hash__ results are (fn __hash__(self) -> self.id)

Quelle dieser Seite