It's hard to ask search this question and the answer would help clean up my code a bit. Basically, in PHP, if I use:
if (this = that)
what is going on? Is it checking that the variable got assigned correctly or is it checking the truth of "that" and as an aside also assigning it to "this?"
I ask because it would be easier if the answer were the former due to it taking an extra line to assign it, then run the conditional, and then use the return of it later. I know it's miniscule to be harping over one line, but over an entire script it can add up. Thanks for any help.
TO CLARIFY: I want to essentially write the equivalent of the following:
$this = something;
if ($this)
do things with $this
by writing it as
if ($this = $myFunctionCall)
do things with $this;
all assuming that $this isn't set beforehand.
It's assigning, and then it's checking the "trueness" of the value that was assigned.
its checking the "truthiness" of this iirc, the assignment occurs before evaluation
Linus,
Regardless of if it works, I'm not a fan of the assignment-within-test approach. I think it's too-easy to overlook the ASSIGNMENT, which is a potential (and easily avoidable) source of future bugs... I think this commonly used coding paradigm is "a bit sloppy".
In almost all "modern" languages you can create and assign a local variable in one step... which I find succinct, self explanatory, and emminently readable.
var stuff = getStuff();
if (stuff == null) {
Message("Sorry, no stuff found.");
return;
}
verses
var thing, widget, stuff, foo;
.... then many lines later ...
if ((stuff=getStuff())) {
// do things with stuff
} else {
// no stuff
Message("Sorry, no stuff found.");
}
As you can tell, I'm also anything but a fan of the old "structured programming" adage that there should be one exit-point per function/method/script. Instead, I believe that whenever we strike a situtation that means we can't continue here, we should leave, by the most direct route possible. This is JUST a personal preference. You can make valid arguements for any approach.
One word of advise: Whatever you do, do it CONSISTENTLY! The programmer who (a few years down the track, when you've moved on) is charged with enhancing your code will catch-on quick enough to "your style". They may not like it, but that's really not important, so long as they UNDERSTAND it. There's always a trade-off between succinctness and explicitness... there is no "correct" style... just some styles seem to WORK better than others, in the long run.
KISS it my son, and booger to brevity.
Cheers. Keith.
It will first set $this to $that, and then if $this == true, the contents of the if statement will be executed.
You would be assigning the value of that to this and checking if this then evaluates to true.
Yes, it first assigns and then checks if it's true.
Like when traversing MySQL tables:
while ($row = mysql_get_row($query)) {
...
}
When it doesn't work anymore (a false pops up), the loop breaks. It assigns and checks validity, all in one line.
I want to say that it assigns as well as check the value, purely based on this code
while($row = mysql_fetch_assoc($query))
{
// Query actions
}
Which we all know loops until there are no more results to process. mysql_fetch_assoc returns false when no results remain, but the value is still assigned, hence, it doesn't check that the value was assigned, but the value that was assigned.
An assignment operation ($foo = 'bar') is an expression in which a value is assigned to a variable. The expression as a whole returns a value. The returned value is the value that was assigned.
So, if ($foo = 'bar') is synonymous to:
$foo = 'bar';
if ('bar') ...
Some demo code
$false = false;
$true = true;
$someVar = true;
function someFunk() {
return false;
}
if ($someVar = $false) {
echo "True \n";
} else {
echo "False \n";
}
if ($someVar = $true) {
echo "True \n";
} else {
echo "False \n";
}
if ($someVar = someFunk()) {
echo "True \n";
} else {
echo "False \n";
}
This outputs
False
True
False
http://codepad.org/8JxX8MYP
if (this = that)
step 1->
this=that; //copy data from that to this
step 2->
If copy succeed then the code became like this
if (1) //true
If copy failed then the code became like this
if (0) //false
Related
I am taking over the maintenance of an old web site and came across this confusing syntax for processing a form that I have never seen before, and I am not exactly certain what it does:
foreach (array('address','comments','country','email','mail_content','name','title') as $vuln)
{
isset($_REQUEST[$vuln]) and $_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
isset($_GET[$vuln]) and $_GET[$vuln] = htmlentities($_GET[$vuln]);
isset($_POST[$vuln]) and $_POST[$vuln] = htmlentities($_POST[$vuln]);
isset($$vuln) and $$vuln = htmlentities($$vuln);
}
It's the "and" that is throwing me - I read it as "if variable is set convert it to htmlentities, but why is there an "and" in there?
Finally what does the last line do?
isset($$vuln) and $$vuln = htmlentities($$vuln);
It's using the operator precedence rules of PHP in an unusual way.
If you have an and statement, PHP will stop processing it if the left side is false - there's no need to check the right hand side, because it won't make a difference to the end result. (The converse is also true for an or statement if the left hand side is true.)
So the coder that wrote this is using it as a shorthand for:
if (isset($_REQUEST[$vuln])) {
$_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
}
They've save a small amount of typing, at the cost of making the code slightly harder to read. It's good practice to use isset to make sure that your array values are set before you use them, which is why the check is there.
As to the last line; logically, it's doing the same as the above, but with a variable variable. The first time through, $vuln will be set to the first item in your array, which is address - the final line of code is checking to see if there's a variable called $address, and if so, set its value to htmlentities($address).
That's what the code is doing. Why it's checking REQUEST, GET, and POST is beyond me.
Hi These are the nothing but the shortend form.
isset($_REQUEST[$vuln]) and $_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
above line means
if(isset($_REQUEST[$vuln])){
$_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
}
Also the $$vuln is a reference variable its checking the same that if reference variable is set then assign it value
isset($var) and <statement goes here that uses $var>;
This basically only executes the <statement ...> if the statement preceding and (in this case isset($var)) evaluates to true. This happens because if anything is false before a and, there's no need to evaluate (or execute) the rest. This works similarly to:
if (false && condition) { ... }
The condition will never be evaluated, since no matter what its value evaluates to, the if condition will always evaluate to false.
A more readable alternative for the first example:
if (isset($var)) {
<statement goes here that uses $var>;
}
As pointed out in the comments by #chris85, see $$variable.
An example of a variable variable:
$vuln = 'abc'; /* Regular variable assignment */
$$vuln = 'def'; /* This is "equivalent" to $abc = 'def'
* because $$vuln expands to $<contents of $vuln>,
* therefore $abc is assigned with 'def'.
*/
/* $abc is now a variable with 'def' as its value */
It might be easier to comprehend as the following, for the first iteration through the array:
<?php
if(isset($_REQUEST['address'])) {
$_REQUEST['address'] = htmlentities($_REQUEST['address']);
}
if(isset($_GET['address'])) {
$_GET['address'] = htmlentities($_GET['address']);
}
if(isset($_POST['address'])) {
$_POST['address'] = htmlentities($_POST['address']);
}
if(isset($address)) {
$address = htmlentities($address);
}
It looks to me like legacy code that probably was a replacement for (or perhaps in addition to) 'magic quoting' when 'register globals' was turned on. Probably so they could do some pseudo escaping of variables before database inserts and or page echos.
I'm sorry the title of this question is odd. I couldn't find a good way to word it!
The idea is simple, sometimes you see PHP tests this way:
if (!a_function("something")) { }
Here you can think of it as "if not true". I sometimes see the exact same thing but with extra parenz:
if (!(a_function("something"))) { }
Why does it require the extra parenz after the bang? Don't they both essentially mean if (!true)?
For extra bonus, what are the reasons for the two styles (does this have a name?) and maybe give examples of how they would give alternate results if not used correctly.
update:
Here is an example in a PHP script I'm using, the author is testing environment variables and seems to use the styles interchangeably:
if (!(extension_loaded("iconv"))) { ... }
if (!(extension_loaded("xml"))) { ... }
if (!function_exists("json_encode")) { ... }
if (!ini_get("short_open_tag")) { ... }
I know you can't answer for the programmer here, but why would they be alternating the use of extra parenz when these small functions are right next to each other?
I happen to know that, for example, the return value of ini_get is just the number 1, and the return value of the extension_loaded functions may also just be the number 1, so it seems like there would be no difference. I'm not 100% sure there isn't some other trick to this than simple preference or order of operation.
update 2:
I understand parenz can be used for either clarity, or order of operations, but I'm not convinced it is only personal preference beyond that.
In my example above, everything depends on what is returned by the functions that are being tested.
It's my understanding that by wrapping a statement in parenz, PHP will force it into a bool. But when it's not in parenz, could there be a return value that breaks the code without using the parenz around it to force a bool?
If people say, in my example code above, that there is nothing but personal preference going on, then I'll just have to accept that, but I have my doubts.
the parenthesizes are used in case if there are more than 1 logical operator with different precedence, to indicate that "!" operator must be applied after all other operators have been processed. For example:
if(!($var1 < $var2))
First will be checked if $var1 is less than $var2, and after that will be checked if the result is false.
If use that:
if(!$var1 < $var2)
then firstly will be checked if $var1 is false and the result will be compared to $var2, that simply do not make sense.
It's not required. It's a matter of personal preference. Sometimes you like to have extra parens to be EXTRA certain of how the expression will be evaluated.
if(a or b and c)
is confusing.
if ((a or b) and c)
is much more clear.
if(a or (b and c))
is much more clear.
They both work, but some people might have different opinions on which one is more readable.
Parenthesis are not required in the given case, but they can be if, for example, you also assign a variable at the same time :
if (($myVar = myFunc()) !== false) {
// Doing something with $myVar, ONLY if $var is not false
}
While, in the following case, it will change the logic
if ($myVar = myFunc() !== false) {
// Here $myVar = true or false instead of the wanted value
}
if( !(should_return_trueA() && should_return_trueB())) {
// at least one have returned false
}
esentially is the same as:
if( !should_return_trueA() || !should_return_trueB() ) {
// at least one have returned false
}
It's, in my case, a practice to avoid mistaken/ommited exclamation marks. Useful, when building more complex conditions and looking for all-false or all-true result.
I was refactoring some old code when I stumbled upon a construct similar to this:
// function bar() returns a value
// if the value is an instance of customException class, terminate with error code
// else process the regular data
$foo = bar();
checkForException($foo) && exit($foo->errorCode());
process($foo);
Now strange as it might seem, this is a lot shorter then
$foo=bar();
if(checkForException($foo)) {
exit($foo->errorCode();
}
else {
process($foo);
}
And somewhat more readable (at least after the initial surprise) then
$foo=bar();
(checkForException($foo)) ? exit($foo->errorCode()) : process($foo);
While shorter code doesn't necessarily mean more readable code, I find this to be somewhere in the middle of the two "standard" ways above.
In other words, instead of
if($foo) {
bar();
}
else {
// there is no real reason for this to exist, since
// I have nothing to write here, but I want to conform
// to the general coding practices and my coding OCD
}
One could simply write
$foo && bar();
So what is the reasoning behind this not seeing much use? Can it be as simple as "Don't reinvent the wheel, write the more readable if/else, and if you really want to shorten it, that's what ternary operator is for"?
EDIT: Please keep in mind that the above code was quickly derived from the original code and was mean to be just an example of the use of "short circuit" code. If you can, please restrain from suggesting code improvements, since that was not the desired outcome of the question.
Example No.2
userCheckedTheBox($user) && displayAppropriateInfo();
While $foo && bar(); is fewer lines of code it's much less readable. Making your code easy to understand is usually more important than reducing the total LoC. Even if it's you're not working in an environment with multiple programmers, you will have to come back and read your code at some point in the future, and you probably won't be able to remember what the rationale was behind every line of code (Eagleson's Law).
Generally, you should limit the use of these kinds of statements to only those cases where the programmer's intent is absolutely clear. In my opinion, it's very bad practice to have code which tests a condition and code which actively modifies the current state of the program on the same statement.
Here's one acceptable use for this kind of code:
$isValidUser = $userName && usernameIsValid();
Here, both sides of the && operator are testing a condition, the fact that the right side is calling a function to do that does not harm the readability of the code.
There's an old technique which I believe was popular in hacked-together perl scripts to show errors. pseudo-code:
myFunction( ) || exitWithError( "Uh-oh" )
When coding-to-a-deadline, and when the user interface doesn't need to be stellar, it's a quick way to avoid errors.
The style is also popular in javascript for default parameters:
function myfunction(foo) {
foo = foo || 0;
// note that a non-zero default won't work so well,
// because the user could call the function with 0
}
and for null-checks:
var bar = foo && foo.property;
I find that once you're used to it, it's very readable and often more intuitive than if/else or ?:. But you should only use it when it makes sense. Using it everywhere is going to get very confusing. For example, in your example, you should not use it. Personally I use it for simple error checking and some default values. In big projects, you almost always want to do a lot more when an error occurs, so in those cases you shouldn't use this.
Also you should be careful; this only works in languages which have short-circuit evaluation (http://en.wikipedia.org/wiki/Short-circuit_evaluation). And sometimes and and or are short-circuit, while && and || are not.
myfunction() or die("I'm melting!"); is also quite satisfying to write.
Finally, empty else blocks as a rule is something I've never seen before, or heard anyone recommend. It seems very pointless to me. The most readable option for your example is, quite simply:
if( $foo ) {
bar( );
}
For errors you should use real exceptions:
try {
$foo = bar();
} catch(FooException $e) {
exit($e->errorCode);
}
process($foo);
See the documentation for errorhandling.
What ever that code is doing, returning an instance of CustomException just doesn't add up. Why not change the function definition a little:
function bar()
{
$stuff = true;
if ($stuff === true)
{
return 'Value on success';
}
//something went wrong:
throw new CustomException('You messed up');
}
try
{//here's the outlandish try-catch block
$foo = bar();
}
catch (CustomException $e)
{
exit($e->message());//fugly exit call, work on this, too
}
//carry on here, no exception was thrown
Also, calling that second function (checkForException($foo)) is just absurd. Function calls are cheap, but not free. You want to know if the function returned an instance of CustomException? Don't turn that into a function, but use instanceof. Using short-circuit to keep the number of chars (ad thus parse-time) down, while at the same time wasting resources on on all other levels is about as silly as turning up in a V8 mustang on a hyper-miling course.
Another possible Solution for your problem:
$foo = bar();
!checkForException($foo) or exit($foo->errorCode);
process($foo);
But better change !checkForException for isNoException or something along those lines.
I have seen programming practices where a string or a boolean can be returned from a function. In such cases, is it recommended to check for empty() and isset() in the if loops, or will just doing a check like if($returnvar) will work or not.
Here's a piece of code I am playing around with. What do you think should be the output and are the checks correct in the if condition?
Thanks,
<?php
function testMe()
{
try
{
$returnText = 'John King Rocks';
return $returnText;
}
catch (Exception $e)
{
return false;
}
}
$str = testMe();
if ($str)
{
echo $str;
}
?>
This code should work (for this specific example of $str), but checking for Boolean in PHP is risky, as you suggested, and should be done with caution, I would suggest (in general) to check it as follows:
if ($str !== false)
{
echo $str;
}
What will happen is $str will be type casted to a boolean. So, the string will evaluate to false when it is:
The empty string
The string "0"
Every other value is considered true, which may not be the behavior you desire. So, to answer your questions:
What do you think should be the output?
Well, the return string doesn't match either of the two conditions, so the if statement will evaluate to true and the $str will be echo()'d. (Not to mention that the above code can never produce an Exception).
Are the checks correct in the if?
That depends on the functionality you're looking for. If you want to consider all strings (including "" and "0") to be valid, and to skip the echo() only when the function returns false, then you should check if the return value's equality with !== false. Otherwise, if those two conditions above are acceptable as false, you should be fine.
if is not a loop. It's a conditional. echo false will be coerced to echo '0', so the if check is only necessary if you don't want to print a zero. However, echo null will not print anything at all. Even better would be to return empty string. You should avoid mixing return types. Many other languages don't even allow it.
By the way your exception handling does nothing .. the contents of the try cannot throw an exception. Swallowing exceptions is also bad, and you need a $ before the e.
In answer to your question, there is a phrase "paranoid programming is professional programming." That is, you should do as many checks as possible if you want your application to work consistently (and the if check is good in this case), but it's also important to know what methods you are working with and the expected result. Do you want some other handling if testMe is false? Or do you want to just not print anything?
I feel dirty every time I "break" out of a for-each construct (PHP/Javascript)
So something like this:
// Javascript example
for (object in objectList)
{
if (object.test == true)
{
//do some process on object
break;
}
}
For large objectLists I would go through the hassle building a more elegant solution. But for small lists there is no noticeable performance issue and hence "why not?" It's quick and more importantly easy to understand and follow.
But it just "feels wrong". Kind of like a goto statement.
How do you handle this kind of situation?
I use a break. It's a perfectly cromulent solution.
It's quick and more importantly easy to understand and follow.
Don't feel bad about break. Goto is frowned upon because it's quick and more importantly not easy to understand and follow.
See, the break doesn't bug me at all. Programming is built on goto, and for-break - like all control structures - is merely a special-purpose form of goto meant to improve the readability of your code. Don't ever feel bad about writing readable code!
Now, I do feel dirty about direct comparisons to true, especially when using the type-converting equality operator... Oh yeah. What you've written - if (object.test == true) - is equivalent to writing if (object.test), but requires more thought. If you really want that comparison to only succeed if object.test is both a boolean value and true, then you'd use the strict equality operator (===)... Otherwise, skip it.
For small lists, there's no issue with doing this.
As you mention, you may want to think about a more 'elegant' solution for large lists (especially lists with unknown sizes).
Sometimes it feels wrong, but it's all right. You'll learn to love break in time.
Like you said ""why not?" It's quick and more importantly easy to understand and follow."
Why feel dirty, I see nothing wrong with this.
I think is is easier to read and hence easier to maintain.
It is meant to be like it. Break is designed to jump out of a loop. If you have found what you need in a loop why keep the loop going?
Breaks and continues are not gotos. They are there for a reason. As soon as you're done with a loop structure, get out of the loop.
Now, what I would avoid is very, very deep nesting (a.k.a. the arrowhead design anti-pattern).
if (someCondition)
{
for (thing in collection)
{
if (someOtherCondition)
{
break;
}
}
}
If you are going to do a break, then make sure that you've structure your code so that it's only ever one level deep. Use function calls to keep the iteration as shallow as possible.
if (someCondition)
{
loopThroughCollection(collection);
}
function loopThroughCollection(collection)
{
for (thing in collection)
{
if (someOtherCondition)
{
doSomethingToObject(thing);
break;
}
}
}
function doSomethingToObject(thing)
{
// etc.
}
I really don't see anythign wrong with breaking out of a for loop. Unless you have some sort of hash table, dictionary where you have some sort of key to obtain a value there really is no other way.
I'd use a break statement.
In general there is nothing wrong with the break statement. However your code can become a problem if blocks like these appear in different places of your code base. In this case the break statements are code small for duplicated code.
You can easily extract the search into a reusable function:
function findFirst(objectList, test)
{
for (var key in objectList) {
var value = objectList[key];
if (test(value)) return value;
}
return null;
}
var first = findFirst(objectList, function(object) {
return object.test == true;
}
if (first) {
//do some process on object
}
If you always process the found element in some way you can simplify your code further:
function processFirstMatch(objectList, test, processor) {
var first = findFirst(objectList, test);
if (first) processor(first);
}
processFirst(
objectList,
function(object) {
return object.test == true;
},
function(object) {
//do some process on object
}
}
So you can use the power of the functional features in JavaScript to make your original code much more expressive. As a side effect this will push the break statement out of your regular code base into a helper function.
Perhaps I'm misunderstanding your use-case, but why break at all? I'm assuming you're expecting the test to be true for at most one element in the list?
If there's no performance issue and you want to clean up the code you could always skip the test and the break.
for (object in objectList)
{
//do some process on object
}
That way if you do need to do the process on more than one element your code won't break (pun intended).
Use a
Object object;
int index = 0;
do
{
object = objectList[index];
index++;
}
while (object.test == false)
if breaking from a for loop makes you feel uneasy.
My preference is to simply use a break. It's quick and typically doesn't complicate things.
If you use a for, while, or do while loop, you can use a variable to determine whether or not to continue:
for ($i = 0, $c = true; ($i < 10) && $c; $i++) {
// do stuff
if ($condition) {
$c= false;
}
}
The only way to break from a foreach loop is to break or return.