2 <<file
:__EnableUnstableFeatures('readonly')>>
6 /** An iterator implementation for iterating over a Vector/ImmVector.
9 final class VectorIterator
<T
> implements HH\KeyedIterator
<int, T
> {
12 public function __construct()[]: void
{ }
14 /** Returns the current value that the iterator points to.
18 public function current()[]: T
;
20 /** Returns the current key that the iterator points to.
24 public function key()[]: int;
26 /** Returns true if the iterator points to a valid value, returns false
31 public function valid()[]: bool;
33 /** Advance this iterator forward one position.
36 public function next()[write_props
]: void
;
38 /** Move this iterator back to the first position.
41 public function rewind()[write_props
]: void
;
47 /** An ordered collection where values are keyed using integers 0 thru n-1 in
50 final class Vector
<T
> implements \MutableVector
<T
> {
52 /** Returns a Vector built from the values produced by the specified Iterable.
53 * @param mixed $iterable
56 public function __construct(mixed $iterable = null)[]: void
;
58 /** Returns true if the Vector is empty, false otherwise.
61 public readonly
function isEmpty()[]: bool {
62 return !$this->count();
65 /** Returns the number of values in the Vector.
68 public readonly
function count()[]: int {
69 return \
count(vec($this));
72 /** Returns an Iterable that produces the values from this Vector.
76 public function items()[]: \LazyIterableView
{
78 return new \
LazyIterableView($this);
81 /** Returns a Vector built from the keys of this Vector.
84 public readonly
function keys()[]: Vector
<int> {
85 return new self($this->toKeysArray());
88 /** Returns a copy of this Vector.
91 public function values()[]: this
{
92 return new self($this);
95 /** Returns a lazy iterable view of this Vector.
99 public function lazy()[]: \LazyKeyedIterableView
{
101 return new \
LazyKeyedIterableView($this);
104 /** Returns the value at the specified key. If the key is not present, an
105 * exception is thrown.
109 public function at(mixed $key)[]: T
{
110 return $this[HH\FIXME\UNSAFE_CAST
<mixed, int>($key)];
113 /** Returns the value at the specified key. If the key is not present, null is
118 public function get(mixed $key)[]: ?T
{
119 // TODO(T125421081) `idx` is special cased in the typechecker, I don't think
120 // it quite understands how to deal with the input being `$this`, for some
123 return idx($this, $key);
126 /** Stores a value into the Vector with the specified key, overwriting any
127 * previous value that was associated with the key; if the key is outside the
128 * bounds of the Vector, an exception is thrown.
130 * @param mixed $value
133 public function set(mixed $key, T
$value)[write_props
]: this
{
135 $result[HH\FIXME\UNSAFE_CAST
<mixed, int>($key)] = $value;
139 /** Stores each value produced by the specified KeyedIterable into the Vector
140 * using its corresponding key, overwriting any previous value that was
141 * associated with that key; if the key is outside the bounds of the Vector,
142 * an exception is thrown.
143 * @param mixed $iterable
146 public function setAll(mixed $iterable)[write_props
]: this
{
147 if ($iterable === null) {
151 HH\FIXME\UNSAFE_CAST
<nonnull
, KeyedTraversable
<int, T
>>($iterable)
154 $this->set($key, $value);
160 private function clearNative()[write_props
]: void
;
162 /** Removes all values from the Vector.
165 public function clear()[write_props
]: this
{
166 $this->clearNative();
170 /** Returns true if the specified key is present in the Vector, returns false
176 "Use Vector::containsKey() for key search or Vector::linearSearch() for value search"
178 public readonly
function contains(mixed $key): bool {
179 if (!($key is
int)) {
180 throw new \
InvalidArgumentException(
181 "Only integer keys may be used with Vectors"
184 return ($key >= 0) && ($key < $this->count());
187 /** Returns true if the specified key is present in the Vector, returns false
192 public readonly
function containsKey(mixed $key)[]: bool {
193 if (!($key is
int)) {
194 throw new \
InvalidArgumentException(
195 "Only integer keys may be used with Vectors"
198 return ($key >= 0) && ($key < $this->count());
202 private function removeKeyNative(mixed $key)[write_props
]: void
;
204 /** Removes the element with the specified key from this Vector and renumbers
205 * the keys of all subsequent elements.
209 public function removeKey(mixed $key)[write_props
]: this
{
210 $this->removeKeyNative($key);
214 /** @param mixed $value
217 public function append(T
$value)[write_props
]: this
{
223 /** Adds the specified value to the end of this Vector using the next available
225 * @param mixed $value
228 public function add(T
$value)[write_props
]: this
{
229 return $this->append($value);
232 /** Adds the values produced by the specified Iterable to the end of this
233 * Vector using the next available integer keys.
234 * @param mixed $iterable
237 public function addAll(mixed $iterable)[write_props
]: this
{
238 if ($iterable === null) {
242 HH\FIXME\UNSAFE_CAST
<nonnull
, KeyedTraversable
<mixed, T
>>($iterable)
245 $this->append($value);
250 /** Adds the keys of the specified KeyedContainer to the end of this Vector
251 * using the next available integer keys.
252 * @param mixed $container
255 public function addAllKeysOf(
257 )[write_props
]: this
{
258 if ($container === null) {
262 HH\FIXME\UNSAFE_CAST
<nonnull
, KeyedTraversable
<T
, mixed>>($container)
273 public function pop()[write_props
]: mixed;
275 /** @param mixed $size
276 * @param mixed $value
279 public function resize(mixed $size, mixed $value)[write_props
]: void
;
281 /** Instructs this Vector to grow its capacity to accommodate the given number
282 * of elements. The caller is expected to make the appropriate add/addAll
283 * calls to fill that reserved capacity.
287 public function reserve(mixed $sz)[]: void
;
289 /** Returns a varray built from the values from this Vector.
292 public function toVArray()[]: varray
<T
> {
293 return varray($this);
296 public function toDArray()[]: darray
<int, T
> {
297 return darray($this);
300 /** Returns a copy of this Vector.
303 public function toVector()[]: Vector
<T
> {
304 return new self($this);
307 /** Returns a ImmVector built from the values of this Vector.
310 public function toImmVector()[]: ImmVector
<T
> {
311 return new ImmVector($this);
314 /** Returns an immutable version of this collection.
317 public function immutable()[]: ImmVector
<T
> {
318 return $this->toImmVector();
321 /** Returns a Map built from the keys and values of this Vector.
325 public function toMap()[]: Map
<int, T
> {
327 return new Map($this);
330 /** Returns a ImmMap built from the keys and values of this Vector.
334 public function toImmMap()[]: ImmMap
<int, T
> {
336 return new ImmMap($this);
339 /** Returns a Set built from the values of this Vector.
343 public function toSet()[]: Set
<T
> where T
as arraykey
{
345 return new Set($this);
348 /** Returns a ImmSet built from the values of this Vector.
352 public function toImmSet()[]: ImmSet
<T
> where T
as arraykey
{
354 return new ImmSet($this);
357 /** Returns a varray built from the keys from this Vector.
360 public readonly
function toKeysArray()[]: varray
<int> {
361 $count = $this->count();
363 ?
varray(HH\FIXME\UNSAFE_CAST
<mixed, varray
<int>>(\range
(0, $count - 1)))
367 /** Returns a varray built from the values from this Vector.
370 public function toValuesArray()[]: varray
<T
> {
371 return $this->toVArray();
374 /** Returns an iterator that points to beginning of this Vector.
378 public function getIterator()[]: Iterator
<T
>;
380 /** Returns a Vector of the values produced by applying the specified callback
381 * on each value from this Vector.
382 * @param mixed $callback
385 public function map
<To
>(
386 (function(T
)[_
]: To
) $callback,
387 )[ctx
$callback]: Vector
<To
> {
389 foreach ($this as $v) {
390 $ret[] = $callback($v);
392 return new Vector($ret);
395 /** Returns a Vector of the values produced by applying the specified callback
396 * on each key and value from this Vector.
397 * @param mixed $callback
400 public function mapWithKey
<To
>(
401 (function(int, T
)[_
]: To
) $callback,
402 )[ctx
$callback]: Vector
<To
> {
404 foreach ($this as $k => $v) {
405 $ret[] = $callback($k, $v);
407 return new Vector($ret);
410 /** Returns a Vector of all the values from this Vector for which the specified
411 * callback returns true.
412 * @param mixed $callback
415 public function filter(
416 (function(T
)[_
]: bool) $callback,
417 )[ctx
$callback]: this
{
419 foreach ($this as $v) {
424 return new Vector($ret);
427 /** Returns a Vector of all the values from this Vector for which the specified
428 * callback returns true.
429 * @param mixed $callback
432 public function filterWithKey(
433 (function(int, T
)[_
]: bool) $callback,
434 )[ctx
$callback]: this
{
436 foreach ($this as $k => $v) {
437 if ($callback($k, $v)) {
441 return new Vector($ret);
444 /** Returns a KeyedIterable produced by combined the specified Iterables
446 * @param mixed $iterable
449 public function zip
<To
>(
451 )[]: Vector
<Pair
<T
, To
>> {
454 $count = $this->count();
456 HH\FIXME\UNSAFE_CAST
<mixed, Traversable
<To
>>($iterable) as $value
461 $result[] = Pair
{ $this[$i], $value };
464 return new self($result);
467 /** Returns a Vector containing the first n values of this Vector.
471 public function take(mixed $n)[]: this
{
473 throw new \
InvalidArgumentException("Parameter n must be an integer");
475 $count = $this->count();
476 $n = $n < 0 ?
0 : ($n > $count ?
$count : $n);
478 for ($i = 0; $i < $n; $i++
) {
479 $result[] = $this[$i];
481 return new self($result);
484 /** Returns a Vector containing the values of this Vector up to but not
485 * including the first value that produces false when passed to the specified
487 * @param mixed $callback
490 public function takeWhile(
491 (function(T
)[_
]: bool) $callback,
492 )[ctx
$callback]: this
{
494 foreach ($this as $v) {
495 if (!$callback($v)) {
500 return new Vector($ret);
503 /** Returns a Vector containing all the values except the first n of this
508 public function skip(mixed $n)[]: this
{
510 throw new \
InvalidArgumentException("Parameter n must be an integer");
512 $count = $this->count();
513 $n = $n < 0 ?
0 : ($n > $count ?
$count : $n);
515 for ($i = $n; $i < $count; $i++
) {
516 $result[] = $this[$i];
518 return new self($result);
521 /** Returns a Vector containing the values of this Vector excluding the first
522 * values that produces true when passed to the specified callback.
526 public function skipWhile((function(T
)[_
]: bool) $fn)[ctx
$fn]: this
{
529 foreach ($this as $v) {
538 return new Vector($ret);
541 /** Returns a Vector containing the specified range of values from this Vector.
542 * The range is specified by two non-negative integers: a starting position
544 * @param mixed $start
548 public function slice(mixed $start, mixed $len)[]: this
{
549 if (!($start is
int) ||
$start < 0) {
550 throw new \
InvalidArgumentException(
551 "Parameter start must be a non-negative integer");
553 if (!($len is
int) ||
$len < 0) {
554 throw new \
InvalidArgumentException(
555 "Parameter len must be a non-negative integer");
557 $count = $this->count();
558 $skip = $start < $count ?
$start : $count;
559 $size = $len < $count - $skip ?
$len : $count - $skip;
561 for ($i = $skip; $i < $skip +
$size; $i++
) {
562 $result[] = $this[$i];
564 return new self($result);
567 /** Builds a new Vector by concatenating the elements of this Vector with the
568 * elements of the specified Iterable.
569 * @param mixed $iterable
572 public function concat
<To super T
>(
575 $result = vec($this);
577 HH\FIXME\UNSAFE_CAST
<mixed, Traversable
<To
>>($iterable) as $value
581 return new self($result);
584 /** Returns the first value from this Vector, or null if this Vector is empty.
587 public function firstValue()[]: mixed {
589 return idx($this, 0);
592 /** Returns the first key from this Vector, or null if this Vector is empty.
595 public readonly
function firstKey()[]: mixed {
596 return $this->count() ?
0 : null;
599 /** Returns the last value from this Vector, or null if this Vector is empty.
602 public function lastValue()[]: mixed {
603 $count = $this->count();
604 return $count ?
$this[$count - 1] : null;
607 /** Returns the last key from this Vector, or null if this Vector is empty.
610 public readonly
function lastKey()[]: mixed {
611 $count = $this->count();
612 return $count ?
($count - 1) : null;
615 /** Reverses the values of the Vector in place.
618 public function reverse()[write_props
]: void
;
620 /** Splices the values of the Vector in place (see the documentation for
621 * array_splice() on php.net for more details.
622 * @param mixed $offset
624 * @param mixed $replacement
627 public function splice(mixed $offset,
629 mixed $replacement = null)[write_props
]: void
;
631 /** Returns index of the specified value if it is present, -1 otherwise.
632 * @param mixed $search_value
635 public readonly
function linearSearch(mixed $search_value)[]: int {
636 foreach (vec($this) as $i => $value) {
637 if ($value === $search_value) {
644 /** Shuffles the values of the Vector randomly in place.
647 public function shuffle()[leak_safe
]: void
;
651 public function __toString()[]: string { return "Vector"; }
653 /** Returns a Vector built from the values produced by the specified Iterable.
654 * @param mixed $iterable
657 public static function fromItems(mixed $iterable)[]: this
{
658 return new self($iterable);
661 /** Returns a Vector built from the keys of the specified container.
662 * @param mixed $container
665 public static function fromKeysOf(mixed $container)[]: this
{
666 if ($container is
null) {
668 } else if (!($container is KeyedContainer
<_
,_
>)) {
669 throw new \
InvalidArgumentException(
670 "Parameter must be a container (array or collection)");
673 foreach ($container as $key => $_) {
676 return new self($result);
679 /** Returns a Vector built from the values from the specified array.
683 public static function fromArray(mixed $arr): this
{
684 return new self($arr);
688 /** An immutable ordered collection where values are keyed using integers 0
691 final class ImmVector
<T
> implements \ConstVector
<T
> {
693 /** Returns a ImmVector built from the values produced by the specified
695 * @param mixed $iterable
698 public function __construct(mixed $iterable = null)[]: void
;
700 /** Returns an ImmVector built from the values produced by the specified
702 * @param mixed $iterable
705 public static function fromItems(mixed $iterable)[]: this
{
706 return new self($iterable);
709 /** Returns a ImmVector built from the keys of the specified container.
710 * @param mixed $container
713 public static function fromKeysOf(mixed $container)[]: this
{
714 if ($container is
null) {
716 } else if (!($container is KeyedContainer
<_
,_
>)) {
717 throw new \
InvalidArgumentException(
718 "Parameter must be a container (array or collection)");
721 foreach ($container as $key => $_) {
724 return new self($result);
727 /** Returns true if the ImmVector is empty, false otherwise.
730 public readonly
function isEmpty()[]: bool {
731 return !$this->count();
734 /** Returns the number of values in the ImmVector.
737 public readonly
function count()[]: int {
738 return \
count(vec($this));
741 /** Returns an Iterable that produces the values from this ImmVector.
745 public function items()[]: \LazyIterableView
{
747 return new \
LazyIterableView($this);
750 /** Returns true if the specified key is present in the ImmVector, returns
755 public readonly
function containsKey(mixed $key)[]: bool {
756 if (!($key is
int)) {
757 throw new \
InvalidArgumentException(
758 "Only integer keys may be used with Vectors"
761 return ($key >= 0) && ($key < $this->count());
764 /** Returns the value at the specified key. If the key is not present, an
765 * exception is thrown.
769 public function at(mixed $key)[]: T
{
770 return $this[HH\FIXME\UNSAFE_CAST
<mixed, int>($key)];
773 /** Returns the value at the specified key. If the key is not present, null is
778 public function get(mixed $key)[]: ?T
{
780 return idx($this, $key);
783 /** Returns an iterator that points to beginning of this ImmVector.
787 public function getIterator()[]: Iterator
<T
>;
789 /** Returns a Vector of the values produced by applying the specified callback
790 * on each value from this ImmVector.
791 * @param mixed $callback
794 public function map
<To
>(
795 (function(T
)[_
]: To
) $callback,
796 )[ctx
$callback]: ImmVector
<To
> {
798 foreach ($this as $v) {
799 $ret[] = $callback($v);
801 return new ImmVector($ret);
804 /** Returns a Vector of the values produced by applying the specified callback
805 * on each key and value from this ImmVector.
806 * @param mixed $callback
809 public function mapWithKey
<To
>(
810 (function(int, T
)[_
]: To
) $callback,
811 )[ctx
$callback]: ImmVector
<To
> {
813 foreach ($this as $k => $v) {
814 $ret[] = $callback($k, $v);
816 return new ImmVector($ret);
819 /** Returns a Vector of all the values from this ImmVector for which the
820 * specified callback returns true.
821 * @param mixed $callback
824 public function filter((function(T
)[_
]: bool) $callback)[ctx
$callback]: this
{
826 foreach ($this as $v) {
831 return new ImmVector($ret);
834 /** Returns a Vector of all the values from this ImmVector for which the
835 * specified callback returns true.
836 * @param mixed $callback
839 public function filterWithKey(
840 (function(int, T
)[_
]: bool) $callback,
841 )[ctx
$callback]: this
{
843 foreach ($this as $k => $v) {
844 if ($callback($k, $v)) {
848 return new ImmVector($ret);
851 /** Returns a KeyedIterable produced by combined the specified Iterables
853 * @param mixed $iterable
856 public function zip
<To
>(
858 )[]: ImmVector
<Pair
<T
, To
>> {
861 $count = $this->count();
863 HH\FIXME\UNSAFE_CAST
<mixed, Traversable
<To
>>($iterable) as $value
868 $result[] = Pair
{ $this[$i], $value };
871 return new self($result);
874 /** Returns a ImmVector containing the first n values of this ImmVector.
878 public function take(mixed $n)[]: this
{
880 throw new \
InvalidArgumentException("Parameter n must be an integer");
882 $count = $this->count();
883 $n = $n < 0 ?
0 : ($n > $count ?
$count : $n);
885 for ($i = 0; $i < $n; $i++
) {
886 $result[] = $this[$i];
888 return new self($result);
891 /** Returns a ImmVector containing the values of this ImmVector up to but not
892 * including the first value that produces false when passed to the specified
894 * @param mixed $callback
897 public function takeWhile(
898 (function(T
)[_
]: bool) $callback,
899 )[ctx
$callback]: this
{
901 foreach ($this as $v) {
902 if (!$callback($v)) {
907 return new ImmVector($ret);
910 /** Returns a ImmVector containing all values except the first n of this
915 public function skip(mixed $n)[]: this
{
917 throw new \
InvalidArgumentException("Parameter n must be an integer");
919 $count = $this->count();
920 $n = $n < 0 ?
0 : ($n > $count ?
$count : $n);
922 for ($i = $n; $i < $count; $i++
) {
923 $result[] = $this[$i];
925 return new self($result);
928 /** Returns a ImmVector containing the values of this ImmVector excluding the
929 * first values that produces true when passed to the specified callback.
933 public function skipWhile((function(T
)[_
]: bool) $fn)[ctx
$fn]: this
{
936 foreach ($this as $v) {
945 return new ImmVector($ret);
948 /** Returns an ImmVector containing the specified range of values from this
949 * ImmVector. The range is specified by two non-negative integers: a starting
950 * position and a length.
951 * @param mixed $start
955 public function slice(mixed $start, mixed $len)[]: this
{
956 if (!($start is
int) ||
$start < 0) {
957 throw new \
InvalidArgumentException(
958 "Parameter start must be a non-negative integer");
960 if (!($len is
int) ||
$len < 0) {
961 throw new \
InvalidArgumentException(
962 "Parameter len must be a non-negative integer");
964 $count = $this->count();
965 $skip = $start < $count ?
$start : $count;
966 $size = $len < $count - $skip ?
$len : $count - $skip;
968 for ($i = $skip; $i < $skip +
$size; $i++
) {
969 $result[] = $this[$i];
971 return new self($result);
974 /** Builds a new ImmVector by concatenating the elements of this ImmVector with
975 * the elements of the specified Iterable.
976 * @param mixed $iterable
979 public function concat
<To super T
>(
982 $result = vec($this);
984 HH\FIXME\UNSAFE_CAST
<mixed, Traversable
<To
>>($iterable) as $value
988 return new self($result);
991 /** Returns the first value from this ImmVector, or null if this ImmVector is
995 public function firstValue()[]: mixed {
997 return idx($this, 0);
1000 /** Returns the first key from this ImmVector, or null if this ImmVector is
1004 public readonly
function firstKey()[]: mixed {
1005 return $this->count() ?
0 : null;
1008 /** Returns the last value from this ImmVector, or null if this ImmVector is
1012 public function lastValue()[]: mixed {
1013 $count = $this->count();
1014 return $count ?
$this[$count - 1] : null;
1017 /** Returns the last key from this ImmVector, or null if this ImmVector is
1021 public readonly
function lastKey()[]: mixed {
1022 $count = $this->count();
1023 return $count ?
($count - 1) : null;
1026 /** Returns an Iterable that produces the keys from this ImmVector.
1029 public function keys()[]: ImmVector
<int> {
1030 return new self($this->toKeysArray());
1035 public function __toString()[]: string { return "ImmVector"; }
1037 /** Returns a Vector built from the values of this ImmVector.
1040 public function toVector()[]: Vector
<T
> {
1041 return new Vector($this);
1044 /** Returns an immutable version of this collection.
1047 public function toImmVector()[]: this
{
1051 /** Returns a Map built from the keys and values of this ImmVector.
1054 /* HH_FIXME[2049] */
1055 public function toMap()[]: Map
<int, T
> {
1056 /* HH_FIXME[2049] */
1057 return new Map($this);
1060 /** Returns a ImmMap built from the keys and values of this ImmVector.
1063 /* HH_FIXME[2049] */
1064 public function toImmMap()[]: ImmMap
<int, T
> {
1065 /* HH_FIXME[2049] */
1066 return new ImmMap($this);
1069 /** Returns a Set built from the values of this ImmVector.
1072 /* HH_FIXME[2049] */
1073 public function toSet()[]: Set
<T
> where T
as arraykey
{
1074 /* HH_FIXME[2049] */
1075 return new Set($this);
1078 /** Returns a ImmSet built from the values of this ImmVector.
1081 /* HH_FIXME[2049] */
1082 public function toImmSet()[]: ImmSet
<T
> where T
as arraykey
{
1083 /* HH_FIXME[2049] */
1084 return new ImmSet($this);
1087 /** Returns an immutable version of this collection.
1090 public function immutable()[]: this
{
1094 /** Returns a copy of this ImmVector.
1097 public function values()[]: this
{
1098 return new self($this);
1101 /** Returns a lazy iterable view of this ImmVector.
1104 /* HH_FIXME[2049] */
1105 public function lazy()[]: \LazyKeyedIterableView
{
1106 /* HH_FIXME[2049] */
1107 return new \
LazyKeyedIterableView($this);
1110 /** Returns a varray built from the values from this ImmVector.
1113 public function toVArray()[]: varray
<T
> {
1114 return varray($this);
1117 public function toDArray()[]: darray
<int, T
> {
1118 return darray($this);
1121 /** Returns a varray built from the keys from this ImmVector.
1124 public readonly
function toKeysArray()[]: varray
<int> {
1125 $count = $this->count();
1127 ?
varray(HH\FIXME\UNSAFE_CAST
<mixed, varray
<int>>(\range
(0, $count - 1)))
1131 /** Returns a varray built from the values from this ImmVector.
1134 public function toValuesArray()[]: varray
<T
> {
1135 return $this->toVArray();
1138 /** Returns index of the specified value if it is present, -1 otherwise.
1139 * @param mixed $search_value
1142 public readonly
function linearSearch(mixed $search_value)[]: int {
1143 foreach (vec($this) as $i => $value) {
1144 if ($value === $search_value) {