Skip navigation.

halO

programming, hackery, rants, science and of course Opera

Posts tagged with "programming"

Operator tricks

, , , ...

Operators behave mostly the same in many different languages, but in some you can use some nice tricks to save some space. For instance, in ecmascript you can assign a variable value from a deep tree without the risk of the script aborting because the array value was undefined.

var foo = c && c[0] && c[0][1];

The code will assign foo the value of c[0][1] or unassigned. The equivalent of this code is

var foo;
if(c)
   if(c[0])
      if(c[0][1])
         foo = c[0][1];

Boolean operators are conditional if you use && or ||. Using the AND operator, the following statements will not be executed if the current is false. Using OR, the same is true if the current is true. Here is an example using conditional OR

var foo = (bar < 10) || 5; // assigns 5 or true

You can use conditional operators as a shorthand of if. The last evaluated statement is the returned value.

Assignation

The assignation operator, =, does in fact return a value and is not always true. The assignation operator returns the value that was assigned, so foo=10 returns 10. This is the basis of how this effective loop works:

for(var n=0,e;e=array[n];n++){}

As long as the array contains values that are not evaluated as false in a boolean context, such as 0, '', false and probably a few others, it works fine. The reason is that the loop continues as long as the middle statement is true, and the returned statement is array[n].

Recursion

, , , ...

I've heard from several sources, on the web that is, that you should stay away from recursion if you need someone else to maintain your code. The argument is that recursion is hard and some people just don't understand it. Well boo hoo. Start understand it or maintain some easier code. I mean, we covered recursions during the first year of uni! (I might be easier to deal with and agree to stay away from recursions if you're paying me lotsah' monies :wink:, but I'm happy where I am right now.)

Generate a thought map in your head. Divide problems into smaller ones and then conquer them. Let's have a look at scanning a tree. We want to see if a tree contains the number 42.

We know for certain we have to look at the root node if it contains the number 42. If it does, we return true and everyone is happy. If not, we should start looking at child nodes. For every child node, we should see if it contains the number 42. It it does, we return true and everyone is happy. If not, we should start looking at child nodes.

Hang on now! During my thought map above, I just repeated the exact same thought sequence. It is as if *gasp* it is a loop!

It is.

The function is just calling itself just as how it would call any other function. I think the word just scares people. Of course, recursions are more prone to infinite loops compared to calling other functions, but for loops are also more prone to infinity than copy&pasting a lot of code! You just have to know how to use the tool.

Here's the code to scan a tree where every node has an int value and an array children.

// scan a node and it's children
function scan(node){
   if(node.value==42){
      return true; // Everyone is happy
   } else {
      // Look at child nodes
      for(var i=0,child; child=node.children[ i]; i++){
         // scan a node and it's children
         if(scan(child))return true;
      }
   }
}

This should demonstrate it is not specifically hard writing recursions. I wrote the above code and it worked the first time I tested it [1]. There is no alterations in the above code after I tested it the first time. I did forget to add return false after the for construct, but looking at the mental spec above, there is no mention of returning false at any point ;-) And besides, undefined is evaluated as false in a boolean context.

// Testing code
alert( scan({value:30,children:[{value:35,children:[]},{value:412,children:[]}]}) ); // undefined
alert( scan({value:30,children:[{value:35,children:[]},{value:42,children:[]}]}) ); // true

[1] Not exactly true, I had to edit it later today. The My Opera editor thought I meant italic text where it now says child=node.children[ i]

Faster for-loops

, ,

I remember learning this from some document about user-javascripts found at opera.com, but haven't been able to relocate it. It's highly useful because it's so simple yet can save quite a bit processing power for large loops, so I figured I'd post it here.

The point is that most people, when writing a for-loop, will do like this:

for(var i=0;i<somearray.length;i++){
   // do something here
}

This is actually quite wasteful since the length of will be evaluated once for every item in the array. It can also cause bugs if one is not aware of this and adds or removes items from the array inside the loop.

A better way to do it is like this:

for(var i=0,end=somearray.length;i<end;i++){
   // do something here
}

Memorize it and do it like this as default. The times you actually need to reevaluate the array length every run, you'll remember it, so don't worry.

A (Re)-Introduction to Javascript

, , ,

I stumbled across a nice paper which summarizes nicely the capabilities of the core functions in java/ecma -script. If you're new, or anything other than an expert, it might provide a nice reference. Combined with Quirksmode.org for an introduction to the correct philosophy (object-detection etc.), the two should provide for a good learning curve for newbies.

Evaluating assignments

,

No, I'm not talking about boring papers handed in by students, but how PHP evaluates assignment of values in a boolean context. I've actually never tested the various values and what they evaluated to before now :whistle:

I won't beat around the Bush, although it's tempting, so here's the result of common assignments in PHP:

$target = null;
$result1 = ($target = 1);     // true
$result2 = ($target = null);  // false
$result3 = ($target = 0);     // false
$result4 = ($target = '');    // false
$result5 = ($target = 'Foo'); // true
$result6 = ($target = false); // false
$result7 = ($target = true);  // true

In case you didn't know, this can be useful for assigning a value and testing wether it worked at the same time. As such:
//...
while($row = mysql_fetch_array($dbresult)){
   // ...
}