Decorator (modifier)
Decorators are used to add or demonstrate a particular state or behavior to a type or function. The syntax of the decorator is as follows.
@deco
X = ...
You can have multiple decorators as long as they don't conflict.
A decorator is not a special object, it's just a one-argument function. The decorator is equivalent to the following pseudocode.
X = ...
X = deco(X)
Erg doesn't allow reassignment of variables, so code like the one above won't work.
For simple variables it's the same as X = deco(...)
, but for instant blocks and subroutines you can't do that, so you need a decorator.
@deco
f x =
y = ...
x + y
# You can also prevent the code from becoming horizontal
@LongNameDeco1
@LongNameDeco2
C = Class...
Below are some frequently used built-in decorators.
Inheritable
Indicates that the defining type is an inheritable class. If you specify "public"
for the argument scope
, it will be possible to inherit even the class of the external module. By default it is "private"
and cannot be inherited externally.
Final
Make the method non-overridable. Adding it to a class makes it a non-inheritable class, but since it's the default it doesn't make sense.
Override
Used when overriding attributes. By default, Erg will throw an error if you try to define the same attribute as the base class.
Impl
Indicates that the argument trait is implemented.
Add = Trait {
.`_+_` = Self.(Self) -> Self
}
Sub = Trait {
.`_-_` = Self.(Self) -> Self
}
C = Class({i = Int}, Impl := Add and Sub)
C.
@Impl Add
`_+_` self, other = C.new {i = self::i + other::i}
@Impl Sub
`_-_` self, other = C.new {i = self::i - other::}
Attach
Specifies the attachment patch that comes with the trait by default. This allows you to reproduce the same behavior as Rust traits.
# foo.er
Add R = Trait {
.AddO = Type
.`_+_` = Self.(R) -> Self.AddO
}
@Attach AddForInt, AddForOdd
ClosedAdd = Subsume Add(Self)
AddForInt = Patch(Int, Impl := ClosedAdd)
AddForInt.AddO = Int
AddForOdd = Patch(Odd, Impl := ClosedAdd)
AddForOdd.AddO = Even
This will automatically apply the attachment patch when importing traits from other modules.
# Originally, IntIsBinAdd and OddIsBinAdd should be imported at the same time, but if it's an attachment patch, you can omit it
{BinAdd; ...} = import "foo"
assert Int. AddO == Int
assert Odd.AddO == Even
Internally it's just attached using the trait's .attach
method. Conflicts can be removed with the trait's .detach
method.
@Attach X
T = Trait ...
assert X in T. attaches
U = T.detach(X).attach(Y)
assert X not in U. attaches
assert Y in U. attaches
Deprecated
Indicates that the variable specification is obsolete and deprecated.
Test
Indicates that this is a test subroutine. Test subroutines are run with the erg test
command.