Repository: scikit-learn/scikit-learn
File: sklearn/metrics/_classification.py (Python)

Code before:
    balanced_accuracy_score : Compute the balanced accuracy to deal with
        imbalanced datasets.
    jaccard_score : Compute the Jaccard similarity coefficient score.
    hamming_loss : Compute the average Hamming loss or Hamming distance between
        two sets of samples.
    zero_one_loss : Compute the Zero-one classification loss. By default, the
        function will return the percentage of imperfectly predicted subsets.

    Examples
    --------
    >>> from sklearn.metrics import accuracy_score
    >>> y_pred = [0, 2, 1, 3]
    >>> y_true = [0, 1, 2, 3]
    >>> accuracy_score(y_true, y_pred)
    0.5
    >>> accuracy_score(y_true, y_pred, normalize=False)
    2.0

    In the multilabel case with binary label indicators:

    >>> import numpy as np
    >>> accuracy_score(np.array([[0, 1], [1, 1]]), np.ones((2, 2)))
    0.5
    """
    xp, _, device = get_namespace_and_device(y_pred)
    y_true, sample_weight = move_to(y_true, sample_weight, xp_ref=xp, device_ref=device)
    # Compute accuracy for each possible representation
    y_true, y_pred = attach_unique(y_true, y_pred)
    y_type, y_true, y_pred, sample_weight = _check_targets(
        y_true, y_pred, sample_weight
    )

    if y_type.startswith("multilabel"):
        differing_labels = _count_nonzero(y_true - y_pred, xp=xp, device=device, axis=1)
        score = xp.asarray(differing_labels == 0, device=device)
    else:
        score = y_true == y_pred

    return float(_average(score, weights=sample_weight, normalize=normalize))


@validate_params(
    {
        "y_true": ["array-like"],
        "y_pred": ["array-like"],
        "labels": ["array-like", None],
        "sample_weight": ["array-like", None],
        "normalize": [StrOptions({"true", "pred", "all"}), None],
    },
    prefer_skip_nested_validation=True,
)

Review comment (refactor):
It feels like we will end up with code like this "everywhere". This makes me wonder if it would be sensible to have one function that contains these two lines of code. Something like:
```python
# The function needs a good name
def clever_name(x, other_arrays):
    """Determine namespace and device of `x` and ensure `other_arrays` use them as well.

    If needed the `other_arrays` will be moved to the namespace and device used by `x`.
    """
    xp, _, device = get_namespace_and_device(x)
    moved_arrays = move_to(*other_arrays, xp_ref=xp, device_ref=device)
    return xp, device, x, *moved_arrays
```

If you squint in just the right way, you might call it `ensure_common_namespace_device`?

What do people think? Premature optimisation? Useful abstraction?

Code after:
@validate_params(
    {
        "y_true": ["array-like", "sparse matrix"],
        "y_pred": ["array-like", "sparse matrix"],
        "normalize": ["boolean"],
        "sample_weight": ["array-like", None],
    },
    prefer_skip_nested_validation=True,
)
def accuracy_score(y_true, y_pred, *, normalize=True, sample_weight=None):
    """Accuracy classification score.

    In multilabel classification, this function computes subset accuracy:
    the set of labels predicted for a sample must *exactly* match the
    corresponding set of labels in y_true.

    Read more in the :ref:`User Guide <accuracy_score>`.

    Parameters
    ----------
    y_true : 1d array-like, or label indicator array / sparse matrix
        Ground truth (correct) labels. Sparse matrix is only supported when
        labels are of :term:`multilabel` type.

    y_pred : 1d array-like, or label indicator array / sparse matrix
        Predicted labels, as returned by a classifier. Sparse matrix is only
        supported when labels are of :term:`multilabel` type.

    normalize : bool, default=True
        If ``False``, return the number of correctly classified samples.
        Otherwise, return the fraction of correctly classified samples.

    sample_weight : array-like of shape (n_samples,), default=None
        Sample weights.

    Returns
    -------
    score : float or int
        If ``normalize == True``, return the fraction of correctly
        classified samples (float), else returns the number of correctly
        classified samples (int).

        The best performance is 1 with ``normalize == True`` and the number
        of samples with ``normalize == False``.

    See Also
    --------
    balanced_accuracy_score : Compute the balanced accuracy to deal with
        imbalanced datasets.
    jaccard_score : Compute the Jaccard similarity coefficient score.
    hamming_loss : Compute the average Hamming loss or Hamming distance between