I am an autistic Motoko developer frustrated that `actor {}`is no longer a valid program because it was beautiful

This is ramblings, but I truly needed to share this.

I think the syntax and mental model of Motoko was clearer, more intuitive, and more readable in the previous model — where variables that needed to persist between upgrades needed to be declared stable, and everything else was transient by default without the need for a keyword.

  1. Before the change actor {} was a valid Motoko program. How fast you can get an app deployed with just a main.mo and dfx.json is absolute wizardry. But persistent actor {} just doesn’t hit the same. I know, I’m insane. Two words is still incredibly short, you’re right. But the beauty is lost. Newbies now have to learn two concepts (actor + persistence) before even being able to write their first program. And if you declare a class? shared ({ caller = superadmin }) persistent actor class X = this {} - something went wrong here.

  2. The stable keyword is consistent with the rest of the IC stack and terminology (stable memory, stable types, stable structures…). Also, it might be personal but the transient keyword absolutely doesn’t speak to me whereas ,again, stable does.

  3. The persistent keyword/concept conflates two different concepts: (a) Data living in your program, always accessible without a database, and (b) data surviving upgrades. The first is the true selling point of the platform. The second, absolutely need to exist for mass adoption, but doesn’t need to be the default. Those two types of persistence are implemented through very different mechanisms (one doesn’t even need the Motoko language but is simply part of how the runtime works), and hiding both behind a single keyword loses important nuance.

  4. Variables wiped during upgrades by default mirrors the reality of Wasm module instantiation. I understand that not having to understand the platform can be a selling point for the Motoko language, But I’d argue that with stable, you had your cake and ate it too: all the magic, plus the right mental model. You didn’t need to know how your variable stayed stable — but you knew “stable” was a thing, and you could dig deeper if you wanted to.

  5. Finally, sometimes you just want to drop data. And this sometimes is more often that you’d think. There are plenty of legitimate reasons: cleanup, archiving, refactoring. Having to manually write a migration.mo is tedious — especially since you need the exact types of the data you want to drop (also why is that the case given that the compiler already has access to them via the .most files. I do not understand this). Let me drop the data!

I don’t want this to sound negative — I’ve been a fan of the Motoko team since day one, and orthogonal persistence is an absolute gem. But in my opinion, this syntax/model change wasn’t necessary. After months of using it, I still don’t see any clear benefit.

9 Likes

its the “no hello” world

3 Likes

Dude you should be an ICP standup. Seriously.

2 Likes

Actually… yeah. Previous syntax was more intuitive. Anyway I do REALLY like that you don’t need to do special migration functions when updating.

But it’s always the defaults that create ambiguity. For me, it would be best if we always had to specify 3 types (not 2).
persistent - always remembered
stable - intermediate state, permanent memory but will not survive an update (e.g. some cache)
transient - dynamic

maybe the code would be more extensive but more unambiguous

2 Likes

I think we are going to be able to get rid of persistent eventually again, but it is needed temporarily to distinguish between old and new mode. I’d imagine that in a future version, after enough time has passed, they will depreciate it and any old programs will just start getting the stable persistent errors.

I like that stable being the default over transient…the original promise for motoko was that it would have orthogonal memory and now it does. Maybe if motoko were moved off the IC to other platforms, then you’re point of view takes hold…hmm…in either case..I actually like being more explicit. In one world both transient and stable are required so you and AIs know eactly what you mean and don’t have to rely on meta knowledge of which compiler you’re in.

I agree that getting rid of data seems to be a pain now, but it seems like there should be some kind of clear override that could be added to the language that say “I’m deleting this and I know what I’m doing” without having to write a migration…or a abstraction over migration that can be written to make things a bit easier. I haven’t gotten into it, but I’ve been hoping that I can refactor @ZhenyaUsenko migration pattern to be used from a migration with one line.

One thing that is going to clean things up a TON is when we get mixins in the main language. It is already in beta! This will make modularization so much easier.

import icrc1 "mo:icrc1-mo";

persistent actor {
  include icrc1-mixin({
     canisterId: self;
     accounts = ?[
        (self, 1000000_00000000)
     ]);
     fee = ?10000;
     minting_account = Principal.fromText("zdgud-kqaaa-aaaal-ajn4q-cai");
     fee_collector = null;
     //...
  
    //public func incAndGet() : async Nat {
        //custom code
     //};
}

I’ll also disagree that stable was consistent. It was/is actually hell trying to describe the difference between what rust means by stable and what motoko meant by stable. Not that we’ve really resolved that…but at least we don’t have to explain streaming all variables out during upgrade anymore.

I think the biggest issue we have to deal with now is that the Motoko team has been moved to the caffeine organization(at least this what I heard on the last motoko call..it may have changed and I don’t have any inside knowledge). This can either be super awesome or super bad as it is likely tied to caffeine for better or worse. Likely, if we want to increase it’s resilience we need to build some kind of momentum behind it and it’s support/development outside of the foundation and/or caffeine. It is on my list, but my list is long.

3 Likes