Associating a specific function in trait implementation - function

Is there a way to declare a generic trait that takes a function as the generic argument and uses it?
To clarify (Non-functioning code):
pub trait Test<F, T> where F: Fn(i32) -> T {
fn test(arg: i32) -> T {
let func: F;
func(arg)
}
}

You can associate specific functions when implementing a trait (didn't knew about this until now):
fn func() -> String {
String::from("hello")
}
trait MyTrait {
const FUNC: fn() -> String;
}
struct MyType;
impl MyTrait for MyType {
const FUNC: fn() -> String = func;
}
fn main() {
println!("{}", (MyType::FUNC)()); // prints hello
}
Playground

You can implement it somehow like this:
trait MyTrait<V: Sized + Fn() -> &'static str>: Sized {
fn construct(fun: V) -> Self;
fn get_fn(&self) -> &V;
fn call_inner(&self) {
println!("{}", (self.get_fn())());
}
}
struct FuncitonContainer<V>
where
V: Sized + Fn() -> &'static str,
{
f: V,
}
impl<V> MyTrait<V> for FuncitonContainer<V>
where
V: Sized + Fn() -> &'static str,
{
fn construct(fun: V) -> Self {
Self { f: fun }
}
fn get_fn(&self) -> &V {
&self.f
}
}
fn main() {
fn get_hello() -> &'static str {
"Hello"
}
FuncitonContainer::construct(get_hello).call_inner();
FuncitonContainer::construct(|| "World").call_inner();
}
It preserves function info and allows to use closures too. However, using it can be little more complex than Mihir's answer.
You can also look how Rust iterators are implemented: Rust iterators implementation

Related

How do I write a function that returns itself?

What I want to make is a function, that returns itself, so I can call it like this:
foo()()...()
In C# it would be done via delegates:
delegate SelfFunc SelfFunc();
static void Main() {
SelfFunc foo = null;
foo = () => {
return foo;
};
foo()()...();
}
Anticipating questions like "why implement such silly behavior?": I want to sum numbers in a very strange way using single function continues calls: foo(1)(2)(3)() = 6, but in this question I just want to know how to return function itself. Example realization of this method that I made in C#. This is all just for fun and to learn Rust:
static int sum = 0;
delegate dynamic InfFunc(int i = int.MaxValue);
static void InfFuncTest() {
InfFunc f = null;
f = (int i) => {
if(i == int.MaxValue) {
return sum;
}
sum += i;
return f;
};
var g = f;
var value = g(1)(2)(3)();
Console.WriteLine(value);
}
A function that returns itself is possible on nightly.
First you need to enable the features unboxed_closures and fn_traits.
Then you can define a struct which, when called, returns self. The full code looks something like this:
#![feature(unboxed_closures, fn_traits)]
struct SelfFunc;
impl FnOnce<()> for SelfFunc {
type Output = SelfFunc;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
self
}
}
Then you can call the function as many times as you want:
fn main() {
let f = SelfFunc;
f()()()()()();
}
Based on #cameron1024's answer, you can "overload" using traits, but you will need 2 structs to handle the empty case properly of foo() (here called Add) without any arguments returning 0.
#![feature(unboxed_closures, fn_traits)]
struct Add;
impl FnOnce<(u32,)> for Add {
type Output = AddImpl;
extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
AddImpl(args.0)
}
}
impl FnOnce<()> for Add {
type Output = u32;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
0
}
}
struct AddImpl(u32);
impl FnOnce<()> for AddImpl {
type Output = u32;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
self.0
}
}
impl FnOnce<(u32,)> for AddImpl {
type Output = AddImpl;
extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
Self(self.0 + args.0)
}
}
fn main() {
dbg!( Add(1)(2)(3)() );
dbg!( Add() );
}
Playground
If you do not care about the no-args foo() requirement, you can make Add a tuple struct instead and remove AddImpl:
#![feature(unboxed_closures, fn_traits)]
struct Add(u32);
impl FnOnce<(u32,)> for Add {
type Output = Add;
extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
Add(self.0 + args.0)
}
}
impl FnOnce<()> for Add {
type Output = u32;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
self.0
}
}
fn main() {
dbg!( Add(1)(2)(3)() );
//dbg!( Add() ); // doesn't compile
}
Playground
Although I should note that this likely isn't such a great idea, using an slice/iterator would likely result in cleaner code:
fn main() {
dbg!([1, 2, 3].iter().copied().sum::<u32>());
}
Playground

How to implement a multi-level currying function in Rust?

