-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Not-Null pipe operator #180
Comments
In Kotlin, scope functions solve this: Person("Tom", age = 12)
|> findFriends(it)
|> storeFriendsList(it)
// Equivalent
Person("tom", age = 12)
.let { findFriends(it) }
.let { storeFriendsList(it) } Source: https://discuss.kotlinlang.org/t/pipe-forward-operator/2098 If we were to adopt this into PHP, this could be written as: new Person('Tom', age: 12)
->let(findFriends(...))
->let(storeFriendsList(...))
;
// Yes, also works on non-objects!
$context->userName()->let(stroupper(...)); We could then simply reuse |
The diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php
index ac3d93a..adbe64b 100755
--- a/src/main/php/lang/ast/emit/PHP.class.php
+++ b/src/main/php/lang/ast/emit/PHP.class.php
@@ -1076,6 +1076,24 @@ abstract class PHP extends Emitter {
}
protected function emitInvoke($result, $invoke) {
+ if ($invoke->expression instanceof InstanceExpression && 'let' === $invoke->expression->member->expression) {
+ if ('nullsafeinstance' === $invoke->expression->kind) {
+ $t= $result->temp();
+ $result->out->write("null===({$t}=");
+ $this->emitOne($result, $invoke->expression->expression);
+ $result->out->write(')?null:(');
+ $this->emitOne($result, $invoke->arguments[0]);
+ $result->out->write(")({$t})");
+ } else {
+ $result->out->write('(');
+ $this->emitOne($result, $invoke->arguments[0]);
+ $result->out->write(')(');
+ $this->emitOne($result, $invoke->expression->expression);
+ $result->out->write(')');
+ }
+ return;
+ }
+
$this->emitOne($result, $invoke->expression);
$result->out->write('(');
$this->emitArguments($result, $invoke->arguments);
|
Here's a real-world example from https://github.com/thekid/dialog: if ($prop= $env->properties($config, optional: true)) {
$this->sources['config']= $prop->readString(...);
} This could be rewritten as follows: // Scope function
$env->properties($config, optional: true)?->let(fn($prop) => $this->sources['config']= $prop->readString(...));
// Pipe operator
$env->properties($config, optional: true) ?|> fn($prop) => $this->sources['config']= $prop->readString(...);
// Hacklang pipes with $$ placeholder
$env->properties($config, optional: true) ?|> $this->sources['config']= $$->readString(...); |
Proposal
Complement the null-coalescing operator:
Sometimes we want to perform an action if the value is null, and perform an alternative instead:
We already have a "standard" for chaining expressions with the pipe operator. The above without null handling would be:
👉 To accomplish this, this feature request suggests a null-safe pipe operator, which would make the following an equivalent of the above:
Consistency
This is consistent with the null-safe object operator. If we rewrote the above using a
String
class, we could have the following:However, wrapping every primitive string in a
String
instance would introduce quite a bit of runtime and development overhead!See also
?>
?|>
!??
?|>
suggestedThe text was updated successfully, but these errors were encountered: