Repository: typst/typst
File: crates/typst/src/foundations/args.rs (Rust)

Code before:
                        .filter(|item| item.name.is_none())
                        .map(|item| item.value.v.clone())
                        .rev()
                        .nth(index)
                } else {
                    let index = index.try_into().ok()?;
                    self.items
                        .iter()
                        .filter(|item| item.name.is_none())
                        .map(|item| item.value.v.clone())
                        .nth(index)
                }
            }

            ArgumentKey::Name(name) => {
                // Accept the last argument with the right name.
                self.items
                    .iter()
                    .filter_map(|item| {
                        item.name.as_ref().map(|k| (k, item.value.v.clone()))
                    })
                    .rfind(|(k, _)| *k == name)
                    .map(|(_, v)| v)
            }
        }
    }
}

#[scope]
impl Args {
    /// Construct spreadable arguments in place.
    ///
    /// This function behaves like `{let args(..sink) = sink}`.
    ///
    /// ```example
    /// #let args = arguments(stroke: red, inset: 1em, [Body])
    /// #box(..args)
    /// ```
    #[func(constructor)]
    pub fn construct(
        /// The real arguments (the other argument is just for the docs).
        /// The docs argument cannot be called `args`.
        args: &mut Args,
        /// The arguments to construct.
        #[external]
        #[variadic]
        arguments: Vec<Value>,
    ) -> Args {
        args.take()
    }


Review comment (suggestion):
```suggestion
    fn get(&self, key: &ArgumentKey) -> Option<&Value> {
        let item = match key {
            &ArgumentKey::Index(index) => {
                let mut iter = self.items.iter().filter(|item| item.name.is_none());
                if index < 0 {
                    let index = (-(index + 1)).try_into().ok()?;
                    iter.nth_back(index)
                } else {
                    let index = index.try_into().ok()?;
                    iter.nth(index)
                }
            }

            // Accept the last argument with the right name.
            ArgumentKey::Name(name) => {
                self.items.iter().rfind(|item| item.name.as_ref() == Some(name))
            }
        };

        item.map(|item| &item.value.v)
    }
```
a bit less code duplication and potential cloning. requires `get(&key).cloned()` below

Code after:
                } else {
                    let index = index.try_into().ok()?;
                    iter.nth(index)
                }
            }
            // Accept the last argument with the right name.
            ArgumentKey::Name(name) => {
                self.items.iter().rfind(|item| item.name.as_ref() == Some(name))
            }
        };
        item.map(|item| &item.value.v)
    }
}

#[scope]
impl Args {
    /// Construct spreadable arguments in place.
    ///
    /// This function behaves like `{let args(..sink) = sink}`.
    ///
    /// ```example
    /// #let args = arguments(stroke: red, inset: 1em, [Body])
    /// #box(..args)
    /// ```
    #[func(constructor)]
    pub fn construct(
        /// The real arguments (the other argument is just for the docs).
        /// The docs argument cannot be called `args`.
        args: &mut Args,
        /// The arguments to construct.
        #[external]
        #[variadic]
        arguments: Vec<Value>,
    ) -> Args {
        args.take()
    }

    /// Returns the positional argument at the specified index, or the named
    /// argument with the specified name.
    ///
    /// If the key is an [integer]($int), this is equivalent to first calling
    /// [`pos`]($arguments.pos) and then [`array.at`]. If it is a [string]($str),
    /// this is equivalent to first calling [`named`]($arguments.named) and then
    /// [`dictionary.at`].
    #[func]
    pub fn at(
        &self,
        /// The index or name of the argument to get.
        key: ArgumentKey,
        /// A default value to return if the key is invalid.
        #[named]