Solidity Basics

Hi Jonathan

Thanks for the very concise answers. I think I am getting it. Basically my confusion over when to use Person and people is answered in your statement - " To create an instance based on a struct ā€œblueprintā€, we need to use the name of the struct. So, this is why we use Person and not the name of the array people"

You also mentioned that ā€˜newPersonā€™, an instance of the Person class is a local variable inside the body of addPerson function. Am I right by saying that code

people.push( newPerson)

add the newPerson instance to the people array? Thus allowing getPerson function to retrieve the instances back when required? The newPerson being pushed to the array would be in ā€˜stateā€™ variable storage?

Thanks
Eric

1 Like

Thank you so much @jon_m ! I think Iā€™ll take your advice and use a struct instead. :+1:

1 Like

Hi Eric,

Glad the answers were helpful :slightly_smiling_face:

Yes ā€¦ā€‚push()ā€‚works in same way as it does in JavaScript: it adds the value between the parentheses to the end of the array. So, the first newPerson pushed to people will be at index 0 (people[0]), the second newPerson pushed will be at index 1 (people[1]) etc.

Yes ā€¦ and the getPerson function works by retrieving specific instances according to their index position within the array e.g.

Person memory person = people[_index];
return(person.age, person.name);

or you could code it without using a local variable, as follows ā€¦

return(people[_index].age, people[_index].name);

The user calls getPerson() with the index position of the instance they want to retrieve.

Correct ā€¦ the people array is a state variable and is saved in persistent storage.

Instead of pushing and storing the struct instances (created in addPerson) to an array, we can also assign them to a mapping. In a mapping, each instance would be mapped to a unique key (an address, for example), and so in the getPerson function a specific person would be retrieved based on its key (e.g. msg.sender) instead of its index number.

Iā€™m not sure if youā€™re covered the section of the course on mappings yet, but you need to watch the videos on mappings to be able to understand my following example:

// Contract State (storage)
Person[] people;  // using an array
mapping(address => Person) people;  // or using a mapping

// addPerson function
Person memory newPerson = Person(30, "Bob");
people.push(newPerson);  // push to an array
people[msg.sender] = newPerson;  // or assign to a mapping

//getPerson function
Person memory person = people[_index]; // retrieve from an array
Person memory person = people[msg.sender]; // retrieve from a mapping
return(person.age, person.name);

As always, just let me know if you have any further questions.

Hi Jonathan,

I am really grateful for your help. I think I can follow much better the course now armed with the new informations provided by you. Yes, just started the video on " Introduction to Mapping". I will definitely seek your help if I do encounter any difficulty further down the road. Thanks a lot.

Eric Wong

1 Like

hi why does my remix doesnt work the same as the remix in the tutorial in loops do? i double checked the words and everything but it doesnt work the same way it do in the tutorial pls help.

Hi @josejalapeno,

Please post a copy of your code (the full file, including the pragma statement), so I can take a look and find out what the problem is.

Follow the instructions here, about how to correctly format your code when posting it in the forum. This will ensure it is clear, easier to read, and easier to debug :slight_smile:

oh sorry theres a very small thing I havent checked and now it totally works, thank you!

1 Like

hello Filip are there any shortcuts or keybinds worth noting? Iā€™m looking for a way to place a semicolon at the end of the line without having to reach over and hit the end key

Hey @NoosphereLabs,

This isnā€™t something I have come across, but after a search Iā€™ve found the following on Ethereum Stack Exchange, which mentions that Remix uses the Brace Editor which supports Emacs and Vim keybindings. Iā€™ve never used these myself, so I canā€™t help you any further Iā€™m afraid. But if you already have a lot of experience with keybindings, maybe this might give you some ideas about where to look nextā€¦

https://ethereum.stackexchange.com/questions/99312/remix-ide-shortcuts

@thecil Is this something you know about, or could help more with?

1 Like

I do not understand the issue to be honest XD, I have always programmed with the same keyboard layout (US layout), although this layout is another alternative for some programmers.

https://www.dvorak-keyboard.com/

Carlos Z

2 Likes

OK, thanks @thecil

I think @NoosphereLabs wants a single key binding that will both add a semicolon to the end of a line of code AND move the cursor to the beginning of the next line with the same indentation.

Personally, Iā€™ve never had a problem with just hittingā€‚ shift + ; ā€‚and then hitting return separately ā€¦ but I do appreciate that other programmers like to use shortcuts as much as possible.

2 Likes

Hi filipļ¼š

I am learning the Smart Contract Programming 101. The course is great,thank you !

Right now I have a small problem when I code in Remix about the ā€œconstructorā€.

No matter what I typed to input , the decoded output is always the same ā€”ā€œHello World!ā€.

Could you pls help to find where did i code wrong!

Thanks again!

Code attached.

pragma solidity 0.7.5;

contract HelloWorld{

string message;

constructor(string memory _message){
    message = _message;
}

function hello() public  returns(string memory){
   
    return message;
}

}

ā€œbut WHYYYYYY!!!ā€ i heard john screamingā€¦
ok no that was just me lol BUT i do have a real question (maybe itā€™s already been answered? the search function for the site --and page itself-- was more burdensome than helpfulā€¦); doesnā€™t it have everything to do with how the key-value pair is stored in memory??

i think this is the critical thing still missing in the videosā€¦ basically a key-value mapping IS an array (using string indices), just that under the hood the data is mapped to stored in computer memory differently such that access is much faster and scales more favorably with increases in data sizeā€¦

no?

1 Like

Thank you for the response @thecil and @jon_m !
My background is in playing world of warcraft where I could keybind all my functions so my hand never left the keyboardā€¦ based on some research it sounds like vim is the text editor I should be using. Iā€™m new to coding and learning all the keybinds, it looks like when Filip writes code in his video, the strings auto populate with " and ) and ; as he writes

