CodingTour
ARTS #16

Algorithm

本周选择的算法题是:Longest Common Prefix

规则如下:

Write a function to find the longest common prefix string amongst an array of strings.

If there is no common prefix, return an empty string "".

Example 1:

Input: ["flower","flow","flight"]
Output: "fl"

Example 2:

Input: ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.

Note:

All given inputs are in lowercase letters a-z.

Solution

我实现的方案:

Runtime:36 ms,快过 91.26%。

Memory:14 MB,低于 6.67%。

class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if len(strs) == 0:
            return ""

        for char_index in range(len(strs[0])):
            char = strs[0][char_index]
            for index in range(1, len(strs)):
                if len(strs[index]) <= char_index or strs[index][char_index] != char:
                    return strs[0][:char_index]
        return strs[0]

Review

Understanding Opaque Return Types in Swift Understanding Opaque Return Types in Swift

这是两篇文章,前者对 Opaque 类型的优势、作用解释得很清楚,后者描述了编译器对此的实现细节。

简而言之,Opaque 的特点如下:

  1. 相比协议,它能被编译器推断出类型,而不用暴露实际的类型给调用者,提高了封装性
  2. 因为没有暴露实际的类型,所以调用者不用担心未来产生的兼容性问题
  3. 提供了在运行时动态返回特定类型的能力,trade off 是不能返回多种类型(因为这种情况下编译器推断不出一个具体类型)
  4. 支持协议中的 Selfassociatedtype
  5. 协议是将返回值的具体类型交给调用者来决定,Opaque 则是由函数本身来决定

在实现上,考虑以下方法:

public func favoriteCreditCard() -> some PaymentType {
    return getLastUsedCreditCard() // () -> CreditCard
}

编译器找断 getLastUsedCreditCard 实际上返回的是一个 CreditCard,于是记录下这个类型:

let favoriteCreditCardMangledName = "$s3MyApp9favoriteCreditCardQryF"
public func favoriteCreditCard() -> @_opaqueReturnTypeOf(favoriteCreditCardMangledName, 0) {
    return getLastUsedCreditCard() // () -> CreditCard
}

该方法的 AST 中会有如下记录:

// The definition of favoriteCreditCard() contains:
(opaque_result_decl
  (opaque_type interface type='(some PaymentType).Type' naming_decl="favoritePaymentType()" underlying:
    substitution τ_0_0 -> CreditCard)))

它的返回类型在编译时就已经决定了,返回 some PaymentType 等同于 CreditCard

Tip

最近刚接触 GitHub Enterprise,了解到 code owners,它可以在 PR 创建时自动为该 PR 指定 Reviewer,这个功能在自动化下很好用,使用起来也没有学习成本,语法与 gitignore 一致。

Share

How To Prepare Your App For iOS 13

这是一份兼容 iOS 13 的 checklist:

  1. 先看看你的 App 在 iOS 13 下运行的怎么样,修复掉明显的问题
  2. 更新的你的依赖,相信有一部分框架会更新以支持 iOS 13
  3. 是否需要支持 Dark 模式,可以在 Info.plist 中配置 UIUserInterfaceStyleLight or Dark
  4. 一些 UI 的外观更新了: 可能涉及到一些 API 的配置,如 tint color
  5. 模态窗口的默认展示方式和交互更新了,如果想维持以前的方式: modalPresentationStyle = .fullScreen
  6. SF Symbols,这是系统级的 icon 支持: 使用默认提供的 icon 或者创建自定义的 icon 都非常简单,具体参见:SF Symbols