Adds a default value to .remove() on dict and array (#2346)

This commit is contained in:
Sébastien d'Herbais de Thun 2023-10-10 11:44:59 +02:00 committed by GitHub
parent cef2d3afca
commit a8af6b449a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 9 deletions

View File

@ -247,9 +247,14 @@ impl Array {
/// The index at which to remove the item. If negative, indexes from /// The index at which to remove the item. If negative, indexes from
/// the back. /// the back.
index: i64, index: i64,
/// A default value to return if the index is out of bounds.
#[named]
default: Option<Value>,
) -> StrResult<Value> { ) -> StrResult<Value> {
let i = self.locate(index, false)?; self.locate_opt(index, false)
Ok(self.0.remove(i)) .map(|i| self.0.remove(i))
.or(default)
.ok_or_else(|| out_of_bounds_no_default(index, self.len()))
} }
/// Extracts a subslice of the array. Fails with an error if the start or /// Extracts a subslice of the array. Fails with an error if the start or

View File

@ -169,11 +169,17 @@ impl Dict {
/// Removes a pair from the dictionary by key and return the value. /// Removes a pair from the dictionary by key and return the value.
#[func] #[func]
pub fn remove(&mut self, key: Str) -> StrResult<Value> { pub fn remove(
match Arc::make_mut(&mut self.0).shift_remove(&key) { &mut self,
Some(value) => Ok(value), key: Str,
None => Err(missing_key(&key)), /// A default value to return if the key does not exist.
} #[named]
default: Option<Value>,
) -> StrResult<Value> {
Arc::make_mut(&mut self.0)
.shift_remove(&key)
.or(default)
.ok_or_else(|| missing_key(&key))
} }
/// Returns the keys of the dictionary as an array in insertion order. /// Returns the keys of the dictionary as an array in insertion order.

View File

@ -51,13 +51,20 @@ pub fn call_mut(
"insert" => { "insert" => {
array.insert(args.expect("index")?, args.expect("value")?).at(span)? array.insert(args.expect("index")?, args.expect("value")?).at(span)?
} }
"remove" => output = array.remove(args.expect("index")?).at(span)?, "remove" => {
output = array
.remove(args.expect("index")?, args.named("default")?)
.at(span)?
}
_ => return missing(), _ => return missing(),
}, },
Value::Dict(dict) => match method { Value::Dict(dict) => match method {
"insert" => dict.insert(args.expect::<Str>("key")?, args.expect("value")?), "insert" => dict.insert(args.expect::<Str>("key")?, args.expect("value")?),
"remove" => output = dict.remove(args.expect::<Str>("key")?).at(span)?, "remove" => {
output =
dict.remove(args.expect("key")?, args.named("default")?).at(span)?
}
_ => return missing(), _ => return missing(),
}, },

View File

@ -63,6 +63,19 @@
#test((1, 2, 3).at(2, default: 5), 3) #test((1, 2, 3).at(2, default: 5), 3)
#test((1, 2, 3).at(3, default: 5), 5) #test((1, 2, 3).at(3, default: 5), 5)
---
// Test remove with default value.
#{
let array = (1, 2, 3)
test(array.remove(2, default: 5), 3)
}
#{
let array = (1, 2, 3)
test(array.remove(3, default: 5), 5)
}
--- ---
// Test bad lvalue. // Test bad lvalue.
// Error: 2:3-2:14 cannot mutate a temporary value // Error: 2:3-2:14 cannot mutate a temporary value

View File

@ -40,6 +40,18 @@
#test((a: 1, b: 2).at("b", default: 3), 2) #test((a: 1, b: 2).at("b", default: 3), 2)
#test((a: 1, b: 2).at("c", default: 3), 3) #test((a: 1, b: 2).at("c", default: 3), 3)
---
// Test remove with default value.
#{
let dict = (a: 1, b: 2)
test(dict.remove("b", default: 3), 2)
}
#{
let dict = (a: 1, b: 2)
test(dict.remove("c", default: 3), 3)
}
--- ---
// Missing lvalue is not automatically none-initialized. // Missing lvalue is not automatically none-initialized.
#{ #{