🔥 중첩된 하위 명령어 정의하기
294자
3분
다음은 Math
세 번째 하위 명령어인 Statistics
를 정의해 볼게요. Statistics
명령어는 설정에서 사용자 정의 명령어 이름(stats
)을 지정해 타입 이름에서 파생된 기본값(statistics
)을 재정의해요. 그리고 추가로 하위 명령어 두 개를 선언하고 있는데, 이는 마치 나무에서 가지가 갈라지듯이, 명령어의 구조가 세분화된다는 것을 의미합니다.
extension Math { struct Statistics: ParsableCommand { static var configuration = CommandConfiguration( commandName: "stats", abstract: "Calculate descriptive statistics.", subcommands: [Average.self, StandardDeviation.self]) } }
swift
마지막으로 Average
와 StandardDeviation
타입으로 하위 명령어를 완성해 볼게요. 각 하위 명령어는 약간 다른 인자를 가지고 있어서 위에서 정의한 Options
타입을 사용하지 않아요. 결국 각 하위 명령어는 독립적이며 공유 인자와 고유 인자를 조합해 사용할 수 있어요.
extension Math.Statistics { struct Average: ParsableCommand { static var configuration = CommandConfiguration( abstract: "Print the average of the values.") enum Kind: String, ExpressibleByArgument { case mean, median, mode } @Option(help: "The kind of average to provide.") var kind: Kind = .mean @Argument(help: "A group of floating-point values to operate on.") var values: [Double] = [] func calculateMean() -> Double { ... } func calculateMedian() -> Double { ... } func calculateMode() -> [Double] { ... } mutating func run() { switch kind { case .mean: print(calculateMean()) case .median: print(calculateMedian()) case .mode: let result = calculateMode() .map(String.init(describing:)) .joined(separator: " ") print(result) } } } struct StandardDeviation: ParsableCommand { static var configuration = CommandConfiguration( commandName: "stdev", abstract: "Print the standard deviation of the values.") @Argument(help: "A group of floating-point values to operate on.") var values: [Double] = [] mutating func run() { if values.isEmpty { print(0.0) } else { let sum = values.reduce(0, +) let mean = sum / Double(values.count) let squaredErrors = values .map { $0 - mean } .map { $0 * $0 } let variance = squaredErrors.reduce(0, +) / Double(values.count) let result = variance.squareRoot() print(result) } } } }
swift