Skip to content

Commit e28b7c7

Browse files
authored
Add Option::zipWith() (#56)
1 parent d9e1289 commit e28b7c7

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

.devcontainer/devcontainer.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
"XDEBUG_SESSION": "1",
1515
"XDEBUG_CONFIG": "log_level=0",
1616
"PATH": "${containerEnv:PATH}:/app/vendor/bin",
17-
"PROMPT_COMMAND": "short_pwd=$(sed \"s:\\([^/\\.]\\)[^/]*/:\\1/:g\" <<< ${PWD/#$HOME/\\~})",
17+
"PROMPT_COMMAND": "short_pwd=$(sed \"s:\\([^/\\.]\\)[^/]*/:\\1/:g\" <<< ${PWD/#$HOME/\\~})",
1818
"PS1": "\\[\\e[0;35m\\]$short_pwd \\n\\[\\e[0;33m\\]$((( _ret_value )) && printf \"\\[\\e[0;31m\\]\")$\\[\\e[0m\\] ",
1919
"PS2": "\\[${_y}\\]❯ \\[${reset}\\]"
2020
},
2121

2222
// Set *default* container specific settings.json values on container create.
2323
"settings": {},
24+
"features": {
25+
"ghcr.io/devcontainers/features/git:1": {},
26+
"ghcr.io/devcontainers/features/sshd:1": {}
27+
},
2428

2529
// Add the IDs of extensions you want installed when the container is created.
2630
// Note that some extensions may not work in Alpine Linux. See https://aka.ms/vscode-remote/linux.

src/Option.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,33 @@ public function mapOrElse(callable $callback, callable $default): mixed;
503503
*/
504504
public function zip(Option $option): Option;
505505

506+
/**
507+
* Zips `$this` and another `Option` with a function.
508+
*
509+
* If `$this` is `Some(s)` and other is `Some(o)`, this method returns `Some(f([s, o]))`.
510+
* Otherwise, `None` is returned.
511+
*
512+
* # Examples
513+
*
514+
* ```
515+
* $x = Option\some(new \DateTime('2025-02-08T23:15:07+00:00'));
516+
* $y = Option\some(new \DateInterval('P1M0D'));
517+
* // @var Option<int> $z
518+
* $z = Option\none();
519+
* self::assertEq($x->zipWith($y, date_add(...)), Option\some(new \DateTimeImmutable('2025-03-08T23:15:07+00:00')));
520+
* self::assertSame($x->zipWith($z, date_add(...)), Option\none());
521+
* self::assertSame($z->zipWith($y, date_add(...)), Option\none());
522+
* ```
523+
*
524+
* @template U
525+
* @template V
526+
* @param Option<U> $option
527+
* @param callable(T, U):V $callback
528+
* @return (T is never ? Option\None : (U is never ? Option\None : Option<V>))
529+
* @phpstan-return Option<V>
530+
*/
531+
public function zipWith(Option $option, callable $callback): Option;
532+
506533
/**
507534
* Transforms the `Option<T>` into a `Result<T, E>`, mapping `Some(v)` to `Ok(v)` and `None` to `Err(err)`.
508535
*

src/Option/None.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,18 @@ public function zip(Option $option): self
161161
return $this;
162162
}
163163

164+
/**
165+
* @template U
166+
* @template V
167+
* @param Option<U> $option
168+
* @param callable(never, U):V $callback
169+
* @return $this
170+
*/
171+
public function zipWith(Option $option, callable $callback): self
172+
{
173+
return $this;
174+
}
175+
164176
/**
165177
* @template E
166178
* @param E $err

src/Option/Some.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,23 @@ public function zip(Option $option): Option
192192
return Option\none();
193193
}
194194

195+
/**
196+
* @template U
197+
* @template V
198+
* @param Option<U> $option
199+
* @param callable(T, U):V $callback
200+
* @return (U is never ? Option\None : Option<V>)
201+
* @return Option<V>
202+
*/
203+
public function zipWith(Option $option, callable $callback): Option
204+
{
205+
foreach ($option as $value) {
206+
return Option\some($callback($this->value, $value));
207+
}
208+
209+
return Option\none();
210+
}
211+
195212
/**
196213
* @template E
197214
* @param E $err

0 commit comments

Comments
 (0)