Forum Moderators: coopster

Message Too Old, No Replies

Can you use a function in a ternary shorthand?

         

csdude55

5:29 pm on Apr 1, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I know that a ternary shorthand returns a copy of the object instead of the object itself, so there's a potential of a memory leak. But benchmark tests find it to return faster than an if/else, so I cautiously use it where possible.

I have an if/else where the else has a foreach() loop in it, so I was trying to test it as a ternary. I thought that this would work:

// this is the original; it's shortened for this post, so please ignore any typos or logic flaws
if (is_numeric($g)) $this_g = $g;

else {
// default if nothing in the loop matches
$this_g = 1;

for ($g = 0; $g < 10; $g++)
if ($foo === $bar[$g])
$this_g = $g;
}

// ternary version that I thought would work, but doesn't
$this_g = is_numeric($g) ? $g : function() {
for ($g = 0; $g < 10; $g++)
if ($foo === $bar[$g])
return $g;

// default if return hasn't been sent
return 1;
};

but it throws a fatal error:

Catchable fatal error: Object of class Closure could not be converted to string

This is in a variables script that runs once on every page of my site, so I do care about speed but the microseconds gained from a ternary aren't exactly critical. This is really more for my education than anything else.

Is there a "proper" way to use a function as the return? Or is that just not going to work here?

csdude55

11:00 pm on Apr 1, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Well, guys and gals, I answered my own question... it's WAY more complicated than I imagined!

Step 1: I have to use "use" to define the variables within the function, which I think is sort of the same as using "global":

function() use ($foo, $bar) { ... }

Step 2: the "true" condition also needs to be a function:

? function() use ($g) { return $g; } :

Step 3: I have to call the whole thing as a function and set the return value to the variable:

$this_g = $this_g();

So the end result:

// in a weak attempt to limit confusion, I changed the name here from $this_g to $func
$func = is_numeric($g) ? function() use ($g) { return $g; } : function() use ($foo, $bar) {
for ($g = 0; $g < 10; $g++)
if ($foo === $bar[$g])
return $g;

// default if return hasn't been sent
return 1;
};

$this_g = $func();

While this finally works now, it's actually much slower than using an if/else condition:

ternary: 0.009315013885498
if/else: 0.0012538433074951

It's also harder to read and maintain, so I can't think of any practical reason to use this. But now I know!