git.delta.rocks / jrsonnet / refs/commits / 21712e70b26b

difftreelog

perf implement std.setDiff in native

Yaroslav Bolyukin2023-08-12parent: #0d47e9f.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -175,6 +175,7 @@
 		// Sets
 		("setMember", builtin_set_member::INST),
 		("setInter", builtin_set_inter::INST),
+		("setDiff", builtin_set_diff::INST),
 		// Compat
 		("__compare", builtin___compare::INST),
 	]
modifiedcrates/jrsonnet-stdlib/src/sets.rsdiffbeforeafterboth
before · crates/jrsonnet-stdlib/src/sets.rs
1use std::cmp::Ordering;23use jrsonnet_evaluator::{4	error::Result,5	function::{builtin, FuncVal},6	operator::evaluate_compare_op,7	val::ArrValue,8	Thunk, Val,9};10use jrsonnet_parser::BinaryOpType;1112#[builtin]13#[allow(non_snake_case)]14pub fn builtin_set_member(x: Thunk<Val>, arr: ArrValue, keyF: Option<FuncVal>) -> Result<bool> {15	let mut low = 0;16	let mut high = arr.len();1718	let keyF = keyF19		.unwrap_or(FuncVal::Id)20		.into_native::<((Thunk<Val>,), Val)>();2122	let x = keyF(x)?;2324	while low < high {25		let middle = (high + low) / 2;26		let comp = keyF(arr.get_lazy(middle).expect("in bounds"))?;27		match evaluate_compare_op(&comp, &x, BinaryOpType::Lt)? {28			Ordering::Less => low = middle + 1,29			Ordering::Equal => return Ok(true),30			Ordering::Greater => high = middle,31		}32	}33	Ok(false)34}3536#[builtin]37#[allow(non_snake_case, clippy::redundant_closure)]38pub fn builtin_set_inter(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {39	let mut a = a.iter_lazy();40	let mut b = b.iter_lazy();4142	let keyF = keyF43		.unwrap_or(FuncVal::identity())44		.into_native::<((Thunk<Val>,), Val)>();45	let keyF = |v| keyF(v);4647	let mut av = a.next();48	let mut bv = b.next();49	let mut ak = av.clone().map(keyF).transpose()?;50	let mut bk = bv.map(keyF).transpose()?;5152	let mut out = Vec::new();53	while let (Some(ac), Some(bc)) = (&ak, &bk) {54		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {55			Ordering::Less => {56				av = a.next();57				ak = av.clone().map(keyF).transpose()?;58			}59			Ordering::Greater => {60				bv = b.next();61				bk = bv.map(keyF).transpose()?;62			}63			Ordering::Equal => {64				out.push(av.clone().expect("ak != None => av != None"));65				av = a.next();66				ak = av.clone().map(keyF).transpose()?;67				bv = b.next();68				bk = bv.map(keyF).transpose()?;69			}70		};71	}72	Ok(ArrValue::lazy(out))73}
after · crates/jrsonnet-stdlib/src/sets.rs
1use std::cmp::Ordering;23use jrsonnet_evaluator::{4	error::Result,5	function::{builtin, FuncVal},6	operator::evaluate_compare_op,7	val::ArrValue,8	Thunk, Val,9};10use jrsonnet_parser::BinaryOpType;1112#[builtin]13#[allow(non_snake_case)]14pub fn builtin_set_member(x: Thunk<Val>, arr: ArrValue, keyF: Option<FuncVal>) -> Result<bool> {15	let mut low = 0;16	let mut high = arr.len();1718	let keyF = keyF19		.unwrap_or(FuncVal::Id)20		.into_native::<((Thunk<Val>,), Val)>();2122	let x = keyF(x)?;2324	while low < high {25		let middle = (high + low) / 2;26		let comp = keyF(arr.get_lazy(middle).expect("in bounds"))?;27		match evaluate_compare_op(&comp, &x, BinaryOpType::Lt)? {28			Ordering::Less => low = middle + 1,29			Ordering::Equal => return Ok(true),30			Ordering::Greater => high = middle,31		}32	}33	Ok(false)34}3536#[builtin]37#[allow(non_snake_case, clippy::redundant_closure)]38pub fn builtin_set_inter(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {39	let mut a = a.iter_lazy();40	let mut b = b.iter_lazy();4142	let keyF = keyF43		.unwrap_or(FuncVal::identity())44		.into_native::<((Thunk<Val>,), Val)>();45	let keyF = |v| keyF(v);4647	let mut av = a.next();48	let mut bv = b.next();49	let mut ak = av.clone().map(keyF).transpose()?;50	let mut bk = bv.map(keyF).transpose()?;5152	let mut out = Vec::new();53	while let (Some(ac), Some(bc)) = (&ak, &bk) {54		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {55			Ordering::Less => {56				av = a.next();57				ak = av.clone().map(keyF).transpose()?;58			}59			Ordering::Greater => {60				bv = b.next();61				bk = bv.map(keyF).transpose()?;62			}63			Ordering::Equal => {64				out.push(av.clone().expect("ak != None => av != None"));65				av = a.next();66				ak = av.clone().map(keyF).transpose()?;67				bv = b.next();68				bk = bv.map(keyF).transpose()?;69			}70		};71	}72	Ok(ArrValue::lazy(out))73}74#[builtin]75#[allow(non_snake_case, clippy::redundant_closure)]76pub fn builtin_set_diff(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {77	let mut a = a.iter_lazy();78	let mut b = b.iter_lazy();7980	let keyF = keyF81		.unwrap_or(FuncVal::identity())82		.into_native::<((Thunk<Val>,), Val)>();83	let keyF = |v| keyF(v);8485	let mut av = a.next();86	let mut bv = b.next();87	let mut ak = av.clone().map(keyF).transpose()?;88	let mut bk = bv.map(keyF).transpose()?;8990	let mut out = Vec::new();91	while let (Some(ac), Some(bc)) = (&ak, &bk) {92		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {93			Ordering::Less => {94				// In a, but not in b95				out.push(av.clone().expect("ak != None"));96				av = a.next();97				ak = av.clone().map(keyF).transpose()?;98			}99			Ordering::Greater => {100				bv = b.next();101				bk = bv.map(keyF).transpose()?;102			}103			Ordering::Equal => {104				av = a.next();105				ak = av.clone().map(keyF).transpose()?;106				bv = b.next();107				bk = bv.map(keyF).transpose()?;108			}109		};110	}111	while let Some(ac) = &ak {112		// In a, but not in b113		out.push(av.clone().expect("ak != None"));114		av = a.next();115		ak = av.clone().map(keyF).transpose()?;116	}117	Ok(ArrValue::lazy(out))118}
modifiedcrates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/std.jsonnet
+++ b/crates/jrsonnet-stdlib/src/std.jsonnet
@@ -214,21 +214,6 @@
           aux(a, b, i, j + 1, acc + [b[j]]) tailstrict;
     aux(a, b, 0, 0, []),
 
-  setDiff(a, b, keyF=id)::
-    local aux(a, b, i, j, acc) =
-      if i >= std.length(a) then
-        acc
-      else if j >= std.length(b) then
-        acc + a[i:]
-      else
-        if keyF(a[i]) == keyF(b[j]) then
-          aux(a, b, i + 1, j + 1, acc) tailstrict
-        else if keyF(a[i]) < keyF(b[j]) then
-          aux(a, b, i + 1, j, acc + [a[i]]) tailstrict
-        else
-          aux(a, b, i, j + 1, acc) tailstrict;
-    aux(a, b, 0, 0, []) tailstrict,
-
   mergePatch(target, patch)::
     if std.isObject(patch) then
       local target_object =