🔥 중첩된 하위 명령어 정의하기
294자
3분
다음은 Math 세 번째 하위 명령어인 Statistics를 정의해 볼게요. Statistics 명령어는 설정에서 사용자 정의 명령어 이름(stats)을 지정해 타입 이름에서 파생된 기본값(statistics)을 재정의해요. 그리고 추가로 하위 명령어 두 개를 선언하고 있는데, 이는 마치 나무에서 가지가 갈라지듯이, 명령어의 구조가 세분화된다는 것을 의미합니다.
swift
extension Math {
struct Statistics: ParsableCommand {
static var configuration = CommandConfiguration(
commandName: "stats",
abstract: "Calculate descriptive statistics.",
subcommands: [Average.self, StandardDeviation.self])
}
}
swift
extension Math {
struct Statistics: ParsableCommand {
static var configuration = CommandConfiguration(
commandName: "stats",
abstract: "Calculate descriptive statistics.",
subcommands: [Average.self, StandardDeviation.self])
}
}
마지막으로 Average와 StandardDeviation 타입으로 하위 명령어를 완성해 볼게요. 각 하위 명령어는 약간 다른 인자를 가지고 있어서 위에서 정의한 Options 타입을 사용하지 않아요. 결국 각 하위 명령어는 독립적이며 공유 인자와 고유 인자를 조합해 사용할 수 있어요.
swift
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
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)
}
}
}
}












