Collect

Краен срок
19.01.2018 17:00

Срокът за предаване на решения е отминал

За това предизвикателство, ще трябва да се сборите с един макрос. Ще се опитаме да нахакаме един list/set comprehension в Rust, който изглежда що-годе като този за хаскел:

let items: Vec<_> = collect![x * y * z; x <- 1..4, y <- vec![1, 3], z <- Some(1)];
assert_eq!(vec![1, 3, 2, 6, 3, 9], items);

let items: HashSet<_> = collect![x * y * z; x <- 1..4, y <- vec![1, 3], z <- Some(1)];
let mut vec_items = Vec::from_iter(items.into_iter());
vec_items.sort();

assert_eq!(vec![1, 2, 3, 6, 9], vec_items);

Basically, макроса collect! има следния общ вид:

collect![ <израз, използващ променливи> ; ( <променлива> <- <колекция>, )+ ]

В горния пример, със x <- 1..4 и y <- vec![1, 3], стойността на x първо ще мине през 1, умножено по стойността 1 на y, после 1, умножено по стойността 3 на y. След това, x ще мине през 2, 3, за стойности на y 1, 3. И т.н. за всяка следваща дефиниция. Basically, погрижете се този пример да връща този резултат:

let items: Vec<_> = collect![x * y * z; x <- 1..4, y <- vec![1, 3]];
assert_eq!(vec![1, 3, 2, 6, 3, 9], items);

Дефиницията ще започне така:

#[macro_export]
macro_rules! collect {
    // ....
}

Задължително е да сложите отгоре #[macro_export].

Винаги ще присъства поне една <променлива> <- <колекция> част. Може да е само една.

Забележете, че в зависимост от типа на резултата, очакваме макроса да върне различни неща. Тоест, в крайна сметка, макроса трябва да викне collect() на някакъв итератор.

Няма да тестваме с trailing запетайки, така че не се притеснявайте за това. Няма и да тестваме с различни типове променливи, само с цели числа (не целим да упражните аритметика или конвертирания, само писане на макроси).

Силно ви съветваме да минете отново през лекцията за макроси, за да си припомните всякакви странни hint-ове. Четете компилаторни грешки внимателно, и започнете с най-простия пример, усложнявайте постепенно.

Решения

