Shared function has non-shared return type - motoko

Getting error Shared function has non-shared return type for returning Item for the get method.
How would one make Item shared or is there a better way going about returning properties/object
public type Item = {
id: Nat;
var name: Text;
};
actor Maas {
var items: [Item] = [];
...
public shared query func get(id: Nat) : async Item {
return businesses[id - 1];
};
};

I just started getting into Motoko but I dug a little bit into documentation.
As I understood you need to make your type shared type (https://smartcontracts.org/docs/language-guide/language-manual.html#sharability)
A type T is shared if it is:
- an object type where all fields are immutable and have shared type, or
- a variant type where all tags have shared type
Since var is declares mutable variables (https://smartcontracts.org/docs/language-guide/mutable-state.html#_immutable_versus_mutable_variables)
The type becomes non shared type.
All there is need to be done is to remove var from the type Item
public type Item = {
id: Nat;
name: Text;
};
actor Maas {
var items: [Item] = [];
...
public shared query func get(id: Nat) : async Item {
return businesses[id - 1];
};
};

Related

Unacceptable type of value for ordered to-many relationship when writing swift case

I am working on a project that requires me to add a new test case on an existing file structure. Right now I am doing a test case that needs to do api call to get maintenance information.
The maintenance information I am getting back is structured as follows:
#objc(MaintenanceData)
class MaintenanceData: WebServiceEntity, Persistable {
static var contentId: ContentId = "maintenance"
#NSManaged var version: String
#NSManaged var maintenance: Bool
#NSManaged var maintenanceDescription: String?
#NSManaged var features: [FeatureMaintenanceData]?
public static func fieldMapping() -> [FieldName: String] {
return [
"version": "version",
"maintenance": "maintenance",
"maintenanceDescription": "maintenanceDescription",
"features": "features"
]
}
}
** For security reasons, I changed some code
Right now I have to mock a fake MaintenanceData to test the features property, which is an array of [FeatureMaintenanceData]
The FeatureMaintenanceData is written as follows:
#objc(FeatureMaintenanceData)
class FeatureMaintenanceData: WebServiceEntity, Persistable {
static var contentId: ContentId = "featureMaintenance"
#NSManaged var identifier: String
#NSManaged var maintenance: Bool
#NSManaged var maintenanceDescription: String?
public static func fieldMapping() -> [FieldName: String] {
return [
"identifier": "identifier",
"maintenance": "maintenance",
"maintenanceDescription": "maintenanceDescription"
]
}
}
Right now I need to mock the data, there is a function in the MockDataFactory which returns a MaintenanceData object, I need to make use of it and pass it to the function for testing. The function is written as follows:
#discardableResult func createAndInsertMaintenance(
version: String = "",
maintenance: Bool = false,
maintenanceDescription: String? = nil,
features: [FeatureMaintenanceData]? = nil,
) -> MaintenanceData {
let maintenance = NSEntityDescription.insertNewObject(
forEntityName: String(describing: MaintenanceData.self),
into: managedObjectContext
) as! MaintenanceData
maintenance.version = version
maintenance.softUpdateMinimalVersion = softUpdateMinimalVersion
maintenance.maintenance = maintenance
maintenance.maintenanceDescription = maintenanceDescription
maintenance.features = features <-----This is where error occurs
return updateMaintenance
}
I created and pass the fake FeatureMaintenanceData to the function
let featureMaintenance = NSEntityDescription.insertNewObject(
forEntityName: "FeatureMaintenanceData",
into: managedObjectContext
) as! FeatureMaintenanceData
featureMaintenance.identifier = "Microwave"
featureMaintenance.maintenance = true
featureMaintenance.maintenanceDescription = "test"
It however returns an error Unacceptable type of value for ordered to-many relationship: property = "features"; desired type = NSOrderedSet;
Since I don't know Obj-c, could someone explain to me what is the problem and how to solve it? Much thanks!

Is there a better way to make setter non primitive user defined type property?

Hi I am new to typescript. I summarized my use case in the following example.
class Movie {
private crew: Crew;
private cast: Cast;
private locations: Location;
private movieId;
constructor(public id: string) {
this.movieId = id;
}
public getMovieId() {
return this.moveId;
}
public setCrew(value: Crew){
this.crew = value;
}
public getCrew() {
return this.crew;
}
...
//other getter and setters.
};
type Crew = {
crew_varA: string,
crew_varB: boolean,
crew_varC: string,
crew_varD: boolean,
}
type Cast = {
cast_varE: string,
cast_varF: string,
cast_varG: string,
}
type Location = {
loc_varX: string,
loc_varY: string,
loc_varZ: string,
}
when I create an object of Movie, I need to call setCrew() method. But only 'crew_varA' variable has value by that time. I am not able to make a call to setCrew() method with only one variable. I need to initialize all variables with some default value which is not appropriate something like this.
let mv = new Movie("SpiderMan");
mv.setCrew({crew_varA: "Peter Parker", crew_varB:false, crew_varC:null, crew_varD:null}; //is there a way to set only one property of Crew and add other properties one by one based on some logic??
I am not sure my approach is correct or not. I appreciate your help.

`java.lang.StackOverflowError` when accessing Kotlin property

I got this (contrived) sample from Packt's "Programming Kotlin" on using secondary constructor with inheritance.
Edit: from the answer it is clear that the issue is about backing field. But the book did not introduced that idea, just with the wrong example.
open class Payment(val amount: Int)
class ChequePayment : Payment {
constructor(amount: Int, name: String, bankId: String) : super(amount) {
this.name = name
this.bankId = bankId
}
var name: String
get() = this.name
var bankId: String
get() = this.bankId
}
val c = ChequePayment(3, "me", "ABC")
println("${c} ${c.amount} ${c.name}")
When I run it this error is shown.
$ kotlinc -script class.kts 2>&1 | more
java.lang.StackOverflowError
at Class$ChequePayment.getName(class.kts:10)
at Class$ChequePayment.getName(class.kts:10)
at Class$ChequePayment.getName(class.kts:10)
Line 10 does seems to be a infinite recursion, how to solve it?
You have a recursion in your code:
class ChequePayment : Payment {
constructor(amount: Int, name: String, bankId: String) : super(amount) {
this.name = name
this.bankId = bankId
}
var name: String
get() = this.name // recursion: will invoke getter of name (itself)
var bankId: String
get() = this.bankId // recursion: will invoke getter of bankId (itself)
}
If you don't need custom logic for your getter, just leave your properties like this:
var name: String
var bankId: String
They will have a default getter, which does nothing more than returning the value of the backing field.
Note: The code as it is can/should be refactored to this:
class ChequePayment(amount: Int, var name: String, var bankId: String) : Payment(amount) {
// ...
}
This uses the primary constructor and is much less redundant.
To access the backing field you have to use the keyword field instead of this.name see https://kotlinlang.org/docs/reference/properties.html#backing-fields
this.name references the getter, which references this.name which is an infinite recursion, as you already noted. In code:
var name: String
get() = field
var bankId: String
get() = field
Side note: Android Studio and Idea will complain rightfully that you don't need a getter in this case. So you can simplify even more:
var name: String
var bankId: String

How to take a subset of an object using an interface?

Suppose I have this class and interface
class User {
name: string;
age: number;
isAdmin: boolean;
}
interface IUser {
name: string;
age: number;
}
And then I get this json object from somewhere
const data = {
name: "John",
age: 25,
isAdmin: true
}
I want to subset data using IUser and remove the isAdmin property like this
let user = subset<IUser>(data);
// user is now { name: "John", age: 25 }
// can safely insert user in the db
My question is how do I implement that function in TypeScript?
function subset<T>(obj: object) {
// keep all properties of obj that are in T
// keep, all optional properties in T
// remove any properties out of T
}
There's no way to do that which is better than:
function subset(obj: IUser) {
return {
name: obj.name,
age: obj.age
}
}
The typescript interfaces don't exist at runtime (which is when subset is invoked) so you cannot use the IUser interface to know which properties are needed and which aren't.
You can use a class which does "survive" the compilation process but:
class IUser {
name: string;
age: number;
}
Compiles to:
var IUser = (function () {
function IUser() {
}
return IUser;
}());
As you can see, the properties aren't part of the compiled output, as the class members are only added to the instance and not to the class, so even a class won't help you.
You can use decorator and metadata (more on that here) but that sounds like an overkill for your scenario.
Another option for a more generic subset function is:
function subset<T>(obj: T, ...keys: (keyof T)[]) {
const result = {} as T;
keys.forEach(key => result[key] = obj[key]);
return result;
}
let user1 = subset(data, "name", "age");
let user2 = subset(data, "name", "ag"); // error: Argument of type '"ag"' is not assignable to parameter of type '"name" | "age" | "isAdmin"'

Access the getter and setter of a typescript property

I have a question about typescript properties: Is it possible to get the setter and getter of a typescript property or to declare a function argument to be of a property of X type?
The reason is to get some sort of "reference" to a variable which is not possible in plain JS without writing getter/setter wrappers or access the variable via parent object itself (obj["varname"]).
For example (with some working code and other parts speculative):
//A sample class with a property
class DataClass<T> {
private T val;
public get value(): T {
return this.val;
}
public set value(value: T) {
this.val = value;
}
}
//Different ways of modifing a member "by reference"
class ModifyRef {
public static void DoSomethingByGetterAndSetter(getter: () => string, setter: (val: string) => void) {
var oldValue = getter();
setter("new value by DoSomethingByGetterAndSetter");
}
public static void DoSomethingByObject(obj: Object, name: string) {
var oldValue = obj[name];
obj[name] = "new value by DoSomethingByObject";
}
//Is something like this possible?
public static void DoSomethingByProperty(somePropery: property<string>) {
var oldVlaue = someProperty;
someProperty = "new value by DoSomethingByProperty";
}
}
var inst = new DataClass<string>();
//Calling the DoSomethingByProperty if possible
ModifyRef.DoSomethingByProperty(inst.value);
//Or if not is something like this possible
ModifyRef.DoSomethingByGetterAndSetter(inst.value.get, inst.value.set);
The simplest way to do this would be to provide methods, rather than a property:
//A sample class with a property
class DataClass<T> {
private val: T;
public getValue(): T {
return this.val;
}
public setValue(value: T) {
this.val = value;
}
}
class ModifyRef {
public static DoSomethingByGetterAndSetter(getter: () => string, setter: (val: string) => void) {
var oldValue = getter();
setter("new value by DoSomethingByGetterAndSetter");
}
}
var inst = new DataClass<string>();
//Or if not is something like this possible
ModifyRef.DoSomethingByGetterAndSetter(inst.getValue, inst.setValue);
I've long found it very surprising that languages with properties don't include a convenient way to make a reference to a property, and have daydreamed about having this feature in C#. It ought to work on local variables as well.
A popular pattern for this kind of first-class or reified property is a single function that can be called in two ways:
no arguments: returns current value.
one argument: sets value, returns undefined.
Or in TypeScript terms:
interface Property<T> {
(): T;
(newVal: T): void;
}
The methods of jQuery objects often work like this. An example of this pattern in modelling pure data is in Knockout, in which such properties also support change subscriptions, and there's a rather elegant pattern for defining computed properties that automatically recompute when their dependencies change.