Skip to content
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

Ternary operator #20

Open
rezen opened this issue Dec 14, 2020 · 6 comments
Open

Ternary operator #20

rezen opened this issue Dec 14, 2020 · 6 comments

Comments

@rezen
Copy link

rezen commented Dec 14, 2020

Wanted to move the discussion from Twitter to here. I looked at the source to evaluate making a PR, and processed through the docs and was struggling with a clear path for multiple reasons.

Firstly, ternary is almost always a ? b : c, so do you implement with the expectation of those specific tokens? This is a minor question, and the answer is probably, no, don't expect specific tokens, the user provides those.

Secondly, all the current operators work with one symbol, not two and you need two or more symbols so all the Verraes\Parsica\Expression\*Assoc classes would probably need to change? OR instead there would it be a new ExpressionType?

@rezen
Copy link
Author

rezen commented Dec 14, 2020

Here are some forms of ternary operators to think about

  • if test do: when_true else: when_false
  • test ? when_true : when_false
  • when_true if test else when_false

@rezen
Copy link
Author

rezen commented Dec 14, 2020

Throwing out some rough code for handling more complex expressions - maybe that is the answer as opposed to a ternary operator?

<?php
use  function Verraes\Parsica\Expression\compound;

// ...
compound(function ($previousPrecedenceLevel) {
 return collect([
    $token('if'),  
    $previousPrecedenceLevel,
    $token('do:'),
    $previousPrecedenceLevel,
    $token('else:'),
    $previousPrecedenceLevel,
 ])
 ->map(fn($v) => [$v[1], $v[3], $v[6]]);
})
->map(fn($test, $whenTrue, $whenFalse) => ... );

@mathiasverraes
Copy link
Collaborator

Thanks for this input.

Something else to consider: So far the expression handler can deal with expression operator expression and variations. Ternaries are typically booleanExpr operator expression operator expression. We'll need to consider whether the parser cares about the difference between booleanExpr and expression.

@mathiasverraes
Copy link
Collaborator

mathiasverraes commented Dec 19, 2020

In math, a ternary operation has the type a -> a -> a -> a, so everything is the same type.
In C-like PLs, the common pattern is bool -> a -> a -> a but I see no reason why we should only support conditional ternaries.

https://en.wikipedia.org/wiki/Ternary_operation

@mathiasverraes
Copy link
Collaborator

#21 is an experiment to gain some insights into how ternary expressions could work.

@rezen
Copy link
Author

rezen commented Dec 21, 2020

In my case I didn't want to make a distinction between booleanExpr vs expression. I tried creating a custom ExpressionType and so far it seems to work the way I would expect it.

class Ternary implements ExpressionType {

    public function buildPrecedenceLevel(Parser $previousPrecedenceLevel): Parser
    {
       
        $question = keepFirst(char("?"), skipHSpace());
        $colon = keepFirst(char(":"), skipHSpace());
        return choice(
            map(
                collect(
                    $previousPrecedenceLevel->thenIgnore($question),
                    $previousPrecedenceLevel->thenIgnore($colon),
                    $previousPrecedenceLevel,
                ),
                function(array $v) {
                    $tern = new _Ternary;
                    $tern->test = $v[0];
                    $tern->whenTrue = $v[1];
                    $tern->whenFalse = $v[2];
                    return $tern;
                }
            ), 
            $previousPrecedenceLevel
        );
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants