Cac/additional extensions#85
Conversation
| guard let lastElement = last else { return "" } | ||
|
|
||
| return reduce("") { partialResult, element in | ||
| if partialResult.isEmpty { |
There was a problem hiding this comment.
split into if's instead to reduce nesting like so
if partialResult.isEmpty {
return element
}
if element == lastElement {
return partialResult + end + element
}
return partialResult + by + elementbut it might equally be written as
if partialResult.isEmpty {
return element
}
let isLastElement = element == lastElement
let concatElement = isLastElement.map(ifTrue: end, ifFalse: by)
return partialResult + concatElement + element| var head: Element? { first } | ||
|
|
||
| /// Removes the first element and retuns a new `Array` containing the rest of the elements. | ||
| var tail: [Element] { Array(dropFirst()) } |
There was a problem hiding this comment.
this should be a function. computed properties are meant for constant operations (O(1))
this is in the best case O(n).
the rational behind this is many, one is: its super easy to use in loops, which would produce quadratic (or worse) runtime performance + the amount of memory consumption is also a concern. besides this does not "access" an element on the array, it actually creates a whole new array. that is very "unexpected" based on a property (usually a "property" is a "property" of a given thing, not a computation per se).
| } | ||
|
|
||
| /// Return the indexed element if within boundaries, else `nil` | ||
| func get(index: Int) -> Element? { |
There was a problem hiding this comment.
given the weird synergy this should potentially be called "getOrNil" to highlight the intention. that way the function is close to self documenting.
| var nilIfEmpty: [Element]? { isEmpty ? nil : self } | ||
|
|
||
| /// Splits the `Array` into two dependent on the "shouldAppendToFirst-Argument", where the first `Array` contains the elements that match the bool and the second `Array` contains the rest. | ||
| func split(by shouldAppendToFirst: (Element) -> Bool) -> ([Element], [Element]) { |
There was a problem hiding this comment.
only thought here is whenever one should make a struct for the result to name the first and second as to match the lambda argument.
| return Calendar.current.date(byAdding: component, value: value, to: self) ?? self | ||
| } | ||
|
|
||
| func date(bySubtracting component: Calendar.Component, value: Int) -> Date { |
There was a problem hiding this comment.
please take the current calendar as a optional parameter with default value to Calendar.current (in case someone is using this with a non default calendar).
func date(
bySubtracting component: Calendar.Component,
value: Int,
withCalendar: Calendar = Calendar.current
) -> Date {
withCalendar.date(
byAdding: component,
value: -value,
to: self
) ?? self
}| Calendar.current.date(byAdding: component, value: -value, to: self) ?? self | ||
| } | ||
|
|
||
| func alignTo(resolution: Calendar.Component) -> Date { |
There was a problem hiding this comment.
same here (wrt to the current calendar as a default paramter)
func alignTo(
resolution: Calendar.Component,
withCalendar: Calendar = Calendar.current
) -> Date {
var dateComponents = withCalendar.dateComponents(
Set([.year, .month, .day, .hour, .minute, .second, .nanosecond, .timeZone]),
from: self)
switch resolution {
case .year:
dateComponents.setValue(0, for: .month)
dateComponents.setValue(0, for: .day)
dateComponents.setValue(0, for: .hour)
dateComponents.setValue(0, for: .minute)
dateComponents.setValue(0, for: .second)
dateComponents.setValue(0, for: .nanosecond)
case .month:
dateComponents.setValue(0, for: .day)
dateComponents.setValue(0, for: .hour)
dateComponents.setValue(0, for: .minute)
dateComponents.setValue(0, for: .second)
dateComponents.setValue(0, for: .nanosecond)
case .day:
dateComponents.setValue(0, for: .hour)
dateComponents.setValue(0, for: .minute)
dateComponents.setValue(0, for: .second)
dateComponents.setValue(0, for: .nanosecond)
case .hour:
dateComponents.setValue(0, for: .minute)
dateComponents.setValue(0, for: .second)
dateComponents.setValue(0, for: .nanosecond)
case .minute:
dateComponents.setValue(0, for: .second)
dateComponents.setValue(0, for: .nanosecond)
case .second:
dateComponents.setValue(0, for: .nanosecond)
default:
break
}
return NSCalendar.current.date(from: dateComponents) ?? self
}another note is that if this switch was split into seperate functions, the code would naturally happen without duplication (eg, alignToYear would set the month to 0, then call allignToMonth)
No description provided.