@jzxchiang, actually, imperative data structures are compatible with stable variables. What isn’t are object-oriented abstractions, because of the functions embedded in the data. But that is an independent dimension, as objects can be either imperative or functional.
To wit, here is a toy example of a counter object that, although functional, cannot be put in a stable var:
class Counter(x : Nat) {
public func get() : Nat { x };
public func inc() : Counter { Counter(x + 1) };
};
stable var c : Counter = Counter(0); // ERROR
On the other hand, here is an imperative counter type that you can store in a stable var just fine:
Right, but once you loosen it like that, the intent is no longer visible in the code. It might or might not be an accident.
In my experience (e.g. in OCaml), the strict rule is good documentation and uncovers many mistakes early on. The occasional ignore in cases like replace is a fair deal in exchange. But like option types, it’s one of these features that you have to learn to “hold right”. When you are working against it (perhaps out of habit) you can end up with repetitive strain injury.
Also, Add a “New developper start here” button with Dr Angela Yu uDemy Web3 video featuring ICP and Motoko. Would have save me a ton of hours searching for basic info as a newbie.
That’s ends up creating a totally different type and reworking the meaning of an optional type into something more JavaScripty though, right?
You can always narrow
type OptionalArgsABC = { a : ?Text; b : ?Text; c : ?Text };
let optionals : OptionalArgsABC = { a = ?"maybe"; b = ?"is"; c = null };
type OptionalArgsAB = { a : ?Text; b : ?Text };
let { a; b }: OptionalArgsAB = optionals;
@tomijaga What’s the common use case you have in mind?
I could see this as a good class constructor scenario as well.
Record extension syntax works for now, but at least that is explicitly saying what the defaults are - it sounds like with this feature you’d like the defaults to implicitly be null.
Yes, that is right.
I was thinking about the user experience when calling a function that takes a record with many optional fields.
An example would be initializing the ICRC-1 token, where some fields are optional and have default values set, so they don’t need to be specified by the user.
This was the Initial type, but I updated it later to the one below because there were too many optional types.
Then we could run a dfx command to generate an example command line argument, dfx canister call Canister1 registerUser --example-cli-arg, which could return:
This is actually supported. You can use dfx canister call Canister1 registerUser --random '' to generate a random value of that type. You can even customize the random value, e.g., use --random '{text = Some "name"}' to generate a random name. The spec of the random config is here: candid/config.md at master · dfinity/candid · GitHub
The Motokodoc is great. Is it possible to have auto-generation/snippet hotkey that fills out each part of a function’s signature as a template? And then an option to hide all unless on hover/specifically selected?
Might be worth autolinking to the corresponding comments in the Candid file as well.
Avoid await when multi-container cascading queries, multi-level query waiting gives the front-end user a very poor experience.
For example container A, B
The queryinfo function of the B container is called in the A container
// ideal situation
public shared query func moreInfo() : async Text {
B. queryinfo();
};
// Current situation
public shared func moreInfo() : async Text {
await B. queryinfo();
}
// #region get_account_identifier
/*
* Get Caller Identifier
* Allows a caller to the accountIdentifier for a given principal
* for a specific token.
*/
public query func get_account_identifier(args : T.GetAccountIdentifierArgs) : async T.GetAccountIdentifierResult {
It will make it so hovering over these fields will show a tooltip that looks like (similar method but with additional formatting used):
I found it very useful when first working with the code, and as not as known as Motoko is every bit helps. To add such a comment, start with a /** and end with a */ where the ending */ must be directly above the field declaration (no vertical line spaces). In the snippet above the opening double asterisk can be separated, but I found that the beginning * of each line of comment will also appear in the tooltip.
Syntax I know of so far:
the Markdown linking syntax works “[“desc”]”(url)
trigger a new line with a \ as the very last character of the current line (no additional white space)
terminating a line with double white space will also trigger a new line
Double asterisk for bold
Single asterisk or underscore for italic
code enclosed as back tick marks `
The @ sign did something once but I don’t remember what specifically triggered it
If the Motokodoc is one line, I personally like to use: /**** <One Line Comment Title Text> ***/
to emphasis it as a header.
I’ve been using 80 character spaces before making a new line (since the tool tip won’t autowrap), but maybe the modern max-width convention is 120 chars?
One thing to note is that the \ new line character isn’t escaped when moc doc is used (at least for html output) which is another task to do.
Finally I mentioned that if it would be possible it might be useful to link one field’s Motokodoc into another, so for instance “non-trivial” Result.Result types could automatically show their Success and Error types if (also defined) and linked. Or equally useful would be a way to import the corresponding did field’s comments, since that’s supposed to be the source of truth about a canister for external callers, and much of the info would likely be the same.
Maybe there is a way to do this already, but how about “pretty print” for debug_show output in the console–specifically formatting for nested types (like records in variants in records, etc)?