# subject

Extention trait pattern helper.

_The author of this crate is not good at English._  
_Forgive me if the document is hard to read._

## What is this?

This simple crate allows the [Extension Trait pattern][ExtTrait]
to be applied without method name collisions.

The core idea is simply to guarantee that `S<T>` has no methods,
neither now nor in the future (there are a more other things, but
they're just [added bonuses](#bonus-items)).

Of course, you can create the same one in an instant.
But documenting the reason why you introduced such an empty type
is probably not a fun task. That's where this crate comes in.

## Extention Trait pattern

A pattern for enabling more places to be written using method call notation.

Method call notation has the following characteristics compared to
standard function call notation.

- The main argument is clear
- Method chaining is supported
- IDE autocomplete is efficient

Therefore, even if the functionality of the function version and
the method version are the same, the latter is generally preferred.

However, we cannot add methods to other crate types. Thus, in the
Extension Trait pattern, methods are added not to the type itself,
but to the trait that the type implements.

In the following example, the `map_nan` method is added
to `f32` in the `std` crate.

```rust
fn main() {
    let x = f32::NAN;
    assert_eq!(x.map_nan(0.0), 0.0);
}

pub trait F32Ext {
    fn map_nan(self, substitute: f32) -> f32;
}

impl F32Ext for f32 {
    fn map_nan(self, substitute: f32) -> f32 {
        if self.is_nan() { substitute } else { self }
    }
}
```

## Target problem and solution

In the previous example, a name collision occurs if a new version of Rust
introduced `map_nan` to `f32`. In this case, an error will occur if counts
and types of arguments differ; otherwise, the target will be changed silently
(in spec as of 2026). And this problem is treated as "possibly breaking" in
[official document][ChangeCategories] (I feel uneasy about this). And if it
becomes a problem, it instructs to use fully qualified syntax. However, it
does not offer the benefits like method notation.

This issue can be solved by this crate as follows.

```rust
use subject::prelude::*;

fn main() {
    let x = f32::NAN;
    assert_eq!(S(x).map_nan(0.0), 0.0);
}

pub trait F32Ext {
    fn map_nan(self, substitute: f32) -> f32;
}

impl F32Ext for S<f32> {
    fn map_nan(self, substitute: f32) -> f32 {
        if self.0.is_nan() { substitute } else { self.0 }
    }
}
```

## Full method chain style

`S(x)` might look a bit clunky when `x` is a method chain. You can write
this as `x.r#use()` by using `UseExt::r#use`. This allows you to combine
the entire expression into a single method chain.

By the way, there is a potential for name collisions here, as mentioned
earlier, but this is unlikely to be a major issue. First, the use of
`UseExt` is optional. Also, as you may have noticed, using keywords as
identifiers helps prevent collisions.

```rust
use subject::prelude::*;
use subject::UseExt;
use std::ops::{Add, Sub};

fn main() {
    let x = f32::NAN;
    assert_eq!(x.add(1.0).sub(1.0).r#use().map_nan(0.0), 0.0);
}

pub trait F32Ext {
    fn map_nan(self, substitute: f32) -> f32;
}

impl F32Ext for S<f32> {
    fn map_nan(self, substitute: f32) -> f32 {
        if self.0.is_nan() { substitute } else { self.0 }
    }
}
```

## Bonus items

This crate includes several commonly used extensions. For example,
`UpgetExt::upget` performs both updates and get operations at once.
(For details, see the `exts` module document.)

## History

See [CHANGELOG](CHANGELOG.md).

<!-- links -->

[ExtTrait]: #extention-trait-pattern
[ChangeCategories]: https://doc.rust-lang.org/cargo/reference/semver.html#change-categories
