nicklockwood,
@nicklockwood@mastodon.social avatar

tip: if you need to bind a non-optional value to a temporary variable inside a conditional statement, you can use case let, e.g:

if indexPath.section < sections.count,
case let section = sections[indexPath.section],
indexPath.row < section.rows.count,
case let row = section.rows[indexPath.row],
row.isEnabled
{
...
}

This saves you needing to split up the condition into multiple statements, and polluting the local namespace with temporary variables you don't need again.

nicklockwood,
@nicklockwood@mastodon.social avatar

Note that in if you find yourself needing to write this particular type of check a lot, it might be better to add an extension like:

extension Array {
subscript(safe index: Int) -> Element? {
indices.contains(index) ? self[index] : nil
}
}

So that you can just write:

if let section = sections[safe: indexPath.section],
let row = section.rows[safe: indexPath.row],
row.isEnabled
{
...
}

But case let can still be useful in other scenarios besides array indexing.

ctietze,
@ctietze@mastodon.social avatar

@nicklockwood indices.contains is interesting. It makes absolute sense.

This could be O(n) instead of O(1), compared to @ericasadun's old extension0 I kept around since 2015:

extension Array {  
 subscript (safe index: UInt) -&gt; Element? {  
 return Int(index) &lt; count ? self[Int(index)] : nil  
 }  
}  

-- but that's surely irrelevant. If that kind of performance matters, one wouldn't use this subscript anyway.

nicklockwood,
@nicklockwood@mastodon.social avatar

@ctietze @ericasadun indices is a Range so lookup is 0(1). That may not be the case for every collection type though.

Incidentally .count is O(n) for Strings IIRC, so that extension isn't necessarily safe either.

ctietze,
@ctietze@mastodon.social avatar

@nicklockwood 👍 To be fair, the count-based subscript was on Array, an so not available on String. Your generalization works better in all cases

nicklockwood,
@nicklockwood@mastodon.social avatar

@ctietze sorry, I meant not safe if applied to other collection types. Plus indices.contains also handles the scenario that index <0, avoiding the need to use UInt, which is kind of a PITA in Swift.

ctietze,
@ctietze@mastodon.social avatar

@nicklockwood Yeah, once every year I'm starting to model types with UInt because I know that <0 should not be allowed -- only to eventually revert to Int because that makes everything else incompatible. (Currently doing the same for a small cell grid. Let's see if it sticks...)

nicklockwood,
@nicklockwood@mastodon.social avatar

@ctietze there was a rationale given in the original Swift book for why they used Int for indices instead of UInt (that I now can't remember), but yeah, you're basically swimming against the tide trying to use it in Swift.

nicklockwood,
@nicklockwood@mastodon.social avatar
ctietze,
@ctietze@mastodon.social avatar

@nicklockwood Aah that's where this was being said! Thank you for digging this up. Goes right into my for future code discussions :)

ctietze,
@ctietze@mastodon.social avatar

@nicklockwood Was rummaging through my notes -- https://www.cocoawithlove.com/blog/2016/01/25/partial-functions-part-one-avoidance.html

I channel @cocoawithlove's reasoning and NonZeroInt in times like these.

nicklockwood,
@nicklockwood@mastodon.social avatar

@ctietze @cocoawithlove yeah, I agree with the idealism of having a separate type for every integer range in principle, but the semantics of the Swift language are not conducive to working that way.

For a glimpse of what that world might look like, you need look no further than Swift's String indexing system, which is universally agreed to be a painful clusterfuck to work with, and yet somehow still doesn't fully manage to prevent out of bounds crashes or accidental O(n^2) operations.

ctietze,
@ctietze@mastodon.social avatar

@nicklockwood Ha, yeah, String's a fair example :)

lorentey,
@lorentey@mastodon.social avatar

@ctietze @nicklockwood Just popping in to note that there is only one String.Index type, shared across all string views. (The indexing model would in fact be simpler to understand/implement if each view had its own index type, but that was deemed too inconvenient. Nevertheless, creating named wrapper types to implement ad hoc subtypes is a highly useful technique, and it should be encouraged and normalized, rather than ridiculed.)

ctietze,
@ctietze@mastodon.social avatar

@lorentey What do you mean when you write 'named wrapper types'? Things like ArraySlice, or to rather what e.g. @cocoawithlove suggested: encapsulate conditions in a new type?

@nicklockwood

MuseumShuffle,
@MuseumShuffle@mastodon.social avatar

@nicklockwood This is something I remember asking ChatGPT not that long ago.

nicklockwood,
@nicklockwood@mastodon.social avatar

@MuseumShuffle wow, that answer was gibberish 😅

MuseumShuffle,
@MuseumShuffle@mastodon.social avatar

@nicklockwood What makes it worse is that we had several back and forth iterations where I kept saying "That's not what I asked" before it finally declared that it can't be done.

czottmann,
@czottmann@norden.social avatar

deleted_by_author

  • Loading...
  • nicklockwood,
    @nicklockwood@mastodon.social avatar

    @czottmann yeah, it's not something you want to overuse, but in scenarios where you'd otherwise have to duplicate the if body (or extract it to a common function so it can be called multiple times), I think it can reduce a lot of code bloat.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • random
  • kavyap
  • thenastyranch
  • tester
  • DreamBathrooms
  • mdbf
  • magazineikmin
  • tacticalgear
  • Youngstown
  • ethstaker
  • osvaldo12
  • slotface
  • everett
  • rosin
  • khanakhh
  • megavids
  • ngwrru68w68
  • Leos
  • modclub
  • cubers
  • cisconetworking
  • Durango
  • InstantRegret
  • GTA5RPClips
  • provamag3
  • normalnudes
  • anitta
  • JUstTest
  • lostlight
  • All magazines