struct initialize to satisfy an interface without explicit method definition - struct

Given pseudo go code below:
type(
MyStruct struct {
AFunction func(string) ([]byte, error)
}
MyInterface interface {
AFunction(string) ([]byte, error)
}
)
func NeedThis(s string) ([]byte, error){
//relevant function stuff
}
m := &MyStruct{AFunction: NeedThis}
The problem arises that m does not satisfy the MyInterface interface; and I can somewhat see why this would be so. Is there a way to attach functions to a struct in such a way that the constructed struct satisfies an interface without actually building out defining methods on the struct? I'm having some shadowy/faulty reasoning around this, maybe help to clarify this for me or show a better way to reason through this situation.

Could you not just define a method AFunction on MyStruct that dispatches to the stored AFunction function pointer? It's not ideal if you have a lot of these, but I think it does the job?
i.e. something like
func (s MyStruct) AFunction(str string) ([]byte, error) {
return s.AFunction(str)
}
edit: the above may cause the compiler to error because s.AFunction is ambiguous, so you might have to give them (the method and the function pointer) different names, but it should give the right idea.

You can wrap it in another struct that implements the interface:
http://play.golang.org/p/AgnYAWBdUp
package main
import "fmt"
type (
MyStruct struct {
AFunction func(string) ([]byte, error)
}
MyInterface interface {
AFunction(string) ([]byte, error)
}
)
func NeedThis(s string) ([]byte, error) {
//relevant function stuff
return nil, nil
}
type Proxy struct {
*MyStruct
}
func (x *Proxy) AFunction(s string) ([]byte, error) {
return x.MyStruct.AFunction(s)
}
func main() {
m := &MyStruct{AFunction: NeedThis}
p := &Proxy{m}
_, ok := MyInterface(p).(MyInterface)
fmt.Println(ok)
}

Related

Determine the parameter type when calling a macro

I have a macro with a path parameter and now I want to call it through a method. However I have a hard time figuring out the parameter type of the of the method parameter that would be passed as a macro parameter.
Below is simple repro. This example use case doesn't make sense but it shows my problem clearly.
Following works:
fn main() {
let val = get_value!(true, DataValue::Int).unwrap();
println!("{}", val);
}
#[macro_export]
macro_rules! get_value {
( $rs: expr, $data_value_type: path ) => {{
let rand_val = return_data_value($rs);
if let $data_value_type(val) = rand_val {
Ok(val)
} else {
Err("This would not work")
}
}};
}
fn return_data_value(random_select: bool) -> DataValue {
if random_select {
DataValue::Int(1)
} else {
DataValue::Float(2.3)
}
}
enum DataValue {
Int(i32),
Float(f64),
String(String),
Bool(bool),
}
Now I want to create a function that calls the macro: (In the real world scenario this would be a much more complex one, but this shows the problem I have)
fn invoke_macro(random_select: bool, fun: <What type?>) -> i32 {
get_value!(random_select, fun).unwrap()
}
So here, what is the type of the parameter fun should be? Whatever I did so far gave me following error:
error: expected tuple struct or tuple variant, found local variable `fun`
label: not a tuple struct or tuple variant
Compiler tells me that the type of $data_value_type (macro parameter) for this particular invocation is fn(i32) -> DataValue {DataValue::Int} but I don't know how I can use that to figure out the parameter type.
You cannot. Not every macro can be made into a function, since macros can do syntax transformations and functions cannot.
DataValue::Int (for instance) is a function, like any tuple struct/enum variant, and that's why the compiler says this is its type. This function allows you to create the variant, like in (playground):
#[derive(Debug)]
struct S(i32);
let f: fn(i32) -> S = S;
let s = f(123);
dbg!(s);
But here, you don't use it as a function, but rather for pattern matching. This does not have a type and cannot be expressed.

Aliasing trait inheritance with generics

