You can't really extend Any, but I often define this function:
infix operator |> { precedence 50 associativity left }
public func |> <T,U>(lhs: T, rhs: T -> U) -> U {
return rhs(lhs)
}
This allows me to terminate a chain like so:
let result = array
.filter { $0.isValid }
.map(transform)
.joined()
|> someFunction
It would perhaps be better with
// ...
.joined()
.apply(someFunction)
But at least you don't have to wrap the entire chain in a function call, and have your eyes alternate between parsing left-right and right-left when reading the code.
You're attempting to calling trimmingCharacters(in:) on the closure. That doesn’t work. You’ll need to either convert the trimming method into a free function or to add parentheses around the first apply expression.
let result = "MiXedCase "
|> { doTheLowercase ? $0.lowercased() : $0 }
|> { $0.trimmingCharacters(in: .whitespaces) }
Also, this works:
let result = ("MiXedCase "
|> { doTheLowercase ? $0.lowercased() : $0 })
.trimmingCharacters(in: .whitespaces)
I'm not sure why you would expect the dot-notation to somehow automatically apply to something other than the preceding expression. Sure, the fact that you cannot extend Any is indeed a limitation of Swift, but that you cannot arbitrarily add dots where ever you feel like without adding parentheses is obviously not. You cannot do that in any language, and I can't understand why you would want to?
Also, if you really want the .apply(_:) function to exist on all kinds of types, you can define it on a custom no-requirements protocol and add conformances to types as you need them. By making NSObject conform, you can at least have it all Apple SDK types:
protocol Applicable {}
extension Applicable {
func apply<T>(_ function: (Self) -> T) -> T {
return function(self)
}
}
extension NSObject: Applicable {}
extension String: Applicable {}
// ... add more of these as needed
let doTheLowercase = true
let result = "MiXedCase "
.apply { doTheLowercase ? $0.lowercased() : $0 }
.trimmingCharacters(in: .whitespaces)
I'm not sure why you would expect the dot-notation to somehow automatically apply to something other than the preceding expression
This is just a question of precedence. When you define new operators, you can set the precedence and the associativity - e.g. I can define how * , + and |> work together
so - there is no problem chaining the + operator
//Works
let result1 = "hi" |> { $0 + "There"} + " Bob"
//Doesn't work
let result1 = "Hi " |> { $0 + "There"} . lowercased()
the dot operator (in effect) has it's own precedence group, which is greater than allowed for custom operators
(note - under the hood, the dot operator may be implemented in a completely different way. In effect though, it works as a max-precedence left-associated operator)
it isn't obvious to me why it you couldn't have
infix operator |> : DotOperatorPrecedence
which would allow chaining (the dot operator acts as if it has left precedence)
Also, if you really want the .apply(_:) function to exist on all kinds of types, you can define it on a custom no-requirements protocol and add conformances to types as you need them
yup - that's probably the best available option
I'm mostly just making a practicality / aesthetic point now
extension NSObject: Applicable {}
extension String: Applicable {}
... very long list of classes and structs
... remember to add this to any new classes you define