trackler 2.2.1.179 → 2.2.1.180
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/yacht/description.md +14 -13
- data/tracks/ballerina/config.json +1 -0
- data/tracks/coffeescript/config.json +138 -41
- data/tracks/coffeescript/docs/ABOUT.md +3 -7
- data/tracks/coq/config.json +1 -0
- data/tracks/d/config.json +1 -0
- data/tracks/dart/config.json +1 -0
- data/tracks/elixir/config.json +17 -16
- data/tracks/elixir/docs/ABOUT.md +10 -2
- data/tracks/fortran/config.json +1 -0
- data/tracks/gnu-apl/config.json +1 -0
- data/tracks/go/config.json +13 -0
- data/tracks/go/exercises/list-ops/README.md +27 -0
- data/tracks/go/exercises/list-ops/example.go +99 -0
- data/tracks/go/exercises/list-ops/listops_test.go +291 -0
- data/tracks/groovy/config.json +1 -0
- data/tracks/haxe/config.json +1 -0
- data/tracks/perl5/exercises/leap/.meta/exercise-data.yaml +3 -5
- data/tracks/perl5/exercises/leap/.meta/solutions/Leap.pm +2 -4
- data/tracks/perl5/exercises/leap/Leap.pm +1 -1
- data/tracks/perl5/exercises/leap/leap.t +2 -2
- data/tracks/php/config.json +1 -0
- data/tracks/plsql/config.json +1 -0
- data/tracks/pony/config.json +1 -0
- data/tracks/purescript/config.json +1 -0
- data/tracks/reasonml/config/exercise_readme.go.tmpl +18 -2
- data/tracks/reasonml/exercises/anagram/README.md +15 -4
- data/tracks/reasonml/exercises/armstrong-numbers/README.md +3 -4
- data/tracks/reasonml/exercises/binary-search/README.md +14 -7
- data/tracks/reasonml/exercises/bob/README.md +14 -6
- data/tracks/reasonml/exercises/change/README.md +2 -4
- data/tracks/reasonml/exercises/hello-world/README.md +2 -3
- data/tracks/reasonml/exercises/isogram/README.md +4 -6
- data/tracks/reasonml/exercises/leap/README.md +14 -4
- data/tracks/reasonml/exercises/pangram/README.md +13 -3
- data/tracks/reasonml/exercises/phone-number/README.md +15 -7
- data/tracks/reasonml/exercises/raindrops/README.md +14 -7
- data/tracks/reasonml/exercises/rna-transcription/README.md +13 -3
- data/tracks/reasonml/exercises/roman-numerals/README.md +4 -8
- data/tracks/reasonml/exercises/run-length-encoding/README.md +14 -7
- data/tracks/reasonml/exercises/space-age/README.md +13 -3
- data/tracks/reasonml/exercises/word-count/README.md +18 -8
- data/tracks/rust/.travis.yml +1 -0
- data/tracks/rust/_test/check-exercises-for-authors.sh +10 -0
- data/tracks/rust/bin/format_exercises +2 -0
- data/tracks/rust/exercises/accumulate/Cargo.toml +0 -1
- data/tracks/rust/exercises/accumulate/example.rs +4 -1
- data/tracks/rust/exercises/acronym/example.rs +6 -5
- data/tracks/rust/exercises/acronym/tests/acronym.rs +1 -1
- data/tracks/rust/exercises/all-your-base/example.rs +8 -2
- data/tracks/rust/exercises/allergies/example.rs +28 -6
- data/tracks/rust/exercises/alphametics/example.rs +18 -10
- data/tracks/rust/exercises/anagram/example.rs +8 -4
- data/tracks/rust/exercises/atbash-cipher/example.rs +15 -15
- data/tracks/rust/exercises/beer-song/example.rs +18 -12
- data/tracks/rust/exercises/binary-search/Cargo.toml +0 -1
- data/tracks/rust/exercises/binary-search/example.rs +3 -4
- data/tracks/rust/exercises/bob/example.rs +11 -5
- data/tracks/rust/exercises/book-store/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/book-store/Cargo.toml +0 -1
- data/tracks/rust/exercises/book-store/example.rs +15 -19
- data/tracks/rust/exercises/bowling/example.rs +3 -1
- data/tracks/rust/exercises/bracket-push/example.rs +7 -2
- data/tracks/rust/exercises/circular-buffer/example.rs +1 -1
- data/tracks/rust/exercises/clock/.meta/ALLOWED_TO_NOT_COMPILE +3 -0
- data/tracks/rust/exercises/clock/Cargo.toml +0 -1
- data/tracks/rust/exercises/clock/example.rs +5 -3
- data/tracks/rust/exercises/clock/src/lib.rs +14 -0
- data/tracks/rust/exercises/collatz-conjecture/example.rs +2 -2
- data/tracks/rust/exercises/crypto-square/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/crypto-square/Cargo.toml +0 -1
- data/tracks/rust/exercises/custom-set/example.rs +17 -15
- data/tracks/rust/exercises/decimal/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/decimal/Cargo.toml +0 -1
- data/tracks/rust/exercises/decimal/example.rs +5 -5
- data/tracks/rust/exercises/diamond/Cargo.toml +0 -1
- data/tracks/rust/exercises/difference-of-squares/example.rs +1 -1
- data/tracks/rust/exercises/dominoes/example.rs +20 -19
- data/tracks/rust/exercises/etl/example.rs +4 -3
- data/tracks/rust/exercises/forth/example.rs +29 -45
- data/tracks/rust/exercises/grade-school/example.rs +4 -2
- data/tracks/rust/exercises/hexadecimal/example.rs +2 -4
- data/tracks/rust/exercises/isbn-verifier/example.rs +5 -6
- data/tracks/rust/exercises/isbn-verifier/tests/isbn-verifier.rs +12 -0
- data/tracks/rust/exercises/isogram/example.rs +9 -3
- data/tracks/rust/exercises/largest-series-product/example.rs +2 -1
- data/tracks/rust/exercises/luhn-from/example.rs +3 -1
- data/tracks/rust/exercises/luhn/example.rs +5 -3
- data/tracks/rust/exercises/macros/Cargo.toml +0 -1
- data/tracks/rust/exercises/nth-prime/Cargo.toml +0 -1
- data/tracks/rust/exercises/nth-prime/example.rs +6 -6
- data/tracks/rust/exercises/nucleotide-codons/Cargo.toml +0 -1
- data/tracks/rust/exercises/nucleotide-codons/example.rs +23 -17
- data/tracks/rust/exercises/nucleotide-count/example.rs +15 -5
- data/tracks/rust/exercises/nucleotide-count/src/lib.rs +15 -0
- data/tracks/rust/exercises/nucleotide-count/tests/nucleotide-count.rs +3 -3
- data/tracks/rust/exercises/palindrome-products/Cargo.toml +0 -1
- data/tracks/rust/exercises/pangram/example.rs +6 -6
- data/tracks/rust/exercises/parallel-letter-frequency/example.rs +7 -4
- data/tracks/rust/exercises/pascals-triangle/example.rs +6 -2
- data/tracks/rust/exercises/perfect-numbers/example.rs +2 -2
- data/tracks/rust/exercises/phone-number/example.rs +11 -15
- data/tracks/rust/exercises/pig-latin/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/pig-latin/Cargo.toml +0 -1
- data/tracks/rust/exercises/pig-latin/example.rs +6 -2
- data/tracks/rust/exercises/poker/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/poker/Cargo.toml +0 -1
- data/tracks/rust/exercises/poker/example.rs +9 -8
- data/tracks/rust/exercises/prime-factors/Cargo.toml +0 -1
- data/tracks/rust/exercises/prime-factors/example.rs +1 -1
- data/tracks/rust/exercises/protein-translation/Cargo.toml +0 -1
- data/tracks/rust/exercises/protein-translation/example.rs +6 -5
- data/tracks/rust/exercises/proverb/Cargo.toml +0 -1
- data/tracks/rust/exercises/proverb/example.rs +0 -1
- data/tracks/rust/exercises/pythagorean-triplet/Cargo.toml +0 -1
- data/tracks/rust/exercises/pythagorean-triplet/example.rs +3 -3
- data/tracks/rust/exercises/queen-attack/example.rs +3 -3
- data/tracks/rust/exercises/react/example.rs +61 -29
- data/tracks/rust/exercises/reverse-string/Cargo.toml +0 -1
- data/tracks/rust/exercises/rna-transcription/example.rs +17 -9
- data/tracks/rust/exercises/robot-name/example.rs +4 -3
- data/tracks/rust/exercises/robot-simulator/example.rs +5 -2
- data/tracks/rust/exercises/roman-numerals/example.rs +15 -14
- data/tracks/rust/exercises/rotational-cipher/Cargo.toml +0 -1
- data/tracks/rust/exercises/rotational-cipher/example.rs +10 -14
- data/tracks/rust/exercises/rotational-cipher/src/lib.rs +7 -1
- data/tracks/rust/exercises/run-length-encoding/Cargo.toml +0 -1
- data/tracks/rust/exercises/run-length-encoding/example.rs +34 -29
- data/tracks/rust/exercises/saddle-points/example.rs +0 -1
- data/tracks/rust/exercises/say/Cargo.toml +0 -1
- data/tracks/rust/exercises/say/example.rs +34 -8
- data/tracks/rust/exercises/series/example.rs +6 -8
- data/tracks/rust/exercises/simple-linked-list/example.rs +0 -2
- data/tracks/rust/exercises/spiral-matrix/example.rs +0 -1
- data/tracks/rust/exercises/tournament/example.rs +33 -20
- data/tracks/rust/exercises/triangle/example.rs +1 -1
- data/tracks/rust/exercises/two-bucket/example.rs +2 -6
- data/tracks/rust/exercises/two-fer/example.rs +3 -3
- data/tracks/rust/exercises/variable-length-quantity/example.rs +2 -3
- data/tracks/rust/exercises/word-count/example.rs +4 -1
- data/tracks/rust/exercises/wordy/example.rs +10 -4
- metadata +7 -2
@@ -2,12 +2,12 @@ use std::collections::BTreeSet;
|
|
2
2
|
use std::iter::FromIterator;
|
3
3
|
|
4
4
|
pub fn is_pangram(sentence: &str) -> bool {
|
5
|
-
sentence
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
sentence
|
6
|
+
.to_lowercase()
|
7
|
+
.chars()
|
8
|
+
.filter(|c| c.is_alphabetic())
|
9
|
+
.filter(|c| c.is_ascii())
|
10
|
+
.collect::<BTreeSet<char>>() == english_letter_set()
|
11
11
|
}
|
12
12
|
|
13
13
|
fn english_letter_set() -> BTreeSet<char> {
|
@@ -1,7 +1,6 @@
|
|
1
1
|
use std::collections::HashMap;
|
2
|
-
use std::thread;
|
3
2
|
use std::sync::mpsc::channel;
|
4
|
-
|
3
|
+
use std::thread;
|
5
4
|
|
6
5
|
/// Compute the frequency of each letter (technically of each unicode codepoint) using the given
|
7
6
|
/// number of worker threads.
|
@@ -9,9 +8,13 @@ pub fn frequency(texts: &[&str], num_workers: usize) -> HashMap<char, usize> {
|
|
9
8
|
assert!(num_workers > 0);
|
10
9
|
let part_size_floor = texts.len() / num_workers;
|
11
10
|
let rem = texts.len() % num_workers;
|
12
|
-
let part_size = if rem > 0 {
|
11
|
+
let part_size = if rem > 0 {
|
12
|
+
part_size_floor + 1
|
13
|
+
} else {
|
14
|
+
part_size_floor
|
15
|
+
};
|
13
16
|
let mut parts: Vec<Vec<String>> = Vec::with_capacity(part_size);
|
14
|
-
for _ in 0
|
17
|
+
for _ in 0..num_workers {
|
15
18
|
parts.push(Vec::with_capacity(part_size));
|
16
19
|
}
|
17
20
|
let mut i = 0;
|
@@ -4,11 +4,15 @@ pub struct PascalsTriangle {
|
|
4
4
|
|
5
5
|
impl PascalsTriangle {
|
6
6
|
pub fn new(row_count: u32) -> Self {
|
7
|
-
PascalsTriangle {
|
7
|
+
PascalsTriangle {
|
8
|
+
row_count: row_count,
|
9
|
+
}
|
8
10
|
}
|
9
11
|
|
10
12
|
pub fn rows(&self) -> Vec<Vec<u32>> {
|
11
|
-
(0..self.row_count)
|
13
|
+
(0..self.row_count)
|
14
|
+
.map(|row| PascalsTriangle::row(row))
|
15
|
+
.collect()
|
12
16
|
}
|
13
17
|
|
14
18
|
pub fn row(number: u32) -> Vec<u32> {
|
@@ -2,7 +2,7 @@ pub fn classify(num: u64) -> Option<Classification> {
|
|
2
2
|
if num == 0 {
|
3
3
|
return None;
|
4
4
|
}
|
5
|
-
let sum: u64 = (1..num).filter(|i| num%i == 0).sum();
|
5
|
+
let sum: u64 = (1..num).filter(|i| num % i == 0).sum();
|
6
6
|
if sum == num {
|
7
7
|
Some(Classification::Perfect)
|
8
8
|
} else if sum < num {
|
@@ -16,5 +16,5 @@ pub fn classify(num: u64) -> Option<Classification> {
|
|
16
16
|
pub enum Classification {
|
17
17
|
Abundant,
|
18
18
|
Perfect,
|
19
|
-
Deficient
|
19
|
+
Deficient,
|
20
20
|
}
|
@@ -1,21 +1,17 @@
|
|
1
1
|
pub fn number(s: &str) -> Option<String> {
|
2
2
|
let digits: String = s.chars().filter(|&c| c.is_digit(10)).collect();
|
3
3
|
match digits.len() {
|
4
|
-
10 => {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Some('1') => Some(digits[1..].to_string()),
|
16
|
-
_ => None,
|
17
|
-
}
|
18
|
-
}
|
4
|
+
10 => match (digits.chars().nth(0), digits.chars().nth(3)) {
|
5
|
+
(Some('0'), _) => None,
|
6
|
+
(Some('1'), _) => None,
|
7
|
+
(_, Some('0')) => None,
|
8
|
+
(_, Some('1')) => None,
|
9
|
+
_ => Some(digits),
|
10
|
+
},
|
11
|
+
11 => match digits.chars().nth(0) {
|
12
|
+
Some('1') => Some(digits[1..].to_string()),
|
13
|
+
_ => None,
|
14
|
+
},
|
19
15
|
_ => None,
|
20
16
|
}
|
21
17
|
}
|
@@ -1,4 +1,5 @@
|
|
1
|
-
#[macro_use]
|
1
|
+
#[macro_use]
|
2
|
+
extern crate lazy_static;
|
2
3
|
extern crate regex;
|
3
4
|
|
4
5
|
use regex::Regex;
|
@@ -24,5 +25,8 @@ pub fn translate_word(word: &str) -> String {
|
|
24
25
|
}
|
25
26
|
|
26
27
|
pub fn translate(text: &str) -> String {
|
27
|
-
text.split(" ")
|
28
|
+
text.split(" ")
|
29
|
+
.map(|w| translate_word(w))
|
30
|
+
.collect::<Vec<_>>()
|
31
|
+
.join(" ")
|
28
32
|
}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
use std::fmt;
|
2
1
|
use std::cmp::Ordering;
|
2
|
+
use std::fmt;
|
3
3
|
|
4
4
|
#[macro_use]
|
5
5
|
extern crate try_opt;
|
@@ -181,8 +181,8 @@ impl PokerHand {
|
|
181
181
|
fn is_ace_low_straight(cards: &[Card]) -> bool {
|
182
182
|
// special case: ace-low straight
|
183
183
|
// still depends on the sorted precondition
|
184
|
-
cards[0].rank.value() == 2 && cards[4].rank == Rank::Ace
|
185
|
-
cards
|
184
|
+
cards[0].rank.value() == 2 && cards[4].rank == Rank::Ace
|
185
|
+
&& cards
|
186
186
|
.windows(2)
|
187
187
|
.take(3) // (0, 1), (1, 2), (2, 3) --> skips 4, ace
|
188
188
|
.map(|pair| pair[1].rank.value() - pair[0].rank.value())
|
@@ -201,8 +201,8 @@ impl PokerHand {
|
|
201
201
|
let is_straight = cards
|
202
202
|
.windows(2)
|
203
203
|
.map(|pair| pair[1].rank.value() - pair[0].rank.value())
|
204
|
-
.all(|diff| diff == 1)
|
205
|
-
PokerHand::is_ace_low_straight(cards);
|
204
|
+
.all(|diff| diff == 1)
|
205
|
+
|| PokerHand::is_ace_low_straight(cards);
|
206
206
|
|
207
207
|
if is_flush && is_straight {
|
208
208
|
return Some(PokerHand::StraightFlush);
|
@@ -269,9 +269,10 @@ impl<'a> Hand<'a> {
|
|
269
269
|
}
|
270
270
|
|
271
271
|
fn cmp_high_card(&self, other: &Hand, card: usize) -> Ordering {
|
272
|
-
let mut ordering = self.cards[card]
|
273
|
-
|
274
|
-
|
272
|
+
let mut ordering = self.cards[card]
|
273
|
+
.rank
|
274
|
+
.value()
|
275
|
+
.cmp(&other.cards[card].rank.value());
|
275
276
|
if card != 0 {
|
276
277
|
ordering = ordering.then_with(|| self.cmp_high_card(other, card - 1));
|
277
278
|
}
|
@@ -1,12 +1,12 @@
|
|
1
1
|
use std::collections::HashMap;
|
2
2
|
|
3
3
|
pub struct CodonInfo<'a> {
|
4
|
-
actual_codons: HashMap<&'a str, &'a str
|
4
|
+
actual_codons: HashMap<&'a str, &'a str>,
|
5
5
|
}
|
6
6
|
|
7
7
|
pub fn parse<'a>(pairs: Vec<(&'a str, &'a str)>) -> CodonInfo<'a> {
|
8
|
-
CodonInfo{
|
9
|
-
actual_codons: pairs.into_iter().collect()
|
8
|
+
CodonInfo {
|
9
|
+
actual_codons: pairs.into_iter().collect(),
|
10
10
|
}
|
11
11
|
}
|
12
12
|
|
@@ -14,12 +14,13 @@ impl<'a> CodonInfo<'a> {
|
|
14
14
|
pub fn name_for(&self, codon: &str) -> Result<&'a str, &'static str> {
|
15
15
|
match self.actual_codons.get(&codon) {
|
16
16
|
Some(name) => Ok(name),
|
17
|
-
None => Err("Invalid")
|
17
|
+
None => Err("Invalid"),
|
18
18
|
}
|
19
19
|
}
|
20
20
|
|
21
21
|
pub fn of_rna(&self, strand: &str) -> Result<Vec<&'a str>, &'static str> {
|
22
|
-
strand
|
22
|
+
strand
|
23
|
+
.chars()
|
23
24
|
.collect::<Vec<char>>()
|
24
25
|
.chunks(3)
|
25
26
|
.map(|chars| self.name_for(&chars.iter().collect::<String>()))
|
@@ -12,9 +12,9 @@ impl ChessPiece for Queen {
|
|
12
12
|
}
|
13
13
|
|
14
14
|
fn can_attack<T: ChessPiece>(&self, piece: &T) -> bool {
|
15
|
-
self.position.horizontal_from(&piece.position())
|
16
|
-
|
17
|
-
|
15
|
+
self.position.horizontal_from(&piece.position())
|
16
|
+
|| self.position.vertical_from(&piece.position())
|
17
|
+
|| self.position.diagonal_from(&piece.position())
|
18
18
|
}
|
19
19
|
}
|
20
20
|
|
@@ -49,7 +49,7 @@ struct ComputeCell<'a, T: Copy> {
|
|
49
49
|
callbacks: HashMap<CallbackID, Box<FnMut(T) -> () + 'a>>,
|
50
50
|
}
|
51
51
|
|
52
|
-
impl
|
52
|
+
impl<T: Copy> Cell<T> {
|
53
53
|
fn new(initial: T) -> Self {
|
54
54
|
Cell {
|
55
55
|
value: initial,
|
@@ -59,7 +59,7 @@ impl <T: Copy> Cell<T> {
|
|
59
59
|
}
|
60
60
|
}
|
61
61
|
|
62
|
-
impl
|
62
|
+
impl<'a, T: Copy> ComputeCell<'a, T> {
|
63
63
|
fn new<F: Fn(&[T]) -> T + 'a>(initial: T, dependencies: Vec<CellID>, f: F) -> Self {
|
64
64
|
ComputeCell {
|
65
65
|
cell: Cell::new(initial),
|
@@ -77,9 +77,9 @@ pub struct Reactor<'a, T: Copy> {
|
|
77
77
|
computes: Vec<ComputeCell<'a, T>>,
|
78
78
|
}
|
79
79
|
|
80
|
-
impl
|
80
|
+
impl<'a, T: Copy + PartialEq> Reactor<'a, T> {
|
81
81
|
pub fn new() -> Self {
|
82
|
-
Reactor{
|
82
|
+
Reactor {
|
83
83
|
inputs: Vec::new(),
|
84
84
|
computes: Vec::new(),
|
85
85
|
}
|
@@ -90,25 +90,42 @@ impl <'a, T: Copy + PartialEq> Reactor<'a, T> {
|
|
90
90
|
InputCellID(self.inputs.len() - 1)
|
91
91
|
}
|
92
92
|
|
93
|
-
pub fn create_compute<F: Fn(&[T]) -> T + 'a>(
|
93
|
+
pub fn create_compute<F: Fn(&[T]) -> T + 'a>(
|
94
|
+
&mut self,
|
95
|
+
dependencies: &[CellID],
|
96
|
+
compute_func: F,
|
97
|
+
) -> Result<ComputeCellID, CellID> {
|
94
98
|
// Check all dependencies' validity before modifying any of them,
|
95
99
|
// so that we don't perform an incorrect partial write.
|
96
100
|
for &dep in dependencies {
|
97
101
|
match dep {
|
98
|
-
CellID::Input(InputCellID(id)) => if id >= self.inputs.len() {
|
99
|
-
|
102
|
+
CellID::Input(InputCellID(id)) => if id >= self.inputs.len() {
|
103
|
+
return Err(dep);
|
104
|
+
},
|
105
|
+
CellID::Compute(ComputeCellID(id)) => if id >= self.computes.len() {
|
106
|
+
return Err(dep);
|
107
|
+
},
|
100
108
|
}
|
101
109
|
}
|
102
110
|
let new_id = ComputeCellID(self.computes.len());
|
103
111
|
for &dep in dependencies {
|
104
112
|
match dep {
|
105
113
|
CellID::Input(InputCellID(id)) => self.inputs[id].dependents.push(new_id),
|
106
|
-
CellID::Compute(ComputeCellID(id)) =>
|
114
|
+
CellID::Compute(ComputeCellID(id)) => {
|
115
|
+
self.computes[id].cell.dependents.push(new_id)
|
116
|
+
}
|
107
117
|
}
|
108
118
|
}
|
109
|
-
let inputs: Vec<_> = dependencies
|
119
|
+
let inputs: Vec<_> = dependencies
|
120
|
+
.iter()
|
121
|
+
.map(|&id| self.value(id).unwrap())
|
122
|
+
.collect();
|
110
123
|
let initial = compute_func(&inputs);
|
111
|
-
self.computes.push(ComputeCell::new(
|
124
|
+
self.computes.push(ComputeCell::new(
|
125
|
+
initial,
|
126
|
+
dependencies.to_vec(),
|
127
|
+
compute_func,
|
128
|
+
));
|
112
129
|
Ok(new_id)
|
113
130
|
}
|
114
131
|
|
@@ -121,22 +138,30 @@ impl <'a, T: Copy + PartialEq> Reactor<'a, T> {
|
|
121
138
|
|
122
139
|
pub fn set_value(&mut self, id: InputCellID, new_value: T) -> bool {
|
123
140
|
let InputCellID(id) = id;
|
124
|
-
self.inputs
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
141
|
+
self.inputs
|
142
|
+
.get_mut(id)
|
143
|
+
.map(|c| {
|
144
|
+
c.value = new_value;
|
145
|
+
c.dependents.clone()
|
146
|
+
})
|
147
|
+
.map(|deps| {
|
148
|
+
for &d in deps.iter() {
|
149
|
+
self.update_dependent(d);
|
150
|
+
}
|
151
|
+
// We can only fire callbacks after all dependents have updated.
|
152
|
+
// So we can't combine this for loop with the one above!
|
153
|
+
for d in deps {
|
154
|
+
self.fire_callbacks(d);
|
155
|
+
}
|
156
|
+
})
|
157
|
+
.is_some()
|
137
158
|
}
|
138
159
|
|
139
|
-
pub fn add_callback<F: FnMut(T) -> () + 'a>(
|
160
|
+
pub fn add_callback<F: FnMut(T) -> () + 'a>(
|
161
|
+
&mut self,
|
162
|
+
id: ComputeCellID,
|
163
|
+
callback: F,
|
164
|
+
) -> Option<CallbackID> {
|
140
165
|
let ComputeCellID(id) = id;
|
141
166
|
self.computes.get_mut(id).map(|c| {
|
142
167
|
c.callbacks_issued += 1;
|
@@ -146,7 +171,11 @@ impl <'a, T: Copy + PartialEq> Reactor<'a, T> {
|
|
146
171
|
})
|
147
172
|
}
|
148
173
|
|
149
|
-
pub fn remove_callback(
|
174
|
+
pub fn remove_callback(
|
175
|
+
&mut self,
|
176
|
+
cell: ComputeCellID,
|
177
|
+
callback: CallbackID,
|
178
|
+
) -> Result<(), RemoveCallbackError> {
|
150
179
|
let ComputeCellID(cell) = cell;
|
151
180
|
match self.computes.get_mut(cell) {
|
152
181
|
Some(c) => match c.callbacks.remove(&callback) {
|
@@ -167,7 +196,10 @@ impl <'a, T: Copy + PartialEq> Reactor<'a, T> {
|
|
167
196
|
Some(c) => (&c.dependencies, &c.f, c.cell.dependents.clone()),
|
168
197
|
None => panic!("Cell to update disappeared while querying"),
|
169
198
|
};
|
170
|
-
let inputs: Vec<_> = dependencies
|
199
|
+
let inputs: Vec<_> = dependencies
|
200
|
+
.iter()
|
201
|
+
.map(|&id| self.value(id).unwrap())
|
202
|
+
.collect();
|
171
203
|
(f(&inputs), dependents)
|
172
204
|
};
|
173
205
|
|
@@ -179,7 +211,7 @@ impl <'a, T: Copy + PartialEq> Reactor<'a, T> {
|
|
179
211
|
return;
|
180
212
|
}
|
181
213
|
c.cell.value = new_value;
|
182
|
-
}
|
214
|
+
}
|
183
215
|
None => panic!("Cell to update disappeared while updating"),
|
184
216
|
}
|
185
217
|
|
@@ -195,14 +227,14 @@ impl <'a, T: Copy + PartialEq> Reactor<'a, T> {
|
|
195
227
|
if c.cell.value == c.cell.last_value {
|
196
228
|
// Value hasn't changed since last callback fire.
|
197
229
|
// We thus shouldn't fire the callbacks.
|
198
|
-
return
|
230
|
+
return;
|
199
231
|
}
|
200
232
|
for cb in c.callbacks.values_mut() {
|
201
233
|
cb(c.cell.value);
|
202
234
|
}
|
203
235
|
c.cell.last_value = c.cell.value;
|
204
236
|
c.cell.dependents.clone()
|
205
|
-
}
|
237
|
+
}
|
206
238
|
None => panic!("Callback cell disappeared"),
|
207
239
|
};
|
208
240
|
|