From c2478e0d9eaeaa7bdd16c67110529d50a223a965 Mon Sep 17 00:00:00 2001 From: Federico De Felici Date: Thu, 2 Apr 2026 10:56:53 +0200 Subject: [PATCH 1/9] chore: refactor special_map logic --- clarity/src/vm/functions/sequences.rs | 53 ++++++++++----------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/clarity/src/vm/functions/sequences.rs b/clarity/src/vm/functions/sequences.rs index 2e2392e86de..1c8b9222011 100644 --- a/clarity/src/vm/functions/sequences.rs +++ b/clarity/src/vm/functions/sequences.rs @@ -193,10 +193,8 @@ pub fn special_map( ))?; let function = lookup_function(function_name, exec_state, invoke_ctx)?; - // Let's consider a function f (f a b c ...) - // We will first re-arrange our sequences [a0, a1, ...] [b0, b1, ...] [c0, c1, ...] ... - // To get something like: [a0, b0, c0, ...] [a1, b1, c1, ...] - let mut mapped_func_args: Vec> = vec![]; + // Evaluate each sequence argument into an iterator and record its length. + let mut args_iterators = Vec::with_capacity(args.len() - 1); let mut min_args_len = usize::MAX; for map_arg in args[1..].iter() { let sequence = @@ -208,38 +206,27 @@ pub fn special_map( )) .into()); }; - let seq_len = seq.len(); - min_args_len = min_args_len.min(seq_len); - for (apply_index, element_result) in seq.into_iter().enumerate() { - let value = element_result.map_err(|_| { - VmInternalError::Expect( - "ERROR: Invalid sequence data successfully constructed".into(), - ) - })?; - if apply_index > min_args_len { - break; - } - if apply_index >= mapped_func_args.len() { - mapped_func_args.push(vec![value]); - } else { - mapped_func_args[apply_index].push(value); - } - } + let args_iter = seq.into_iter(); + min_args_len = min_args_len.min(args_iter.len()); + args_iterators.push(args_iter); } - // We can now apply the map - let mut mapped_results = vec![]; - let mut previous_len = None; - for arguments in mapped_func_args.into_iter() { - // Stop iterating when we are done with the shortest sequence - if let Some(previous_len) = previous_len { - if previous_len != arguments.len() { - break; - } - } else { - previous_len = Some(arguments.len()); + // Apply the function element-wise, stopping at the shortest sequence. + let mut mapped_results = Vec::with_capacity(min_args_len); + for _ in 0..min_args_len { + let mut call_args = Vec::with_capacity(args_iterators.len()); + for iter in args_iterators.iter_mut() { + let value = iter + .next() + .expect("infallible: iterator can't be shorter than min len") + .map_err(|_| { + VmInternalError::Expect( + "ERROR: Invalid sequence data successfully constructed".into(), + ) + })?; + call_args.push(value); } - let res = apply_evaluated(&function, arguments, exec_state, invoke_ctx)?; + let res = apply_evaluated(&function, call_args, exec_state, invoke_ctx)?; mapped_results.push(res); } From ac27302014926b5ebed455aa4b2e6f3f5c90585e Mon Sep 17 00:00:00 2001 From: Federico De Felici Date: Thu, 2 Apr 2026 18:03:22 +0200 Subject: [PATCH 2/9] test: add scenarios to test_variadic_map_list --- clarity/src/vm/tests/sequences.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/clarity/src/vm/tests/sequences.rs b/clarity/src/vm/tests/sequences.rs index 40e498a4605..80c24b745bc 100644 --- a/clarity/src/vm/tests/sequences.rs +++ b/clarity/src/vm/tests/sequences.rs @@ -428,6 +428,18 @@ fn test_variadic_map_list() { ]) .unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); + + // 3 sequences: last is the longest, result contains 2 elements. + let test = "(map + (list 1 2) (list 10 20 30) (list 100 200 300 400))"; + + let expected = Value::list_from(vec![Value::Int(111), Value::Int(222)]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // 3 sequences: last is the shortest, result contains 1 element. + let test = "(map + (list 1 2) (list 10 20 30) (list 100))"; + + let expected = Value::list_from(vec![Value::Int(111)]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); } #[test] From 6fe63ec92d99361fa66e164d1424c5e02efc1235 Mon Sep 17 00:00:00 2001 From: Federico De Felici Date: Thu, 2 Apr 2026 18:28:53 +0200 Subject: [PATCH 3/9] chore: add changelog entry --- changelog.d/7068-refactor-special-map.changed | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7068-refactor-special-map.changed diff --git a/changelog.d/7068-refactor-special-map.changed b/changelog.d/7068-refactor-special-map.changed new file mode 100644 index 00000000000..78948ead746 --- /dev/null +++ b/changelog.d/7068-refactor-special-map.changed @@ -0,0 +1 @@ +Refactor special_map to simplify logic and reduce memory allocations \ No newline at end of file From b184f097bd6c58b117416ac6d03cc782a9b96ad1 Mon Sep 17 00:00:00 2001 From: Federico De Felici Date: Wed, 15 Apr 2026 10:13:15 +0200 Subject: [PATCH 4/9] crc: improve unreachable error semantic in apply_evaluated() --- clarity/src/vm/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clarity/src/vm/mod.rs b/clarity/src/vm/mod.rs index 76be418584c..d41ec556c2f 100644 --- a/clarity/src/vm/mod.rs +++ b/clarity/src/vm/mod.rs @@ -428,7 +428,7 @@ pub fn apply_evaluated( // SpecialFunctions require unevaluated SymbolicExpressions. They cannot appear as // fold/map step functions after type-checking, so this branch is unreachable in practice. if matches!(function, CallableType::SpecialFunction(..)) { - return Err(VmInternalError::Expect( + return Err(RuntimeCheckErrorKind::Unreachable( "apply_evaluated: SpecialFunction cannot receive pre-evaluated args".into(), ) .into()); From be4ec9f4134617ea1b947ee13f3172e81d801c5d Mon Sep 17 00:00:00 2001 From: Federico De Felici Date: Thu, 23 Apr 2026 10:41:21 +0200 Subject: [PATCH 5/9] test: refactor test_variadic_map_list() and improve test coverage related to the empty list case --- clarity/src/vm/tests/sequences.rs | 85 +++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/clarity/src/vm/tests/sequences.rs b/clarity/src/vm/tests/sequences.rs index 3e3ca842beb..0499bfd076b 100644 --- a/clarity/src/vm/tests/sequences.rs +++ b/clarity/src/vm/tests/sequences.rs @@ -389,9 +389,34 @@ fn test_simple_map_list() { #[test] fn test_variadic_map_list() { + // User functions + // - 1 sequence: 1 empty, result empty. let test = "(define-private (area (w int) (h int)) (* w h)) - (map area (list 5 10 1 2) (list 5 2 30 3))"; + (map area (list))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + // - 2 sequences: 2 empties, result empty. + let test = "(define-private (area (w int) (h int)) (* w h)) + (map area (list) (list))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 2 sequences: 1 empty and 1 not, result empty. + let test = "(define-private (area (w int) (h int)) (* w h)) + (map area (list) (list 10 20))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 3 sequences: 1 empty in between, result empty. + let test = "(define-private (area (w int) (h int)) (* w h)) + (map area (list 1 2 3) (list) (list 10 20))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 2 sequences: same length 4, result contains 4 elements. + let test = "(define-private (area (w int) (h int)) (* w h)) + (map area (list 5 10 1 2) (list 5 2 30 3))"; let expected = Value::list_from(vec![ Value::Int(25), Value::Int(20), @@ -401,9 +426,9 @@ fn test_variadic_map_list() { .unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); + // - 2 sequences: same length 4 with different int types, result contains 4 elements. let test = "(define-private (u+ (a uint) (b int)) (+ a (to-uint b))) - (map u+ (list u5 u10 u1 u2) (list 5 2 30 3))"; - + (map u+ (list u5 u10 u1 u2) (list 5 2 30 3))"; let expected = Value::list_from(vec![ Value::UInt(10), Value::UInt(12), @@ -413,13 +438,29 @@ fn test_variadic_map_list() { .unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); - let test = "(map + (list 5 10) (list 5 2 30 3))"; + // Native functions + // - 1 sequence: 1 empty, result empty. + let test = "(map pow (list))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); - let expected = Value::list_from(vec![Value::Int(10), Value::Int(12)]).unwrap(); + // - 2 sequences: 2 empties, result empty. + let test = "(map pow (list) (list))"; + let expected = Value::list_from(vec![]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); - let test = "(map pow (list 2 2 2 2) (list 1 2 3 4 5 6 7))"; + // - 2 sequences: 1 empty and 1 not, result empty. + let test = "(map pow (list) (list 10 20))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + // - 3 sequences: 1 empty in between, result empty. + let test = "(map pow (list 1 2 3) (list) (list 10 20))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 2 sequences: last is longer, result contains 4 elements. + let test = "(map pow (list 2 2 2 2) (list 1 2 3 4 5 6 7))"; let expected = Value::list_from(vec![ Value::Int(2), Value::Int(4), @@ -429,15 +470,39 @@ fn test_variadic_map_list() { .unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); - // 3 sequences: last is the longest, result contains 2 elements. - let test = "(map + (list 1 2) (list 10 20 30) (list 100 200 300 400))"; + // Special Functions + // - 1 sequence: 1 empty, result empty. + let test = "(map + (list))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 2 sequences: 2 empties, result empty. + let test = "(map + (list) (list))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 2 sequences: 1 empty and 1 not, result empty. + let test = "(map + (list) (list 10 20))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + // - 3 sequences: 1 empty in between, result empty. + let test = "(map + (list 1 2 3) (list) (list 10 20))"; + let expected = Value::list_from(vec![]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 2 sequences: last is longer, result contains 2 elements. + let test = "(map + (list 5 10) (list 5 2 30 3))"; + let expected = Value::list_from(vec![Value::Int(10), Value::Int(12)]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 3 sequences: last is the longest, result contains 2 elements. + let test = "(map + (list 1 2) (list 10 20 30) (list 100 200 300 400))"; let expected = Value::list_from(vec![Value::Int(111), Value::Int(222)]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); - // 3 sequences: last is the shortest, result contains 1 element. + // - 3 sequences: last is the shortest, result contains 1 element. let test = "(map + (list 1 2) (list 10 20 30) (list 100))"; - let expected = Value::list_from(vec![Value::Int(111)]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); } From cf136311704e226c7959e80826fda08b9b01e1b8 Mon Sep 17 00:00:00 2001 From: Federico De Felici Date: Thu, 23 Apr 2026 10:53:28 +0200 Subject: [PATCH 6/9] test: improved test coverage for type_checker(s) to cover map rejection when used with empty list --- .../analysis/type_checker/v2_05/tests/mod.rs | 3 +++ .../analysis/type_checker/v2_1/tests/mod.rs | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs index 05fae0997ba..e193a3d2f35 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs @@ -925,6 +925,9 @@ fn test_lists() { "(map hash160 (+ u1 u2))", "(len 1)", "(map + (list 1 2 3 4 5) (list true true true true true))", + "(map + (list) (list 1))", + "(map pow (list) (list 1))", + "(define-private (add (x int) (y int)) (+ x y)) (map add (list) (list 1))", ]; let bad_expected = [ StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), diff --git a/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs index de7bd5d2b22..86ff431de86 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs @@ -1520,6 +1520,9 @@ fn test_lists() { "(map hash160 (+ u1 u2))", "(len 1)", "(map + (list 1 2 3 4 5) (list true true true true true))", + "(map + (list) (list 1))", + "(map pow (list) (list 1))", + "(define-private (add (x int) (y int)) (+ x y)) (map add (list) (list 1))", ]; let bad_expected = [ StaticCheckErrorKind::TypeError(Box::new(BoolType), Box::new(IntType)), @@ -1539,6 +1542,30 @@ fn test_lists() { StaticCheckErrorKind::ExpectedSequence(Box::new(UIntType)), StaticCheckErrorKind::ExpectedSequence(Box::new(IntType)), StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::UnionTypeError( + vec![IntType, UIntType], + Box::new(TypeSignature::NoType), + ), + StaticCheckErrorKind::UnionTypeError( + vec![IntType, UIntType], + Box::new(TypeSignature::NoType), + ), + StaticCheckErrorKind::TypeError( + Box::new(TypeSignature::IntType), + Box::new(TypeSignature::NoType), + ), + StaticCheckErrorKind::UnionTypeError( + vec![IntType, UIntType], + Box::new(TypeSignature::NoType), + ), + StaticCheckErrorKind::UnionTypeError( + vec![IntType, UIntType], + Box::new(TypeSignature::NoType), + ), + StaticCheckErrorKind::TypeError( + Box::new(TypeSignature::IntType), + Box::new(TypeSignature::NoType), + ), ]; for (good_test, expected) in good.iter().zip(expected.iter()) { From b0beaa7d1d69307d2dac7c0576621a5d83d79d14 Mon Sep 17 00:00:00 2001 From: Federico De Felici Date: Thu, 23 Apr 2026 11:01:17 +0200 Subject: [PATCH 7/9] crc: convert expect() to RuntimeCheckErrorKind::Unreachable --- clarity/src/vm/functions/sequences.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clarity/src/vm/functions/sequences.rs b/clarity/src/vm/functions/sequences.rs index 0a78fce9616..1a8054de2ed 100644 --- a/clarity/src/vm/functions/sequences.rs +++ b/clarity/src/vm/functions/sequences.rs @@ -229,7 +229,11 @@ pub fn special_map( for iter in args_iterators.iter_mut() { let value = iter .next() - .expect("infallible: iterator can't be shorter than min len") + .ok_or_else(|| { + RuntimeCheckErrorKind::Unreachable( + "iterator can't be shorter than min len".into(), + ) + })? .map_err(|_| { VmInternalError::Expect( "ERROR: Invalid sequence data successfully constructed".into(), From b28368b4255575a846decb7746fcdd59e7d27646 Mon Sep 17 00:00:00 2001 From: Federico De Felici Date: Thu, 23 Apr 2026 11:15:14 +0200 Subject: [PATCH 8/9] chore: improved test automation for type_checker(s) tests --- .../analysis/type_checker/v2_05/tests/mod.rs | 22 +++++++++++++++++++ .../analysis/type_checker/v2_1/tests/mod.rs | 22 +++++++++---------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs index e193a3d2f35..e697129e55e 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs @@ -947,8 +947,25 @@ fn test_lists() { StaticCheckErrorKind::ExpectedSequence(Box::new(UIntType)), StaticCheckErrorKind::ExpectedSequence(Box::new(IntType)), StaticCheckErrorKind::TypeError(Box::new(IntType), Box::new(BoolType)), + StaticCheckErrorKind::UnionTypeError( + vec![IntType, UIntType], + Box::new(TypeSignature::NoType), + ), + StaticCheckErrorKind::UnionTypeError( + vec![IntType, UIntType], + Box::new(TypeSignature::NoType), + ), + StaticCheckErrorKind::TypeError( + Box::new(TypeSignature::IntType), + Box::new(TypeSignature::NoType), + ), ]; + assert_eq!( + good.len(), + expected.len(), + "Good tests should match related expected count" + ); for (good_test, expected) in good.iter().zip(expected.iter()) { assert_eq!( expected, @@ -956,6 +973,11 @@ fn test_lists() { ); } + assert_eq!( + bad.len(), + bad_expected.len(), + "Bad tests should match related expected count" + ); for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); } diff --git a/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs index 86ff431de86..b383ccd4d78 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs @@ -1554,20 +1554,13 @@ fn test_lists() { Box::new(TypeSignature::IntType), Box::new(TypeSignature::NoType), ), - StaticCheckErrorKind::UnionTypeError( - vec![IntType, UIntType], - Box::new(TypeSignature::NoType), - ), - StaticCheckErrorKind::UnionTypeError( - vec![IntType, UIntType], - Box::new(TypeSignature::NoType), - ), - StaticCheckErrorKind::TypeError( - Box::new(TypeSignature::IntType), - Box::new(TypeSignature::NoType), - ), ]; + assert_eq!( + good.len(), + expected.len(), + "Good tests should match related expected count" + ); for (good_test, expected) in good.iter().zip(expected.iter()) { assert_eq!( expected, @@ -1575,6 +1568,11 @@ fn test_lists() { ); } + assert_eq!( + bad.len(), + bad_expected.len(), + "Bad tests should match related expected count" + ); for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) { assert_eq!(*expected, *type_check_helper(bad_test).unwrap_err().err); } From df9ed4b6b32b7de9110a222d803e26331f0f5b27 Mon Sep 17 00:00:00 2001 From: Federico De Felici Date: Thu, 23 Apr 2026 13:41:28 +0200 Subject: [PATCH 9/9] test: improve test_variadic_map_list() for special functions --- clarity/src/vm/tests/sequences.rs | 52 ++++++++++++++----------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/clarity/src/vm/tests/sequences.rs b/clarity/src/vm/tests/sequences.rs index 0499bfd076b..5e08cac2c0e 100644 --- a/clarity/src/vm/tests/sequences.rs +++ b/clarity/src/vm/tests/sequences.rs @@ -440,70 +440,64 @@ fn test_variadic_map_list() { // Native functions // - 1 sequence: 1 empty, result empty. - let test = "(map pow (list))"; + let test = "(map + (list))"; let expected = Value::list_from(vec![]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); // - 2 sequences: 2 empties, result empty. - let test = "(map pow (list) (list))"; + let test = "(map + (list) (list))"; let expected = Value::list_from(vec![]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); // - 2 sequences: 1 empty and 1 not, result empty. - let test = "(map pow (list) (list 10 20))"; + let test = "(map + (list) (list 10 20))"; let expected = Value::list_from(vec![]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); // - 3 sequences: 1 empty in between, result empty. - let test = "(map pow (list 1 2 3) (list) (list 10 20))"; + let test = "(map + (list 1 2 3) (list) (list 10 20))"; let expected = Value::list_from(vec![]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); - // - 2 sequences: last is longer, result contains 4 elements. - let test = "(map pow (list 2 2 2 2) (list 1 2 3 4 5 6 7))"; - let expected = Value::list_from(vec![ - Value::Int(2), - Value::Int(4), - Value::Int(8), - Value::Int(16), - ]) - .unwrap(); + // - 2 sequences: last is longer, result contains 2 elements. + let test = "(map + (list 5 10) (list 5 2 30 3))"; + let expected = Value::list_from(vec![Value::Int(10), Value::Int(12)]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 3 sequences: last is the longest, result contains 2 elements. + let test = "(map + (list 1 2) (list 10 20 30) (list 100 200 300 400))"; + let expected = Value::list_from(vec![Value::Int(111), Value::Int(222)]).unwrap(); + assert_eq!(expected, execute(test).unwrap().unwrap()); + + // - 3 sequences: last is the shortest, result contains 1 element. + let test = "(map + (list 1 2) (list 10 20 30) (list 100))"; + let expected = Value::list_from(vec![Value::Int(111)]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); // Special Functions // - 1 sequence: 1 empty, result empty. - let test = "(map + (list))"; + let test = "(map > (list))"; let expected = Value::list_from(vec![]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); // - 2 sequences: 2 empties, result empty. - let test = "(map + (list) (list))"; + let test = "(map > (list) (list))"; let expected = Value::list_from(vec![]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); // - 2 sequences: 1 empty and 1 not, result empty. - let test = "(map + (list) (list 10 20))"; + let test = "(map > (list) (list 10 20))"; let expected = Value::list_from(vec![]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); // - 3 sequences: 1 empty in between, result empty. - let test = "(map + (list 1 2 3) (list) (list 10 20))"; + let test = "(map > (list 1 2 3) (list) (list 10 20))"; let expected = Value::list_from(vec![]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); // - 2 sequences: last is longer, result contains 2 elements. - let test = "(map + (list 5 10) (list 5 2 30 3))"; - let expected = Value::list_from(vec![Value::Int(10), Value::Int(12)]).unwrap(); - assert_eq!(expected, execute(test).unwrap().unwrap()); - - // - 3 sequences: last is the longest, result contains 2 elements. - let test = "(map + (list 1 2) (list 10 20 30) (list 100 200 300 400))"; - let expected = Value::list_from(vec![Value::Int(111), Value::Int(222)]).unwrap(); - assert_eq!(expected, execute(test).unwrap().unwrap()); - - // - 3 sequences: last is the shortest, result contains 1 element. - let test = "(map + (list 1 2) (list 10 20 30) (list 100))"; - let expected = Value::list_from(vec![Value::Int(111)]).unwrap(); + let test = "(map > (list 1 10) (list 2 3 4 5))"; + let expected = Value::list_from(vec![Value::Bool(false), Value::Bool(true)]).unwrap(); assert_eq!(expected, execute(test).unwrap().unwrap()); }