1/4: add real HSL to HHVM repo :)
[hiphop-php.git] / hphp / hsl / src / keyset / select.php
blob8241e610fed2ea2b1dbe5fc07dee36a7b6858651
1 <?hh
2 /*
3 * Copyright (c) 2004-present, Facebook, Inc.
4 * All rights reserved.
6 * This source code is licensed under the MIT license found in the
7 * LICENSE file in the root directory of this source tree.
9 */
11 namespace HH\Lib\Keyset;
13 use namespace HH\Lib\C;
15 /**
16 * Returns a new keyset containing only the elements of the first Traversable
17 * that do not appear in any of the other ones.
19 * Time complexity: O(n + m), where n is size of `$first` and m is the combined
20 * size of `$second` plus all the `...$rest`
21 * Space complexity: O(n + m), where n is size of `$first` and m is the combined
22 * size of `$second` plus all the `...$rest` -- note that this is bigger than
23 * O(n)
25 function diff<Tv1 as arraykey, Tv2 as arraykey>(
26 Traversable<Tv1> $first,
27 Traversable<Tv2> $second,
28 Container<Tv2> ...$rest
29 )[]: keyset<Tv1> {
30 if (!$first) {
31 return keyset[];
33 if (!$second && !$rest) {
34 return keyset($first);
36 $union = !$rest ? keyset($second) : union($second, ...$rest);
37 return filter($first, $value ==> !C\contains_key($union, $value));
39 /**
40 * Returns a new keyset containing all except the first `$n` elements of
41 * the given Traversable.
43 * To take only the first `$n` elements, see `Keyset\take()`.
45 * Time complexity: O(n), where n is the size of `$traversable`
46 * Space complexity: O(n), where n is the size of `$traversable`
48 function drop<Tv as arraykey>(
49 Traversable<Tv> $traversable,
50 int $n,
51 )[]: keyset<Tv> {
52 invariant($n >= 0, 'Expected non-negative N, got %d.', $n);
53 $result = keyset[];
54 $ii = -1;
55 foreach ($traversable as $value) {
56 $ii++;
57 if ($ii < $n) {
58 continue;
60 $result[] = $value;
62 return $result;
65 /**
66 * Returns a new keyset containing only the values for which the given predicate
67 * returns `true`. The default predicate is casting the value to boolean.
69 * To remove null values in a typechecker-visible way, see `Keyset\filter_nulls()`.
71 * Time complexity: O(n * p), where p is the complexity of `$value_predicate`
72 * Space complexity: O(n)
74 function filter<Tv as arraykey>(
75 Traversable<Tv> $traversable,
76 ?(function(Tv)[_]: bool) $value_predicate = null,
77 )[ctx $value_predicate]: keyset<Tv> {
78 $value_predicate ??= \HH\Lib\_Private\boolval<>;
79 $result = keyset[];
80 foreach ($traversable as $value) {
81 if ($value_predicate($value)) {
82 $result[] = $value;
85 return $result;
88 /**
89 * Returns a new keyset containing only non-null values of the given
90 * Traversable.
92 * Time complexity: O(n)
93 * Space complexity: O(n)
95 function filter_nulls<Tv as arraykey>(
96 Traversable<?Tv> $traversable,
97 )[]: keyset<Tv> {
98 $result = keyset[];
99 foreach ($traversable as $value) {
100 if ($value !== null) {
101 $result[] = $value;
104 return $result;
108 * Returns a new keyset containing only the values for which the given predicate
109 * returns `true`.
111 * If you don't need access to the key, see `Keyset\filter()`.
113 * Time complexity: O(n * p), where p is the complexity of `$predicate`
114 * Space complexity: O(n)
116 function filter_with_key<Tk, Tv as arraykey>(
117 KeyedTraversable<Tk, Tv> $traversable,
118 (function(Tk, Tv)[_]: bool) $predicate,
119 )[ctx $predicate]: keyset<Tv> {
120 $result = keyset[];
121 foreach ($traversable as $key => $value) {
122 if ($predicate($key, $value)) {
123 $result[] = $value;
126 return $result;
130 * Returns a new keyset containing the keys of the given KeyedTraversable,
131 * maintaining the iteration order.
133 function keys<Tk as arraykey, Tv>(
134 KeyedTraversable<Tk, Tv> $traversable,
135 )[]: keyset<Tk> {
136 $result = keyset[];
137 foreach ($traversable as $key => $_) {
138 $result[] = $key;
140 return $result;
144 * Returns a new keyset containing only the elements of the first Traversable
145 * that appear in all the other ones.
147 * Time complexity: O(n + m), where n is size of `$first` and m is the combined
148 * size of `$second` plus all the `...$rest`
149 * Space complexity: O(n), where n is size of `$first`
151 function intersect<Tv as arraykey>(
152 Traversable<Tv> $first,
153 Traversable<Tv> $second,
154 Container<Tv> ...$rest
155 )[]: keyset<Tv> {
156 if (!$first || !$second) {
157 return keyset[];
159 $intersection = keyset($first);
160 $rest[] = $second;
161 foreach ($rest as $traversable) {
162 $next_intersection = keyset[];
163 $keyed_traversable = keyset($traversable);
164 foreach ($intersection as $value) {
165 if (C\contains_key($keyed_traversable, $value)) {
166 $next_intersection[] = $value;
169 if (!$next_intersection) {
170 return keyset[];
172 $intersection = $next_intersection;
174 return $intersection;
178 * Returns a new keyset containing the first `$n` elements of the given
179 * Traversable.
181 * If there are duplicate values in the Traversable, the keyset may be shorter
182 * than the specified length.
184 * To drop the first `$n` elements, see `Keyset\drop()`.
186 * Time complexity: O(n), where n is `$n`
187 * Space complexity: O(n), where n is `$n`
189 function take<Tv as arraykey>(
190 Traversable<Tv> $traversable,
191 int $n,
192 )[]: keyset<Tv> {
193 if ($n === 0) {
194 return keyset[];
196 invariant($n > 0, 'Expected non-negative N, got %d.', $n);
197 $result = keyset[];
198 $ii = 0;
199 foreach ($traversable as $value) {
200 $result[] = $value;
201 $ii++;
202 if ($ii === $n) {
203 break;
206 return $result;