How to call and declare a method that needs to receive a vector of number and text values

I would like to declare a canister method that is able to receive a vector with an arbitrary number of Text and Nat values. For instance [1;“y”;3; “x”] or [1;2;3,“z”]. How should I update the following method declaration?
setData: (vec XX) -> ();

Have a look at the variant type, each vector entry would be basically a variant of either nat or text.

1 Like

Just to clarify, candid is strictly typed so a value cannot be two types at once as seen in JavaScript (and TypeScript).

How would look like the declaration of the method? Could you give me an example of how I would call the final method to send a vector like [1;“y”;3; “x”]?

Both record and variant are the same in js, an object with key(s) and their values. Only difference is that a variant is a single key with a value and a record is all keys with their values.

For a variant vec with text and nat:

vec variant { a: text; b: nat }

JavaScript array:

[{a: 'hello''}, {b: 123}]

See the reference in the docs for all candid types and their types in different languages: Candid reference | Internet Computer

2 Likes

Could you tell me what is my error declaring and using the variant below?

import Int "mo:base/Text";
import Nat "mo:base/Nat";

type dataMember = {
    #number : Nat; // variant 
    #symbol : Text; 
  };
var actor_data: [dataMember] = [1,"2",3];

Valid syntax should be:

import Int "mo:base/Text";
import Nat "mo:base/Nat";

type DataMember = {
    #number : Nat; // variant 
    #symbol : Text; 
  };
var actor_data: [DataMember] = [#number(1), #symbol("2"), #number(3)];
1 Like

How would it look a dfx call to a method accepting a vector of this variant?
This one does not wok:
dfx canister call backend mymethod '(vec {1; "2"; 3})'

Try dfx canister call backend mymethod '(vec { variant { number = 1}; variant { symbol = "2" }; variant { number = 3}; )'

2 Likes

I have complicated a bit the methjod declaration:
setData: (vec vec dataMember) -> (vec dataMember);

so now I would like to accept data object like:

[[#number(1), #number(3), #symbol("2")],
 [#number(2), #number(2), #symbol("1")],
 [#number(3), #number(3), #symbol("2")],
 [#number(4), #number(2), #symbol("1")]];

I have tried the following dfx call:
dfx canister call motokolearn_backend setData '(vec { vec {variant {number=1}; variant {symbol="2"}; variant {number=3}}; vec {variant {number=2}; variant {symbol="2"}; variant {number=3}}; vec {variant {number=3}; variant {symbol="2"}; variant {number=3}}})'

But I get an error:

Error: Failed update call.
Caused by: Failed update call.
  The replica returned a replica error: Replica Error: reject code DestinationInvalid, reject message Canister bkyz2-fmaaa-aaaaa-qaaaq-cai has no update method 'setTrainingData (vec { vec {variant {number=1}; variant {symbol="2"}; variant {number=3}};  vec {variant {number=2}; variant {symbol="2"}; variant {number=3}}; vec {variant {number=3}; variant {symbol="2"}; variant {number=3}}}) ', error code None

Could you point me out what am I doing wrong?

Your dfx call and the error message don’t match up. Can you check the invocation again? It sounds like you accidentally had 'setTrainingData instead of setData ' in your call

$ dfx canister call motokolearn_backend setTrainingData '(vec { vec {variant {number=1}; variant {symbol="2"}; variant {number=3};};  vec {variant {number=2}; variant {symbol="2"}; variant {number=3};}; vec {variant {number=3}; variant {symbol="2"}; variant {number=3};};})' 
Error: Failed update call.
Caused by: Failed update call.
  The replica returned a replica error: Replica Error: reject code DestinationInvalid, reject message Canister bkyz2-fmaaa-aaaaa-qaaaq-cai has no update method 'setTrainingData (vec { vec {variant {number=1}; variant {symbol="2"}; variant {number=3};};  vec {variant {number=2}; variant {symbol="2"}; variant {number=3};}; vec {variant {number=3}; variant {symbol="2"}; variant {number=3};};}) ', error code None

Actually, the right method name is “setTrainingData”. I think that it is something else… I think is related to the right way to nest vectors of variants but I cannot figure out the right way. Can you see any error in the parameter format?

the right way:

dfx canister call motokolearn_backend setTrainingData '(vec { vec {variant {number=1}; variant {number=11}; variant {symbol="1"};}; vec {variant {number=2}; variant {number=21}; variant {symbol="2"};}; vec {variant {number=3}; variant {number=31}; variant {symbol="3"};};})'