# Variables & Constants & Collection Overview

## Variables and Constants

### How to declare

`let` represents a constant, and `var` represents a variable.

```swift
pub fun main {
   var a: Int = 2 // Regular types cannot contain nil (null).
   var a: Int? = nil // To allow variables to hold nil, use an Optional Type.
   var b Int = a!  // To convert an Optional type to a regular variable, use !. (In this case, it's nil, so it will result in an error.)
}
```

In Cadence, it is common to convert an optional type to a regular type. Using optional binding (the `if let` statement) simplifies this process, as the variable within the `if let` block is no longer optional.

* * *

## Types

### **Boolean type**

```swift
let boolVar: Bool = true
```

* * *

### **Int type**

```typescript
let int8: Int8 = 127 // -128~127
let int16: Int16 = 32767 // -32768~32767
let int32: Int32 = 2147483647 // -2147483648~2147483647
let int64: Int64 = 9223372036854775807 // -9223372036854775808~9223372036854775807
let int128: Int128 = 9223372036854775808 // -2^127~2^127 − 1
let int256: Int256 = 9223372036854775808 // -2^255~2^255 − 1
```

* * *

### **UInt type**

```typescript
let uint8: UInt8 = 255 // 0~255
let uint16: UInt16 = 65535 // 0~65535
let uint32: UInt32 = 4294967295 // 0~4294967295
let uint64: UInt64 = 18446744073709551615 // 0~18446744073709551615
let uint128: UInt128 = 18446744073709551616 // 0~2^128 − 1
let uint256: UInt256 = 18446744073709551616 // 0~2^256 − 1
```

* * *

### Arbitrary-precision type (`Int`/`UInt`)

```swift
let integer: Int = 1 // Arbitrary-precision (unbounded)
let uinteger: UInt = 1 // Arbitrary-precision (unbounded)
```

* * *

### **Word** type

Unsigned integer types that do not perform overflow or underflow checks, i.e., those that wrap around, have the prefix “Word” and can represent values within the following range.

```typescript
let nilWord: Word8? = Word8.fromString("1024") // nil, out of bounds, 0~255
let word16: Word16? = Word16.fromString("255") // 0~65535
let word32: Word32? = Word32.fromString("255") // 0~4294967295
let word64: Word64? = Word64.fromString("255") // 0~18446744073709551615
```

* * *

### **Fix / UFix** type

```typescript
let fix64: Fix64? = Fix64.fromString("-0.1") // ok, -92233720368.54775808~92233720368.54775807
let ufix64: UFix64? = UFix64.fromString("-0.1") // nil, 0.0~184467440737.09551615
```

* * *

### **Address** type

```typescript
let some: Address = 0x436164656E636521 // UInt64 length. (Max:18446744073709551615)
```

* * *

### **AnyStruct / AnyResource** type

All types are classified as either `AnyStruct` or `AnyResource`. The `AnyStruct` type can represent all types except for `Resource` types.

```typescript
var someStruct: AnyStruct = 1 // Can represent all types except Resource type
var someResource: @AnyResource <- create TestResource()
```

Always prefix the resource type with the `@` directive. Use the `<-` operator for moves.

* * *

### **Never** type

```typescript
 let x: Never = nil
```

**Return type of the panic function**

* * *

### **Character / String** type

```typescript
let char: Character = "\u{FC}"
let someString: String = "Hello, world!"
```

* * *

## Functions for each type

### **Int / Address type functions**

```typescript
/* Convert a number to a string */
let int8Number: Int8 = 127
let int8str String = int8Number.toString()


/* Returns a byte array in big-endian order */
let largeNumber: Int32 = 1234567890
let arr: [UInt8] = largeNumber.toBigEndianBytes() //[73, 150, 2, 210]


/* Convert a string to a number */
let int8str: String = "42"
let int8number: Int64? = Int64.fromString(int8str)


/* Return the maximum value of a number */
let max = UInt8.max // 255


/* Return the minimum value of a number */
let min = UInt8.min // 0


/* Convert a FixedPointNumber to a string */
let fix64number: Fix64 = 1.23
let fix64str String = fix64number.toString()


/* Convert an Address to a string */
let shortAddress: Address = 0x1
let str: String = shortAddress.toString()  // "0x0000000000000001"


/* Convert an Address to a UInt8 array */
let someAddress: Address = 0x436164656E636521
someAddress.toBytes()  // is [67, 97, 100, 101, 110, 99, 101, 33]
```

* * *

### **String type functions**

```typescript
/* Get the length of a string */
let example: String = "hello"
let length: Int = example.length // 5


/* Convert a string to a byte array using UTF8 encoding */
let str: String = "hello"
let utf8: [UInt8] = str.utf8()


/* Concatenate strings */
let str1 = "hello"
let str2 = "world"
let helloWorld = str1.concat(str2) // "helloworld"


/* Get a part of a string */
let example = "helloworld"
let slice = example.slice(from: 3, upTo: 6) // "low"


/* Convert a string to a byte array represented as a hexadecimal string */
let example = "436164656e636521"
example.decodeHex() // is [67, 97, 100, 101, 110, 99, 101, 33]


/* Convert a string to lowercase */
let example = "Flowers"
example.toLower() // `flowers`


/* Convert a byte array to a hexadecimal string */
let data = [1 as UInt8, 2, 3, 0xCA, 0xDE]
String.encodeHex(data) // is "010203cade"


/* Get one character from a string */
let str = "abc"
let c: Character = str[0] // is the Character "a"

```

