0

I'm learning about the struct data type and I want to know if:

  • it's possible to return multiple instances of a struct object at the same time.
  • an instance declared locally (inside a function) can return its value.

I want to get the details of all the instances (book1, book2, and book3) returned to me at the SAME TIME. I ran the code and could only get the details for ONE INSTANCE at A GIVEN TIME. So, the two instances I declared at state-level (book1 and book2) returned values WHEN CALLED SEPARATELY. However, book3, which was declared locally, didn't return its value when called. What I got was a declaration error (DeclarationError: Undeclared Identifier).

  1. How do I return all the values together?
  2. Why is book3 not returning its value? Can't a struct have a local instance?
pragma solidity >=0.4.0 <0.9.0;

// Creating a struct contract
contract MyStruct {

    // Declaring a struct
    struct Book {
        string name;
        string writer;
        uint id;
        bool available;
    }
    
    // Declaring a structure object, book1 (state variable of type struct; no values)
    Book book1;
    
    // Assigning values to fields for another struct instance, book2
    Book book2 = Book ("Building Ethereum DApps", "Roberto Infante", 2, false);


    // Defining a function to set values for the fields for structures
    function setBookDetails() public {
        // Assigning values to book 1 (state struct above)      
        book1 = Book("Introducing Ethereum and Solidity", "Chris Dannen", 1, true);

        // Defining a new book instance locally, book3 (local struct)
        Book memory book3 = Book ("Solidity Programming Essentials", "Ritesh Modi", 3, true);
    }
        
    // Defining function to print book1 details
    function getBookDetails() public view returns (string memory, string memory, uint, bool) {
          return (book1.name, book1.writer, book1.id, book1.available);
        //return (book2.name, book2.writer, book2.id, book2.available);
        //return (book3.name, book3.writer, book3.id, book3.available);
    }
}
ATRUES
  • 3
  • 2

2 Answers2

3
  1. You can return ALL book objects with return statement if you would use array. ALSO Solidity creates getter functions automatically for public variables. As your array could be public, a public getter function would be generated for it automatically. The getter function is used to access the array variables directly and not for retrieving the array itself.
  2. There is a difference between Storage and Memory variables. The Solidity Smart Contract can use any amount of memory during the execution but once the execution stops, the Memory is completely wiped off for the next execution. Whereas Storage on the other hand is persistent, each execution of the Smart contract has access to the data previously stored on the storage area.
Peteris
  • 418
  • 2
  • 13
  • I had to look into arrays and it seems it's the best way to store and retrieve data. After modifying and simplifying my code a little, I was able to get all instances of the Book struct with a single return statement. Thanks, Peteris. – ATRUES Aug 17 '21 at 04:20
1

I just wanted to add to @Peteris' answer by saying that it is also possible to return multiple instances of a struct without creating an array. A function can have multiple return values but you still use a single return in that case:

function getBookDetails()
    public
    view
    returns (Book memory, Book memory, Book memory)
{
    return (book1, book2, book3);
}

Of course, since book3 is only visible in setBookDetails, it will only work if you make it available to the function, e.g. by making it a storage variable, moving the declaration to the function or passing it in via a parameter.

cameel
  • 706
  • 2
  • 8
  • I also tried this method and it worked, though I had to explicitly change the compiler to `pragma abicoder v2`. I later found out from the Solidity doc (https://docs.soliditylang.org/en/v0.8.7/layout-of-source-files.html#abi-coder-pragma) that is automatically activated by default starting from Solidity 0.8.0. So I used a more recent version to test this method and it worked. Thanks for the help @cameel. – ATRUES Aug 17 '21 at 04:38
  • True, with such a wide version range (`>=0.4.0 <0.9.0`) you do need the pragma. If your contract is actually meant to work with all these versions, you should use the older form (`pragma experimental ABIEncoderV2`) which works also before 0.7.4. But I'd actually recommend to just be more specific about the versions you support. – cameel Aug 17 '21 at 22:23
  • Also note that the reason you need the abicoder pragma is the use of a struct as the return value on an external function. You do not need it for value types like `uint` or `address` or if the function is internal. But anyway, if you do not have a good reason to stick with older compiler versions it's better to just use 0.8.x where you do not have to worry about it. – cameel Aug 17 '21 at 22:27