trackler 2.0.3.0 → 2.0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/fixtures/common/exercises/no-metadata/description.md +1 -0
- data/lib/trackler/problem.rb +12 -0
- data/lib/trackler/problems.rb +8 -12
- data/lib/trackler/version.rb +1 -1
- data/tracks/bash/README.md +2 -0
- data/tracks/c/config.json +9 -2
- data/tracks/c/exercises/sieve/makefile +15 -0
- data/tracks/c/exercises/sieve/src/example.c +50 -0
- data/tracks/c/exercises/sieve/src/sieve.h +10 -0
- data/tracks/c/exercises/sieve/test/test_sieve.c +113 -0
- data/tracks/c/exercises/sieve/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/sieve/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/sieve/test/vendor/unity_internals.h +701 -0
- data/tracks/coffeescript/.travis.yml +1 -0
- data/tracks/coldfusion/.travis.yml +1 -0
- data/tracks/crystal/Makefile +18 -15
- data/tracks/crystal/README.md +5 -5
- data/tracks/crystal/config.json +6 -0
- data/tracks/crystal/exercises/acronym/src/acronym.cr +1 -0
- data/tracks/crystal/exercises/anagram/src/anagram.cr +1 -0
- data/tracks/crystal/exercises/atbash-cipher/src/atbash_cipher.cr +1 -0
- data/tracks/crystal/exercises/binary/src/binary.cr +1 -0
- data/tracks/crystal/exercises/bob/src/bob.cr +1 -0
- data/tracks/crystal/exercises/bracket-push/src/bracket_push.cr +1 -0
- data/tracks/crystal/exercises/difference-of-squares/spec/difference_of_squares_spec.cr +44 -0
- data/tracks/crystal/exercises/difference-of-squares/src/example.cr +15 -0
- data/tracks/crystal/exercises/forth/src/forth.cr +1 -0
- data/tracks/crystal/exercises/gigasecond/src/gigasecond.cr +1 -0
- data/tracks/crystal/exercises/hamming/src/hamming.cr +1 -0
- data/tracks/crystal/exercises/hello-world/src/hello_world.cr +1 -0
- data/tracks/crystal/exercises/largest-series-product/src/largest_series_product.cr +1 -0
- data/tracks/crystal/exercises/leap/src/leap.cr +1 -0
- data/tracks/crystal/exercises/pangram/src/pangram.cr +1 -0
- data/tracks/crystal/exercises/raindrops/src/raindrops.cr +1 -0
- data/tracks/crystal/exercises/react/src/react.cr +1 -0
- data/tracks/crystal/exercises/rna-transcription/src/rna_transcription.cr +1 -0
- data/tracks/crystal/exercises/roman-numerals/src/roman_numerals.cr +1 -0
- data/tracks/crystal/exercises/sieve/src/sieve.cr +1 -0
- data/tracks/crystal/src/generator/exercises/difference_of_squares.cr +39 -0
- data/tracks/go/exercises/allergies/allergies_test.go +2 -2
- data/tracks/go/exercises/anagram/anagram_test.go +3 -3
- data/tracks/go/exercises/grade-school/grade_school_test.go +3 -3
- data/tracks/go/exercises/secret-handshake/secret_handshake_test.go +1 -1
- data/tracks/java/config.json +13 -1
- data/tracks/java/exercises/binary-search-tree/build.gradle +18 -0
- data/tracks/java/exercises/binary-search-tree/src/example/java/BST.java +122 -0
- data/tracks/java/exercises/binary-search-tree/src/main/java/.keep +0 -0
- data/tracks/java/exercises/binary-search-tree/src/test/java/.keep +0 -0
- data/tracks/java/exercises/binary-search-tree/src/test/java/BSTTest.java +163 -0
- data/tracks/java/exercises/pythagorean-triplet/build.gradle +18 -0
- data/tracks/java/exercises/pythagorean-triplet/src/example/java/PythagoreanTriplet.java +117 -0
- data/tracks/java/exercises/pythagorean-triplet/src/main/java/PythagoreanTriplet.java +3 -0
- data/tracks/java/exercises/pythagorean-triplet/src/test/java/PythagoreanTripletTest.java +95 -0
- data/tracks/java/exercises/settings.gradle +2 -0
- data/tracks/julia/README.md +16 -0
- data/tracks/perl5/README.md +2 -0
- data/tracks/perl6/README.md +2 -1
- data/tracks/php/config.json +5 -0
- data/tracks/php/exercises/sieve/example.php +29 -0
- data/tracks/php/exercises/sieve/sieve_test.php +201 -0
- data/tracks/pony/.travis.yml +1 -0
- data/tracks/python/exercises/anagram/anagram_test.py +1 -0
- data/tracks/python/exercises/beer-song/beer_song_test.py +1 -0
- data/tracks/python/exercises/binary-search/binary_search_test.py +1 -0
- data/tracks/python/exercises/binary/binary_test.py +1 -0
- data/tracks/python/exercises/bob/bob_test.py +1 -0
- data/tracks/python/exercises/clock/clock_test.py +1 -0
- data/tracks/python/exercises/etl/etl_test.py +1 -0
- data/tracks/python/exercises/gigasecond/gigasecond_test.py +1 -0
- data/tracks/python/exercises/grains/grains_test.py +1 -0
- data/tracks/python/exercises/leap/leap_test.py +1 -0
- data/tracks/python/exercises/meetup/meetup_test.py +1 -0
- data/tracks/python/exercises/nucleotide-count/nucleotide_count_test.py +1 -0
- data/tracks/python/exercises/ocr-numbers/example.py +1 -0
- data/tracks/python/exercises/ocr-numbers/ocr_test.py +1 -0
- data/tracks/python/exercises/perfect-numbers/perfect_numbers_test.py +1 -0
- data/tracks/python/exercises/phone-number/phone_number_test.py +1 -0
- data/tracks/python/exercises/pig-latin/pig_latin_test.py +1 -0
- data/tracks/python/exercises/point-mutations/point_mutations_test.py +1 -0
- data/tracks/python/exercises/poker/poker_test.py +1 -0
- data/tracks/python/exercises/prime-factors/prime_factors_test.py +1 -0
- data/tracks/python/exercises/pythagorean-triplet/example.py +2 -3
- data/tracks/python/exercises/rail-fence-cipher/rail_fence_cipher_test.py +1 -0
- data/tracks/python/exercises/raindrops/raindrops_test.py +1 -0
- data/tracks/python/exercises/rectangles/rectangles_count_test.py +1 -0
- data/tracks/python/exercises/robot-simulator/robot_simulator_test.py +1 -0
- data/tracks/python/exercises/roman-numerals/roman_numerals_test.py +1 -0
- data/tracks/python/exercises/run-length-encoding/run_length_test.py +1 -0
- data/tracks/python/exercises/say/say_test.py +1 -0
- data/tracks/python/exercises/scrabble-score/scrabble_score_test.py +1 -0
- data/tracks/python/exercises/sieve/sieve_test.py +1 -0
- data/tracks/python/exercises/space-age/space_age_test.py +1 -0
- data/tracks/python/exercises/triangle/triangle_test.py +1 -0
- data/tracks/python/exercises/word-count/word_count_test.py +1 -0
- data/tracks/python/requirements-travis.txt +1 -1
- data/tracks/ruby/docs/24pullrequests.md +21 -0
- data/tracks/ruby/exercises/bowling/.version +1 -1
- data/tracks/ruby/exercises/bowling/bowling_test.rb +44 -15
- data/tracks/ruby/exercises/bowling/example.rb +10 -5
- data/tracks/ruby/exercises/bowling/example.tt +4 -2
- data/tracks/ruby/lib/bowling_cases.rb +1 -1
- data/tracks/scala/exercises/bank-account/HINTS.md +11 -0
- data/tracks/scala/exercises/bank-account/example.scala +2 -4
- data/tracks/scala/exercises/bank-account/src/main/scala/BankAccount.scala +13 -0
- data/tracks/scala/exercises/bank-account/src/test/scala/BankAccountTest.scala +5 -5
- data/tracks/scala/exercises/hamming/HINTS.md +57 -0
- data/tracks/scala/exercises/hello-world/HINTS.md +8 -0
- data/tracks/scala/exercises/nucleotide-count/HINTS.md +61 -0
- metadata +48 -2
@@ -0,0 +1,21 @@
|
|
1
|
+
## 24 Pull Requests for Exercism - Ruby Edition!
|
2
|
+
|
3
|
+
We are welcoming contributors to the project.
|
4
|
+
|
5
|
+
Look for the following labels in our issue list:
|
6
|
+
|
7
|
+
* first-timers only
|
8
|
+
* good first patch
|
9
|
+
* bug
|
10
|
+
* enhancement
|
11
|
+
|
12
|
+
Or notice something to contribute? Documentation not quite up to par?
|
13
|
+
Something missing? Submitting and reviewing exercises on Exercism and
|
14
|
+
notice something you don't like? Create a pull request!
|
15
|
+
|
16
|
+
Or notice something to contribute? Documentation not quite up to par?
|
17
|
+
Something missing? Create a pull request!
|
18
|
+
|
19
|
+
Check out the [Getting Involved in a Track](https://github.com/exercism/exercism.io/blob/master/docs/getting-involved-in-a-track.md) documentation, and some [ideas for things we are looking for](http://exercism.io/languages/ruby/todo) for exercises that are needed to be implemented.
|
20
|
+
|
21
|
+
We are available to answer questions in the [![Join the chat at https://gitter.im/exercism/xruby](https://badges.gitter.im/exercism/xruby.svg)](https://gitter.im/exercism/xruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge).
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3
|
@@ -3,8 +3,8 @@ gem 'minitest', '>= 5.0.0'
|
|
3
3
|
require 'minitest/autorun'
|
4
4
|
require_relative 'bowling'
|
5
5
|
|
6
|
-
# Test data version:
|
7
|
-
#
|
6
|
+
# Test data version: c59c2c4
|
7
|
+
#
|
8
8
|
class BowlingTest < Minitest::Test
|
9
9
|
def setup
|
10
10
|
@game = Game.new
|
@@ -50,7 +50,7 @@ class BowlingTest < Minitest::Test
|
|
50
50
|
assert_equal 17, @game.score
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
53
|
+
def test_a_strike_earns_ten_points_in_a_frame_with_a_single_roll
|
54
54
|
skip
|
55
55
|
roll([10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
56
56
|
assert_equal 10, @game.score
|
@@ -100,7 +100,7 @@ class BowlingTest < Minitest::Test
|
|
100
100
|
|
101
101
|
def test_rolls_can_not_score_negative_points
|
102
102
|
skip
|
103
|
-
assert_raises
|
103
|
+
assert_raises Game::BowlingError do
|
104
104
|
roll([-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
105
105
|
@game.score
|
106
106
|
end
|
@@ -108,7 +108,7 @@ class BowlingTest < Minitest::Test
|
|
108
108
|
|
109
109
|
def test_a_roll_can_not_score_more_than_10_points
|
110
110
|
skip
|
111
|
-
assert_raises
|
111
|
+
assert_raises Game::BowlingError do
|
112
112
|
roll([11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
113
113
|
@game.score
|
114
114
|
end
|
@@ -116,23 +116,53 @@ class BowlingTest < Minitest::Test
|
|
116
116
|
|
117
117
|
def test_two_rolls_in_a_frame_can_not_score_more_than_10_points
|
118
118
|
skip
|
119
|
-
assert_raises
|
119
|
+
assert_raises Game::BowlingError do
|
120
120
|
roll([5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
121
121
|
@game.score
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
+
def test_bonus_roll_after_a_strike_in_the_last_frame_can_not_score_more_than_10_points
|
126
|
+
skip
|
127
|
+
assert_raises Game::BowlingError do
|
128
|
+
roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11])
|
129
|
+
@game.score
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
125
133
|
def test_two_bonus_rolls_after_a_strike_in_the_last_frame_can_not_score_more_than_10_points
|
126
134
|
skip
|
127
|
-
assert_raises
|
135
|
+
assert_raises Game::BowlingError do
|
128
136
|
roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6])
|
129
137
|
@game.score
|
130
138
|
end
|
131
139
|
end
|
132
140
|
|
141
|
+
def test_two_bonus_rolls_after_a_strike_in_the_last_frame_can_score_more_than_10_points_if_one_is_a_strike
|
142
|
+
skip
|
143
|
+
roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 6])
|
144
|
+
assert_equal 26, @game.score
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_the_second_bonus_rolls_after_a_strike_in_the_last_frame_can_not_be_a_strike_if_the_first_one_is_not_a_strike
|
148
|
+
skip
|
149
|
+
assert_raises Game::BowlingError do
|
150
|
+
roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6, 10])
|
151
|
+
@game.score
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_second_bonus_roll_after_a_strike_in_the_last_frame_can_not_score_than_10_points
|
156
|
+
skip
|
157
|
+
assert_raises Game::BowlingError do
|
158
|
+
roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 11])
|
159
|
+
@game.score
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
133
163
|
def test_an_unstarted_game_can_not_be_scored
|
134
164
|
skip
|
135
|
-
assert_raises
|
165
|
+
assert_raises Game::BowlingError do
|
136
166
|
roll([])
|
137
167
|
@game.score
|
138
168
|
end
|
@@ -140,7 +170,7 @@ class BowlingTest < Minitest::Test
|
|
140
170
|
|
141
171
|
def test_an_incomplete_game_can_not_be_scored
|
142
172
|
skip
|
143
|
-
assert_raises
|
173
|
+
assert_raises Game::BowlingError do
|
144
174
|
roll([0, 0])
|
145
175
|
@game.score
|
146
176
|
end
|
@@ -148,7 +178,7 @@ class BowlingTest < Minitest::Test
|
|
148
178
|
|
149
179
|
def test_a_game_with_more_than_ten_frames_can_not_be_scored
|
150
180
|
skip
|
151
|
-
assert_raises
|
181
|
+
assert_raises Game::BowlingError do
|
152
182
|
roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
153
183
|
@game.score
|
154
184
|
end
|
@@ -156,7 +186,7 @@ class BowlingTest < Minitest::Test
|
|
156
186
|
|
157
187
|
def test_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
|
158
188
|
skip
|
159
|
-
assert_raises
|
189
|
+
assert_raises Game::BowlingError do
|
160
190
|
roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10])
|
161
191
|
@game.score
|
162
192
|
end
|
@@ -164,7 +194,7 @@ class BowlingTest < Minitest::Test
|
|
164
194
|
|
165
195
|
def test_both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
|
166
196
|
skip
|
167
|
-
assert_raises
|
197
|
+
assert_raises Game::BowlingError do
|
168
198
|
roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10])
|
169
199
|
@game.score
|
170
200
|
end
|
@@ -172,7 +202,7 @@ class BowlingTest < Minitest::Test
|
|
172
202
|
|
173
203
|
def test_bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
|
174
204
|
skip
|
175
|
-
assert_raises
|
205
|
+
assert_raises Game::BowlingError do
|
176
206
|
roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3])
|
177
207
|
@game.score
|
178
208
|
end
|
@@ -194,9 +224,8 @@ class BowlingTest < Minitest::Test
|
|
194
224
|
#
|
195
225
|
# If you are curious, read more about constants on RubyDoc:
|
196
226
|
# http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html
|
197
|
-
|
198
227
|
def test_bookkeeping
|
199
228
|
skip
|
200
|
-
assert_equal
|
229
|
+
assert_equal 3, BookKeeping::VERSION
|
201
230
|
end
|
202
231
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
module BookKeeping
|
2
|
-
VERSION =
|
2
|
+
VERSION = 3
|
3
3
|
end
|
4
4
|
|
5
5
|
class Game
|
6
6
|
PINS = { MIN: 0, MAX: 10 }.freeze
|
7
7
|
at_exit { public :roll, :score }
|
8
8
|
|
9
|
+
|
10
|
+
class BowlingError < StandardError; end
|
11
|
+
class RollError < BowlingError; end
|
12
|
+
class GameError < BowlingError; end
|
13
|
+
|
9
14
|
private
|
10
15
|
|
11
16
|
def initialize
|
@@ -20,9 +25,9 @@ class Game
|
|
20
25
|
end
|
21
26
|
|
22
27
|
def validate(pins)
|
23
|
-
raise
|
24
|
-
raise
|
25
|
-
raise
|
28
|
+
raise RollError, 'Invalid number of pins' unless (PINS[:MIN]..PINS[:MAX]).cover?(pins)
|
29
|
+
raise RollError, 'Too many pins in frame' unless valid_frame?(pins)
|
30
|
+
raise GameError, 'Game is over, no rolls allowed' if game_complete?
|
26
31
|
end
|
27
32
|
|
28
33
|
def valid_frame?(pins)
|
@@ -33,7 +38,7 @@ class Game
|
|
33
38
|
end
|
34
39
|
|
35
40
|
def score
|
36
|
-
raise
|
41
|
+
raise GameError, 'Score unavailable until end of the game' unless game_complete?
|
37
42
|
@score_card.values.map.with_index(1) do |f, i|
|
38
43
|
score_frame(f, i)
|
39
44
|
end.reduce(:+)
|
@@ -3,8 +3,8 @@ gem 'minitest', '>= 5.0.0'
|
|
3
3
|
require 'minitest/autorun'
|
4
4
|
require_relative 'bowling'
|
5
5
|
|
6
|
-
# Test data version:
|
7
|
-
#
|
6
|
+
# Test data version: <%= sha1 %>
|
7
|
+
#
|
8
8
|
class BowlingTest < Minitest::Test
|
9
9
|
def setup
|
10
10
|
@game = Game.new
|
@@ -13,11 +13,13 @@ class BowlingTest < Minitest::Test
|
|
13
13
|
def roll(rolls)
|
14
14
|
rolls.each { |pins| @game.roll(pins) }
|
15
15
|
end
|
16
|
+
|
16
17
|
<% test_cases.each do |test_case| %>
|
17
18
|
def <%= test_case.test_name %>
|
18
19
|
<%= test_case.skipped %>
|
19
20
|
<%= test_case.work_load %>
|
20
21
|
end
|
22
|
+
|
21
23
|
<% end %>
|
22
24
|
<%= IO.read(XRUBY_LIB + '/bookkeeping.md') %>
|
23
25
|
def test_bookkeeping
|
@@ -0,0 +1,11 @@
|
|
1
|
+
## Hints
|
2
|
+
|
3
|
+
This exercise is testing mutable state that can be accessed saftely from multiple threads. Scala provides a variety of ways to protect
|
4
|
+
mutable state. For developers familiar with Java concurrency, Scala can utilize the Java concurrency support such as the Java synchronized block.
|
5
|
+
|
6
|
+
### Common Pitfalls
|
7
|
+
|
8
|
+
In Scala there are two ways to achieve mutable state: Use a "var" or a mutable object.
|
9
|
+
Two common mistakes here are:
|
10
|
+
- Do not use a "var" that is also a mutable object. One is enough, but not both together.
|
11
|
+
- Don't expose the "var" or mutable object to the outside world. So make them "private" and change the mutable object into immutable before you return it as a value.
|
@@ -3,12 +3,12 @@ import org.scalatest.{Matchers, FunSuite}
|
|
3
3
|
|
4
4
|
class BankAccountTest extends FunSuite with Matchers with Conductors with IntegrationPatience {
|
5
5
|
test("open account") {
|
6
|
-
|
6
|
+
Bank.openAccount().getBalance should be (Some(0))
|
7
7
|
}
|
8
8
|
|
9
9
|
test("incrementing and checking balance") {
|
10
10
|
pending
|
11
|
-
val acct =
|
11
|
+
val acct = Bank.openAccount()
|
12
12
|
acct.getBalance should be (Some(0))
|
13
13
|
acct.incrementBalance(10) should be (Some(10))
|
14
14
|
acct.getBalance should be (Some(10))
|
@@ -18,7 +18,7 @@ class BankAccountTest extends FunSuite with Matchers with Conductors with Integr
|
|
18
18
|
|
19
19
|
test("closed account should hold no balance") {
|
20
20
|
pending
|
21
|
-
val acct =
|
21
|
+
val acct = Bank.openAccount()
|
22
22
|
acct.closeAccount()
|
23
23
|
acct.incrementBalance(10)
|
24
24
|
acct.incrementBalance(10)
|
@@ -30,7 +30,7 @@ class BankAccountTest extends FunSuite with Matchers with Conductors with Integr
|
|
30
30
|
val conductor = new Conductor
|
31
31
|
import conductor._
|
32
32
|
|
33
|
-
val acct =
|
33
|
+
val acct = Bank.openAccount()
|
34
34
|
|
35
35
|
thread("t1") {
|
36
36
|
acct.incrementBalance(10)
|
@@ -54,7 +54,7 @@ class BankAccountTest extends FunSuite with Matchers with Conductors with Integr
|
|
54
54
|
val conductor = new Conductor
|
55
55
|
import conductor._
|
56
56
|
|
57
|
-
val acct =
|
57
|
+
val acct = Bank.openAccount()
|
58
58
|
|
59
59
|
thread("t1") {
|
60
60
|
for (a <- 1 to 10)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
## Hints
|
2
|
+
`Option` is used to indicate a computation that may possibly have no useful result
|
3
|
+
(for example due to an error or invalid input).
|
4
|
+
If you are unfamiliar with `Option` you may read [this tutorial](http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html).
|
5
|
+
`Option` is a so-called [Monad](https://en.wikipedia.org/wiki/Monad_(functional_programming)) which covers a "computational aspect", in this case possible absence of a value.
|
6
|
+
Proper use of Monads can result in very concise yet elegant
|
7
|
+
and readable code. Improper use can easily result in the contrary.
|
8
|
+
Watch [this video](https://www.youtube.com/watch?v=Mw_Jnn_Y5iA) to learn more.
|
9
|
+
#### Common pitfalls that you should avoid
|
10
|
+
There are a few rules of thumbs for `Option`:
|
11
|
+
1. If you don't need it don't use it. Instead of
|
12
|
+
```scala
|
13
|
+
def add1(x: Int): Option[Int] = Some(x + 1)
|
14
|
+
```
|
15
|
+
better have
|
16
|
+
```scala
|
17
|
+
def add1(x: Int): Int = x + 1
|
18
|
+
```
|
19
|
+
(there is `Option.map` to apply such simple functions,
|
20
|
+
so you don't have to clutter them with `Option`).
|
21
|
+
2. Don't "unwrap" if you don't really need to.
|
22
|
+
Often there are built-in functions for your purpose. Indicators of premature
|
23
|
+
unwrapping are `isDefined/isEmpty` or pattern matching. Instead of
|
24
|
+
```scala
|
25
|
+
val x: Option[Int] = ...
|
26
|
+
|
27
|
+
if (x.isDefined) x.get + 1 else 0
|
28
|
+
// or
|
29
|
+
x match {
|
30
|
+
case Some(n) => n + 1
|
31
|
+
case None => 0
|
32
|
+
}
|
33
|
+
```
|
34
|
+
better have
|
35
|
+
```scala
|
36
|
+
x map (_ + 1) getOrElse 0
|
37
|
+
```
|
38
|
+
3. Monads can be used inside a for-comprehension FTW.
|
39
|
+
This is advisable when you want to "compose" several `Option` instances. Instead of
|
40
|
+
```scala
|
41
|
+
val xo: Option[Int] = ...
|
42
|
+
val yo: Option[Int] = ...
|
43
|
+
val zo: Option[Int] = ...
|
44
|
+
|
45
|
+
xo.flatMap(x =>
|
46
|
+
yo.flatMap(y =>
|
47
|
+
zo.map(z =>
|
48
|
+
x + y + z)))
|
49
|
+
```
|
50
|
+
better have
|
51
|
+
```scala
|
52
|
+
for {
|
53
|
+
x <- xo
|
54
|
+
y <- yo
|
55
|
+
z <- zo
|
56
|
+
} yield x + y + z
|
57
|
+
```
|