Skip to content

Commit d6aa473

Browse files
phananclaude
andcommitted
Add when and unless for conditional value resolution
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 63aaefd commit d6aa473

7 files changed

Lines changed: 223 additions & 0 deletions

File tree

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@
122122
"src/Functional/True.php",
123123
"src/Functional/Truthy.php",
124124
"src/Functional/Unique.php",
125+
"src/Functional/Unless.php",
125126
"src/Functional/ValueToKey.php",
127+
"src/Functional/When.php",
126128
"src/Functional/With.php",
127129
"src/Functional/Zip.php",
128130
"src/Functional/ZipAll.php"

docs/functional-php.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,35 @@ use function Functional\tap;
10361036
tap(create_user('John Doe'), fn ($user) => send_welcome_email($user))->login();
10371037
```
10381038

1039+
## when()
1040+
1041+
``mixed when(mixed|Closure $condition, mixed|Closure $value, mixed|Closure $default = null)``
1042+
Return a value if the given condition is true. All three arguments can be closures — `$condition` is evaluated, and `$value` or `$default` is resolved accordingly.
1043+
1044+
```php
1045+
use function Functional\when;
1046+
1047+
when(true, 'yes'); // 'yes'
1048+
when(false, 'yes'); // null
1049+
when(false, 'yes', 'no'); // 'no'
1050+
when(fn () => true, 'yes'); // 'yes'
1051+
when(true, fn () => 'computed'); // 'computed'
1052+
```
1053+
1054+
## unless()
1055+
1056+
``mixed unless(mixed|Closure $condition, mixed|Closure $value, mixed|Closure $default = null)``
1057+
Return a value if the given condition is false. The inverse of `when()`.
1058+
1059+
```php
1060+
use function Functional\unless;
1061+
1062+
unless(false, 'yes'); // 'yes'
1063+
unless(true, 'yes'); // null
1064+
unless(true, 'yes', 'no'); // 'no'
1065+
unless(fn () => false, 'yes'); // 'yes'
1066+
```
1067+
10391068
## repeat()
10401069

10411070
Creates and returns a function that can be used to execute the given closure multiple times.

src/Functional/Functional.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,11 +493,21 @@ final class Functional
493493
*/
494494
const unique = '\Functional\unique';
495495

496+
/**
497+
* @see \Functional\unless
498+
*/
499+
const unless = '\Functional\unless';
500+
496501
/**
497502
* @see \Functional\value_to_key
498503
*/
499504
const value_to_key = '\Functional\value_to_key';
500505

506+
/**
507+
* @see \Functional\when
508+
*/
509+
const when = '\Functional\when';
510+
501511
/**
502512
* @see \Functional\with
503513
*/

src/Functional/Unless.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/**
4+
* @package Functional-php
5+
* @author Lars Strojny <lstrojny@php.net>
6+
* @copyright 2011-2021 Lars Strojny
7+
* @license https://opensource.org/licenses/MIT MIT
8+
* @link https://github.com/lstrojny/functional-php
9+
*/
10+
11+
namespace Functional;
12+
13+
/**
14+
* Return a value if the given condition is false.
15+
*
16+
* @param mixed|\Closure $condition
17+
* @param mixed|\Closure $value
18+
* @param mixed|\Closure $default
19+
*
20+
* @return mixed
21+
* @no-named-arguments
22+
*/
23+
function unless($condition, $value, $default = null)
24+
{
25+
$condition = $condition instanceof \Closure ? $condition() : $condition;
26+
27+
if (!$condition) {
28+
return $value instanceof \Closure ? $value($condition) : $value;
29+
}
30+
31+
return $default instanceof \Closure ? $default($condition) : $default;
32+
}

src/Functional/When.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/**
4+
* @package Functional-php
5+
* @author Lars Strojny <lstrojny@php.net>
6+
* @copyright 2011-2021 Lars Strojny
7+
* @license https://opensource.org/licenses/MIT MIT
8+
* @link https://github.com/lstrojny/functional-php
9+
*/
10+
11+
namespace Functional;
12+
13+
/**
14+
* Return a value if the given condition is true.
15+
*
16+
* @param mixed|\Closure $condition
17+
* @param mixed|\Closure $value
18+
* @param mixed|\Closure $default
19+
*
20+
* @return mixed
21+
* @no-named-arguments
22+
*/
23+
function when($condition, $value, $default = null)
24+
{
25+
$condition = $condition instanceof \Closure ? $condition() : $condition;
26+
27+
if ($condition) {
28+
return $value instanceof \Closure ? $value($condition) : $value;
29+
}
30+
31+
return $default instanceof \Closure ? $default($condition) : $default;
32+
}

tests/Functional/UnlessTest.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/**
4+
* @package Functional-php
5+
* @author Lars Strojny <lstrojny@php.net>
6+
* @copyright 2011-2021 Lars Strojny
7+
* @license https://opensource.org/licenses/MIT MIT
8+
* @link https://github.com/lstrojny/functional-php
9+
*/
10+
11+
namespace Functional\Tests;
12+
13+
use function Functional\unless;
14+
15+
class UnlessTest extends AbstractTestCase
16+
{
17+
public function testUnlessConditionIsFalsy(): void
18+
{
19+
self::assertEquals('yes', unless(false, 'yes'));
20+
}
21+
22+
public function testUnlessConditionIsTruthy(): void
23+
{
24+
self::assertNull(unless(true, 'yes'));
25+
}
26+
27+
public function testUnlessConditionIsTruthyWithDefault(): void
28+
{
29+
self::assertEquals('no', unless(true, 'yes', 'no'));
30+
}
31+
32+
public function testUnlessValueIsClosure(): void
33+
{
34+
self::assertEquals('fallback', unless(false, function () {
35+
return 'fallback';
36+
}));
37+
}
38+
39+
public function testUnlessDefaultIsClosure(): void
40+
{
41+
self::assertEquals('default', unless(true, 'yes', function () {
42+
return 'default';
43+
}));
44+
}
45+
46+
public function testUnlessConditionIsClosure(): void
47+
{
48+
self::assertEquals('yes', unless(function () {
49+
return false;
50+
}, 'yes'));
51+
}
52+
53+
public function testUnlessConditionIsClosureReturningTruthy(): void
54+
{
55+
self::assertNull(unless(function () {
56+
return true;
57+
}, 'yes'));
58+
}
59+
}

tests/Functional/WhenTest.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/**
4+
* @package Functional-php
5+
* @author Lars Strojny <lstrojny@php.net>
6+
* @copyright 2011-2021 Lars Strojny
7+
* @license https://opensource.org/licenses/MIT MIT
8+
* @link https://github.com/lstrojny/functional-php
9+
*/
10+
11+
namespace Functional\Tests;
12+
13+
use function Functional\when;
14+
15+
class WhenTest extends AbstractTestCase
16+
{
17+
public function testWhenConditionIsTruthy(): void
18+
{
19+
self::assertEquals('yes', when(true, 'yes'));
20+
}
21+
22+
public function testWhenConditionIsFalsy(): void
23+
{
24+
self::assertNull(when(false, 'yes'));
25+
}
26+
27+
public function testWhenConditionIsFalsyWithDefault(): void
28+
{
29+
self::assertEquals('no', when(false, 'yes', 'no'));
30+
}
31+
32+
public function testWhenValueIsClosure(): void
33+
{
34+
self::assertEquals('condition was true', when(true, function ($condition) {
35+
return $condition ? 'condition was true' : 'condition was false';
36+
}));
37+
}
38+
39+
public function testWhenDefaultIsClosure(): void
40+
{
41+
self::assertEquals('fallback', when(false, 'yes', function () {
42+
return 'fallback';
43+
}));
44+
}
45+
46+
public function testWhenConditionIsClosure(): void
47+
{
48+
self::assertEquals('yes', when(function () {
49+
return true;
50+
}, 'yes'));
51+
}
52+
53+
public function testWhenConditionIsClosureReturningFalsy(): void
54+
{
55+
self::assertNull(when(function () {
56+
return false;
57+
}, 'yes'));
58+
}
59+
}

0 commit comments

Comments
 (0)