Solidity Memory data location - memory

I've been following my new journey into learning Solidity. Now I'm into a structs + Data locations course, and I came to a situation when I didn't use the exact same example as the instructor did, both works. I would like to know which one is technically more correct.
Concerning the way the instructor did, I understand that if that data variable already exists, filled with data, and we're using it on a Storage, that would be understandable but for the Memory case, I still don't get the meaning of it.
Here are the two exmples:
Mine:
struct PERSON {
uint256 id;
string name;
}
PERSON public personList;
function updateNewPerson(uint256 _index, string memory _name) public {
PERSON memory newUpdatedPerson;
newUpdatedPerson.name = _name;
personList[_index] = newUpdatedPerson;
}
Instructor code:
struct PERSON {
uint256 id;
string name;
}
PERSON public personList;
function updateNewPerson(uint256 _index, string memory _name) public {
PERSON memory newUpdatedPerson = personList[index];
newUpdatedPerson.name = _name;
personList[_index] = newUpdatedPerson;
}
This is the same example with Storage data location I'm reffering to:
function updateStoragePerson(uint256 _index, string memory _name) public {
PERSON storage newUpdatedPerson = personList[_index];
newUpdatedPerson.name = _name;
}
I'm trying to figure out the is there's any difference there and i think I'm starting to uderstand it, and please correct me if I'm wrong.
So in my example I'm basically just passing the new user insert new value, which is in this case _name, then when giving it back to the array handing it to its position through the index array.
When on the instructor example, he's passing through the array index case content, which is id and name, then insering the new name value from the function before passing back the data to the array, and in this case id and _name are identical.

What I can see is that, in your code, when you create a newUpdatedPerson, you are creating an empty variable of type PERSON, and then you only fill it with the name, whereas your instructor takes the original value from a person which already exists and then updates its value. This will result in your newUpdatedPerson in your personList to update its name but its id will become empty.
The newUpdatedPerson will be stored in personList as copies from storage to local storage actually copy a reference to the storage so any update on newUpdatedPerson will result in an update to personList.
Assignments from storage to a local storage variable also only assign a reference.
I hope you find this information helpful :)

State variables are storage by default (values are stored in the blockchain).
Local variables in functions are memory by default (values are stored temporarily in memory).
Structs are storage by default (values are stored in the blockchain).
I explained how memory and storage type behave differently on this stackoverflow post

Related

Can't see origin from: "Non-nullable instance field ‘{0}’ must be initialized."

So I am trying to get into app development and following this guys yt-tutorial (yt-vid from The Net Ninja). However I stumbled over the following error:
Non-nullable instance field ‘{0}’ must be initialized. (error on dart.dev explained). The whole code is shown in this image
img coding: comparison mine with yt:
The issue I am facing is that I don't understand the origin of that error. I understand that you can't use a variable that was not initialized yet and that this error is trying to tell you that before you run the code and run into an exception in runtime.
I also know that I can fix this using "late" in front of the variables, but as far as I'm concerned that's just "ignoring" the error.
So my main question is: why do I have this error while the yt doesn't even though we have (except for some names and assignments) the same code?
I appreciate every answer and hope you have a great day
the links:
error on dart.dev explained
You should change your User class to:
class User {
String username;
int age;
User(this.username, this.age);
}
By doing so, the variables will be initialized with values (since we are then able to use this values in the constructor body) as part of initialization of the object.
Dart does object creation in two steps:
Initialize object.
Run constructor body.
So when the constructor body is running, the object must be initialized with values (well, the non-nullable values at least). To do so, we have a code block which is executed before { } like:
class User {
String username;
int age;
User(String username, int age)
: this.username = username,
this.age = age;
}
But since this is kinda redundant, we have the shortcut form as I first suggested.
When initializing an object, we are not allowed to use variables from the object since the object is ongoing its creation.

What is the use of msg.sender in solidity?

