Mix between ternary and bitwise?

  • mindfullsilence
  • Professor
  • Professor
  • User avatar
  • Posts: 854

Post 3+ Months Ago

I feel like there should be a shortcut for something like this:

PHP Code: [ Select ]
$a = ("check if $b exists") ? "return $b" : "return $c";
 
  1. $a = ("check if $b exists") ? "return $b" : "return $c";
  2.  


Bitwise "OR" operators only return true or false:
PHP Code: [ Select ]
$a = $b | $c;
 
'aka'
if( isset($b) ) {
  return true;
}
elseif( isset($c) ) {
  return true;
}
else {
  return false;
}
 
 
  1. $a = $b | $c;
  2.  
  3. 'aka'
  4. if( isset($b) ) {
  5.   return true;
  6. }
  7. elseif( isset($c) ) {
  8.   return true;
  9. }
  10. else {
  11.   return false;
  12. }
  13.  
  14.  


Ternary operators seem rather long for something so simple:
PHP Code: [ Select ]
$a = ( isset($b) ) ? $b : $c;
 
'aka'
if( isset($b) ) {
  return $b;
}
else {
  return false;
}
 
  1. $a = ( isset($b) ) ? $b : $c;
  2.  
  3. 'aka'
  4. if( isset($b) ) {
  5.   return $b;
  6. }
  7. else {
  8.   return false;
  9. }
  10.  


Is there any way to get a bitwise OR operator-like syntax that returns the references themselves rather than a true or false?
PHP Code: [ Select ]
$a = $b | $c;
 
'aka'
if( isset($b) ) {
  return $b;
}
elseif( isset($c) ) {
  return $c;
}
else {
  return false;
}
 
  1. $a = $b | $c;
  2.  
  3. 'aka'
  4. if( isset($b) ) {
  5.   return $b;
  6. }
  7. elseif( isset($c) ) {
  8.   return $c;
  9. }
  10. else {
  11.   return false;
  12. }
  13.  


Just wondering
  • Anonymous
  • Bot
  • No Avatar
  • Posts: ?
  • Loc: Ozzuland
  • Status: Online

Post 3+ Months Ago

  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13503
  • Loc: Florida

Post 3+ Months Ago

Logical operators return true or false. Bitwise operators work a little differently.

Code: [ Select ]
<pre><?php

$a[0] = 7;
$a[1] = 3;
$a[2] = $a[0] | $a[1];

var_dump($a);

?></pre>
  1. <pre><?php
  2. $a[0] = 7;
  3. $a[1] = 3;
  4. $a[2] = $a[0] | $a[1];
  5. var_dump($a);
  6. ?></pre>


Code: [ Select ]
array(3) {
 [0]=> int(7)
 [1]=> int(13)
 [2]=> int(15)
}
  1. array(3) {
  2.  [0]=> int(7)
  3.  [1]=> int(13)
  4.  [2]=> int(15)
  5. }


Can you tell me why that third element returns 15, instead of 7, 13, true, or false?
  • mindfullsilence
  • Professor
  • Professor
  • User avatar
  • Posts: 854

Post 3+ Months Ago

My mistake, I suppose I was talking about logical operators. As far as manipulating bits...way over my head at this point - but still wondering if there is a way to return one var or the other, in which if the first is set, then it is returned, otherwise return the other.
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13503
  • Loc: Florida

Post 3+ Months Ago

You could use a helper function, that wraps what usually becomes a complicated ternary statement.

Code: [ Select ]
function dfi($default, $for, &$in)
{
  return empty($in[$for]) ? $default : $in[$for];
}

$a = 6;
$b = 7;
$c = dfi($b, 'a', $GLOBALS);
var_dump($c);

$d = dfi('default value', 'q', $_GET);
var_dump($d);
  1. function dfi($default, $for, &$in)
  2. {
  3.   return empty($in[$for]) ? $default : $in[$for];
  4. }
  5. $a = 6;
  6. $b = 7;
  7. $c = dfi($b, 'a', $GLOBALS);
  8. var_dump($c);
  9. $d = dfi('default value', 'q', $_GET);
  10. var_dump($d);
  • ScottG
  • Proficient
  • Proficient
  • ScottG
  • Posts: 477

Post 3+ Months Ago

why not something like
PHP Code: [ Select ]
$a = (isset($b)) ? 'B is set' : ((isset($c)) ? 'C is set' : 'Not Found');
 
  1. $a = (isset($b)) ? 'B is set' : ((isset($c)) ? 'C is set' : 'Not Found');
  2.  
  • Rabid Dog
  • Web Master
  • Web Master
  • User avatar
  • Posts: 3245
  • Loc: South Africa

Post 3+ Months Ago

The problem is that your responsibilities are being mixed

Consider the ternary operator

Code: [ Select ]
outcome = condition ? if true : if false;


The sole responsibility of this is to perform the if else. Nesting these is a bit of a no no as it becomes difficult to read. If your intent is to evaluate if something is isset then use the method provided

Code: [ Select ]
$output = isset($a) ? operation1($a) : operation2($a)


Joe suggested a helper function that will do the isset check and assign values as needed.

My default answer is to actually check for "null" before performing the operation and decided if it is an exceptional state or I can gracefully recover

