Subsets
A subset is a definition which specifies the upper limit of inheritance, with optional argument validation.
1
subset Integer < Number { |n| n.is_int }
2
subset Natural < Integer { |n| n.is_pos }
3
subset EvenNatural < Natural { |n| n.is_even }
4
5
func foo(n < EvenNatural) {
6
say n
7
}
8
9
foo(42) # ok
10
foo(43) # failed assertion at run-time
Copied!
In some sense, a subset is the opposite of a type. For example, let's consider the following class hierarchy:
1
class Hello(name) {
2
method greet { say "Hello, #{self.name}!" }
3
}
4
5
class Hi < Hello {
6
method greet { say "Hi, #{self.name}!" }
7
}
8
9
class Hey < Hi {
10
method greet { say "Hey, #{self.name}!" }
11
}
Copied!
If we declare a function that accepts a subset of Hi, it will accept Hello, but it cannot accept Hey:
1
func greet(obj < Hi) { obj.greet } # `Hi` is the upper limit
2
3
greet(Hi("Foo")) # ok
4
greet(Hello("Bar")) # ok
5
greet(Hey("Baz")) # fail: `Hey` is too evolved
Copied!
On the other hand, if we use Hi as a type assertion, it will accept Hey, but not Hello:
1
func greet(Hi obj) { obj.greet } # `Hi` is the lower limit
2
3
greet(Hi("Foo")) # ok
4
greet(Hey("Baz")) # ok
5
greet(Hello("Bar")) # fail: `Hello` is too primitive
Copied!
Subsets can also be used for combining multiple types into one type, creating an union type:
1
subset StrNum < String, Number
2
3
func concat(a < StrNum, b < StrNum) {
4
a + b
5
}
6
7
say concat("o", "k") # ok
8
say concat(13, 29) # 42
9
say concat([41], [42]) # runtime error
Copied!
Last modified 1yr ago
Copy link