-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
nil.cr
127 lines (114 loc) · 2.71 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
# 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`.
#
# See also: `Object#not_nil!`.
def not_nil! : NoReturn
raise NilAssertionError.new
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