Андрей
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Андрей
#[macro_export]
macro_rules! collect {
($body:expr; $var:ident <- $source:expr, $($next_var:ident <- $next_source:expr),*) => {
{
$source.into_iter().flat_map(|element| {
let $var = element;
collect!(@nested $body; $($next_var <- $next_source),*)
}).collect()
}
};
($body:expr; $var:ident <- $source:expr) => {
{
$source.into_iter().map(|element| {
let $var = element;
$body
}).collect()
}
};
(@nested $body:expr; $var:ident <- $source:expr, $($next_var:ident <- $next_source:expr),*) => {
{
$source.into_iter().flat_map(move |element| {
let $var = element;
collect!(@nested $body; $($next_var <- $next_source),*)
})
}
};
(@nested $body:expr; $var:ident <- $source:expr) => {
{
$source.into_iter().map(move |element| {
let $var = element;
$body
})
}
};
}
Compiling solution v0.1.0 (file:///tmp/d20180119-3040-12riidi/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 3.44 secs
     Running target/debug/deps/solution-ce0b707f0d16a543

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-370f3a629b3a1ef4

running 3 tests
test solution_test::test_different_collections ... ok
test solution_test::test_multiple_sources ... ok
test solution_test::test_single_source ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Михаил Младенов
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Михаил Младенов
#[macro_export]
macro_rules! set_product {
($c0:expr) => {{
$c0.into_iter()
}};
($c0:expr, $($ck:expr),+ ) => {{
$c0.into_iter().flat_map(|x| set_product!($($ck),+).zip(Some(x).into_iter().cycle()))
}};
}
#[macro_export]
macro_rules! gather_vars {
($v0:ident) => {
$v0
};
($v0:ident, $($vk:ident),+ ) => {
(gather_vars![$($vk),+], $v0)
};
}
#[macro_export]
macro_rules! collect {
($e:expr; $($vk:ident <- $ck:expr),+ ) => {
set_product![$($ck),+].map(|gather_vars![$($vk),+]| $e).collect()
};
}
#[macro_export]
macro_rules! collect {
($e:expr; $($vk:ident <- $ck:expr),+ ) => {
set_product![$($ck),+].map(|gather_vars![$($vk),+]| $e).collect()
};
}
Compiling solution v0.1.0 (file:///tmp/d20180119-3040-131nzg0/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 3.39 secs
     Running target/debug/deps/solution-ce0b707f0d16a543

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-370f3a629b3a1ef4

running 3 tests
test solution_test::test_different_collections ... ok
test solution_test::test_multiple_sources ... ok
test solution_test::test_single_source ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Николай Коцев
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Николай Коцев
#[macro_export]
macro_rules! collect {
[
@inner $result:ident | $expr:expr; $i:ident <- $domain:expr $(,)*
] => (
for $i in $domain.into_iter() {
$result.push($expr)
}
);
[
@inner $result:ident | $expr:expr; $i:ident <- $domain:expr, $($rest:tt)+
] => (
for $i in $domain.into_iter() {
collect!(@inner $result | $expr; $($rest)*)
}
);
[
$($all:tt)*
] => (
{
let mut result = Vec::new();
collect!(@inner result | $($all)*);
result.into_iter().collect()
}
);
}
Compiling solution v0.1.0 (file:///tmp/d20180119-3040-1rii11a/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.78 secs
     Running target/debug/deps/solution-ce0b707f0d16a543

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-370f3a629b3a1ef4

running 3 tests
test solution_test::test_different_collections ... ok
test solution_test::test_multiple_sources ... ok
test solution_test::test_single_source ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Радослав Георгиев
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Радослав Георгиев
#[macro_export]
macro_rules! collect {
[$expression: expr; $($bindings: ident <- $value_lists: expr),+] => {
{
let mut container = Vec::new();
collect!(@collect container, $expression, $($bindings <- $value_lists),+);
container.into_iter().collect()
}
};
(@collect $container: ident, $expression: expr) => {
$container.push($expression);
};
(@collect $container: ident, $expression: expr, $binding: ident <- $value_list: expr) => {
for $binding in $value_list {
collect!(@collect $container, $expression);
}
};
(@collect $container: ident, $expression: expr, $binding: ident <- $value_list: expr, $($bindings: ident <- $value_lists: expr),*) => {
for $binding in $value_list {
collect!(@collect $container, $expression, $($bindings <- $value_lists),*);
}
};
}
Compiling solution v0.1.0 (file:///tmp/d20180119-3040-12fu8pf/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.84 secs
     Running target/debug/deps/solution-ce0b707f0d16a543

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-370f3a629b3a1ef4

running 3 tests
test solution_test::test_different_collections ... ok
test solution_test::test_multiple_sources ... ok
test solution_test::test_single_source ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Иван Иванов
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Иван Иванов
// Kолкото да има нещо написано за 5 минути.... Ще работи само до 3 аргумента
#[macro_export]
macro_rules! collect {
( $expr: expr; $lhs1: ident <- $rhs1: expr, $lhs2: ident <- $rhs2: expr, $lhs3: ident <- $rhs3: expr) =>
{
{
let mut v = Vec::new();
for $lhs1 in $rhs1 {
let $lhs1 = $lhs1.clone();
for $lhs2 in $rhs2 {
let $lhs2 = $lhs2.clone();
for $lhs3 in $rhs3 {
let $lhs3 = $lhs3.clone();
v.push($expr);
}
}
}
v.into_iter().collect()
}
};
( $expr: expr; $lhs1: ident <- $rhs1: expr, $lhs2: ident <- $rhs2: expr) =>
{
{
let mut v = Vec::new();
for $lhs1 in $rhs1 {
let $lhs1 = $lhs1.clone();
for $lhs2 in $rhs2 {
let $lhs2 = $lhs2.clone();
v.push($expr);
}
}
v.into_iter().collect()
}
};
( $expr: expr; $lhs: ident <- $rhs: expr) =>
{
{
let mut v = Vec::new();
for $lhs in $rhs {
let $lhs = $lhs.clone();
v.push($expr);
}
v.into_iter().collect()
}
};
}
Compiling solution v0.1.0 (file:///tmp/d20180119-3040-qc2vym/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 3.6 secs
     Running target/debug/deps/solution-ce0b707f0d16a543

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-370f3a629b3a1ef4

running 3 tests
test solution_test::test_different_collections ... ok
test solution_test::test_multiple_sources ... ok
test solution_test::test_single_source ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out