In this codpiece, I am finding it hard to figure out what is msg.sender is and how it works internally.
What I am understanding is, we have a mapping favoriteNumber, and the key is an address and the value is a uint.
What is the meaning of comment - "Update our favoriteNumber mapping to store _myNumber under msg.sender, I am understanding that we are updating favoriteNumber, but what does it mean that under msg.sender. What is the role of this method, how it's working?
mapping (address => uint) favoriteNumber;
function setMyNumber(uint _myNumber) public {
// Update our `favoriteNumber` mapping to store `_myNumber` under `msg.sender`
favoriteNumber[msg.sender] = _myNumber;
// ^ The syntax for storing data in a mapping is just like with arrays
}
function whatIsMyNumber() public view returns (uint) {
// Retrieve the value stored in the sender's address
// Will be `0` if the sender hasn't called `setMyNumber` yet
return favoriteNumber[msg.sender];
}
Every smart contract invocation has a caller address. Each EVM (Ethereum Virtual Machine that executes the code) knows which
account carries out each action. In Solidity, you can access the calling account by
referencing msg.sender
So when you call a function of solidity contract, your contract already gets the information of your account, so your account is the msg.sender
favoriteNumber is a mapping. think it like a javascript object. It maps the account addresses to their favourite number.
0x9C6520Dd9F8d0af1DA494C37b64D4Cea9A65243C -> 10
So when you call setMyNumber(_myNumber), you are passing your favourite number. so this number will be stored in favoriteNumber mapping like this:
yourAccountAdress -> yourFavouriteNumber
So when you call whatIsMyNumber function, since EVM already gets your account number, checks in the mappings and returns you your favourite number.
In solidity exists 3 types of variables: state, local and global.
example of global variables:
msg.sender (sender of the message)
msg.value (number of wei sent with the message)
pseudocode from favoriteNumber[msg.sender] = _myNumber;
given a favoriteNumber list,
select the address of the account calling this function,
assign _myNumber to that address
note: global variables are available in all contracts by default. see more info here: solidity docs - global variable

Way to defensive check value assigned to public const variable in immutable class in C++17?

