Решение на 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 (преди над 4 години)
Тодор качи решение на 15.01.2021 13:17 (преди над 4 години)
Големите match-ове могат ли да се съкратят някак?
Тодор качи решение на 15.01.2021 14:24 (преди над 4 години)
Тодор качи решение на 16.01.2021 17:29 (преди над 4 години)
Сори, че чак сега пиша. Предполагам, че говориш за тоя блок?
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-неш неща от стека тук, но виждам, че си сложил тази логика другаде.
Не съм го пробвал, но поне на мен ми изглежда, че би сработило нещо такова.