diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..b10b354 --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +CARGO_TERM_COLOR=always +RUST_BACKTRACE=full +RUST_LOG=debug,concision=info \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index d9fe139..8f2cefa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,9 +73,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.51" +version = "1.2.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" +checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3" dependencies = [ "find-msvc-tools", "shlex", @@ -128,18 +128,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstyle", "clap_lex", @@ -282,9 +282,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "find-msvc-tools" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" +checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41" [[package]] name = "fnv" @@ -393,9 +393,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -436,9 +436,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libm" @@ -461,12 +461,38 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matrixmultiply" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" +dependencies = [ + "autocfg", + "rawpointer", +] + [[package]] name = "memchr" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +[[package]] +name = "ndarray" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "portable-atomic", + "portable-atomic-util", + "rawpointer", + "serde", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -493,6 +519,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -565,6 +600,21 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "portable-atomic" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -582,18 +632,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" dependencies = [ "proc-macro2", ] @@ -662,6 +712,12 @@ dependencies = [ "serde_with", ] +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rayon" version = "1.11.0" @@ -713,7 +769,7 @@ checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rspace" -version = "0.0.7" +version = "0.0.8" dependencies = [ "criterion", "rspace-core", @@ -724,7 +780,7 @@ dependencies = [ [[package]] name = "rspace-core" -version = "0.0.7" +version = "0.0.8" dependencies = [ "getrandom", "hashbrown 0.16.1", @@ -742,9 +798,10 @@ dependencies = [ [[package]] name = "rspace-traits" -version = "0.0.7" +version = "0.0.8" dependencies = [ "hashbrown 0.16.1", + "ndarray", "num-complex", "num-traits", "paste", @@ -804,9 +861,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.148" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", @@ -825,7 +882,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.12.1", + "indexmap 2.13.0", "serde", "serde_derive", "serde_json", @@ -874,9 +931,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.112" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -1208,18 +1265,18 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", "quote", @@ -1228,6 +1285,6 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.7" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de9211a9f64b825911bdf0240f58b7a8dac217fe260fc61f080a07f61372fbd5" +checksum = "ac93432f5b761b22864c774aac244fa5c0fd877678a4c37ebf6cf42208f9c9ec" diff --git a/Cargo.toml b/Cargo.toml index 19e725b..2daf505 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,16 +20,17 @@ license = "Apache-2.0" readme = "README.md" repository = "https://github.com/FL03/rspace.git" rust-version = "1.85.0" -version = "0.0.7" +version = "0.0.8" [workspace.dependencies] -rspace = { default-features = false, path = "rspace", version = "0.0.7" } -rspace-core = { default-features = false, path = "core", version = "0.0.7" } -rspace-traits = { default-features = false, path = "traits", version = "0.0.7" } +rspace = { default-features = false, path = "rspace", version = "0.0.8" } +rspace-core = { default-features = false, path = "core", version = "0.0.8" } +rspace-traits = { default-features = false, path = "traits", version = "0.0.8" } # development & benchmarking criterion = { version = "0.8" } # data structures hashbrown = { default-features = false, version = "0.16" } +ndarray = { default-features = false, version = "0.17" } # error handling anyhow = { default-features = false, version = "1" } thiserror = { default-features = false, version = "2" } diff --git a/core/Cargo.toml b/core/Cargo.toml index 4326b64..c6cdbf8 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -56,6 +56,7 @@ default = ["std"] full = [ "default", "complex", + "ndarray", "hashbrown", "json", "rand", @@ -80,6 +81,7 @@ nightly = [ # ********* [FF] Environments ********* std = [ "alloc", + "getrandom?/std", "rspace-traits/std", "hashbrown?/default", "num-complex?/std", @@ -113,6 +115,10 @@ alloc = [ complex = ["dep:num-complex"] +ndarray = [ + "rspace-traits/ndarray", +] + hashbrown = [ "dep:hashbrown", "rspace-traits/hashbrown", diff --git a/default.nix b/default.nix index b7dacd0..5528100 100644 --- a/default.nix +++ b/default.nix @@ -26,7 +26,7 @@ let }; common = { - version = "0.0.7"; + version = "0.0.8"; src = self; cargoLock = { diff --git a/flake.nix b/flake.nix index 07a096e..454b6f1 100644 --- a/flake.nix +++ b/flake.nix @@ -19,7 +19,7 @@ in rec { packages.default = pkgs.rustPlatform.buildRustPackage { pname = "rspace"; - version = "0.0.7"; + version = "0.0.8"; src = self; # ./.; cargoLock = { lockFile = ./Cargo.lock; diff --git a/rspace/Cargo.toml b/rspace/Cargo.toml index c2ab9df..7c876e4 100644 --- a/rspace/Cargo.toml +++ b/rspace/Cargo.toml @@ -54,6 +54,7 @@ default = ["std"] full = [ "default", "complex", + "ndarray", "hashbrown", "json", "rand", @@ -104,6 +105,11 @@ complex = [ "rspace-traits/complex", ] +ndarray = [ + "rspace-core/ndarray", + "rspace-traits/ndarray", +] + hashbrown = [ "rspace-core/hashbrown", "rspace-traits/hashbrown", diff --git a/rspace/lib.rs b/rspace/lib.rs index be5b6b8..3bc43b9 100644 --- a/rspace/lib.rs +++ b/rspace/lib.rs @@ -27,7 +27,7 @@ pub use rspace_traits as traits; #[doc(inline)] pub use rspace_core::*; #[doc(inline)] -pub use rspace_traits::*; +pub use rspace_traits::prelude::*; // prelude #[doc(hidden)] pub mod prelude { diff --git a/traits/Cargo.toml b/traits/Cargo.toml index d019ade..10fb53e 100644 --- a/traits/Cargo.toml +++ b/traits/Cargo.toml @@ -34,6 +34,7 @@ test = true [dependencies] # data-structures hashbrown = { optional = true, workspace = true } +ndarray = { optional = true, workspace = true } # mathematics num-complex = { optional = true, workspace = true } num-traits = { workspace = true } @@ -48,19 +49,24 @@ default = ["std"] full = [ "default", "complex", + "ndarray", "hashbrown", "rand", "serde", ] +# ********* [FF] Features ********* + nightly = [ "hashbrown?/nightly", ] -# ************* [FF:Environments] ************* +# ********* [FF] Environments ********* + std = [ "alloc", "hashbrown?/default", + "ndarray?/std", "num-complex?/std", "num-traits/std", ] @@ -70,7 +76,9 @@ wasi = [] wasm = [ "wasm_bindgen", ] -# ************* [FF:Dependencies] ************* + +# ********* [FF] Dependencies ********* + alloc = [ "hashbrown?/alloc", ] @@ -79,6 +87,8 @@ complex = ["dep:num-complex"] hashbrown = ["dep:hashbrown"] +ndarray = ["dep:ndarray"] + rayon = [ "hashbrown?/rayon", ] @@ -89,6 +99,7 @@ rand = [ serde = [ "hashbrown?/serde", + "ndarray?/serde", "num-complex/serde", ] diff --git a/traits/src/functor.rs b/traits/src/functor.rs index 201e639..cafe884 100644 --- a/traits/src/functor.rs +++ b/traits/src/functor.rs @@ -3,6 +3,10 @@ Contrib: @FL03 */ +#[deprecated( + since = "0.0.7", + note = "The `Functor` trait has been renamed to `MapTo` and `MapInto` for better clarity." +)] /// The [`Functor`] trait describes an interface for a higher-kinded type that can be mapped /// over. The trait is parameterized over a function `F` and a target type `T`, allowing for /// granular control over the mapping process itself, relying on associated types like @@ -34,6 +38,7 @@ where /* ************* Implementations ************* */ +#[allow(deprecated)] impl Functor for Option where F: FnOnce(U) -> V, @@ -46,6 +51,7 @@ where } } +#[allow(deprecated)] impl<'a, U, V, F> Functor for &'a Option where F: FnOnce(&U) -> V, @@ -58,6 +64,7 @@ where } } +#[allow(deprecated)] #[cfg(test)] mod tests { use super::*; diff --git a/traits/src/impls/impl_apply.rs b/traits/src/impls/impl_apply.rs index 08715cf..5eb8b04 100644 --- a/traits/src/impls/impl_apply.rs +++ b/traits/src/impls/impl_apply.rs @@ -3,7 +3,7 @@ Created At: 2026.01.01:21:39:28 Contrib: @FL03 */ -use crate::ops::apply::{Apply, ApplyMut, ApplyOnce}; +use crate::ops::{Apply, ApplyMut, ApplyOnce}; impl ApplyOnce for Option where diff --git a/traits/src/impls/impl_map.rs b/traits/src/impls/impl_map.rs index 5df7572..51810df 100644 --- a/traits/src/impls/impl_map.rs +++ b/traits/src/impls/impl_map.rs @@ -3,16 +3,16 @@ Created At: 2026.01.01:21:59:39 Contrib: @FL03 */ -use crate::ops::map::{MapInto, MapTo}; +use crate::ops::{MapInto, MapTo}; -impl MapInto for Option +impl MapInto for Option where - F: FnOnce(X) -> Y, + F: FnOnce(U) -> V, { - type Cont = Option; - type Elem = X; + type Cont = Option; + type Elem = U; - fn map_into(self, f: F) -> Self::Cont { + fn apply(self, f: F) -> Self::Cont { self.map(f) } } @@ -24,53 +24,88 @@ where type Cont = Option; type Elem = &'a X; - fn map_into(self, f: F) -> Self::Cont { + fn apply(self, f: F) -> Self::Cont { self.as_ref().map(f) } } -impl MapTo for Option +impl<'a, U, V, F> MapTo for Option<&'a U> where - F: FnOnce(&X) -> Y, + for<'b> F: FnOnce(&'b U) -> V, { - type Cont = Option; - type Elem = X; + type Cont = Option; + type Elem = &'a U; - fn map_to(&self, f: F) -> Self::Cont { - self.as_ref().map(f) + fn apply(&self, f: F) -> Self::Cont { + self.map(f) + } +} + +#[cfg(feature = "ndarray")] +mod impl_ndarray { + use super::{MapInto, MapTo}; + use ndarray::{Array, ArrayBase, Data, Dimension}; + + impl MapInto for ArrayBase + where + A: Clone, + D: Dimension, + S: Data, + F: Fn(A) -> B, + { + type Cont = Array; + type Elem = A; + + fn apply(self, f: F) -> Self::Cont { + self.mapv(f) + } + } + + impl MapTo for ArrayBase + where + A: Clone, + D: Dimension, + S: Data, + F: Fn(A) -> B, + { + type Cont = Array; + type Elem = A; + + fn apply(&self, f: F) -> Self::Cont { + self.mapv(f) + } } } #[cfg(all(feature = "alloc", feature = "nightly"))] mod impl_alloc { - use crate::ops::map::{MapInto, MapTo}; + use super::{MapInto, MapTo}; use alloc::alloc::Allocator; use alloc::vec::Vec; - impl MapInto for Vec + impl MapInto for Vec where A: Allocator, - F: FnMut(X) -> Y, - Vec: FromIterator, + F: FnMut(U) -> V, + Vec: FromIterator, { - type Cont = Vec; - type Elem = X; + type Cont<_T> = Vec<_T, A>; + type Elem = U; - fn map_into(self, f: F) -> Self::Cont { + fn apply(self, f: F) -> Self::Cont { self.into_iter().map(f).collect() } } - impl MapTo for Vec + impl<'a, U, V, A, F> MapTo for &'a Vec where A: Allocator, - F: FnMut(&X) -> Y, - Vec: FromIterator, + F: FnMut(&U) -> V, { - type Cont = Vec; - type Elem = X; + type Cont<_T> = Vec<_T, A>; + type Elem = &'a U; - fn map_to(&self, f: F) -> Self::Cont { + fn apply(&self, f: F) -> Self::Cont { self.iter().map(f).collect() } } @@ -78,7 +113,7 @@ mod impl_alloc { #[cfg(all(feature = "alloc", not(feature = "nightly")))] mod impl_alloc { - use crate::ops::map::{MapInto, MapTo}; + use super::{MapInto, MapTo}; use alloc::vec::Vec; impl MapInto for Vec @@ -86,23 +121,22 @@ mod impl_alloc { F: FnMut(X) -> Y, Vec: FromIterator, { - type Cont = Vec; + type Cont<_U> = Vec<_U>; type Elem = X; - fn map_into(self, f: F) -> Self::Cont { + fn apply(self, f: F) -> Self::Cont { self.into_iter().map(f).collect() } } - impl MapTo for Vec + impl<'a, U, V, F> MapTo for &'a Vec where - F: FnMut(&X) -> Y, - Vec: FromIterator, + F: FnMut(&U) -> V, { - type Cont = Vec; - type Elem = X; + type Cont<_T> = Vec<_T>; + type Elem = &'a U; - fn map_to(&self, f: F) -> Self::Cont { + fn apply(&self, f: F) -> Self::Cont { self.iter().map(f).collect() } } diff --git a/traits/src/impls/impl_space.rs b/traits/src/impls/impl_space.rs index a4a1869..bd172fd 100644 --- a/traits/src/impls/impl_space.rs +++ b/traits/src/impls/impl_space.rs @@ -51,6 +51,7 @@ impl_scalar_space! { bool, char } } + #[cfg(feature = "alloc")] impl_scalar_space! { impl RawSpace for { @@ -123,7 +124,6 @@ impl_raw_space! { std::sync::LazyLock, std::collections::HashMap, std::collections::HashSet, - } } @@ -135,6 +135,13 @@ impl_raw_space! { } } +#[cfg(feature = "ndarray")] +impl_raw_space! { + impl RawSpace for { + ndarray::ArrayBase { where S: ndarray::Data, D: ndarray::Dimension }, + } +} + #[cfg(feature = "complex")] impl RawSpace for num_complex::Complex { type Elem = T; diff --git a/traits/src/lib.rs b/traits/src/lib.rs index 4fffa12..2c7552b 100644 --- a/traits/src/lib.rs +++ b/traits/src/lib.rs @@ -45,9 +45,9 @@ pub mod ops { #[doc(inline)] pub use self::{apply::*, get::*, map::*}; - pub(crate) mod apply; - pub(crate) mod get; - pub(crate) mod map; + mod apply; + mod get; + mod map; pub(crate) mod prelude { pub use super::apply::*; @@ -57,7 +57,7 @@ pub mod ops { } // re-exports #[doc(inline)] -pub use self::{container::*, functor::*, ops::*, space::*, store::*}; +pub use self::{container::*, functor::*, ops::prelude::*, space::*, store::*}; // prelude #[doc(hidden)] pub mod prelude { diff --git a/traits/src/ops/apply.rs b/traits/src/ops/apply.rs index 5354ae0..025847c 100644 --- a/traits/src/ops/apply.rs +++ b/traits/src/ops/apply.rs @@ -3,8 +3,8 @@ Created At: 2025.12.24:17:20:29 Contrib: @FL03 */ -/// [`Apply`] defines an interface for objects capable of _applying_ the given function onto -/// itself or its elements to produce some output. +/// [`Apply`] establishes a binary operator for applying a given object, typically a function or +/// closure, onto a target object, producing some output. pub trait Apply { type Output; diff --git a/traits/src/ops/map.rs b/traits/src/ops/map.rs index acd5d6d..75c1aa5 100644 --- a/traits/src/ops/map.rs +++ b/traits/src/ops/map.rs @@ -3,36 +3,59 @@ Created At: 2026.01.01:21:31:12 Contrib: @FL03 */ -/// The [`MapTo`] trait defines an interface for containers able to _map_ or apply a given -/// function onto a reference to each of its constituting elements, producing a new container -/// with the results of those function applications. The construction of the trait itself -/// allows implementors to have granular controls over exactly which type of function and -/// output is being produced, relying on associated type parameters to define the container -/// and its _current_ element type. -pub trait MapTo +/// [`MapInto`] defines an interface for containers capable of applying a given function onto +/// each of their elements and consuming the container in the process, producing a new +/// container containing the captured results of each invocation. The trait's design allows +/// implementors to specify the exact function signature and output type, utilizing associated +/// type parameters to define the container and its _current_ element type. +pub trait MapInto where - F: FnOnce(&Self::Elem) -> X, + F: FnOnce(Self::Elem) -> T, { - type Cont: ?Sized; + type Cont<_T>: ?Sized; + /// the current type of element associated with the contained type Elem; - fn map_to(&self, f: F) -> Self::Cont; + fn apply(self, f: F) -> Self::Cont; } -/// [`MapInto`] describes a consuming interface for containers that enables the mapping of a -/// given function onto each element of the container. While the trait definition constrains -/// the generic function parameters, `F` to a `FnOnce` closure, implementors coulds choose -/// to strengthen this constraint to `FnMut` or `Fn` as needed. -pub trait MapInto + +/// The [`MapTo`] trait is similar to [`MapInto`], but it operates on references to the +/// container rather than consuming it. This allows for mapping functions over the elements +/// of a container while retaining ownership of the original container. +pub trait MapTo where F: FnOnce(Self::Elem) -> X, { - type Cont: ?Sized; - /// the current type of element associated with the contained + type Cont: ?Sized; type Elem; - fn map_into(self, f: F) -> Self::Cont; + fn apply(&self, f: F) -> Self::Cont; } /* ************* Implementations ************* */ + +#[cfg(test)] +mod tests { + + #[test] + fn test_map_into_on_option() { + use super::MapInto; + fn sample_once(input: u8) -> f32 { + input as f32 + 1.25 + } + let exp = Some(43.25f32); + assert_eq! { Some(42u8).apply(sample_once), exp } + } + + #[test] + fn test_map_to_on_option() { + use super::MapTo; + fn sample_ref(input: &u8) -> f32 { + *input as f32 + 1.25 + } + let exp = Some(43.25f32); + assert_eq! { Some(&42u8).apply(sample_ref), exp } + } +}