65
pragma solidity ^0.4.8;

library Library {
  struct data {
     unit val;
   }
}

contract Array{
    using Library for Library.data;
    mapping(address => Library.data) clusterContract;
function addCluster(address id) returns(bool){
    if (clusterContract[id] == address(0)) {  // error occurs!
        clusterContract[id] = list;
        return true;
    }
    return false; 
}

}

Following comparission if (clusterContract[id] == address(0)) gives the following error:

Operator == not compatible with types struct Library.data storage ref and address
E               if(clusterContract[id] == address(0)) {...

How could I fix this error?

alper
  • 8,395
  • 11
  • 63
  • 152

2 Answers2

62

You can't directly find out if any key exists in a mapping, ever, because they all exist.

mapping(key => value) name;

creates a namespace in which all possible keys exist, and values are initialized to 0/false.

If you want to check that a value was explicitly set, and not merely the default (0), then you have to program something. In some cases, value > 0 is enough, but if 0 has meaning in your application, then another struct member can help ... bool isValue;, for example.

library Library {
  struct data {
     uint val;
     bool isValue;
   }
}

contract Array{

using Library for Library.data;
mapping(address => Library.data) clusterContract;

function addCluster(address id) returns(bool){
    if(clusterContract[id].isValue) throw; // duplicate key
    // insert this 
    return true; 
}

}

I noticed "addCluster" has the appearance of a contract factory (in progress), so you probably intend to keep track of contracts created as you go.

I assembled a little summary of different ways of organizing common data patterns in Solidity. It might be helpful to take a look here: Blog: Simple Storage Patterns in Solidity

Hope it helps.

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
  • Under // insert this I have to put clusterContract[id].isValue=true so when same id is provided on the next function call, it will enter into throw; right? And thank you for the the design patterns I will work on them. @RobHitchens. – alper Mar 13 '17 at 16:06
  • 1
    Yes. Exactly. You explicitly mark it in a way that leaves no doubt about the data being "real". I just figured you were planning to press on and create a contract and then you would need a way to store the address ... or similar. – Rob Hitchens Mar 13 '17 at 16:22
  • Could you explain (or potentially point me to a resource) that explains this idea of creates a namespace in which all possible keys exist, and values are initialized to 0/false. What are the memory implications of this? Does it dynamically instantiate a struct when I try to access it? – Olshansky Jul 31 '17 at 00:30
  • I took a stab at explaining mappings here. https://medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a – Rob Hitchens Jul 31 '17 at 03:16
3

This solution seems working, but I am open to any advices.

In C following should not work since clusterContract[id].flag does not exist in the first call to create map for id. But in this example clusterContract[id].flag != 1 returns true at initial step to create map from id. After clusterContract[id].flagassigned to 1 clusterContract[id].flag != 1 returns false.

pragma solidity ^0.4.8;

library Library {
  struct data {
     uint val;
     uint8 flag;
   }
}

contract Array{
    using Library for Library.data;
    mapping(address => Library.data) clusterContract;

    function addCluster(address id) returns(bool){
        if(clusterContract[id].flag != 1 ){ 
            clusterContract[id] = list;
            clusterContract[id].flag = 1;
            return true;
        }
        return false; 
    }
}
Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
alper
  • 8,395
  • 11
  • 63
  • 152
  • Yes, it does exist and it defaults to false, so != 1/true. It doesn't need someone to set it in order to exist. In a mapping, all possible keys exist and corresponding values have zeroish defaults. – Rob Hitchens Mar 13 '17 at 16:41
  • Are you trying to track structs for entities that have predetermined addresses, such as users who enroll, or are you trying to create new contracts on demand? Or maybe a little bit of both? – Rob Hitchens Mar 13 '17 at 16:47
  • I am trying to do first one, like you said students who enroll. If the same user try to enroll again, contract should not allow since it has enrolled already. @RobHitchens – alper Mar 14 '17 at 05:28