-
Notifications
You must be signed in to change notification settings - Fork 100
Buffer Class Extension #416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Apologies that this is such a large PR. I'll definitely keep in mind for the future to break PRs into smaller, more frequent chunks. |
}; | ||
|
||
return true; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, here:
public func isStrictSuffixOf<X>(suffix : Buffer<X>, buffer : Buffer<X>, equal : (X, X) -> Bool) : Bool {
if (buffer.size() <= suffix.size()) {
return false;
};
isSuffixOf(suffix, buffer, equal);
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work, lots of functionality. Just had a few small suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the changes.
src/Array.mo
Outdated
@@ -42,7 +41,7 @@ module { | |||
}; | |||
}; | |||
|
|||
/// Sorts the given array according to the `cmp` function. | |||
/// Sorts the given array according to the `compare` function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Sorts the given array according to the `compare` function. | |
/// Sorts the given array, in ascending order, according to the `compare` function. |
src/Array.mo
Outdated
freeze(tmp) | ||
}; | ||
|
||
/// Sorts the given array in place according to the `cmp` function. | ||
/// Sorts the given array in place according to the `compare` function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Sorts the given array in place according to the `compare` function. | |
/// Sorts the given array in place, in ascending order, according to the `compare` function. |
src/Buffer.mo
Outdated
/// `capacity` is the length of the underyling array that backs this list. | ||
/// `capacity` >= `size` is an invariant for this class. | ||
/// | ||
/// Like arrays, elements in the buffer are ordered by indices from 0 to size-1. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Like arrays, elements in the buffer are ordered by indices from 0 to size-1. | |
/// Like arrays, elements in the buffer are ordered by indices from 0 to `size`-1. |
_size += size2; | ||
}; | ||
|
||
/// Sorts the elements in the buffer according to `compare`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Sorts the elements in the buffer according to `compare`. | |
/// Sorts the elements in the buffer, in ascending order, according to `compare`. |
src/Buffer.mo
Outdated
/// If any invocation of `f` produces an #err, returns an #err. Otherwise | ||
/// Returns an #ok containing the new buffer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// If any invocation of `f` produces an #err, returns an #err. Otherwise | |
/// Returns an #ok containing the new buffer. | |
/// If any invocation of `f` produces an `#err`, returns an `#err`. Otherwise | |
/// Returns an `#ok` containing the new buffer. |
src/Buffer.mo
Outdated
i := 0; | ||
j := 0; | ||
while (i < subSize and j < size) { | ||
if (equal(subBuffer.get(i), buffer.get(j)) and i == (subSize - 1 : Nat)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be worth hoisting (subSize - 1 : Nat) out of the loop, computing it just once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay will do!
It would be cool to have a loop invariant pass for hosting these, since subSize is bound to a let
.
src/Buffer.mo
Outdated
let size = buffer.size(); | ||
if (size == 0) { [var] } else { | ||
let newArray = Prim.Array_init<X>(size, buffer.get(0)); | ||
var i = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var i = 0; | |
var i = 1; |
Can't you start from 1 since you've already copied position 0?
src/Buffer.mo
Outdated
Prim.trap "Chunk size must be non-zero in chunk"; | ||
}; | ||
|
||
let newBuffer = Buffer<Buffer<X>>(Prim.abs(Prim.floatToInt(Prim.floatCeil(Prim.intToFloat(buffer.size()) / Prim.intToFloat(size))))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you really need to use floats here. Isn't integer division and remainder enough?
src/Buffer.mo
Outdated
// The length of `elements` is increased by `INCREASE_FACTOR` when capacity is reached. | ||
// The length of `elements` is decreased by `DECREASE_FACTOR` when capacity is strictly less than | ||
// `DECREASE_THRESHOLD`. | ||
private let INCREASE_FACTOR = 1.5; // Keep this factor low to minimize cycle limit problem |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The floats make me slightly nervous - could you use a ratio instead? I.e. Integer multiply by 3 and divide by 2 or some other numerator denominator pair?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, will change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some more suggestions. Lovely work! Next time, submit in smaller morsels - it's hard for a reviewer to take in so much code in one bite.
src/Buffer.mo
Outdated
Prim.abs(Prim.floatToInt(Prim.floatCeil(Prim.intToFloat(oldCapacity) * INCREASE_FACTOR))); | ||
// calculates ceil(oldCapacity * INCREASE_FACTOR) without floats | ||
let product = oldCapacity * INCREASE_FACTOR_NUME; | ||
(product / INCREASE_FACTOR_DENOM) + (if (product % INCREASE_FACTOR_DENOM != 0) { 1 } else { 0 }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(product / INCREASE_FACTOR_DENOM) + (if (product % INCREASE_FACTOR_DENOM != 0) { 1 } else { 0 }) | |
(product + INCREASE_FACTOR_DENOM - 1 ) / INCREASE_FACTOR_DENOM |
Might do the trick as well. @ggreif amirite? I very well may not be
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@crusso yep this should work. Example: ((57 * 7) + 3 - 1) / 3
gives 133.7
, 57 * 7/3 = 133
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay will swap out
src/Buffer.mo
Outdated
buffer.size() / size + | ||
(if (buffer.size() % size != 0) { 1 } else { 0 }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
buffer.size() / size + | |
(if (buffer.size() % size != 0) { 1 } else { 0 }) | |
(buffer.size() + size - 1) / size |
analogously. But check my arithmetic. (cc @ggreif)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(but see small refactorings, if correct)
I'd like to re-open this as the commits have been removed from |
Base Library Extension Doc: https://docs.google.com/document/d/1uKouujLL3KueLpqjjFV2gd4dqu_6GYD107WBb6_GSVE/edit
Complete unit tests
Consider making initCapacity an optional value with a default initial capacity
While loop iterations over Arrays may be faster with an iterator due to a compiler optimization
In functions where a new buffer is being constructed, have some consistent scheme for how to determine the new buffer's capacity. Should the new buffer have just enough space to hold its element, or be given some insertion leeway?
Some class methods can be moved outside of the class since they don't need access to the underlying array
Consider behavior of transpose on empty Buffers
sort() can be optimized by hoisting helper functions
Restore broken methods in Array.mo and Hash.mo
Compare with original Buffer class and try to keep some level of backwards compatibility / deprecate old functions
Fix naming to be consistent with user friendliness, other classes, and style / interface guide
Add user friendly error messages / error checking
Cleanup tests
Add documentation for each function
Add examples for each function (put up as a separate PR)
A primitive array tabulate for var arrays would allow some nice optimizations (put up as a separate PR)
Profile this class to see if a more scalable dynamic sequence is necessary and to resolve ambiguous design decisions
This last point is related to the RRB Trees, Rope, and Finger Trees data structures that I was discussing before. For various reasons, I am leaning towards an RRB Tree implementation of a scalable sequence structure, if it is necessary. See a talk on this data structure here: https://www.youtube.com/watch?v=sPhpelUfu8Q