Copy generictype + trait implementation for array needed in a separate function


#1

Hello to all

I face some issues trying to port code from Scala to Rust.

  1. Copy and generic in argument function passing

Let assume that we have this 2 generic functions

fn foo1<A>(a :&A) {}
fn foo2<A>(a :&mut A) {}

In the case of A is a copyable type, does Rust will copy a in the case of foo1 and passing a reference/pointer in the case of foo2?

  1. trait implementation for array
    I manage to implement a trait for array and use functions as extensions functions. However I do not manage to use it in a separate generic function (it works with hashmap fo example).

use std::collections::*;
use std::hash::*;

type Int = i32;
type Real = f64;
type Size = usize;



trait Tensor<K, V> {
	fn size(&self) -> Size;
	fn apply(&self, k :K) -> V;
	fn update(&mut self, k :K, v :V);
}


impl <V> Tensor<Size, V> for [V] {
	fn size(&self) -> Size {
		self.len()
	}
	
	fn apply(&self, k: Size) -> V {
		(*self)[k]
	}
	
	fn update(&mut self, k :Size, v :V) {
		(*self)[k] = v
	}
}

impl <K :Eq + Hash, V> Tensor<K, V> for HashMap<K, V> {
	fn size(&self) -> Size {
		self.len() as Size
	}
	
	fn apply(&self, k: K) -> V {
		(*self)[&k]
	}
	
	fn update(&mut self, k :K, v :V) {
		self.insert(k, v);
	}
}


fn test<
	K, V,
	C :Tensor<K, V>
	>(c :&C) {
}

fn test2<
	K1, K2, V, 
	C2 :Tensor<K2, V>, 
	C1 :Tensor<K1, C2>,
	>(c :&C1) {
}


use std::rc::*;

fn main() {
	let mut a = [1, 2, 3, 8];
	a.apply(2);
	a[0] = 5;
	let h = 5;
	let r = Rc::new(&h)
	let mut map2 = HashMap::new();
	map2.insert("a", r.clone());
	println!("{}", *r);
	let mut map = HashMap::new();
	map.insert("a", map2);
	test(&map);
	test(&a);  // THIS DOES NOT WORK
	test2(&map);
}

Kind regards

Sebastien


#2

You might want to edit your post and format the code properly. You want to put Rust code inside fences like so:

```rust
fn foo1(a: &A) {}
// ...
```

#3

Is there a typo somewhere? Both functions take A by reference.

As the compiler has pointed out, [i32; 4] and [i32] are different types.

Apparently either DST or deref coercions work out in this case but not in the test(&a) case. You can work around that by slicing the array manually:

fn test<K, V, C: Tensor<K, V> + ?Sized>(c: &C) {}
//...
test(&a[..]);

#4

Thanks for the reply.

There is no typo error.
My question was about the representation of a reference in Rust. In C++, as far as I know compiler optimize reference passing. In the case of an immutable reference of an object that can be copied, I would guess that passing by copy is more efficient.

On the same subject is it possible to define different passing argument strategies depending if an object can be copy or not?


#5
fn foo<A>(a: A) {}        // Passed by value; copied if A: Copy, else moved
fn foo1<A>(a: &A) {}      // Passed by immutable (shared) reference
fn foo2<A>(a: &mut A) {}  // Passed by mutable (unique) reference

The compiler is free to make any optimizations that preserve the semantics. But the above are the semantics that each of these types of argument passing have. If you’re interested in what it actually compiles down to, https://play.rust-lang.org/ and http://rust.godbolt.org/ can help you see what some given code actually optimizes down into; the latter provides some nice visualization since it uses debug information to highlight lines corresponding the original source, though this actually disables some optimizations so you may need to turn it off if you want to see the fully optimized code.


What is the implementation of `count_ones`?