Сопоставление ржавчины с вектором
В учебном пособии показаны некоторые очень простые примеры сопоставления с образцом, например сопоставление по целому числу для эмуляции оператора switch в стиле c. Учебное пособие также показывает, как выполнить базовую деструктуризацию по типу кортежа и деструктурирующие структуры.
Кажется, должно быть возможно сопоставить образец по вектору, но я не могу понять правильный синтаксис для него, и я не нашел никаких примеров этого.
Например, в Haskell вы можете легко деструктурировать список:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr func initValue [] = initValue
foldr func initValue (x:xs) = func initValue $ foldr initValue func xs
Итак, глядя на грубый перевод, было бы неплохо сделать следующее:
fn foldr<A, B>(func: fn(A, B) -> B,
initValue: B,
vals: [A]) -> B {
alt vals {
[] { ret initValue; }
_ {
let h = vec::head(vals),
t = vec::tail(vals);
ret foldr(func, func(initValue, h), t);
}
}
}
Примечание: я знаю, что вы могли бы использовать здесь выражение if, я просто использую это как пример сопоставления с шаблоном по вектору.
Это в настоящее время возвращает:
patterns.rs:10:4: 10:5 error: constant contains unimplemented expression type
patterns.rs:10 [] { ret initValue; }
^
error: aborting due to previous errors
В учебном пособии есть пример для разрушения структур (определяется с помощью { .. }
) и кортежи (определяются с помощью ( .. )
), поэтому кажется, что должна быть встроенная поддержка векторов, а также учитывая, что они также содержат специальный синтаксис (определенный с помощью [ .. ]
).
Не стесняйтесь поправлять меня, если я тоже использую векторы неправильно.
1 ответ
Хотелось бы дать более общий совет о том, как наилучшим образом использовать сопоставление с образцом для векторов, но вот как вы можете использовать их для проверки пустых векторов (по крайней мере, я думаю, что это то, что делает код на Haskell...):
use std;
import std::io::println;
fn main() {
let empty: [int] = [];
println(vec_alt(empty));
println(vec_alt([1,2,3]));
}
fn vec_alt<A>(vals: [A]) -> str {
alt vals {
x if x == [] { "empty" }
_ { "otherwise" }
}
}
Обратите внимание, что пытаясь просто пройти []
как аргумент не удается, потому что компилятор не может определить тип для вектора. Кажется, можно пройти [()]
(вектор с nil
внутри) без предварительного объявления, но alt
Кажется, оператор не в состоянии проверить, соответствует ли выражение головы [()]
(он просто падает по умолчанию).
В целом, векторы кажутся немного грубыми в данный момент. Если есть какое-то конкретное применение, которое вы имеете в виду, что Rust, похоже, не поддерживает, разработчики вполне открыты для предложений и критики: https://mail.mozilla.org/listinfo/rust-dev
Также см. Справочное руководство для более формального определения и несколько примеров, чтобы помочь прояснить ситуацию: http://doc.rust-lang.org/doc/rust.html
Вам нужен этот https://doc.rust-lang.org/reference/patterns.html
fn vec_alt<A>(vals: Vec<A>) -> str {
match vals[..] {
[] => { "empty" }
_ => { "otherwise" }
}
}