motoko icon indicating copy to clipboard operation
motoko copied to clipboard

FR: treating actor self references as initially defined

Open crusso opened this issue 2 years ago • 2 comments

@nomeata @ggreif and I were discussing this again. This would solve the problem that you can't obtain the principal of 'this' in an actor's constructor, which is another common issue and inconvenience (e.g. https://forum.dfinity.org/t/heartbeat-improvements-timers-community-consideration/14201/134)

However, that could also be solved by treating this as defined, not undefined, to avoid the undefinedness error. Do you recall why we don't treat this as defined within the initializer? It seems like an unnecessary restriction to me, since you can't do anything with the principal anyway (message sends are verboten from the initializer.)

Originally posted by @crusso in https://github.com/dfinity/motoko/issues/2264#issuecomment-1400219196

crusso avatar Jan 23 '23 12:01 crusso

Possible counter-example, depending on how the compiler compiles Echo.say.

actor Echo = {

  let f : shared Text -> async () = Echo.say;

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

crusso avatar Jan 23 '23 12:01 crusso

This is also related to forum issue https://forum.dfinity.org/t/heartbeat-improvements-timers-community-consideration/14201/135, where a user want to access this from a time callback set up in the constructor.

Attempted workarounds like these don't work: https://m7sm4-2iaaa-aaaab-qabra-cai.ic0.app/?tag=1729196235

import { print } = "mo:base/Debug";
import { abs } = "mo:base/Int";
import { now } = "mo:base/Time";
import Principal = "mo:base/Principal";
import { setTimer; recurringTimer } = "mo:base/Timer";

actor Reminder = {

  var This : Principal = Principal.fromBlob("");

  private func act() : async () {
    print("Happy New Year!");
  };

  private func ensureThis() {
    if (This == Principal.fromBlob(""))  {
      This := Principal.fromActor(Reminder);
    };      
  };

  ignore setTimer(#seconds 5,
    func () : async () {
      //ensureThis();  // doesn't work
      // This := Principal.fromActor(Reminder); //doesn't work
      assert This != Principal.fromBlob("");
      ignore recurringTimer(#seconds 5, act);
    
      await act();
  });
}

crusso avatar Feb 07 '23 10:02 crusso