Skip to content

Commit

Permalink
Add C\pop_back as replacements for \array_pop (hhvm#143)
Browse files Browse the repository at this point in the history
Summary:
fixes hhvm#137
references hhvm/hsl-experimental#86 (comment)

Pull Request resolved: hhvm#143

Reviewed By: fredemmott

Differential Revision: D23611657

Pulled By: jjergus

fbshipit-source-id: a243bd04c52fa538296e23ba122efab03ceedbb4
  • Loading branch information
lexidor authored and facebook-github-bot committed Jan 29, 2021
1 parent d87aeb0 commit 745be36
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/c/select.php
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,51 @@ function onlyx<T>(
/* HH_FIXME[4110] $first is false implies $result is set to T */
return $result;
}

/**
* Removes the last element from a Container and returns it.
* If the Container is empty, null will be returned.
*
* When an immutable Hack Collection is passed, the result will
* be defined by your version of hhvm and not give the expected results.
*
* For non-empty Containers, see `pop_backx`.
*
* Time complexity: O(1 or N) If the operation can happen in-place, O(1)
* if it must copy the Container, O(N).
* Space complexity: O(1 or N) If the operation can happen in-place, O(1)
* if it must copy the Container, O(N).
*/
function pop_back<T as Container<Tv>, Tv>(inout T $container): ?Tv {
if (is_empty($container)) {
return null;
}
/* HH_FIXME[2049] __PHPStdLib */
/* HH_FIXME[4107] __PHPStdLib */
return \array_pop(inout $container);
}

/**
* Removes the last element from a Container and returns it.
* If the Container is empty, an `InvariantException` is thrown.
*
* When an immutable Hack Collection is passed, the result will
* be defined by your version of hhvm and not give the expected results.
*
* For maybe empty Containers, see `pop_back`.
*
* Time complexity: O(1 or N) If the operation can happen in-place, O(1)
* if it must copy the Container, O(N).
* Space complexity: O(1 or N) If the operation can happen in-place, O(1)
* if it must copy the Container, O(N).
*/
function pop_backx<T as Container<Tv>, Tv>(inout T $container): Tv {
invariant(
!is_empty($container),
'%s: Expected at least one element',
__FUNCTION__,
);
/* HH_FIXME[2049] __PHPStdLib */
/* HH_FIXME[4107] __PHPStdLib */
return \array_pop(inout $container);
}
81 changes: 81 additions & 0 deletions tests/c/CSelectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -790,4 +790,85 @@ public function testOnlyxWithCustomMessage<T>(): void {
)
->toEqual(42);
}

public static function provideTestPopBack(
): vec<(Container<mixed>, Container<mixed>, mixed)> {
return vec[
tuple(vec[1], vec[], 1),
tuple(vec[1, 2, 3], vec[1, 2], 3),
tuple(vec[], vec[], null),
tuple(vec[null], vec[], null),
tuple(keyset['apple', 'banana'], keyset['apple'], 'banana'),
tuple(varray[1, 2, 3], varray[1, 2], 3),
tuple(dict['a' => 1, 'b' => 2], dict['a' => 1], 2),
tuple(Vector {1, 2, 3}, Vector {1, 2}, 3),
tuple(Set {}, Set {}, null),
];
}

<<DataProvider('provideTestPopBack')>>
public function testPopBack(
Container<mixed> $before,
Container<mixed> $after,
mixed $value,
): void {
$return_value = C\pop_back(inout $before);
invariant(
$after is KeyedContainer<_, _>,
'->toHaveSameContentAs() takes a KeyedContainer.'.
'There are currently no Containers in Hack which are not also KeyedContainers.',
);
expect($before)->toHaveSameContentAs($after);
expect($return_value)->toEqual($value);
}

public static function provideTestPopBackx(
): vec<(Container<mixed>, Container<mixed>, mixed)> {
return vec[
tuple(vec[1], vec[], 1),
tuple(vec[1, 2, 3], vec[1, 2], 3),
tuple(keyset['apple', 'banana'], keyset['apple'], 'banana'),
tuple(varray[1, 2, 3], varray[1, 2], 3),
tuple(dict['a' => 1, 'b' => 2], dict['a' => 1], 2),
tuple(Vector {1, 2, 3}, Vector {1, 2}, 3),
tuple(vec[null], vec[], null),
];
}

<<DataProvider('provideTestPopBackx')>>
public function testPopBackx(
Container<mixed> $before,
Container<mixed> $after,
mixed $value,
): void {
$return_value = C\pop_backx(inout $before);
invariant(
$after is KeyedContainer<_, _>,
'->toHaveSameContentAs() takes a KeyedContainer.'.
'There are currently no Containers in Hack which are not also KeyedContainers.',
);
expect($before)->toHaveSameContentAs($after);
expect($return_value)->toEqual($value);
}

public static function provideTestPopBackxThrowsOnEmptyContainers(
): vec<(Container<mixed>)> {
return vec[
tuple(vec[]),
tuple(dict[]),
tuple(keyset[]),
tuple(Vector {}),
tuple(Map {}),
];
}

<<DataProvider('provideTestPopBackxThrowsOnEmptyContainers')>>
public function testPopBackxThrowOnEmptyContainers(
Container<mixed> $container,
): void {
expect(() ==> C\pop_backx(inout $container))->toThrow(
InvariantException::class,
'Expected at least one element',
);
}
}

0 comments on commit 745be36

Please sign in to comment.