-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathnil.cr
133 lines (120 loc) · 2.88 KB
/
nil.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# The `Nil` type has only one possible value: `nil`.
#
# `nil` is commonly used to represent the absence of a value.
# For example, `String#index` returns the position of the character or `nil` if it's not
# in the string:
#
# ```
# str = "Hello world"
# str.index 'e' # => 1
# str.index 'a' # => nil
# ```
#
# In the above example, trying to invoke a method on the returned value will
# give a compile time error unless both `Int32` and `Nil` define that method:
#
# ```
# str = "Hello world"
# idx = str.index 'e'
# idx + 1 # Error: undefined method '+' for Nil
# ```
#
# The language and the standard library provide short, readable, easy ways to deal with `nil`,
# such as `Object#try` and `Object#not_nil!`:
#
# ```
# str = "Hello world"
#
# # The index of 'e' in str or 0 if not found
# idx1 = str.index('e') || 0
#
# idx2 = str.index('a')
# if idx2
# # Compiles: idx2 can't be nil here
# idx2 + 1
# end
#
# # Tell the compiler that we are sure the returned
# # value is not nil: raises a runtime exception
# # if our assumption doesn't hold.
# idx3 = str.index('o').not_nil!
# ```
#
# See [`Nil` literal](https://crystal-lang.org/reference/syntax_and_semantics/literals/nil.html) in the language reference.
struct Nil
# Returns `0_u64`. Even though `Nil` is not a `Reference` type, it is usually
# mixed with them to form nilable types so it's useful to have an
# object id for `nil`.
def object_id : UInt64
0_u64
end
# :nodoc:
def crystal_type_id
0
end
# Returns `true`: `Nil` has only one singleton value: `nil`.
def ==(other : Nil)
true
end
# Returns `true`: `Nil` has only one singleton value: `nil`.
def same?(other : Nil)
true
end
# Returns `false`.
def same?(other : Reference) : Bool
false
end
# See `Object#hash(hasher)`
def hash(hasher)
hasher.nil
end
# Returns an empty string.
def to_s : String
""
end
# Doesn't write anything to the given `IO`.
def to_s(io : IO) : Nil
# Nothing to do
end
# Returns `"nil"`.
def inspect : String
"nil"
end
# Writes `"nil"` to the given `IO`.
def inspect(io : IO) : Nil
io << "nil"
end
# Doesn't yield to the block.
#
# See also: `Object#try`.
def try(&block)
self
end
# Raises `NilAssertionError`.
#
# If *message* is given, it is forwarded as error message of `NilAssertionError`.
#
# See also: `Object#not_nil!`.
def not_nil!(message = nil) : NoReturn
if message
raise NilAssertionError.new(message)
else
raise NilAssertionError.new
end
end
# Returns `self`.
# This method enables to call the `presence` method (see `String#presence`) on a union with `Nil`.
# The idea is to return `nil` when the value is `nil` or empty.
#
# ```
# config = {"empty" => ""}
# config["empty"]?.presence # => nil
# config["missing"]?.presence # => nil
# ```
def presence : Nil
self
end
def clone
self
end
end