Jump to content

Accumulator factory: Difference between revisions

Add complicated generic solution for Rust
m (Modfiy rust solution to use impl Trait instead of Box<dyn Trait>)
(Add complicated generic solution for Rust)
Line 2,866:
8.3
</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}}==
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.