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 shorthand #134

Closed
lmcd opened this issue Sep 24, 2010 · 14 comments
Closed

Ternary operator shorthand #134

lmcd opened this issue Sep 24, 2010 · 14 comments

Comments

@lmcd
Copy link

lmcd commented Sep 24, 2010

I tend to find myself doing a lot of things like this:
{{ foo ? 'yes' : '' }}

This happens quite often when defining CSS class names. Would it be possible to shorten the code in these instances to:
{{ foo ? 'yes' }}

@markstory
Copy link
Contributor

I don't know if overloading the ? like that is a good idea. This could easily be confused with PHP 5.3's shortcut ternary ?:, or a broken ternary. Perhaps something like {{ condition ?= 'output' }} could work.

@lmcd
Copy link
Author

lmcd commented Sep 28, 2010

I can't really see how it would cause confusion. I've always read the ternary operator as:
{{ if ? then : else }}
The proposed change just optionally drops the else. So:
{{ if ? then }}

Either way, the '?=' syntax isn't bad either and is still cleaner than the current method.

@elliot
Copy link

elliot commented Nov 8, 2010

Would you be looking for the default filter?

eg:
{{ foo | default('yes') }}

@fabpot
Copy link
Contributor

fabpot commented Nov 26, 2010

Like eliot said, the default filter is probably the best answer.

@Seldaek
Copy link
Contributor

Seldaek commented Nov 28, 2010

Nah this has nothing to do with the default filter. {{ foo|default('yes') }} is equivalent to {{ foo ? foo : 'yes'}} or shorthand {{ foo ?: 'yes' }}. What was proposed by lmcd is to be able to drop the "false" case, i.e. {{ foo ? 'yes' : '' }} or shorthand {{ foo ? 'yes' }}.

I think this would be a good change for brevity's sake (which adds readability in cluttered templates), even supporting the {{ foo ?: 'bar' }} wouldn't be bad imo.

@vladcosorg
Copy link

So was it implemented?
I find myself constantly dropping the 'else' part, wouldn't it be easier to make implement suggested syntax?

@lmcd
Copy link
Author

lmcd commented Oct 25, 2012

Still wouldn't mind seeing this implemented either. As @sedaek said, would be a step towards making complicated templates more readable.

@char101
Copy link
Contributor

char101 commented Oct 26, 2012

I think this is more in line with current twig syntax

{{ 'yes' if foo }}

with else

{{ 'yes' if foo else 'no' }}

@fabpot
Copy link
Contributor

fabpot commented Oct 26, 2012

@char101 I kinda like this proposal as it reminds me of my good old Perl days ;)

@char101
Copy link
Contributor

char101 commented Oct 26, 2012

@fabpot It's also the syntax used by python. Since twig seems to take inspiration from Jinja, I think it's only natural to add the if expression syntax from python.

@fabpot
Copy link
Contributor

fabpot commented Oct 26, 2012

Anyone willing to see if the implementation would be easy or hard? I suspect that it won't be that easy.

@mrxotey
Copy link

mrxotey commented Oct 26, 2012

There is implementation of "if()" filter in Twig-Extensions: twigphp/Twig-extensions#43

I use this filter in my projects.

@char101
Copy link
Contributor

char101 commented Oct 26, 2012

This is an example implementation

protected function parseConditionalExpression($expr)
{
    $ternary = false;
    while ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '?')) {
        $this->parser->getStream()->next();
        $expr2 = $this->parseExpression();
        $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'The ternary operator must have a default value');
        $expr3 = $this->parseExpression();

        $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
        $ternary = true;
    }

    if (! $ternary) {
        while ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'if')) {
            $this->parser->getStream()->next();
            $condition_expr = $this->parseExpression();
            if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'else')) {
                $this->parser->getStream()->next();
                $else_expr = $this->parseExpression();
            } else {
                $else_expr = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine());
            }
            $expr = new Twig_Node_Expression_Conditional($condition_expr, $expr, $else_expr, $this->parser->getCurrentToken()->getLine());
        }
    }

    return $expr;
}

test case

<?php

require_once 'Twig/Autoloader.php';
Twig_Autoloader::register();

$loader = new Twig_Loader_String;
$twig = new Twig_Environment($loader);

echo $twig->render('{{ "Hello" if false else "World" }}');

@char101
Copy link
Contributor

char101 commented Oct 26, 2012

Some test cases

input : 'Hello' if true
output: Hello
input : 'Hello' if false else 'World'
output: World
input : 'Hello' if 1 + 1 > 0
output: Hello
input : 'Hello' if 0 else 'a' ~ 'b'
output: ab
input : 'Hello' if 1 if true
output: Hello
input : 'Hello' if 1 if false else 0
output:
input : 'Hello' if 1 if false else 0 else 'World'
output: World

@fabpot fabpot reopened this Nov 6, 2012
@fabpot fabpot closed this as completed in f85076b Nov 14, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

7 participants