1

Refactoring legacy code I have found various occurrences of the following construct:

((bool) ~~$field->req ? ' required' : '')

According to the manual the Tilde (~) in PHP is the bitwise not, which simple shifts all bits in a variable to their opposite.

If I shift all bits in a variable to their opposite and then shift it back, the variable should be exactly the same as it was before right? So why would somebody do this? Am I missing something?

Blackbam
  • 17,496
  • 26
  • 97
  • 150
  • 3
    Not sure this warrants a downvote. This might explain it, albeit for a different language: https://stackoverflow.com/questions/4055633/what-does-double-tilde-do-in-javascript – nickb Jun 26 '18 at 11:40
  • 1
    This does not deserve a downvote, I can't find an answer except for JavaScript too. Found [this link](https://j11y.io/cool-stuff/double-bitwise-not/) if it helps – AymDev Jun 26 '18 at 11:43
  • 2
    Bottom line: `(bool) 0.123` returns true, `(bool) ~~0.123` returns false. – Ivar Jun 26 '18 at 11:44
  • @Ivar Is right! And why is that? – Blackbam Jun 26 '18 at 11:48
  • For the same reason why that works in JavaScript. See the link in nickb's comment. – Ivar Jun 26 '18 at 11:49
  • Ok I think I understand from the JavaScript explanations. So the last thing I wonder about what the advantage in this boolean context is. It is already clear that the shifting makes a difference. – Blackbam Jun 26 '18 at 11:54
  • *"also called “double tilde”"* -- who is calling it this way? Post an official reference if there is one. – axiac Jun 26 '18 at 12:49
  • @axiac Wikipedia might not be an official reference but indicates that a semantic term is widely accepted: https://en.wikipedia.org/wiki/Double_tilde. `Double tilde may refer to: Double binary NOT operator` – Blackbam Jun 26 '18 at 13:28
  • 1
    Wikipedia says *"Used in languages like JavaScript and PHP as a quick way to cast variable as integer."* but at least about PHP it is completely wrong: https://3v4l.org/jpdfs – axiac Jun 26 '18 at 13:44
  • 1
    To me, the `~~` in the code you posted is a no-op (as you also said in the question). I guess the original coder mistaken `!` with `~` then added `(bool)` in front of it to get the desired outcome. – axiac Jun 26 '18 at 13:48

1 Answers1

1

It should be !! (it converts the value to a boolean) but it is not needed at all. I guess the original coder mistaken ~ for ! then they added (bool) in front of it to achieve the desired result (because, as you noticed in the question, ~~ is a no-op).

The ternary operator (?:) forces the evaluation of its first argument as boolean.

The boolean value of $field->req is the same as of !! $field->req and (bool) ~~$field->req (and (bool)$field->req btw).

I would remove the (bool) ~~ part completely to get smaller and cleaner code.

Edit by questioner: The only effect of ~~ in PHP is to cut of decimals from a float value.

See the following results:

$a = 2.123;
$b = -2.123;
$c = new stdClass();
$d = ["a",2,"c"];
$e = "lord";
$f = -3;
$g = false;
$h = null;
$j = -2.99;
$k = 2.99;


var_dump(~~$a);
var_dump(~~$b);
// var_dump(~~$c); // error
// var_dump(~~$d); // error
var_dump(~~$e);
var_dump(~~$f);
// var_dump(~~$g); // error
// var_dump(~~$h); // error
var_dump(~~$j);
var_dump(~~$k);

var_dump(!!$a);
var_dump(!!$b);
var_dump(!!$c);
var_dump(!!$d);
var_dump(!!$e);
var_dump(!!$f);
var_dump(!!$g);
var_dump(!!$h);
var_dump(!!$j);
var_dump(!!$k);

int(2) int(-2) string(4) "lord" int(-3) int(-2) int(2) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(false) bool(false) bool(true) bool(true)

Blackbam
  • 17,496
  • 26
  • 97
  • 150
axiac
  • 68,258
  • 9
  • 99
  • 134
  • @Blackbam you know that you can post the addition as a separate answer (and maybe get some votes for it ;-) ) – axiac Jun 26 '18 at 14:43
  • Sure but you brought up the keypoints therefore I think it should be your votes – Blackbam Jun 26 '18 at 15:36