I am starting to play with Rust for a new library. I'm trying to wrap my head around the possible ways to implement the following.
What follows is more of desired expression not real syntax. All of the ways I've tried to express this either don't compile, or don't compile when I go to implement one of the alias traits.
struct ConcreteType;
struct CommonType;
trait Handler<Rin, Rout = Rin>{
fn handle_event(&self, msg: &Rin);
}
// alias Handler with one of the types defined as a common case
trait HandlerToMessage<M> : Handler <ConcreteType, M>{
fn handle_event(&self, msg: &ConcreteType) {
// default implementation of parent trait
// example is simplified, forget about how Rout/M is actually used
self.decode(msg)
}
// method to implement
fn decode(&self, msg: &ConcreteType) -> M;
}
// another alias for most common case where Rin/Rout are ConcreteType, CommonType most often
trait HandlerToCommonType : HandlerToMessage <ConcreteType, CommonType>{
fn decode(&self, msg: &ConcreteType) -> CommonType
{
...
};
}
Alternative using associated types
trait Handler{
type Rin;
type Rout; // not yet able to do Rout = Rin with associated types
fn handle_event(&self, msg: &Self::Rin) -> Self::Rout;
}
trait HandlerToMessage : Handler <Rin=ConcreteType>{
fn handle_event(&self, msg: &Self::Rin) {
// common functionality
self.decode(msg)
}
// method to implement
fn decode(&self, msg: &Self::Rin) -> Self::Rout;
}
trait HandlerToCommonType : HandlerToMessage <Rout=CommonType>{
fn decode(&self, msg: &ConcreteType) -> CommonType
{
...
}
}
In C++ this is roughly what I want to accomplish
// real world example I've seen in the wild of this structure
template <class Rout>
class Context {
public:
void dispatch(Rout* msg);
};
template <class Rin, Rout = Rin>
class ReadHandler {
public:
void read (Context* ctx, Rin* msg) = 0;
private:
Context<Rout> ctx_;
};
// very common to convert from a byte buffer some message type
template <class M>
class BytesToMessageDecoder : ReadHandler<IOBuffer, M> {
public:
// Template method pattern
void read (Context* ctx, IOBuffer* msg) {
M msgOut;
bool success;
success = this->decode(msg, &msgOut);
if (success) {
ctx->dispatch(msgOut);
}
}
bool decode(IOBuffer* msg, M* msgOut) = 0;
}
// convert one byte buffer to another is common
typedef BytesToMessageDecoder<IOBuffer> BytesToBytesDecoder;
// Concrete implementations
// look for fixed number of bytes incoming
class FixedLengthFrameDecoder : BytesToBytesDecoder {
bool decode(IOBuffer* msg, IOBuffer* msgOut) { ... }
}
// fields are prefixed with a length. Wait for that many bytes and then dispatch
class LengthBasedFieldDecoder: BytesToBytesDecoder {
bool decode(IOBuffer* msg, IOBuffer* msgOut) { ... }
}
class StringDecoder : BytesToMessageDecoder<std::string> {
// decode from byte buffer to a string
bool decode(IOBuffer* msg, std::string* msgOut) { ... }
}
Basically the top level trait Handler is the most generic but maybe not meant to be implemented by anyone but advanced library users. The HandlerToMessage trait is meant to be a common conversion where we take ConcreteType and convert to some other type. The library may implement several of these. The HandlerToCommonType is the most common case that numerous library types would want to start from.
The details on how Rout is used in the Handler trait is not of importance. I tried to simplify the example and left off some arguments to hopefully make what I'm trying to convey more concise. All of my searching on this either has me thinking this isn't possible to convey or I am misusing it. I don't quite understand if this falls under the new specialization implementation, it doesn't feel like it from my understanding though.
I realize Rust is not C++ and so maybe what I'm trying to do is either not supported or has a different syntax. Any help is appreciated either in correct syntax or a more idiomatic Rust way.
Perhaps you can just have separate traits and implement one for all implementers of the other:
struct ConcreteType;
struct CommonType;
trait Handler<Input, Output = Input> {
fn handle_event(&self, msg: &Input) -> Output;
}
trait HandlerToMessage<M> {
fn decode(&self, msg: &ConcreteType) -> M;
}
impl<T, M> Handler<ConcreteType, M> for T
where T: HandlerToMessage<M>
{
fn handle_event(&self, msg: &ConcreteType) -> M {
self.decode(msg)
}
}
impl HandlerToMessage<CommonType> for () {
fn decode(&self, _msg: &ConcreteType) -> CommonType {
unimplemented!()
}
}
fn main() {}
The last one is really awkward because you'd normally implement a trait for a concrete type, but you haven't really presented any that make sense to implement for.

Get you struct back to it's data type after passing it as an interface and run it's methods?

I have a struct as follows
type MyStruct {
EmbeddedFooBar
}
func (m *MyStruct) Foo(b *http.Request) {
// Doing something
}
func fn(args ...interfaces) {
// It's here I want to get my struct back and run the "Get" method
// Please keep in mind I am too pass a pointer param into the struct method
strt := args[0]
....
get struct back to static data type MyStruct
and run "Get()", dont mind how/where I will get *http.Request to pass, assume I can
....
strt.Get(*http.Request)
}
func main() {
a := &MyStruct{}
fn(a)
}
I am passing the struct above to a variadic function fn that expects ...interfaces{} (thus any type can satisfy the params)
Inside the function fn I want to get back my struct MyStruct to it's data type and value and run it's method Get that can also accept receivers such as *http.Request
How do I get My Struct back from the interface arg[0] and run the method Get of the struct with the ability of passing a pointer.
What you want is Type Assertion. Solution could something like this:
func fn(args ...interfaces) {
if strt, ok := args[0].(*MyStruct); ok {
// use struct
} else {
// something went wrong
}
// .......
}
It sounds like what you want here is a specific interface, specifically one that has a Get method that accepts a pointer to an http.Request.
For example:
type Getter interface {
Get(*http.Request)
}
func fn(getters ...Getter) {
getter := getters[0]
getter.Get(*http.Request)
}
func main() {
a := &MyStruct{}
fn(a)
}
This allows the compiler to check that the arguments to fn have exactly the methods you need, but it doesn't need to know anything else about the type. Read more about interfaces here.

