diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json
index 997b2dc..ef15830 100644
--- a/dev/.documenter-siteinfo.json
+++ b/dev/.documenter-siteinfo.json
@@ -1 +1 @@
-{"documenter":{"julia_version":"1.8.5","generation_timestamp":"2024-05-08T08:39:13","documenter_version":"1.4.1"}}
\ No newline at end of file
+{"documenter":{"julia_version":"1.8.5","generation_timestamp":"2024-11-19T07:39:35","documenter_version":"1.8.0"}}
\ No newline at end of file
diff --git a/dev/assets/documenter.js b/dev/assets/documenter.js
index c6562b5..7d68cd8 100644
--- a/dev/assets/documenter.js
+++ b/dev/assets/documenter.js
@@ -77,30 +77,35 @@ require(['jquery'], function($) {
let timer = 0;
var isExpanded = true;
-$(document).on("click", ".docstring header", function () {
- let articleToggleTitle = "Expand docstring";
-
- debounce(() => {
- if ($(this).siblings("section").is(":visible")) {
- $(this)
- .find(".docstring-article-toggle-button")
- .removeClass("fa-chevron-down")
- .addClass("fa-chevron-right");
- } else {
- $(this)
- .find(".docstring-article-toggle-button")
- .removeClass("fa-chevron-right")
- .addClass("fa-chevron-down");
+$(document).on(
+ "click",
+ ".docstring .docstring-article-toggle-button",
+ function () {
+ let articleToggleTitle = "Expand docstring";
+ const parent = $(this).parent();
+
+ debounce(() => {
+ if (parent.siblings("section").is(":visible")) {
+ parent
+ .find("a.docstring-article-toggle-button")
+ .removeClass("fa-chevron-down")
+ .addClass("fa-chevron-right");
+ } else {
+ parent
+ .find("a.docstring-article-toggle-button")
+ .removeClass("fa-chevron-right")
+ .addClass("fa-chevron-down");
- articleToggleTitle = "Collapse docstring";
- }
+ articleToggleTitle = "Collapse docstring";
+ }
- $(this)
- .find(".docstring-article-toggle-button")
- .prop("title", articleToggleTitle);
- $(this).siblings("section").slideToggle();
- });
-});
+ parent
+ .children(".docstring-article-toggle-button")
+ .prop("title", articleToggleTitle);
+ parent.siblings("section").slideToggle();
+ });
+ }
+);
$(document).on("click", ".docs-article-toggle-button", function (event) {
let articleToggleTitle = "Expand docstring";
@@ -110,7 +115,7 @@ $(document).on("click", ".docs-article-toggle-button", function (event) {
debounce(() => {
if (isExpanded) {
$(this).removeClass("fa-chevron-up").addClass("fa-chevron-down");
- $(".docstring-article-toggle-button")
+ $("a.docstring-article-toggle-button")
.removeClass("fa-chevron-down")
.addClass("fa-chevron-right");
@@ -119,7 +124,7 @@ $(document).on("click", ".docs-article-toggle-button", function (event) {
$(".docstring section").slideUp(animationSpeed);
} else {
$(this).removeClass("fa-chevron-down").addClass("fa-chevron-up");
- $(".docstring-article-toggle-button")
+ $("a.docstring-article-toggle-button")
.removeClass("fa-chevron-right")
.addClass("fa-chevron-down");
@@ -484,6 +489,14 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
: string || "";
}
+ /**
+ * RegX escape function from MDN
+ * Refer: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
+ */
+ function escapeRegExp(string) {
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
+ }
+
/**
* Make the result component given a minisearch result data object and the value
* of the search input as queryString. To view the result object structure, refer:
@@ -502,8 +515,8 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
if (result.page !== "") {
display_link += ` (${result.page})`;
}
-
- let textindex = new RegExp(`${querystring}`, "i").exec(result.text);
+ searchstring = escapeRegExp(querystring);
+ let textindex = new RegExp(`${searchstring}`, "i").exec(result.text);
let text =
textindex !== null
? result.text.slice(
@@ -520,7 +533,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
let display_result = text.length
? "..." +
text.replace(
- new RegExp(`${escape(querystring)}`, "i"), // For first occurrence
+ new RegExp(`${escape(searchstring)}`, "i"), // For first occurrence
'$&'
) +
"..."
@@ -566,6 +579,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
// Only return relevant results
return result.score >= 1;
},
+ combineWith: "AND",
});
// Pre-filter to deduplicate and limit to 200 per category to the extent
@@ -598,176 +612,194 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
};
}
-// `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript!
-const filters = [
- ...new Set(documenterSearchIndex["docs"].map((x) => x.category)),
-];
-const worker_str =
- "(" +
- worker_function.toString() +
- ")(" +
- JSON.stringify(documenterSearchIndex["docs"]) +
- "," +
- JSON.stringify(documenterBaseURL) +
- "," +
- JSON.stringify(filters) +
- ")";
-const worker_blob = new Blob([worker_str], { type: "text/javascript" });
-const worker = new Worker(URL.createObjectURL(worker_blob));
-
/////// SEARCH MAIN ///////
-// Whether the worker is currently handling a search. This is a boolean
-// as the worker only ever handles 1 or 0 searches at a time.
-var worker_is_running = false;
-
-// The last search text that was sent to the worker. This is used to determine
-// if the worker should be launched again when it reports back results.
-var last_search_text = "";
-
-// The results of the last search. This, in combination with the state of the filters
-// in the DOM, is used compute the results to display on calls to update_search.
-var unfiltered_results = [];
-
-// Which filter is currently selected
-var selected_filter = "";
-
-$(document).on("input", ".documenter-search-input", function (event) {
- if (!worker_is_running) {
- launch_search();
- }
-});
-
-function launch_search() {
- worker_is_running = true;
- last_search_text = $(".documenter-search-input").val();
- worker.postMessage(last_search_text);
-}
-
-worker.onmessage = function (e) {
- if (last_search_text !== $(".documenter-search-input").val()) {
- launch_search();
- } else {
- worker_is_running = false;
- }
-
- unfiltered_results = e.data;
- update_search();
-};
+function runSearchMainCode() {
+ // `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript!
+ const filters = [
+ ...new Set(documenterSearchIndex["docs"].map((x) => x.category)),
+ ];
+ const worker_str =
+ "(" +
+ worker_function.toString() +
+ ")(" +
+ JSON.stringify(documenterSearchIndex["docs"]) +
+ "," +
+ JSON.stringify(documenterBaseURL) +
+ "," +
+ JSON.stringify(filters) +
+ ")";
+ const worker_blob = new Blob([worker_str], { type: "text/javascript" });
+ const worker = new Worker(URL.createObjectURL(worker_blob));
+
+ // Whether the worker is currently handling a search. This is a boolean
+ // as the worker only ever handles 1 or 0 searches at a time.
+ var worker_is_running = false;
+
+ // The last search text that was sent to the worker. This is used to determine
+ // if the worker should be launched again when it reports back results.
+ var last_search_text = "";
+
+ // The results of the last search. This, in combination with the state of the filters
+ // in the DOM, is used compute the results to display on calls to update_search.
+ var unfiltered_results = [];
+
+ // Which filter is currently selected
+ var selected_filter = "";
+
+ $(document).on("input", ".documenter-search-input", function (event) {
+ if (!worker_is_running) {
+ launch_search();
+ }
+ });
-$(document).on("click", ".search-filter", function () {
- if ($(this).hasClass("search-filter-selected")) {
- selected_filter = "";
- } else {
- selected_filter = $(this).text().toLowerCase();
+ function launch_search() {
+ worker_is_running = true;
+ last_search_text = $(".documenter-search-input").val();
+ worker.postMessage(last_search_text);
}
- // This updates search results and toggles classes for UI:
- update_search();
-});
+ worker.onmessage = function (e) {
+ if (last_search_text !== $(".documenter-search-input").val()) {
+ launch_search();
+ } else {
+ worker_is_running = false;
+ }
-/**
- * Make/Update the search component
- */
-function update_search() {
- let querystring = $(".documenter-search-input").val();
+ unfiltered_results = e.data;
+ update_search();
+ };
- if (querystring.trim()) {
- if (selected_filter == "") {
- results = unfiltered_results;
+ $(document).on("click", ".search-filter", function () {
+ if ($(this).hasClass("search-filter-selected")) {
+ selected_filter = "";
} else {
- results = unfiltered_results.filter((result) => {
- return selected_filter == result.category.toLowerCase();
- });
+ selected_filter = $(this).text().toLowerCase();
}
- let search_result_container = ``;
- let modal_filters = make_modal_body_filters();
- let search_divider = `
`;
+ // This updates search results and toggles classes for UI:
+ update_search();
+ });
- if (results.length) {
- let links = [];
- let count = 0;
- let search_results = "";
-
- for (var i = 0, n = results.length; i < n && count < 200; ++i) {
- let result = results[i];
- if (result.location && !links.includes(result.location)) {
- search_results += result.div;
- count++;
- links.push(result.location);
- }
- }
+ /**
+ * Make/Update the search component
+ */
+ function update_search() {
+ let querystring = $(".documenter-search-input").val();
- if (count == 1) {
- count_str = "1 result";
- } else if (count == 200) {
- count_str = "200+ results";
+ if (querystring.trim()) {
+ if (selected_filter == "") {
+ results = unfiltered_results;
} else {
- count_str = count + " results";
+ results = unfiltered_results.filter((result) => {
+ return selected_filter == result.category.toLowerCase();
+ });
}
- let result_count = `
${count_str}
`;
- search_result_container = `
+ let search_result_container = ``;
+ let modal_filters = make_modal_body_filters();
+ let search_divider = ``;
+
+ if (results.length) {
+ let links = [];
+ let count = 0;
+ let search_results = "";
+
+ for (var i = 0, n = results.length; i < n && count < 200; ++i) {
+ let result = results[i];
+ if (result.location && !links.includes(result.location)) {
+ search_results += result.div;
+ count++;
+ links.push(result.location);
+ }
+ }
+
+ if (count == 1) {
+ count_str = "1 result";
+ } else if (count == 200) {
+ count_str = "200+ results";
+ } else {
+ count_str = count + " results";
+ }
+ let result_count = `
SplitApplyCombine.jl has "tools [that] come in the form of high-level functions that operate on iterable or indexable containers in an intuitive and simple way"
Settings
This document was generated with Documenter.jl version 1.4.1 on Wednesday 8 May 2024. Using Julia version 1.8.5.
SplitApplyCombine.jl has "tools [that] come in the form of high-level functions that operate on iterable or indexable containers in an intuitive and simple way"
Settings
This document was generated with Documenter.jl version 1.8.0 on Tuesday 19 November 2024. Using Julia version 1.8.5.
Be aware that if iterating the original has a side-effect it will not be repeated when iterating again, – indeed that is a key feature of the CachedIterator. Be aware also that if the original iterator is nondeterminatistic in its order, when iterating again from the cache it will infact be determinatistic and will be the same order as before – this also is a feature.
Iterate through values skipping over those already encountered.
julia> for i in distinct([1,1,2,1,2,4,1,2,3,4])
+
Be aware that if iterating the original has a side-effect it will not be repeated when iterating again, – indeed that is a key feature of the CachedIterator. Be aware also that if the original iterator is nondeterminatistic in its order, when iterating again from the cache it will infact be determinatistic and will be the same order as before – this also is a feature.
Group consecutive values that share the same result of applying f.
julia> for i in groupby(x -> x[1], ["face", "foo", "bar", "book", "baz", "zzz"])
@show i
end
i = ["face", "foo"]
i = ["bar", "book", "baz"]
-i = ["zzz"]
Iterate over values of a function applied to successive values from one or more iterators. Like Iterators.zip, the iterator is done when any of the input iterators have been exhausted.
julia> for i in imap(+, [1,2,3], [4,5,6])
+i = ["zzz"]
Iterate over values of a function applied to successive values from one or more iterators. Like Iterators.zip, the iterator is done when any of the input iterators have been exhausted.
julia> for i in imap(+, [1,2,3], [4,5,6])
@show i
end
i = 5
i = 7
-i = 9
If the predicate is Base.isless (the default) and both inputs are sorted, this produces the sorted output. If the predicate is a stateful functor that alternates true-false-true-false... then this produces the classic interleave operation as described e.g. in the definition of microkanren.
Iterate over successive applications of f, as in x, f(x), f(f(x)), f(f(f(x))), ...
Use Base.Iterators.take() to obtain the required number of elements.
julia> for i in Iterators.take(iterated(x -> 2x, 1), 5)
+ 6
If the predicate is Base.isless (the default) and both inputs are sorted, this produces the sorted output. If the predicate is a stateful functor that alternates true-false-true-false... then this produces the classic interleave operation as described e.g. in the definition of microkanren.
Iterate over successive applications of f, as in x, f(x), f(f(x)), f(f(f(x))), ...
Use Base.Iterators.take() to obtain the required number of elements.
julia> for i in Iterators.take(iterated(x -> 2x, 1), 5)
@show i
end
i = 1
@@ -62,7 +62,7 @@
i = 3.1622776601683795
i = 1.7782794100389228
i = 1.333521432163324
-i = 1.1547819846894583
Iterate over every subset of the indexable collection xs. You can restrict the subsets to a specific size k.
Giving the subset size in the form Val{k}() allows the compiler to produce code optimized for the particular size requested. This leads to performance comparable to hand-written loops if k is small and known at compile time, but may or may not improve performance otherwise.
julia> for i in subsets([1, 2, 3])
@show i
@@ -173,19 +173,19 @@
i = (1, 4)
i = (2, 3)
i = (2, 4)
-i = (3, 4)
For one or more iterable objects, return an iterable of tuples, where the ith tuple contains the ith component of each input iterable if it is not finished, and default otherwise. default can be a scalar, or a tuple with one default per iterable.
For one or more iterable objects, return an iterable of tuples, where the ith tuple contains the ith component of each input iterable if it is not finished, and default otherwise. default can be a scalar, or a tuple with one default per iterable.
julia> for t in zip_longest(1:2, 5:8)
@show t
end
t = (1, 5)
@@ -200,7 +200,7 @@
t = ('b', 'n')
t = ('c', 'x')
t = ('d', 'x')
-t = ('e', 'x')
If expr evaluates to nothing, equivalent to return nothing, otherwise the macro evaluates to the value of expr. Not exported, useful for implementing iterators.
If expr evaluates to nothing, equivalent to return nothing, otherwise the macro evaluates to the value of expr. Not exported, useful for implementing iterators.
julia> IterTools.@ifsomething iterate(1:2)
(1, 1)
-julia> let elt, state = IterTools.@ifsomething iterate(1:2, 2); println("not reached"); end