# Nested if statements with assignments?

**URL:** <https://forum.flow.com/t/nested-if-statements-with-assignments/758>\
**Category:** 🏄🏻‍♀️ Cadence\
**Created:** [January 7, 2021, 6:58pm UTC](https://forum.flow.com/t/nested-if-statements-with-assignments/758 "2021-01-07T18:58:07Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![qvvg](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/qvvg/32/78_2.png) [@qvvg](https://forum.flow.com/u/qvvg)\
**Post date:** [January 7, 2021, 6:58pm UTC](https://forum.flow.com/t/nested-if-statements-with-assignments/758/1 "2021-01-07T18:58:07Z")

</div>

I often find myself needing to nest if statements with assignments. This is usually done in a script where exploding because something is lacking is bad, the return value for these scripts is usually an optional struct.

In general I am not needing the capability past the point of know if it exists or not. I mostly need access to the information inside a resource if its there otherwise i want the value for everything to be nil. The question is can this be done in a nicer way?

```auto
import BarCollection from 0x___

pub fun main(addr: Address, id: UFix64): BarCollection.ReadOnly? {
  let collectionCapability = getAccount(address)
    .getCapability<&BarCollection.Collection{BarCollection.CollectionPublic}>(BarCollection.publicPath)!
  
  if let collection = collectionCap.borrow() {
    if let nft = collection.borrowNFT(id: id) {
      return nft.asReadOnly()
    }
  }

  return nil
}

```

We need to do these additional checks because there is no optional equivalent to the above `collection.borrowNFT` in the NFT spec. (Line 130: [https://flow-view-source.com/testnet/account/0x631e88ae7f1d7c20/contract/NonFungibleToken](https://flow-view-source.com/testnet/account/0x631e88ae7f1d7c20/contract/NonFungibleToken))

In the above case it doesn’t seem that bad, but there are situations, like in a market place, where we may want to receive both the listing info as well as the the NFTs info. In which case the above gets fairly more complex/messy… Once again, if the nft or the listing isnt a thing I am wanting it to return nil

```auto
import BarCollection from 0x___
import BarMarket from 0x___

pub struct ReadOnly {
  let listing: BarMarket.ReadOnly
  let nft: BarCollection.ReadOnly

  init(listing: BarMarket.ReadOnly, nft: BarCollection.ReadOnly) {
    self.listing = listing
    self.nft = nft
  }
}

pub fun main(addr: Address, id: UFix64): ReadOnly? {
  let collectionCapability = getAccount(address).getCapability<&BarCollection.Collection{BarCollection.CollectionPublic}>(BarCollection.publicPath)!
  let marketCapability = getAccount(address).getCapability<&BarMarket.Collection{BarMarket.CollectionPublic}>(BarMarket.publicPath)!
 
  if let market = marketCapability.borrow() {
    if let listing = market.borrowListing(id: id) {
      if let collection = collectionCap.borrow() {
        if let nft = collection.borrowNFT(id: id) {
          return ReadOnly(listing: listing.asReadOnly(), nft: nft.asReadOnly())
        }
      }
    }
  }

  return nil
}

```

Maybe I am completely missing something? Maybe some sort of optional chaining?Is there a nicer way of doing the above?

---

<div class="post-metadata">

**Author:** ![qvvg](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/qvvg/32/78_2.png) [@qvvg](https://forum.flow.com/u/qvvg)\
**Post date:** [January 7, 2021, 7:12pm UTC](https://forum.flow.com/t/nested-if-statements-with-assignments/758/2 "2021-01-07T19:12:04Z")

</div>

If there isn’t currently a nicer way of doing this, I would like to offer up some inspiration from elixirs with statement ([https://elixir-lang.org/getting-started/mix-otp/docs-tests-and-with.html#with](https://elixir-lang.org/getting-started/mix-otp/docs-tests-and-with.html#with)).

Very roughly translated the above code in elixir could looks something like this:

```auto
def main(addr, id) do
  with acct <- getAccount(addr),
       {:ok, nft} <- acct.getCapability<___>(___)!.borrow()!.borrowNFT(id: id),
       {:ok, listing} <- acct.getCapability<___>(___)!.borrow()!.borrowListing(id: id) do
    %{nft: nft, listing: listing}
  else
    _ -> nil
  end     
end

```

---

<div class="post-metadata">

**Author:** ![bastian](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/bastian/32/183_2.png) [@bastian](https://forum.flow.com/u/bastian)\
**Post date:** [January 7, 2021, 7:31pm UTC](https://forum.flow.com/t/nested-if-statements-with-assignments/758/3 "2021-01-07T19:31:18Z")

</div>

Great point that if-let statements are not ideal for working with multiple optionals, as they lead to deep nesting.

Here are some ideas on how this could be improved:

- Swift has `guard` statements, see [https://docs.swift.org/swift-book/ReferenceManual/Statements.html#ID524](https://docs.swift.org/swift-book/ReferenceManual/Statements.html#ID524), which are a bit like the inverse of the `if`: when the condition is false or the binding fails (due to the value being nil), the block is executed and it must somehow stop execution of the function at the end, e.g. by using a return statement.

- In addition, Swift allows multiple optional bindings in if-statements and guard-statements, which reduces the nesting.

- In Kotlin, `return` can be used in expressions, and it is common to used with nil coalescing operator.

````auto
    pub fun main(addr: Address, id: UFix64): BarCollection.ReadOnly? {
      let collectionCapability = getAccount(address)
        .getCapability<&BarCollection.Collection{BarCollection.CollectionPublic}>(BarCollection.publicPath)!
  
      let collection = collectionCap.borrow() ?? return nil
      let nft = collection.borrowNFT(id: id) ?? return nil
      return nft.asReadOnly()
    }
    ```
````

---

<div class="post-metadata">

**Author:** ![qvvg](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/qvvg/32/78_2.png) [@qvvg](https://forum.flow.com/u/qvvg)\
**Post date:** [January 7, 2021, 7:37pm UTC](https://forum.flow.com/t/nested-if-statements-with-assignments/758/4 "2021-01-07T19:37:46Z")

</div>

Okay, so I think what I am seeing is that it isn’t currently possible to make that nicer?

I dont really have any issues about the stuff you are suggesting there from the other languages. A couple points I wouldn’t mind highlighting though.

- Returning from a nullish coalescing operator like in kotlin might be confusing in cadence given how return currently works.
- Multiple lets per if statement would probably work just fine
- I like the guard idea, sort of like an early return in javascript

A try catch sort of thing could also work for this i think. Write the code in a very explicit way like you are expecting it to be there, and then if if throws an error catch and return nil, but can also see some issues with that like partial state reverting in transactions which could lead to all sorts of really bad things 😕 don’t know if thats a thing we really want in cadence without really really thinking it through.

```swift
pub fun main(address: Address, id: UInt64) {
  try {
    let listing = getAccount(address).getCapability<__>(__)!.borrow()!.borrowListing(id: id).asReadOnly()
    let nft = getAccount(address).getCapability<__>(__)!.borrow()!.borrowNFT(id: id).asReadOnly()
    return ReadOnly(listing: listing, nft: nft)
  } catch _e {
    return nil
  }
}

```

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/daniel/32/77_2.png) [@daniel](https://forum.flow.com/u/daniel)\
**Post date:** [January 8, 2021, 1:10am UTC](https://forum.flow.com/t/nested-if-statements-with-assignments/758/5 "2021-01-08T01:10:02Z")

</div>

Was looking for `guard` myself when doing nested ifs.
