What is special about actor wrapper and this? - Motoko

This behavior seems strange, but maybe I’m missing something. @claudio @ggreif

import Timer "mo:base/Timer";
import Principal "mo:base/Principal";

shared ({ caller = _owner }) actor class Token  () = this{

  type anActorType = actor{
    autoInit :  () -> async ();
  };


  ignore Timer.setTimer<system>(#nanoseconds(0), func initer() : async () {
    //let something = this;  <---If I uncomment this line building fails, but the line below also references this and works fine.
    let anActor: anActorType = actor(Principal.toText(Principal.fromActor(this)));
    await anActor.autoInit();
  });

  // Say the given phase.
  public query func say(phrase : Text) : async Text {
    return phrase;
  };
};

Got it to compile and deploy

It deploys fine as is…I just want to know why it WONT compile if I remove the comments on the line.

Coincidentally I am working on this right now: feat: allow access to `Self` and its public methods from actor initialisers by ggreif · Pull Request #4719 · dfinity/motoko · GitHub

No ETA yet, as there are quite a few more wrinkles to iron out.

It works! I get the proper principle from the actor, so maybe this is a bug, but it is a fortunate one for now…now to figure out WHY it works.

I’ve shared the private repo with you two…don’t want to release this if it will break later.

At the moment, that is probably a bug, since it also allows references to other not yet defined identifiers. But I think we will be able to fix the bug, but enable your code at the same time.

Yeah, it will be fixed with #4719.

moc 0.13.2 fixes this bug and allows you to use this directly. No need for actor ... Principal.fromActor any more. It also makes the type annotation let anActor: anActorType = redundant.

I’d love to hear success stories before I push it towards dfx, though.

1 Like

I used this today to extract a bunch of cruft from my Class+ helper library. It seems to be working well. I’ll push up my code when I get a chance for you all to look at.

2 Likes

Did you use the dfx 0.24.2 beta or pure moc?

dfx 0.24.2-beta-0

some other stuff to post

1 Like

Send you guys invites to https://github.com/icdevsorg/class-plus

I’ve gotten the class plus boiler plate down to

  let initManager = ClassPlus.ClassPlusInitializationManager(_owner, Principal.fromActor(this));
   
  stable var aClass_state : State = AClassLib.initialState();

  let aClass = AClassLib.Init<system>({
    manager = initManager;
    initialState = aClass_state;
    args = ?({messageModifier = "Hello World"});
    pullEnvironment = ?(func() : Environment {
      {
        thisActor = actor(Principal.toText(Principal.fromActor(this)));
      };
    });
    onInitialize = ?(func (newClass: AClassLib.AClass) : async* () {
        //_aClass := ?newClass;
        D.print("Initializing AClass");
      });
    onStorageChange = func(new_state: State) {
        aClass_state := new_state;
      } 
  });

From Aclass:

public func Init<system>(config : {
      manager: ClassPlusLib.ClassPlusInitializationManager;
      initialState: State;
      args : ?InitArgs;
      pullEnvironment : ?(() -> Environment);
      onInitialize: ?(AClass -> async*());
      onStorageChange : ((State) ->())
    }) :()-> AClass{

      ClassPlusLib.ClassPlus<system,
        AClass, 
        State,
        InitArgs,
        Environment>({config with constructor = AClass}).get;
    };

  

  public class AClass(stored: ?State, caller: Principal, canister: Principal, args: ?InitArgs, _environment: ?Environment, onStateChange: (State) -> ()){

public let state = switch(stored){
      case(?val) val;
      case(null) initialState() : State;
    };

    onStateChange(state); //passes state tracker back to actor to update the var.

...rest of class
}

I’ve haven’t had a chance to review what @infu has done with the module stuff, but this is working nicely and I have the @ZhenyaUsenko migration pattern working nicely under the hood where I need it. I’m hoping this will survive the upgrade to OEP as long as I keep variant vars out of my object states(this makes the pattern much less powerful but it hasn’t seemed to be much of an issue in the libraries I’ve reviewed…my biggest concerns are places where I’m keeping track of some state and want track states with variants…if the pattern changes in the future I’ll be in trouble.)