Решение на Reversible Interpreter от Тодор Димов
Резултати
- 15 точки от тестове
- 0 бонус точки
- 15 точки общо
- 12 успешни тест(а)
- 0 неуспешни тест(а)
Код
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20210120-1538662-18g2stx/solution)
Finished test [unoptimized + debuginfo] target(s) in 2.55s
Running target/debug/deps/solution_test-8916805fc40a2dab
running 12 tests
test solution_test::test_arg_number ... ok
test solution_test::test_arithmetic_back ... ok
test solution_test::test_arithmetic_basic ... ok
test solution_test::test_div_1 ... ok
test solution_test::test_div_2 ... ok
test solution_test::test_errors_1 ... ok
test solution_test::test_errors_2 ... ok
test solution_test::test_instructions_after_error ... ok
test solution_test::test_invalid_args ... ok
test solution_test::test_pop ... ok
test solution_test::test_push ... ok
test solution_test::test_restoring_instructions ... ok
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
История (5 версии и 2 коментара)
Тодор качи решение на 15.01.2021 01:38 (преди почти 5 години)
Тодор качи решение на 15.01.2021 13:17 (преди почти 5 години)
Големите match-ове могат ли да се съкратят някак?
Тодор качи решение на 15.01.2021 14:24 (преди почти 5 години)
Тодор качи решение на 16.01.2021 17:29 (преди почти 5 години)
Сори, че чак сега пиша. Предполагам, че говориш за тоя блок?
match instruction.next() {
Some( "PUSH" ) =>
match instruction.map( str::parse::<i32> ).collect::<Result<Vec<i32>,_>>() {
Ok( args ) if args.len() == 1 => Ok( Op::Push( args[ 0 ] ) ),
_ => Err( RuntimeError::InvalidCommand ),
},
Some( "POP" ) => instruction.next().map( |_| Op::Pop( 0 ) ).xor( Some( Op::Pop( 0 ) ) ).ok_or( RuntimeError::InvalidCommand ),
Some( "ADD" ) => instruction.next().map( |_| Op::Pop( 0 ) ).xor( Some( Op::Add( 0, 0 ) ) ).ok_or( RuntimeError::InvalidCommand ),
...
Винаги можеш поне част от общата логика да я побереш синтактично в макрос. Примерно нещо като:
Some("ADD") => build_instruction!(Op::Add(0))
С дефиниция на макроса над match-а:
macro_rules! build_instruction {
($expr:expr) => {
instruction.next().map(|_| Op::Pop( 0 )).xor(Some($expr)).ok_or(RuntimeError::InvalidCommand)
}
}
Честно казано, обаче, не съм сигурен какво точно се опитваш да постигнеш с pop-а и xor-овете. Може да пробваш да match-неш (instruction.next(), instruction.next()) и така валидния клон на PUSH ще е Some("PUSH"), Some(arg), валидните на останалите ще са Some("ADD"), None, и default-ния ще си остане InvalidCommand. Във всеки от клоновете просто ще си върнеш Ok(Op::<whatever>(...)). Или даже може да пробваш да pop-неш неща от стека тук, но виждам, че си сложил тази логика другаде.
Не съм го пробвал, но поне на мен ми изглежда, че би сработило нещо такова.
