1

let's say I have a Struct like this.

Struct MyStruct {

  my_variable:bool

}

and an impl

impl MyStruct {

  pub fn new() {

    Self::my_variable = true; //Error

  }

}

gives me

no function or associated item named my_variable found for struct MyStruct in the current scope

My goal here is to set an event callback to pass as an argument of a method from web_sys;

basically I would like to convert this typescript class/behaviour to Rust

class Peer {

  makingOffer = false;

    peer:RTCPeerConnection

    constructor() {

      this.peer = new RTCPeerConnection();

      this.peer.onnegotiationneeded = this.onNegotiationNeeded

    }

  onNegotiationNeeded = async () => {

          this.makingOffer = true;

  }

}

and here is my Rust implementation

Struct Peer {

  peer:RtcPeerConnection
  making_offer:bool

}


impl Peer {

  pub fn new() -> Self {

    let making_offer = false;

    let peer: RtcPeerConnection= RtcPeerConnection::new().expect("failed to construct new peer connection");

    peer.set_onnegotiationneeded(/*callback should go here*/);

    Peer {
      peer,
      making_offer
    }

  }

}

I'm really new to rust and come from javascript where this kind of behaviour is fairly simple to me, so I don't master all of the code I wrote but some of it is taken from the wasm bingen tutorials.

JSmith
  • 4,519
  • 4
  • 29
  • 45
  • `my_variable` in your code snippet shown is not a global variable; it's an instance variable belonging to the struct, and you'll get a fresh version of it each time you make an instance of that struct. If you really want a global variable, then I believe [this question](https://stackoverflow.com/questions/27791532/how-do-i-create-a-global-mutable-singleton) is the one you're looking for. If you want a local variable to the struct, then I can write up an answer on how to write a constructor (`new`) for that. – Silvio Mayolo Apr 19 '23 at 02:07
  • @SilvioMayolo Thank you for your answer.I've noticed Rust is not that much OOP by default so if you are able to write me how to achieve what I would like and answer I'll be glad to mark it as answer and upvote it.I would prefer to avoid global variables and keep it as OOP as possible.Many thanks in advance. – JSmith Apr 19 '23 at 02:29
  • 1
    Take a look at my answer and see if it helps. I'm not entirely sure what's going on with your `animal` snippet so I can't really speak to that *too* much. But if you need some more specific help with that use case, feel free to clarify (or split it into another question, if you think it's too much of a tangent) and we can take a look at that as well. – Silvio Mayolo Apr 19 '23 at 02:39

1 Answers1

2

Based on the comment, it sounds to me like you aren't looking for a global variable but are instead looking to make a variable on the struct. If so, you've got the right syntax for declaring the variable.

struct MyStruct {
  my_variable: bool
}

(Side note: Rust struct variables are private by default. I assume this is what you want, but if you want the variable to be public to folks outside the current module, you can prefix the variable name with pub as pub my_variable: bool)

Now here's the part where things start to diverge. You're writing an associated function called new. The name new is commonly used to construct objects in Rust, and indeed we often call it a constructor, but it's not special. You mentioned coming from other more typical OOP languages, so for comparison, new is not at all like a constructor in Java, which is a designated function treated specially by the compiler.

The "constructor" for your struct is the special syntax MyStruct { my_variable: ... }. This syntax cannot be overridden and no custom behavior can be added to it.

However, since your structure has private members, you can only use this syntax in the current module. So what we're going to do (and this pattern is very common) is write an associated function called new that calls this constructor. This associated function is basically the equivalent of a static function in Java. Whenever you write a new function in Rust, you're basically writing a static factory function, to borrow Java terminology.

Now since this is a static function, it doesn't get a self. In fact, we're just going to construct a new instance of the structure and then return it.

impl MyStruct {
  pub fn new() -> MyStruct {
    MyStruct {
      my_variable: true
    }
  }
}

Remember that, in Rust, the last expression of a block is returned by default, so it's as though we wrote return MyStruct { my_variable: true }.

We call this constructor-like function as MyStruct::new().

Now, when you write other functions on the inherent impl, they can take a self argument.

impl MyStruct {
  pub fn is_my_variable_true(&self) -> bool {
    self.my_variable
  }
}

We always take an explicit self in Rust if we want one; we never just "get an instance" for free. It's sort of like in Python, where we always write self explicitly, except that the keyword self is special in Rust and enables the instance-method-like call syntax, not just a convention.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • Please take a look at [this](https://rustwasm.github.io/docs/wasm-bindgen/examples/webrtc_datachannel.html).one of the many events methods are used to set an event callback like `set_ondatachannel`. here is the full doc all starting by `set` here is [the one I'm using](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.RtcPeerConnection.html#method.set_onnegotiationneeded).Basically I need to have access to this variable as a member.If I create a function in my impl I will need to add `&self` which breaks the event setter prototype.Thanks in advance :). – JSmith Apr 19 '23 at 02:54
  • @JSmith I can't say I've used those particular bindings, but it looks like that `Closure` type is designed to work with Rust closures, which can close around arbitrary variables. if you want to set an instance variable, you'll need to either take a `&mut self` (meaning exclusive access), or do some sort of interior mutability with `Mutex` or `RefCell` (the former does what it sounds like, the latter is a very powerful but easily misused tool for getting interior mutability). But the `Closure` type, at least looking at it right now, wouldn't preclude you from using `&mut self`. – Silvio Mayolo Apr 19 '23 at 03:19
  • Thank you for your time really appreciate it. I'll have a look at what you've told me but , my explanations or perhaps bad.Thanks again – JSmith Apr 19 '23 at 03:24
  • Hello again, I've changed my post to help people understand the problem a bit more.Thanks in advance – JSmith Apr 19 '23 at 20:36