Hi, I am trying to design wrapper around https://github.com/Microsoft/CNTK/blob/release/2.2/Source/CNTKv2LibraryDll/API/CNTKLibrary.h.
I have first version up and running, but I am quite unhappy with the ergonimics (and maybe that the wrapper seems like C++ forced into Rust).
I have functions with signature:
fn plus(x: &Variable, y: &Variable) -> Variable
fn times(x: &Variable, y: &Variable) -> Variable
In C++ the Variable class contains couple of shared_ptr
s. Thus Variable type needs to implement Drop, thus cannot implement Copy, but still can be Cloned.
My problem is around ergonomics where composing functions. Current state is like this:
let w = Variable::new(...);
let b = Variable::new(...);
let x = Variable::new(...);
let res = plus(×(&w, &x), &b);
The number of & feels quite high to me.
The question is: can this be fixed? Is any of following signatures better in communicating underlying intent:
fn plus(x: Variable, y: Variable) -> Variable
This would require couple of clones during calls (which I can live with and maybe better communicates the intent), but no & in function composition, which is nice.
fn plus<T: Borrow<Variable>, U: Borrow<Variable>>(x: T, y: U) -> Variable
This can be called either with reference or by value, but I feel, that it hides a lot of stuff and there are hidden implicit traps.
Second question: Since the most API variables are sort equivalents to Rc<T>
or Rc<RefCell<T>>
is the idiomatic way of passing Rc<T>
to function by value or by reference?