public protocol PredicateExpression<Output> {
    associatedtype Output   
    func evaluate(_ bindings: PredicateBindings) throws -> Output
}

<aside> πŸ’‘ predicate을 κ΅¬μ„±ν•˜λŠ” ν‘œν˜„μ‹μ΄ μ€€μˆ˜ν•΄μ•Ό ν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ˜ λͺ…μ„Έ.

</aside>

ν•΄λ‹Ή ν”„λ‘œν† μ½œμ€ κΈ°λ³Έ predicate νƒ€μž…μ΄ λ§€ν¬λ‘œμ—μ„œ expression treeλ₯Ό ν˜•μ„±ν•˜κΈ° μœ„ν•΄ κ΅¬ν˜„ν•΄μ•Ό ν•˜λŠ” ν•„μˆ˜ λ©”μ†Œλ“œλ₯Ό λͺ…μ„Έν•œλ‹€. ν•΄λ‹Ή λ©”μ†Œλ“œλ₯Ό μ μ§„μ μœΌλ‘œ ν˜ΈμΆœν•΄μ„œ ν•˜μœ„ ν‘œν˜„μ‹μ„ μˆœνšŒν•˜λ©° predicate 자료ꡬ쑰둜 λ³€ν™˜ν•˜λŠ” 과정을 tree walking이라고 μΉ­ν•˜λŠ”λ°, μœ„ ν”„λ‘œν† μ½œκ³Ό μœ μ‚¬ν•˜κ²Œ tree walking을 μˆ˜ν–‰ν•˜λŠ” ν”„λ‘œν† μ½œμ„ μž‘μ„±ν•˜κ³ , 각 ν‘œν˜„μ‹μ— μ΅μŠ€ν…μ…˜μ„ μΆ”κ°€ν•΄ ν•΄λ‹Ή ν”„λ‘œν† μ½œμ„ μ±„νƒν•˜λ©΄ predicate λ§€ν¬λ‘œλ‘œλΆ€ν„° Predicate νƒ€μž… 이외에 μ›ν•˜λŠ” 포맷의 결과값을 μ–»μ–΄λ‚Ό 수 μžˆλ‹€. SQL 쿼리 string, 기타 DB 쿼리 객체 ν˜•νƒœλ₯Ό μ–»μ–΄λ‚΄κ³ μž ν•˜λŠ” 경우 μœ μš©ν•  수 μžˆλ‹€.

<aside> πŸ’‘ tree walkingν•  ν‘œν˜„μ‹μ—μ„œ λ³€μˆ˜κ°’(μž…λ ₯κ°’ 포함)을 전달받고 μ‚¬μš©ν•΄μ•Ό ν•  경우, μœ„ evaluate(_:) λ©”μ†Œλ“œμ²˜λŸΌ [PredicateBindings](<https://doldamul.notion.site/PredicateBindings-b00582ac55b54546ae3fc882ae0def33>) νƒ€μž…μ„ μ „νŒŒν•œλ‹€. μžμ„Έν•œ μ„€λͺ…은 ν•΄λ‹Ή νŽ˜μ΄μ§€μ—μ„œ.

</aside>

예λ₯Ό λ“€μ–΄, λ‹€μŒκ³Ό 같은 ν”„λ‘œν† μ½œμ΄ μžˆλ‹€κ³  ν•˜μž:

protocol ProsePredicateExpression {
    func proseQuery() -> String
}

ν•΄λ‹Ή ν”„λ‘œν† μ½œμ„ μ±„νƒν•˜λŠ” ν‘œν˜„μ‹μ˜ extension μ½”λ“œλ₯Ό λ‹€μŒκ³Ό 같이 μž‘μ„±ν•  수 μžˆλ‹€:

extension PredicateExpressions.Equal: ProsePredicateExpression 
        where LHS: ProsePredicateExpression, RHS: ProsePredicateExpression {
    func proseQuery() -> String {
        return lhs.proseQuery() + " is equal to " + rhs.proseQuery()
    }
}

Predicate νƒ€μž…μ— ν•΄λ‹Ή tree walking λ©”μ†Œλ“œμ˜ μ΅œμƒμœ„ 레벨 λ©”μ†Œλ“œλ₯Ό μΆ”κ°€ν•œλ‹€:

extension Predicate  {
    func proseQuery() -> String? {
        guard let expression = expression as? ProsePredicateExpression else { return nil }
        return expression.proseQuery()
    }
}

더 λ‚˜μ•„κ°„λ‹€λ©΄, ν•΄λ‹Ή μœ μ‚¬ ν”„λ‘œν† μ½œμ„ μ±„νƒν•˜λŠ” μ»€μŠ€ν…€ Predicate νƒ€μž…μ„ μ •μ˜ν•  μˆ˜λ„ μžˆμ„ 것이닀. μ΄λ ‡κ²Œ ν•  경우 μ§€μ›ν•˜μ§€ μ•ŠλŠ” ν‘œν˜„μ‹μ€ μ‚¬μš©λ  수 없도둝 μ°¨λ‹¨ν•œλ‹€λŠ” μž₯점이 μžˆμœΌλ‚˜, μ»€μŠ€ν…€ Predicate νƒ€μž…μ„ μ •μ˜ν•˜λŠ” 방법 및 κ΄€λ ¨ APIκΉŒμ§€λŠ” 아직 proposal이 μ˜¬λΌμ˜€μ§€ μ•Šμ•˜λ‹€.

struct ProsePredicate<Input...> {
	let expression: any ProsePredicateExpression<Bool>
	    
	// ...
	    
	func convertToProseQuery() -> String {
		return expression.proseQuery()
	}
}

참고자료