Code: [ Select ]
//Precondition check
function myFunction($a){
if(!isset($a)){
 throw new Exception("Could not fulfill your request")

//continue operations here
return outcome
}
//graceful
myFunction($a){
 //This could potential be wrapped in a function
 $fixedA = isset($a) ? $a : "My Default Value";

 //continue operations here
 return outcome
}
  1. //Precondition check
  2. function myFunction($a){
  3. if(!isset($a)){
  4.  throw new Exception("Could not fulfill your request")
  5. //continue operations here
  6. return outcome
  7. }
  8. //graceful
  9. myFunction($a){
  10.  //This could potential be wrapped in a function
  11.  $fixedA = isset($a) ? $a : "My Default Value";
  12.  //continue operations here
  13.  return outcome
  14. }


All in all, just remember to keep your code readable and minimize duplication. If you write the isset query more than twice wrap it in a function as defined by Joe. Also try and keep your functions returning the same types. Returning a bool when you expecting a string makes code less readable. I don't know what your function does but looking at the example

Code: [ Select ]
$a = $b | $c;


$a could turn out to be a number of things and types which means you will have to do a stack of checks and parsing to make sure the type it returns is what you are looking for on the other end. I would be interested to know the use case that this arouse in as I have never needed something like this.

C# has a nasty thing called an "out" assignment, which would do exactly what you are trying to achieve
Code: [ Select ]
public bool TryParse(out DateTime value, String input){
 // try parse and return boolean indicating the success of the attempt
 // if the parsing was successful assign the outcome to the 'value' veriable
}

//usage would be something like
DateTime parsedDate = null;
var inputDate = "2013/01/01"

if(TryParse(out parsedDate, inputDate){
 //parsedDate is now of type DateTime and represents the date 1st Jan 2013
}else{
 parsedDate = DateTime.Now;
}
  1. public bool TryParse(out DateTime value, String input){
  2.  // try parse and return boolean indicating the success of the attempt
  3.  // if the parsing was successful assign the outcome to the 'value' veriable
  4. }
  5. //usage would be something like
  6. DateTime parsedDate = null;
  7. var inputDate = "2013/01/01"
  8. if(TryParse(out parsedDate, inputDate){
  9.  //parsedDate is now of type DateTime and represents the date 1st Jan 2013
  10. }else{
  11.  parsedDate = DateTime.Now;
  12. }


That is really nasty. Again, try and encapsulate this and always return the same types :)

My 2c
  • mindfullsilence
  • Professor
  • Professor
  • User avatar
  • Posts: 854

Post 3+ Months Ago

Example:

JAVASCRIPT Code: [ Select ]
var a = ['give', 'receive', 'give', null, undefined],
  b = 'give',
  i = 0,
  keyword;
 
for(i; i < a.length; i++) {
  keyword = a[i] | b; // returns one if exists, otherwise returns the other.
  someFunc(keyword);
}
 
  1. var a = ['give', 'receive', 'give', null, undefined],
  2.   b = 'give',
  3.   i = 0,
  4.   keyword;
  5.  
  6. for(i; i < a.length; i++) {
  7.   keyword = a[i] | b; // returns one if exists, otherwise returns the other.
  8.   someFunc(keyword);
  9. }
  10.  


Herein we set a default of "give" as a string if the index in the array "a" evaluates to false. Wasn't implying that any type could be passed into the evaluator, that would be messy and poorly written. Rather, the intent was to explore my own simple curiosity as to whether or not this sort of operation existed. I do like joeberts helper function, and have in fact used it since this this thread was started. Works like a charm :)
  • Bogey
  • Genius
  • Genius
  • Bogey
  • Posts: 8397
  • Loc: USA

Post 3+ Months Ago

Sorry, but I just noticed something on the web... seems to me perl has something like this?

PERL Code: [ Select ]
$ip = $req->header('Client-IP') || $req->header('Remote-Addr');


Straight copy/paste from here.

This is the first time I see source code of perl... never knew it looked so close to PHP (or PHP looked so close to it since perl came first... I think).
  • spork
  • Brewmaster
  • Silver Member
  • User avatar
  • Posts: 6252
  • Loc: Seattle, WA

Post 3+ Months Ago

That's still making use of logical operators. Essentially that code boils down to this:

Code: [ Select ]
lvalue = (expr1) or (expr2)


expr1 will be evaluated, and if it evaluates to true (i.e. returns a valid IP address) then that value is assigned to lvalue. If it returns false, then expr2 is evaluated and its value is assigned to lvalue.

This is really just basic logic; the expression (A||B) will evaluate to true as long as A or B are true, and to false iff both A and B are false.

Both Perl and PHP (to my knowledge) support logical "short circuiting", which essentially prevents any other expressions in an "or" chain from evaluating after one of them evaluates as true, meaning that in your original example:

PERL Code: [ Select ]
$ip = $req->header('Client-IP') || $req->header('Remote-Addr');


$req->header('Remote-Addr') won't even be called unless $req->header('Client-IP') evaluates to false, indicating an error. Which is the entire point. :)
  • spork
  • Brewmaster
  • Silver Member
  • User avatar
  • Posts: 6252
  • Loc: Seattle, WA

Post 3+ Months Ago

And yes, Perl had an (unfortunately) major influence on PHP, at least syntactically.

Post Information

  • Total Posts in this topic: 10 posts
  • Users browsing this forum: No registered users and 169 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.