Reassigning object properties for a simple boolean

I am trying to change a variable field in motoko and I keep getting “type error, expected mutable assignment target” exactly like mentioned in this tread: Reassigning object properties . When I apply the answer as followed:

public type ForSale = Bool;

public type Ticket = {
tokenIndex: TokenIndex;
user: AccountIdentifier;
qrCode: QRCode;
seatId: SeatId;
name: Name;
description: Description;
image: Image;
var forSale: ForSale;
};

var dummyTicket: Ticket = {
tokenIndex = 0;
user = "";
qrCode = NatThirtyTwo.toText(0);
seatId = "";
name = "";
description = "";
image = "";
var forSale = False;
};

I obtain this mysterious compiler error:

main.mo:152.54-152.78: type error [M0032], shared function has non-shared 
return type
tixBalanceResponse = {#err : CommonError/1; #ok : [Ticket]}
type
tixBalanceResponse = {#err : CommonError/1; #ok : [Ticket]}
is or contains non-shared type
var ForSale

I think the key point in the erroe is “shared function has non-shared
return type”

My end goal is simply to upday the field forSale like so:

ticket.forSale := true;

It should be really easy it seems…Can someone help demistify this error, I am new to motoko and maybe I miss a public or shared statement somewhere

Thanks a bunch!

Shared functions can only consume and produce shared types, which precludes var field, [var …] arrays and things containing local functions (roughly).

The compiler is complaining because the Ticket type returned as part of the async return type has a mutable field (forSale).

2 Likes

Ok for those reading this later, I found 2 ways to get rid of the error: 1) I made the function private and removed the “async” 2) or I refrained from returning the type Ticket…

In my ignorance, it seems crippling to have to choose between the ability to edit a variable or the ability to return the variable…does it have to do with blockchain data being immutable? Or is there a pattern to go around this?

Thanks for your insights!

It’s because the canisters communicate asynchronously using a queued messaging system (based on the actor model), you wouldn’t want/be able to have another canister hold onto a pointer or swap an underlying value in memory. This is fine internally, so mutable variables are a tool you can use there, but to send data across the canister interface you’d need to “freeze” any mutable data structures.
You’ll find some of the base library modules have freeze and thaw functions that do this (eg Array) and you could use these or follow a similar approach for your own data structures.

2 Likes

OK Thank you, this make a lot of sense and the freeze/thaw functions will come handy!

For those later reading this, i found this link explaining mutability interesting!

Cheers!

1 Like