Subscripts: Dynamic Member Lookup
Tags: swift, dynamic, member, lookup
Published: 2020-08-08 05:06:23

Previously I have about `subscripts`, a really basic post to get involved with `subscripts`.

{% post fdorado985/subscripts-3obd %}

And a second one to see related to their parameters and static ones.

{% post fdorado985/subscripts-parameters-static-3koh %}

Now, let's see another topic related to them... **Dynamic Member Lookup**.

First of all, what comes in your mind when you hear about **Swift** language?

> If you think about **safety** we are just right now on the same path.

One of the greatest features in **Swift** is that it is a **safety** language.

Unlike **Python** or **PHP**. But hey!, I'm not saying they are not safe, I'm just saying they are relaxed on that aspect.

But don't misunderstand me, everybody can write bad code on any language, it is that we just need to think much more on what we are doing on the code.

> Just try to run `"Hey Swift" + 5.3` on a playground in Xcode... that's right! it is going to complain as soon as it tries to compile it. (Of course it make sense because how are you going to sum a `String` with a `Double`).

Now, it was too much talk!... what is this for? - Answer this is as easy that just say *provide arbitrary dot-syntax to your type*.

You could be thinking, but `Swift` already provides *dot-syntax* - That's true, let's dive in on our example.

## Example

```swift
struct Character {

  let name: String
  let costume: Costume

  enum Costume: String {
    case `default`
    case stars
    case re3Style
  }
}
``` 

We have our `struct`, and if we create an `instance` of our `struct`, we can get the properties using *dot-syntax* right?.

```swift
let jill = Character(name: "Jill Valentine", costume: .re3Style)

jill.name
jill.costume
```

Let's extend our `struct` with another `property`.

```swift
struct Character {

  // ...

  let quickSlots: [QuickSlot: String]

  enum QuickSlot {
    case up
    case left
    case right
    case down
  }

  // ...
}
```

> The quick slots in the game will be the shortcuts to access to equipment from our items.

Now we will set this in our `initializer`

```swift
let jill = Character(..., quickSlots: [.up: "Beretta 92FS", .right: "M26 Hand Grenade"])
```

If we plan to access to the quick slot with the `key` `up`, we will need to do something like this.

```swift
jill.quickSlots[.up] // Beretta 92FS
jill.quickSlots[.down] // nil
```

But if I would like to access to them with something like this...

```swift
jill.up
jill.down
```

![dot-syntax issue](https://dev-to-uploads.s3.amazonaws.com/i/jmp3yje11f6cox7e7jnm.png)

Here comes the `Dynamic Member Lookup`

First we need to add this core attributed `@dynamicMemberLookup`, and to make it work this needs the required `subscript` method `subscript(dynamicMember:)`

So our `struct` will look like this.

```swift
@dynamicMemberLookup
struct Character {

  let name: String
  let costume: Costume
  var quickSlots: [QuickSlot: String]

  enum Costume: String {
    case `default`
    case stars
    case re3Style
  }

  enum QuickSlot: String {
    case up
    case left
    case right
    case down
  }

  subscript(dynamicMember key: String) -> String? {
    guard let quickSlotKey = QuickSlot(rawValue: key) else { return nil }
    return quickSlots[quickSlotKey, default: "No Item"]
  }
}
```

> I use `: String` on the `QuickSlot` enum to be easier to access by its `rawValue`

Now if we try to use our previous `dot-syntax` call we get this.

```swift
jill.up // Beretta 92FS
jill.down // No Item
```

Although this seems great, be careful because you can use whatever `dot-syntax` variable, even if this doesn't exist.

```swift
jill.asdfsdfsdf // nil
```

> `dynamicMemberLookup` is evaluated at runtime not at compile time.

You can use `dynamicMemberLookup` for your own purposes but the main one is to interact with codes like Python.

> Also as quick tip:
> * You can inherit `dynamicMemberLookup` from your `base class` to your `children`.
> * You can use `class subscripts` that works such as `static subscripts`
> * These can be used with `keypath` (but that will be a topic for other day).

I think this `subscript` posts work for you!.
It is just practice, so practice, practice, practice.

Happy coding 👨‍💻!