LIst (Array) in Sophia

Hello,
I want to use an Array in Sophia programming language, but I realized that Sophia uses list instead. So my question is how do I add an item to the list… here is my code, I don’t know what I’m doing wrong

record state =
	{ owner : address,
      currentPositionId : int,
      positionIdsByAddress: map(address, list(int))}

stateful entrypoint init() : state  =
	{ owner = Call.caller, currentPositionId = 0, positionIdsByAddress = {} }


payable stateful entrypoint depositAE(numDays: int) =
   let newPositionIdsByAddress = state.positionIdsByAddress[Call.caller] ++ [state.currentPositionId]
   put(state{positionIdsByAddress[Call.caller] = newPositionIdsByAddress })

I just want to add an item to the positionIdsByAddress map whenever depositAE function is called. this is my first time coding in Sophia programming language.

Hello @paschal533,

As I understand from your code, you are trying to update the map positionIdsByAddress but it’s not working for you.

You are trying to create a new map newPositionIdsByAddress and then assigning it to the positionIdsByAddress map in the state, which is fine, but there are a couple of issues to note in your code.

1. The way the new map (i.e. newPositionIdsByAddress) is created

By doing state.positionIdsByAddress[Call.caller], you are trying to access the element of the map with the key Call.caller and you are getting an error. In Sophia, no default value is assigned to a key that does not exist in the map, so you will get the error FATE error: Maps: Key does not exist by doing that.

To fix that, we have a special syntax for assigning values to key that you are not sure if it exist: m{ [key = defaultValue] @ oldValue = newValue }, you can read more about this in the docs Features - æternity Sophia Language.

In your case, it will become like this:

let newPositionIdsByAddress = state.positionIdsByAddress{[Call.caller = []] @ positions = positions ++ [state.currentPositionId]}
  1. The [] is the default value which is assigned to the key in case it does not exist yet in the map.
  2. positions is the old value of the key Call.caller (if there is no old value, it will just be the default value).
  3. positions ++ [state.currentPositionId] will be the new values (appending state.currentPositionId to the existing list).

2. When placing the newPositionIdsByAddress in the state

The right way to do this is

put(state{positionIdsByAddress = newPositionIdsByAddress })

Because you need to assign the new map to positionIdsByAddress which is the map in the state record, and you do not need to assign it to positionIdsByAddress[Call.caller] which is a list (because you’re accessing an element of that map).

I hope this was helpful, please do not hesitate to ask more questions if anything was not clear enough.

4 Likes

Thank you so much

2 Likes

To quickly add a single item to a list use the :: operator. ++ is used to conatenate lists and is quite slow (linear time to the length of the left-side list).

4 Likes

Understood
thank you

1 Like