1 Like

Hey @NoosphereLabs,

When I typeā€‚ " ā€‚ or ā€‚ ( ā€‚ my Remix text editor automatically adds the closing quotation marks or closing parenthesis after the cursor. Also, whenever I hitā€‚RETURN , my cursor automatically jumps to the same indentation on the next line. I imagine these are the default key bindings that Remix comes with. Does yours not come with these? Personally, Iā€™ve never felt the need to add any additional ones, but from the link I sent you, it seems like you can if you already have some knowledge about how to configure key bindings, and it sounds like youā€™ve already made some progress with your research :+1:

My Remix default settings donā€™t automatically add a semi colon to the end of each line of code I start typing. To me this makes sense, because not every new line will be a statement that requires one (e.g. function headers).

I guess, if you have your own particular key binding preferences, then you could code your contracts in your text editor of choice, and configure your key bindings there. You can then copy and paste your contracts into Remix to compile and deploy them. However, I can think of a couple of disadvantages with this method, which, while youā€™re still learning Solidity, will probably end up wasting more time than you save with your key bindingsā€¦

  • Writing your contracts directly within Remix has the advantage of being able to compile and check your code for errors as you code (set your Compiler Configuration to Auto compile in the Solidity Compiler panel). If you copy and paste your contracts from a different text editor into Remix, then, initially, you will probably have several compiler errors that you still need to correct before deployment.
  • Copying and pasting often fails to reproduce the same indentation, and so you would probably still need to make some further adjustments to your code in Remix anyway.
1 Like

Hi @michael356,

The contract you have posted needs to be deployed with a string (entered into the input box next to the orange Deploy button). From what you have explained, I assume you are already doing this with the stringā€‚"Hello World!"

The constructor is only called on deployment, and so if you donā€™t have another function which you can call to change the string stored in the message state variable, whenever you call the hello() function, it will always outputā€‚"Hello World!"

For example, if we add the following function to your contract ā€¦

function updateMessage(string memory _message) public {
    message = _message;
}

ā€¦ we can then do the following ā€¦

  1. Deploy the contract withā€‚"Hello World!" ā€” this assignsā€‚"Hello World!"ā€‚to the message state variable.
  2. Call hello() ā€” this outputs the messageā€‚"Hello World!"
  3. Call updateMessage() with a different string ā€” this assigns the new string to the message state variable, replacingā€‚"Hello World!"
  4. Call hello() ā€” this now outputs the new message.

Let me know if this answers your question and resolves your issue, or whether you still have questions :slight_smile:

You are also missing the view keyword in the hello() function header. You should get an orange/yellow compiler warning highlighting this.

There are 4 function types (3 of which we define with specific keywords in the function header) as follows:

  1. pure (most restrictive)
    Cannot change or read the contract state.
  2. view
    Can read the contract state, but cannot change it.
  3. undefined (no type declared in the function header)
    Can read and change the contract state (but cannot receive ether)
  4. payable (least restrictive)
    Can read and change the contract state, and can also receive ether.
    (We will look at payable later in the course)

Let me know if you have any questions.

Hi @B_S,

Leaving aside the similarities and differences of how mappings and arrays are compiled into bytecode and stored by the EVM ā€” which, due to the peculiarities of the EVM, isnā€™t the same as how arrays and maps in other programming languages are saved in computer memory ā€” letā€™s consider the similarities and differences that determine how, on a more practical level, arrays and mappings are used by Solidity developers to write their smart contract codeā€¦

The values stored in an array are ordered according to a fixed sequence of indices (0,1, 2, 3 etc.). Each index number and its associated value is a key/value pair (each unique key being an index number). This means that, as well as being able to reference or retrieve values by their specific index number (if we know it), arrays can also be iterated over. The ability to iterate over an array, means we can search for specifc data stored within it, without needing to know specific index numbers (keys). In Solidity, only fixed-size arrays can have values added to specifc index numbers. To add values to a dynamic-sized array, they have to be pushed using the .push() array method.

Mappings are also data structures which store key/value pairs. However, unlike arrays, values can be mapped to unique keys of data-types other than uint e.g. addresses or strings. There is, therefore, no need for values to be added and stored in a mapping according to a fixed, sequential order of integers, which must begin with 0.

Because a mapping can be defined with uint keys, values could potentially be added and mapped according to a fixed sequence of uint keys which mirror an arrayā€™s index values. However, this would most probably be an inefficient use of a mapping, and it is generally accepted that mappings cannot be iterated over (although, strictly speaking, this doesnā€™t seem to me to be completely true). In Solidity, mappings are commonly used to map values to Ethereum addresses, and in this case, they cannot be iterated over. In order to add, modify, reference or retrieve a value mapped to an address, this unique address needs to be known. This gives mappings the ability to provide more in-built data privacy than arrays.

Generally speaking, if you need to store and look up large amounts of data, using mappings will save you a noticeable amount of gas (as opposed to using arrays); and, as you say, usually ā€¦

With large amounts of data, using arrays, where mappings could provide the same results, runs the risk of transactions running out of gas and failing, because the gas limit has been reached.

I hope this gives you a clearer picture of the differences between mappings and arrays in Solidity. Let me know if you have any further questions.

1 Like

@jon_m thanks for such a thorough response!

arrays, unlike mappings, can be iterated over their VALUESā€¦:exploding_head:

are there type rules for mappings? e.g. do the keys (and/or values) in each mapping have to be of the same type as each other? or is it possible to have strings in some and uint in some and int in some, etc, all within the same mapping structure?

You can use a mapping that forward to a struct.

Something like

struct Person{
uint id;
string name;
int age;
}

mapping (address => Person) Clients;

Carlos Z

1 Like