forked from javierjulio/ruby-koans-completed
-
Notifications
You must be signed in to change notification settings - Fork 0
/
about_symbols.rb
139 lines (107 loc) · 4.53 KB
/
about_symbols.rb
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
134
135
136
137
138
139
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
class AboutSymbols < EdgeCase::Koan
def test_symbols_are_symbols
symbol = :ruby
assert_equal true, symbol.is_a?(Symbol)
end
def test_symbols_can_be_compared
symbol1 = :a_symbol
symbol2 = :a_symbol
symbol3 = :something_else
assert_equal true, symbol1 == symbol2
assert_equal false, symbol1 == symbol3
end
# A Ruby symbol is a constant, unique name, but its contens can't be changed
def test_identical_symbols_are_a_single_internal_object
symbol1 = :a_symbol
symbol2 = :a_symbol
assert_equal true, symbol1 == symbol2
assert_equal true, symbol1.object_id == symbol2.object_id
end
# Unlike strings, symbols of the same name are initialized and exist in memory
# only once during a session of ruby. Symbols are most obviously useful when
# youÕre going to be reusing strings representing something else.
# even if the symbol was used as a key in two different hashes they are still the
# same object so for example, patient1 and patient2 :ruby keys would be the same object
# patient1 = { :ruby => "red" }
# patient2 = { :ruby => "testing" }
# patient1.each_key {|key| puts key.object_id.to_s]
# patient2.each_key {|key| puts key.object_id.to_s}
# both result in 3918094 so its the same object
# Two symbols with the same name are always the same underlying object:
# so "open".object_id != "open".object_id
# but :open.object_id == :open.object_id
def test_method_names_become_symbols
symbols_as_strings = Symbol.all_symbols.map { |x| x.to_s }
assert_equal true, symbols_as_strings.include?("test_method_names_become_symbols")
end
# THINK ABOUT IT:
#
# Why do we convert the list of symbols to strings and then compare
# against the string value rather than against symbols?
# Because Symbols aren't Strings so we have to convert them to strings to do a
# string compare on the values. A later test shows that using .eql? doesn't work
# Great tips on how to think between the two:
# (1) If the contents (i.e. the sequence of characters) of the object is important, use a String.
# (2) If the identity of the object is important, use a Symbol.
in_ruby_version("mri") do
RubyConstant = "What is the sound of one hand clapping?"
def test_constants_become_symbols
all_symbols = Symbol.all_symbols
assert_equal false, all_symbols.include?(RubyConstant)
end
end
def test_symbols_can_be_made_from_strings
string = "catsAndDogs"
assert_equal :catsAndDogs, string.to_sym
end
def test_symbols_with_spaces_can_be_built
symbol = :"cats and dogs"
assert_equal symbol, :"cats and dogs".to_sym
end
def test_symbols_with_interpolation_can_be_built
value = "and"
symbol = :"cats #{value} dogs"
assert_equal symbol, :"cats and dogs".to_sym
end
def test_to_s_is_called_on_interpolated_symbols
symbol = :cats
string = "It is raining #{symbol} and dogs."
assert_equal "It is raining cats and dogs.", string
end
def test_symbols_are_not_strings
symbol = :ruby
assert_equal false, symbol.is_a?(String)
assert_equal false, symbol.eql?("ruby") # even if ":ruby" result is false
end
# Symbols are not Strings but they can be converted using .to_s and vice versa,
# where Strings can be converted to Symbols using .to_sym
def test_symbols_do_not_have_string_methods
symbol = :not_a_string
assert_equal false, symbol.respond_to?(:each_char)
assert_equal false, symbol.respond_to?(:reverse)
end
# It's important to realize that symbols are not "immutable
# strings", though they are immutable. None of the
# interesting string operations are available on symbols.
def test_symbols_cannot_be_concatenated
# Exceptions will be pondered further father down the path
assert_raise(NoMethodError) do
:cats + :dogs
end
end
# while symbols can't be concatenated you can convert each to a string, concatenate
# the strings and them convert to a symbol, for example:
#
# puts (:test1.to_s + " " + :test2.to_s).to_sym
# puts :"test1 test2".is_a?(Symbol)
def test_symbols_can_be_dynamically_created
assert_equal :catsdogs, ("cats" + "dogs").to_sym
end
# THINK ABOUT IT:
#
# Why is it not a good idea to dynamically create a lot of symbols?
# Creating a lot of symbols dynamically allocates a lot of memory that can't be
# freed until the program ends. Ruby Symbols are put into memory only once so they
# are very efficient for things like hash keys.
end