I attempt to implement a currying function similar to Functional Programming Jargon in Rust:
fn add_origin(x: i32) -> impl Fn(i32) -> i32 {
return move |y| {
x + y
};
}
fn main() {
let add5 = add_origin(5);
println!("Call closure: {}", add5(6));
}
This works, but if I add one level deeper:
fn add(x: i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 {
return move |y: i32| {
return move |z: i32| {
x + y + z
}
};
}
fn main() {
let add5 = add(5);
let add5_10 = add5(10);
println!("Call closure: {}", add5_10(6));
}
Compiler does not accept and tells me:
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/main.rs:7:35
|
7 | fn add(x: i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 {
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
Why is this not allowed? Is there a better alternative in Rust?
impl Trait syntax can only be used in argument position or return position of a function signature. Both of these are fine:
fn takes_fn(fn_arg: impl Fn(i32) -> i32) {}
fn returns_fn() -> impl Fn(i32) -> i32 {
|x| x
}
However neither of these work:
fn takes_fn(fn_arg: impl Fn(i32) -> impl Fn(i32) -> i32) {}
fn returns_fn() -> impl Fn(i32) -> impl Fn(i32) -> i32 {
|x| x
}
Because the second nested impl Trait is no longer in argument or return position but is now part of the argument or return type's signature, which is not somewhere where it is allowed. Basically, multiple nested impl Traits will never work regardless of where you place them and you'll always get the same compile error.
The good news is this doesn't stop you from accomplishing what you want to accomplish because impl Trait is just syntax sugar and its use is optional. In your particular example we can use a boxed trait object to return your curried function.
fn add(x: i32) -> impl Fn(i32) -> Box<dyn Fn(i32) -> i32> {
move |y: i32| {
Box::new(move |z: i32| {
x + y + z
})
}
}
fn main() {
let add5 = add(5);
let add5_10 = add5(10);
println!("Call closure: {}", add5_10(6)); // prints "Call closure: 21"
}
playground
See also:
What does `impl` mean when used as the argument type or return type of a function?
What makes `impl Trait` as an argument "universal" and as a return value "existential"?

Why does function pointer behaviour differ in Rust depending on the mutability of the function pointer?

When storing raw pointers to functions in structs in Rust, the behaviour of the program can change in unexpected ways depending on the mutability of the raw pointer.
Using const pointers gives the expected result.
The following code can also be viewed on the playground:
type ExternFn = unsafe extern "C" fn() -> ();
unsafe extern "C" fn test_fn() {
println!("Hello!");
}
mod mut_ptr {
use super::{ExternFn, test_fn};
#[derive(Debug, Eq, PartialEq)]
pub struct FunctionHolder {
function: *mut ExternFn,
}
impl FunctionHolder {
pub fn new() -> Self {
FunctionHolder {
function: (&mut (test_fn as ExternFn) as *mut _),
}
}
pub fn call(&self) {
if !self.function.is_null() {
unsafe { (&*self.function)(); }
}
}
}
}
mod const_ptr {
use super::{ExternFn, test_fn};
#[derive(Debug, Eq, PartialEq)]
pub struct FunctionHolder {
function: *const ExternFn,
}
impl FunctionHolder {
pub fn new() -> Self {
FunctionHolder {
function: (&(test_fn as ExternFn) as *const _),
}
}
pub fn call(&self) {
if !self.function.is_null() {
unsafe { (&*self.function)(); }
}
}
}
}
// use const_ptr::FunctionHolder;
use mut_ptr::FunctionHolder;
fn check_holder(holder: &FunctionHolder) -> bool {
let good = FunctionHolder::new();
println!("parameter = {:#?}", holder);
println!("expected = {:#?}", good);
holder == &good
}
fn main() {
let f0 = FunctionHolder::new();
println!("{:?}", f0);
let f1 = FunctionHolder::new();
println!("{:?}", f1);
// uncomment this line to cause a segfault if using the
// mut_ptr version :-(
// f1.call();
assert!(check_holder(&f1));
}
In the const_ptr module, the code behaves as expected: The pointer value stored in the FunctionHolder struct is the same regardless of where the function is called, and using the FunctionHolder::call method calls the function as required.
In the mut_ptr module, there are some unexpected differences:
The FunctionHolder::new method returns a struct holding a different value depending on the function in which it is called,
The FunctionHolder::call method causes a segfault.
fn() -> () is a function pointer. *const fn() -> () and *mut fn() -> () are function pointer pointers.
You want to use much simpler code, which also means there's no difference between the two implementations:
#[derive(Debug, Eq, PartialEq)]
pub struct FunctionHolder {
function: Option<ExternFn>,
}
impl FunctionHolder {
pub fn new() -> Self {
FunctionHolder {
function: Some(test_fn as ExternFn),
}
}
pub fn call(&self) {
if let Some(f) = self.function {
unsafe { f(); }
}
}
}
As mentioned in the comments, taking a mutable reference to a literal value constructs a new value each time:
fn main() {
println!("{:p}", &42);
println!("{:p}", &42);
println!("{:p}", &42);
println!("{:p}", &mut 42);
println!("{:p}", &mut 42);
println!("{:p}", &mut 42);
}
0x55a551c03a34
0x55a551c03a34
0x55a551c03a34
0x7ffd40dbb95c
0x7ffd40dbb9bc
0x7ffd40dbba1c
Immutable references to literals have implicit static promotion:
let a = &42;
// More-or-less
static HIDDEN: i32 = 42;
let a = &HIDDEN;
Mutable references to literals desugar to effectively:
let mut hidden: i32 = 42;
let a = &mut hidden;
By using raw pointers, you lose the support of the borrow checker to point out that your references don't live long enough for the mutable case.
See also:
Why is it legal to borrow a temporary?
Why can I return a reference to a local literal but not a variable?
What are the semantics of mutably borrowing a literal in Rust?

How to find the type of the caller of a function in Rust?

How can I get the caller type in my function?
struct A;
struct B;
impl A {
fn new() -> Self {
A
}
fn call_function(&self) {
B::my_function();
}
}
impl B {
pub fn my_function() {
println!("Hello");
// println!("{}" type_of_the_caller) // I want to get type A here
// Is it possible to get the caller type which is A in this case?
}
}
fn main() {
let a = A::new();
a.call_function();
}
Here is the working code in playground. This is simplified code for an example.
Rust doesn't have any machinery like this built-in. If you want to know some context inside a function then you'll need to pass it in as an argument.
Also, Rust doesn't have a way to get the name of a type, so you'd have to provide that too. For example, with a trait:
trait Named {
fn name() -> &'static str;
}
impl Named for A {
fn name() -> &'static str {
"A"
}
}
Which you might use like this:
impl B {
pub fn my_function<T: Named>(_: &T) {
println!("Hello");
println!("{}", T::name());
}
}
You just have to pass in the caller when you call it:
impl A {
fn call_function(&self) {
B::my_function(self);
}
}
Outputs:
Hello
A
You can have the compiler write the boilerplate by creating a macro and making use of the stringify! macro.
struct A;
struct B;
struct C;
trait Named {
fn name() -> &'static str;
}
macro_rules! make_named {
( $($x:ty),* ) => {
$(
impl Named for $x {
fn name() -> &'static str {
stringify!($x)
}
}
)*
};
}
make_named!(A, B);
make_named!(C);
fn main() {
println!("{:#?}", A::name());
println!("{:#?}", B::name());
println!("{:#?}", C::name());
}
playground

Is there a way to avoid dereferencing with trait objects?

I came across a problem which I thought would be perfect to use trait objects for. While I managed to make it work, it looks far more complicated than it should so I would like to know if there is a more optimal way to use trait objects.
Exemplified code:
/* This takes a slice of objects implementing trait and compares each of
them with all other objects in the slice, if they interact with each other
both objects should call a certain function with the other object as a parameter.
This is used for a collision system, in case you know of a better way to solve this please
let me know. */
fn foo(objects: &mut [Box<Trait>]) {
let mut active_objects: Vec<&mut Box<Trait>> = vec!();
for current in objects.iter_mut() {
for other in active_objects.iter_mut() {
if (**current).is_interacting(&***other) {
current.boo(&mut ***other);
other.boo(&mut **current);
}
}
active_objects.push(current);
}
}
trait Trait {
fn boo(&mut self, other: &mut Trait);
fn is_interacting(&self, other: & Trait) -> bool;
}
Is there a way I don't have to write something like &*** every time I want to use the actual object?
if (**current).is_interacting(&***other) becomes if current.is_interacting(&***other) as Rust automatically dereferences in this case.
As red75prime points out, as_mut() is a possibility to take a mutable reference to a Box, which provides an even better solution:
fn foo(objects: &mut [Box<Trait>]) {
let mut active_objects: Vec<&mut Box<Trait>> = vec!();
for current in objects.iter_mut() {
for other in active_objects.iter_mut() {
let current = current.as_mut();
let other = other.as_mut();
if current.is_interacting(other) {
current.boo(other);
other.boo(current);
}
}
active_objects.push(current);
}
}
trait Trait {
fn boo(&mut self, other: &mut Trait);
fn is_interacting(&self, other: &Trait) -> bool;
}
It's not necessary to keep references to Box objects in the active_objects vector. This should work and eliminates most of the dereferencing:
fn foo(objects: &mut [Box<Trait>]) {
let mut active_objects: Vec<&mut Trait> = vec!();
for current in objects.iter_mut() {
let current = current.as_mut();
for other in active_objects.iter_mut() {
if current.is_interacting(*other) {
current.boo(*other);
other.boo(current);
}
}
active_objects.push(current);
}
}
You can remove all dereferences in your code:
fn foo(objects: &mut [Box<Trait>]) {
let mut active_objects: Vec<&mut Box<Trait>> = vec![];
for current in objects.iter_mut() {
for other in active_objects.iter_mut() {
if current.is_interacting(other) {
current.boo(other);
other.boo(current);
}
}
active_objects.push(current);
}
}
You enable this by implementing the trait itself for references and boxes to the type:
impl<'a, T> Trait for &'a mut T
where
T: Trait + ?Sized,
{
fn boo(&mut self, other: &mut Trait) {
(**self).boo(other)
}
fn is_interacting(&self, other: &Trait) -> bool {
(**self).is_interacting(other)
}
}
impl<T> Trait for Box<T>
where
T: Trait + ?Sized,
{
fn boo(&mut self, other: &mut Trait) {
(**self).boo(other)
}
fn is_interacting(&self, other: &Trait) -> bool {
(**self).is_interacting(other)
}
}
This is a one-time piece of code that you add near your trait definition allowing the call site to be cleaner.