* * *

### **Character type functions**

```typescript
/* Convert a character to a string */
let c: Character = "x"
c.toString()  // is "x"


/* Convert an array of characters to a string */
let rawUwU: [Character] = ["U", "w", "U"]
let uwu: String = String.fromCharacters(rawUwU) // "UwU" 
```

* * *

# Collection Types

## Array type

### How to declare

They can be declared within `contract`, `struct`, or `resource` types, as well as within transaction code. When defined within a smart contract, initialization via `init` is required.

```typescript
access(all) contract SampleContract {
    access(contract) var allNames: [String]
    init() {
      self.allNames = []
    }
 }
```

A `Contract` is also a type, but in this case, the address where it is deployed is included as part of the type definition. Consequently, `Struct` and `Resource` types are never confused with types defined within other Contracts.

* * *

### **Array type functions**

```typescript
/* Retrieve the length of an array */
self.allNames.length


/* Concatenate arrays */
self.allNames.concat(allNames2)


/* Check if an array contains a value */
self.allNames.contains("Kitty")


/* Add a value to array */
self.allNames.append("Jane") // This function mutates the array.


/* Add multiple values to an array */
self.allNames.appendAll("Jane", "Daisy") // This function mutates the array.


/* Get the index of a value in an array */
self.allNames.firstIndex(of: "Daisy")


/* Get a portion of an array */
self.allNames.slice(from: 1, upTo: 3)


/* Insert a value at any position in an array */
self.allNames.insert(at: 2, "Daisy") // This function mutates the array.


/* Remove a value from an array */
self.allNames.remove(at: 1) // This function mutates the array.


/* Remove the first value from an array */
self.allNames.removeFirst() // This function mutates the array.


/* Remove the last value from an array */
self.allNames.removeLast() // This function mutates the array.
```

* * *

## Dictionary type

### How to declare

They can be declared within `contract`, `struct`, or `resource` types, as well as within transaction code. When defined within a smart contract, initialization via `init` is required.

```typescript
access(all) var luckeyNumbers: {String: Int}
init() {
  self.luckeyNumbers = {}
}
```

When `self` is referenced within a `struct` type, it represents the `struct` type; within a `resource` type, it represents the `resource` type; and within a `contract`, it represents the `contract` type.

* * *

### **Dictionary type functions**

```swift
/* Insert a value */
self.luckeyNumbers["Daisy"] = 7


/* ・If you want to raise an error when "Daisy" is not present in `luckeyNumbers`, you can achieve this by using a `pre` block. */
pre {
    self.luckeyNumbers.contains("Daisy"): "Not in luckeyNumbers"
}


/* Get all keys from a Dictionary */
self.luckeyNumbers.keys


/* Get all values from a Dictionary */
self.luckeyNumbers.values // This method cannot be used with a Dictionary containing resources (resources cannot be moved without the <- operator).


/* Insert a value at any position in a Dictionary */
self.luckeyNumbers.insert(key: "Jessica", 42) // If a value already exists, it is returned as an Optional type.


/* Retrieve a value from a Dictionary */
self.luckeyNumbers.remove(key: "Joe") // If a value is present, it returns that value as an Optional type; otherwise, it returns nil.


/* Check if a Dictionary contains a value */
self.luckeyNumbers.containsKey("Kitty")


/* Iterates over all keys in the Dictionary */
self.luckeyNumbers.forEachKey(fun (key: String): Bool {
    // The returned boolean value signals whether to continue
    // true = `continue`
    // false = `break`
    return true
})
```

* * *

### pre and post blocks

The `pre{}` block contains validation logic to be checked before the transaction is executed,

while the `post{}` block contains validation logic to verify the transaction's validity immediately before it is included in the blockchain.

As the name implies, the `pre` block is used to verify the validity of values ​​at the beginning of a method. If a value is invalid, a panic (transaction failure) occurs, and the string following the colon (`:`) is displayed in the transaction result output.

Similarly, the `post` block is used to verify the validity of values ​​at the end of a method. If a value is invalid, a panic (transaction failure) occurs, and the string following the colon (`:`) is displayed in the transaction result output.

`pre` and `post` blocks can also be used in transaction code; transaction processing proceeds in the order: `prepare` block -> `pre` block -> `execute` block -> `post` block. (In principle, anything that can be written in a smart contract—except for event declarations—can also be written in transaction code.)

* * *

### **event**

You can declare it within the smart contract and invoke it during transaction execution; it can be called from either a smart contract or transaction code. When invoking it, you can pass arguments of the types specified in the event declaration, and by monitoring these in Go or JavaScript, you can track what is happening. Retrieving events is slightly more complex than retrieving blockchain information based on a transaction ID.

* * *