If struct A is embedded in B, can methods on A access method and fields of B?

struct A {}
func (a *A) BName(id int) string {
return a.Name
}
struct B {
*A
Name string
}
func main() {
b := &B{Name: "abc"}
fmt.Println(b.Name)
}
the code failure, I want know how to write code to achieve, A.BName can access B struct attribute Name
This is not possible. struct A does not know anything about the types it is embedded into. Think about it, A can be embedded into any other struct, so how could you know ahead of time the type of the struct that A is embedded into.
If you want to do this, you need to place a reference to B, the outer structure into A.
type A struct {
*B
}
func (a *A) PrintName() string { return a.B.Name }
type B struct {
A // no need to use a pointer here
Name string
}
var b B
b.A.B = &b
fmt.Println(b.PrintName())
A accessing B reminds me of a is-a relationship, where A "is-a" B.
The article "Is Go an Object Oriented language?" does note that there is no true subtyping in Go:
if it was truly subtyping then the anonymous field would cause the outer type to become the inner type. In Go this is simply not the case. The two types remain distinct.
The anonymous fields are still accessible as if they were embedded
Example:
package main
type A struct{
// doesn't know anything about B
}
type B struct {
A //B is-a A
}
func (a *A) f() { fmt.Println("A.f") }
func (b *B) f() { fmt.Println("B.f") }
func save(A) {
//do something
}
func main() {
b := B
save(&b) //OOOPS! b IS NOT A
b.f() // B.f()
b.A.f() // A.f()
}
One of the issues with multiple inheritance is that languages are often non obvious and sometimes even ambiguous as to which methods are used when identical methods exist on more than one parent class.
With Go you can always access the individual methods through a property which has the same name as the type.
In reality when you are using Anonymous fields, Go is creating an accessor with the same name as your type.
That is what "b.A" is: an accessor to an anonymous field..

Rust inheritance: call parent method

How does Rust call "parent method"? Like this in Javaļ¼š
public class parent{
...
public void doSomething(){
System.out.println("Parent method");
}
}
public class child extends parent{
...
public void doSomething(){
super.doSomething();
System.out.println("Child method.");
}
}
In Go, we can simulate it by anonymous fields in struct:
type parent struct{}
func (self *parent) doSomething() {
fmt.Println("parent method")
}
type child struct {
parent
}
func (self *child) doSomething() {
self.parent.doSomething()
fmt.Println("child method")
}
func main() {
var c1 child
c1.doSomething()
}
How to simulate it in Rust? Thanks!
It's not quite the same under the hood, but something like
trait DoThings {
fn do_something(&self);
}
struct Parent;
impl DoThings for Parent {
fn do_something(&self) { println("doing something"); }
}
struct Child {
parent: Parent
}
impl DoThings for Child {
fn do_something(&self) {
self.parent.do_something();
println("child");
}
}
fn main() {
let c = Child { parent: Parent };
c.do_something();
}
There are a few proposals for making parts of this automatic (e.g. if we wanted to just call the parent's method directly, i.e. don't override the method in the child, then currently one has to explicitly call the parent's method oneself).
The point of inheritance is being able to overwrite an inherited method. The samples provided above still deal with delegation and not with inheritance.
Let's have a look at some Go code to illustrate this:
type Base struct {}
func (Base) Magic() { fmt.Print("base magic") }
func (self Base) MoreMagic() {
self.Magic()
}
type Foo struct {
Base
}
func (Foo) Magic() { fmt.Print("foo magic") }
If you run the code above this way
f := new(Foo)
f.Magic()
it will print "foo magic" to the console and not "base magic". However, if we run this code
f := new(Foo)
f.MoreMagic()
it will not print "foo magic" as well, but this time "base magic". This is because of the lack of inheritance and thus not being able to overwrite method Magic (aka dynamic linking). So we are still dealing with delegation.
You can work around this f.ex. as described in the section "Inner Patern" in this article. I don't know exactly about this concerning Rust. At first sight it seems to be the same.

Resources