Accumulator factory: Difference between revisions
Content added Content deleted
m (Modfiy rust solution to use impl Trait instead of Box<dyn Trait>) |
(Add complicated generic solution for Rust) |
||
Line 2,866: | Line 2,866: | ||
8.3 |
8.3 |
||
</pre> |
</pre> |
||
=== Over-engineered Solution === |
|||
This solution uses a custom number type that can be either an i64 or f64. It also creates a generic struct that is callable using the unstable fn traits, which can be called to add anything that can be added to it's accumulator value. |
|||
<lang rust>// Accumulator |
|||
#![feature(unboxed_closures, fn_traits)] |
|||
pub struct Accumulator<T> { |
|||
value: T, |
|||
} |
|||
impl<T> Accumulator<T> { |
|||
pub fn new(value: T) -> Self { |
|||
Self { value } |
|||
} |
|||
} |
|||
impl<T, N> FnOnce<(N,)> for Accumulator<T> |
|||
where |
|||
T: std::ops::AddAssign<N> + Clone, |
|||
{ |
|||
type Output = T; |
|||
extern "rust-call" fn call_once(mut self, (n,): (N,)) -> T { |
|||
self.value += n; |
|||
self.value |
|||
} |
|||
} |
|||
impl<T, N> FnMut<(N,)> for Accumulator<T> |
|||
where |
|||
T: std::ops::AddAssign<N> + Clone, |
|||
{ |
|||
extern "rust-call" fn call_mut(&mut self, (n,): (N,)) -> T { |
|||
self.value += n; |
|||
self.value.clone() |
|||
} |
|||
} |
|||
// Number |
|||
#[derive(Copy, Clone, Debug)] |
|||
pub enum Number { |
|||
Int(i64), |
|||
Float(f64), |
|||
} |
|||
impl From<i64> for Number { |
|||
fn from(int: i64) -> Number { |
|||
Number::Int(int) |
|||
} |
|||
} |
|||
impl From<f64> for Number { |
|||
fn from(float: f64) -> Number { |
|||
Number::Float(float) |
|||
} |
|||
} |
|||
impl std::ops::AddAssign<i64> for Number { |
|||
fn add_assign(&mut self, n: i64) { |
|||
match self { |
|||
Number::Int(s) => *s += n, |
|||
Number::Float(s) => *s += n as f64, |
|||
} |
|||
} |
|||
} |
|||
impl std::ops::AddAssign<f64> for Number { |
|||
fn add_assign(&mut self, n: f64) { |
|||
*self = match *self { |
|||
Number::Int(s) => Number::Float(s as f64 + n), |
|||
Number::Float(s) => Number::Float(s + n), |
|||
} |
|||
} |
|||
} |
|||
impl std::fmt::Display for Number { |
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
|||
match self { |
|||
Number::Int(x) => write!(f, "{}", x), |
|||
Number::Float(x) => write!(f, "{}", x), |
|||
} |
|||
} |
|||
} |
|||
// Demonstration |
|||
fn foo(n: impl Into<Number>) -> Accumulator<Number> { |
|||
Accumulator::new(n.into()) |
|||
} |
|||
fn main() { |
|||
let mut x = foo(1); |
|||
x(5); |
|||
foo(3); |
|||
println!("{}", x(2.3)); |
|||
let mut s = Accumulator::new(String::from("rosetta")); |
|||
s(" "); |
|||
println!("{}", s("code")); |
|||
}</lang> |
|||
{{out}} |
|||
<pre>8.3 |
|||
rosetta code</pre> |
|||
=={{header|Scala}}== |
=={{header|Scala}}== |