Coming back to C++ after a hiatus in Java. Attempting to create an immutable object and after working in Java, a public const variable seems the most sensible (like Java final).
public:
const int A;
All well and good, but if I want to defensive check this value, how might I go about it. The code below seems strange to me, but unlike Java final members, I can't seem to set A in the constructor after defensive checks (compiler error).
MyObj::MyObj(int a) : A(a) {
if (a < 0)
throw invalid_argument("must be positive");
}
A public const variable for A seems like a clearer, cleaner solution than a getter only with a non const int behind it, but open to that or other ideas if this is bad practice.
Your example as it stands should work fine:
class MyObj {
public:
const int var;
MyObj(int var) : var(var) {
if (var < 0)
throw std::invalid_argument("must be positive");
}
};
(Live example, or with out-of-line constructor)
If you intend that MyObj will always be immutable, then a const member is
probably fine. If you want the variable to be immutable in general, but still have the possibility to overwrite the entire object with an assignment, then better to have a private variable with a getter:
class MyObj {
int var;
public:
MyObj(int var) : var(var) {
if (var < 0)
throw std::invalid_argument("must be positive");
}
int getVar() const { return var; }
};
// now allows
MyObj a(5);
MyObj b(10);
a = b;
Edit
Apparently, what you want to do is something like
MyObj(int var) {
if (var < 0)
throw std::invalid_argument("must be positive");
this->var = var;
}
This is not possible; once a const variable has a value it cannot be changed. Once the body ({} bit) of the constructor starts, const variables already have a value, though in this case the value is "undefined" since you're not setting it (and the compiler is throwing an error because of it).
Moreover, there's actually no point to this. There is no efficiency difference in setting the variable after the checks or before them, and it's not like any external observers will be able to see the difference regardless since the throw statement will unroll the stack, deconstructing the object straight away.
Generally the answer by N. Shead is the regular practice - but you can also consider:
Create domain-specific types and use them instead of general primitives. E.g., if your field is a telephone number, have a type TelephoneNumber which, in its constructor (or factory), taking a string, does all the telephone number validation you'd like (and throws on invalid). Then you write something like:
class Contact {
const TelephoneNumber phone_;
public:
Contact(string phone) : phone_(phone) { ... }
...
When you do this the constructor for TelephoneNumber taking a string argument will be called when initializing the field phone_ and the validation will happen.
Using domain-specific types this way is discussed on the web under the name "primitive obsession" as a "code smell".
(The problem with this approach IMO is that you pretty much have to use it everywhere, and from the start of your project, otherwise you start having to have explicit (or implicit) casting all over the place and your code looks like crap and you can never be sure if the value you have has been validated or not. If you're working with an existing codebase it is nearly impossible to retrofit it completely though you might just start using it for particularly important/ubiquitous types.)
Create validation methods that take and return some value, and which perform the validation necessary - throwing when invalid otherwise returning its argument. Here's an example validator:
string ValidatePhoneNumber(string v) {
<some kind of validation throwing on invalid...>
return v;
}
And use it as follows:
class Contact {
const string phone_;
public:
Contact(string phone) : phone_(ValidatePhoneNumber(phone)) { ... }
I've seen this used when an application or library is doing so much validation of domain-specific types that a small library of these domain-specific validator methods has been built up and code readers are used to them. I wouldn't really consider it idiomatic, but it does have the advantage that the validation is right out there in the open where you can see it.

Delete Persistent Store data when App is uninstalled/deleted

I have a BlackBerry application that starts (App load) with a Registration screen when the App is first installed. Later, the App will load with the home screen. Registration screen only appears on first load. I am achieving this by storing a boolean value in PersistentStore. If the value exists, then Registration screen will not appear.
PersistentStoreHelper.persistentHashtable.put("flagged",Boolean.TRUE);
PersistentStoreHelper.persistentObject.commit();
UiApplication.getUiApplication().pushScreen(new MyScreen());
I am aware of the fact that in order to delete the Persistent Store on deleting/uninstalling the App, I have to make the Hashtable a subclass of my own and therefore I have declared the Hashtable in a separate class:
public class PersistentStoreHelper extends Hashtable implements Persistable{
public static PersistentObject persistentObject;
public static final long KEY = 0x9df9f961bc6d6daL;
public static Hashtable persistentHashtable;
}
However this has not helped and the boolean value of flag is not cleared from PersistentStore. Please advice.
EDIT: When I change the above PersistentStoreHelper class to
public static PersistentObject persistentObject =
PersistentStore.getPersistentObject(KEY);
and remove
PersistentStoreHelper.persistentObject =
PersistentStore.getPersistentObject(PersistentStoreHelper.KEY);
from class B where boolean value is being saved, I observe that the boolean value is removed every time the App is closed. This should not happen and the value should only be removed in case the App is deleted/uninstalled. Any pointers?
The way this works is that the BlackBerry OS looks at the objects you are storing in the PersistentStore. If it recognizes that those objects can only be used by your app, then it will delete them when you uninstall the app. However, if the classes of the stored objects are classes that are used by other apps, then your data will not be deleted.
You have declared your helper class like this:
public class PersistentStoreHelper extends Hashtable implements Persistable{
but the helper class is not what is being stored. Your helper class is just a helper, that stores other things for you. In your case, it is storing this:
public static Hashtable persistentHashtable;
but, that object is of type java.util.Hashtable, which is a class used by many apps. So, it won't be deleted when you uninstall your app. What you should do is something like this:
public class PersistentStoreHelper implements Persistable { // so inner class = Persistable
public static PersistentObject persistentObject;
public static final long KEY = 0x9df9f961bc6d6daL;
/**
* persistentHashtable is now an instance of a class that
* only exists in your app
*/
public static MyAppsHashtable persistentHashtable;
private class MyAppsHashtable extends Hashtable implements Persistable {
// don't need anything else ... the declaration does it all!
}
}
I can't see it here, but I'm assuming that somewhere you have this code:
persistentObject = PersistentStore.getPersistentObject(KEY);
and then when you want to save the data back to the store, you're doing something like this;
persistentHashtable.put("SomeKey", someNewData);
persistentObject.setContents(persistentHashtable);
persistentObject.commit();
just adding data to the persistentHashtable doesn't save it (permanently). Hopefully, you already had that part somewhere.
Note: if you make these changes, don't expect this line of code to work, the next time you run your app:
persistentHashtable = (MyAppsHashtable)persistentObject.getContents();
because the last version of your code did not use the MyAppsHashtable class, so the loaded data won't be of that type. This is one reason that it's important to get this right the first time. In general, I always wind up saving data in the PersistentStore that's contained in one top level Hashtable subclass, that implements Persistable. I may later change what goes in it, but I won't ever change the signature of that top-level storage object. Hopefully, you haven't released your app already.
Update: In response to your comment/question below:
if (PersistentStoreHelper.persistentObject.getContents() == null) {
PersistentStoreHelper.persistentHashtable = new MyAppsHashtable();
PersistentStoreHelper.persistentObject.setContents(PersistentStoreHelper.persist‌entHashtable);
} else {
PersistentStoreHelper.persistentHashtable =
(MyAppsHashtable)PersistentStoreHelper.persistentObject.getContents();
}

How do I use the persistent object store in Blackberry?

I want to create a simple CRUD application to test out the data handling capabilities of the Blackberry.
How do I create a simple save function?
In this example I'm storing a vector in the persistent store.
You have to come up with a store ID, which should be of type long. I usually create this by concating the fully qualified Application's Class name to some string that makes it unique with in my application.
//class Fields...
//Use the application fully qualified name so that you don't have store collisions.
static String ApplicaitonID = Application.getApplication().getClass().getName();
static String STORE_NAME = "myTestStore_V1";
long storeId = StringUtilities.stringHashToLong( ApplicationID + STORE_NAME );
private static PersistentObject myStoredObject;
private static ContentProtectedVector myObjects;
//End class fields.
Example of loading a Vector from the store:
myStoredObject = PersistentStore.getPersistentObject( storeId );
myObjects = (ContentProtectedVector) myStoredObject.getContents();
//Print the number of objects in storeage:
System.out.println( myObjects.size() );
//Insert an element and update the store on "disk"...
myObjects.addElement( "New String" );
myStoredObject.setContents(myObjects);
myStoredObject.commit();
Example of initializing this store and saving it to disk for the first time:
myStoredObject = PersistentStore.getPersistentObject( storeId );
myObjects = (ContentProtectedVector) myStoredObject.getContents();
if(myObjects == null)
myObjects = new ContentProtectedVector();
myStoredObject.setContents(myObjects);
myStoredObject.commit();
If you want to commit changes (aka save changes to disk), you need to repeat the bottom two lines. setContents(OBJ); and Commit().
You can store the following without having to do anything special:
java.lang.Boolean
java.lang.Byte
java.lang.Character
java.lang.Integer
java.lang.Long
java.lang.Object
java.lang.Short
java.lang.String
java.util.Vector
java.util.Hashtable
#see : http://docs.blackberry.com/en/developers/deliverables/17952/Storing_objects_persistently_1219782_11.jsp
To store your own Classes, they (and all sub classes) have to implement the "Persistable" interface. I recommend that you do this, as these stores get cleaned up automatically when your application is uninstalled. This is because the OS cleans stored objects up, when "any" referenced classname in the store no longer has an application associated with it. So if your store is only using Strings, it's never going to get cleaned up.

Resources