jump to navigation

Closures: Environments December 31, 2009

Posted by Andor Saga in JavaScript, Open Source.
add a comment

Yesterday I wrote a blog post on closures. Today I continue my learning experience with some fun scripts. Keep in mind these scripts I have might not make sense, they just serve as examples and could be written without closures. I’m just playing with the concepts.

So I wanted to create something more practical than I had in my last post. I figured I would make a Person ‘class’ using closures. I also wanted to play with the concept of environments which I’ll get to in a minute.

Take a look at the following bit of JavaScript.

function Person(){
  var age = 0;

  return {
    getAge: function() {
      return age;
    },
    setAge: function(newAge) {
      // After searching for the oldest living people,  
      // I found the age to be somewhere under 125, so 
      // if you're older than that, too bad, you can't 
      // use this script
      if(newAge >= 0 && newAge <= 125) {
        age = newAge;
      }
    },
    alertAge: function() {
      alert(age);
    }
  };
}

var p1 = Person();
p1.alertAge(); //  0
p1.setAge(25);
p1.alertAge(); //  25

// Try to access local and assign invalid data
var age = p1.getAge();
age = -1;
p1.alertAge(); // still 25

// Create new closure
var p2 = Person();

// New closure has its own environment
p2.alertAge(); // 0

// New closure has not changed first one
p1.alertAge(); // still 25

The example has more code than the other scripts in my last blog, but it isn’t more complex. We first define a Person function/class with a local variable age. When the Person function is called, age is set to a safe value. Person will then return an unnamed object instead of a function (which my other scripts did). Because we still have nested functions, a closure is still created. Now, within the unnamed object we have a bunch of functions which all act on age.

  • getAge
  • setAge
  • alertAge

We ‘instantiate’ a Person and assign the unnamed object to p1 and ensure age is zero, which it is. Good. We then set the age to 25 using setAge and check to make sure it worked. It did. Great.

But what if we use getAge to ‘steal’ the reference to the local age variable and bypass the range checking? Well, from my attempt here to assign -1, it does not work. I wouldn’t be surprised if there was a way to do it, but this script prevents accidental invalid assignment to age. It does not prevent malice. However, I’m open to suggestions of ways to bypass the checking, so comment if you have a way. Because I just love making code do wacky things. That’s half the fun! The importance of this is that we have encapsulated the age variable very easily using closures, one of the benefits of using them.

Anyway, we then create a new closure with p2. This is where environments come into play. By making another Person, we have created a separate environment from p1. This is desired in this case. A few lines after creating p2 we again ensure it is indeed separate. It is, yay! Both p1 and p2 therefore have their own copies of age floating around somewhere in memory even after the Person function has ended.

Now, what if only a single environment is desired? I’ll use the same example and modify it slightly to keep things simple.

Things start to get very cool.

// Define Person, call it, and assign 
// return value to p1
var p1 = (function Person(){
  var age = 0;

  return{
    getAge: function(){
      return age;
    },
    setAge: function(newAge){
      // prevent crazy values from being assigned to age
      if(newAge >= 0 && newAge <= 125){
        age = newAge;
      }
    },
    alertAge: function(){
      alert(age);
    }
  };
})();// Person gets called here

p1.alertAge(); // 0
p1.setAge(25);
p1.alertAge(); // 25

// try to access local and assign
// invalid data
var age = p1.getAge();
age = -1;
p1.alertAge(); // still 25

var p2 = p1;
p2.setAge(50);
p1.alertAge(); // 50, it is the same environment

The script above only allows one environment of Person to be created because we define the function and call it in one shot. Once it’s created, there really isn’t an easy way to make a new environment. We can create another reference p2, but it will refer to the same closure as p1.

Well, that’s all for today. If you’re still confused, the best way to grasp the concept is to try it out yourself.

Advertisements

Closures December 31, 2009

Posted by Andor Saga in JavaScript, Open Source.
1 comment so far

The first time I tried learning closures I didn’t quite get it. I found myself re-reading the same lines from my JavaScript book. I gave up and moved onto other things. Well, a few months ago, I took an open source course at Seneca College. My professor Dave Humphrey gave the class an explanation on closures. It definitely helped and things started to make sense, but I knew to truly understand them I needed to a) experiment with closures myself and b) teach them to others to prove I have really learned (at least the basics). This is the purpose of this blog.

Of course there are countless other blogs, tutorials, whatever on the subject written by much more skilled programmers. So if you’re goal is to learn what closures are and how to use them, you may be better off running a search instead since I’m still trying to learn this and I’ll be making mistakes here and there.

One thing I didn’t like about other resources I found online was that they gave an explanation of what closures were before examples. The explanations quickly became convoluted and without source I was left without any foundation. It didn’t help. So instead of giving you a paragraph of what they are, let’s just ease our way into these ‘closures’.

Let’s start with a very simple (non-closure) example.

// Create a function
function sayHello1(){
  alert('Hello!');
}

// Call the function
sayHello1();

We created a function and called it. Not too bad. Now let’s see what happens when we create a function in a function.

function sayHello2(){

  // Create a function in a function 
  var innerFunc = function(){
    alert('silence...');
  }
}

// Assign it
var myFunc = sayHello2;

// Call it
sayHello2();

// Call it another way
myFunc();

The sayHello2 function is named. We can assign it to a variable, call it and refer to it because it has a name. The inner function isn’t named and is therefore called an anonymous function. We have however assigned it, so we could add some lines to this example and actually call it.

If you run this bit of code nothing happens even though we called sayHello2. This is because when sayHello2 is called, it simply creates a variable that holds a function, nowhere is innerFunc actually called.

But what if we return that inner function?

function sayHello3(){

  // Create a function in a function 
  var innerFunc = function(){
    alert('Hello from inside!');
  }

  return innerFunc;
}

// Call it, but the return value is lost
sayHello3();

// Call it. Now the return value (which is a function)
// is stored in sh3
var sh3 = sayHello3();

// Call the inner function, prints
// "Hello from inside!"
sh3();

// Call it another way, prints
// "Hello from inside!"
sayHello3()();

Things get interesting here. We created an inner function in the sayHello3 function and returned it. If we call sayHello3, it just creates a function and returns it, so we’ll need to either store that return value in sh3 or since the return is just a function, we can call it using double parenthesis. Neat! Now, let’s throw in some variables.

function sayHello4(){

  // Create a local variable in this function
  var num = 41;

  // Create and return a function in a function 
  return function(){
    num++;
    alert("Hey there...number is: " + num);
  }
}

// Calls and returns the inner function
var sh4 = sayHello4();

// Call the inner function, prints
// "Hey there...number is: 42"
sh4();

// Results in an error, num is local to sayHello4
// alert(num);

If you examine the source, you’ll notice instead of assigning and then returning the innner function, we just returned it. Because num is declared within sayHello4, we can modify it in the anonymous function and print out its value. Also note that trying to print out the value of num after we indirectly call the inner function does not work since num is local. You’ll see the relevance of this in a minute.

Okay, let’s take a break from code and review garbage collection. If you’re like me, you take out the trash when convenient and one day it disappears. Of course the sanitation engineers have taken it. Now every JavaScript implementation is responsible for having something similar, but we call it the garbage collector. It’s a bit of code that runs whenever it feels like it and finds any variables which no longer have references. Since these can’t be referred and used, the garbage collector frees that bit of memory for other objects. This prevents us from having to do our own memory management.

When a function is called in JavaScript, its local variables are created, some logic is executed, the function returns and the local variables are destroyed. Take a look the the last example. You’ll see that num should have been collected, yet we can still access it after the function has returned. This is because we created a closure! And when a closure is created, all the local vars within the function are kept alive instead of being garbage collected. Closures have many practical applications, one of which I demonstrated here. How? Well, num has been encapsulated! Cool!

I’ll stop there because I still have to play around with closures a bit more. Maybe I’ll write a follow-up blog in the future and correct any mistakes made in this one.

Release 0.3 December 12, 2009

Posted by Andor Saga in Open Source, Processing.js, webgl.
5 comments

My release 0.3 for my open source class is uhh…complete? Hmm.. my professor Dave stated our 0.3 release should be a polished version of our previous work, release 0.1 and release 0.2. Since I’ve just been adding more features, not much polishing has occurred. To make things worse, I couldn’t finish the tasks I signed up for, namely completing my 3D implementations for triangle() and rect(). But I’m not that surprised. About half the students working on the Processing.js in the course decided to work on 3D. The problem was we had the same due date but needed each others code to complete and properly test our functions. I needed Anna’s sphere() and box() functions, so my lights could be tested. She needed my shader and WebGL initialization code done to get her objects rendered…And there are four of us! Well, you can imagine that this makes development a huge challenge.

Patience is a virtue I have yet to posses. So I hit fast-forward. I got my WebGL initialization running, harcoded anything I could, threw in vertices of a rectangle. Wrote Buffers, shaders, perspective projection, transformations until … I got something that didn’t suck! I figured the other students might want the code so I released a runnable version which they could use in their own code.

Once I had a rectangle rendered, I progressed to rendering a sphere so I could work on my lighting functions. I also worked on rect() and triangle(), but again, since I couldn’t test the code since the positioning of the objects was dependent on the camera, I decided to switch to writing the ref tests instead which we’ll eventually need. Over the Winter break, I’ll be able to finish the code. In any case, here are my deliverables:


Directional Light Demo

Ambient & Dir Light Demo

0.3 Deliverables

My 0.3 two cents

In my last open source class, Dave led a discussion of what open source means to us. We talked about the many things which open source is, both good and bad. From collaboration with experts, humility on blogs and contributing at whatever commitment level you stood. Open source is many things. It can be free and it can be expensive. It can be flexible in terms of licensing and inflexible when submitting a patch: “Your indentation is all wrong!”. But what happens when you bring it to the classroom? In many courses, students try do the least amount of work for the highest mark. To a motivated student, an open source course can topple this paradigm.”You’re going to be working on a visualization language. You’ll be implementing stub functions and adding 3D functionality using WebGL”. Wait, I get a credit for doing this? It’s amazing that this opportunity has just fallen into our laps. It allowed us to put in as much work as we wanted. And the project itself? Working on Processing? I still don’t think I understand what we did here. “Work on a real world software project”. It gets me every time. I can’t wait to start DPS911.

My Open Source Perspective

From the first few weeks of school I didn’t do the readings and other work because my professors told me to. I did them because I wanted to. Going back to the beginning of the semester I remember I came to CDOT on the weekend and got to watch Revolution OS. I didn’t think about what marks I would get, I thought about what I’d get to learn. Marks became a by-product of well…having fun.

Open source is many things. In the center of the class whiteboard, among licensing, IRC, blogs, wikis and collaboration, at the heart of open source is one thing: Love. We do it because we love it.

sphere(), directionalLight(): Take 4 December 5, 2009

Posted by Andor Saga in Open Source, Processing.js, webgl.
2 comments

I updated my demo!

The lighting in my last demo worked because the sphere wasn’t being transformed. But because the user will be moving spheres around and rotating them, the normals of the sphere will also need to be transformed along with the vertices. To transform normals, they need to be transformed by the inverse transpose of the modelview matrix. I just took the inverse and transpose matrix functions from the c3dl.org site and plugged them into Processing.js.

Yes, it’s 3D!

Anna said that in my other demo, the sphere didn’t look 3D. So just to prove this is indeed a 3D object, I’m render it here in wireframe.

sphere(), directionalLight(): Take 3 December 4, 2009

Posted by Andor Saga in Open Source, Processing.js, webgl.
add a comment

Here is a working demo which uses the directionalLight() and sphere() functions in Processing.js, which I have added. I have included the Processing.js source under the canvas, however there is still a huge amount of hardcoding going on, so don’t assume modifying the script will actually work.

Worst…Bug….Ever!

While working on this, I found that the demo ran in Safari but not in Minefield. I was getting this exception:
Error: uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE)
[nsICanvasRenderingContextWebGL.vertexAttribPointer]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame ::
file:///Users/andor/Documents/Processing-js-git/processing-js/processing.js :: rect :: line 2010" data: no]

Uh-huh. So after double checking my VBO’s, shaders, vertices, normals, matrices, JavaScript… I gave up. I needed another approach. Luckily my rect demo was still online. I decided to see if that one would run on Minefield. It did! That was great because it gave me a place to start working backwards. Interestingly enough, today in my open source class we learned about minimizing variables in code when we encounter bugs. So that’s what I started doing. I took the rect demo and started cutting everything out that I didn’t need until two versions I had of the demo (one working, one not) only differed by the size of the canvas….Well, You can figure out the rest. But getting a vertexAttribPointer() exception because the canvas size in the tag and the size() call in the Processing.js script are different? Ouch. That hurts. Hurts like 1 AM hurts. This crazy bug needs to get filed, and soon. But I’m exhausted, so tomorrow will have to do.

sphere(), directionalLight(): Take 2 December 4, 2009

Posted by Andor Saga in Open Source, Processing.js, webgl.
add a comment

While trying to get directional light for 3D objects working in Processing.js, I had to spend quite a bit of time with Blender’s insane UI trying to get the normals. Then I realized I could have pretty much used the vertices. Note to self: Think before trying to solve a problem.

sphere(), directionalLight(): Take 1 December 4, 2009

Posted by Andor Saga in Open Source, Processing.js.
add a comment

I exported a sphere from Blender, imported it in C3DL and made it spit out the vertices and normals after parsing. I then threw those two arrays as literals in the Processing.js library. I updated my shaders and now I have some form of directional light code and this is the result. But you’ll notice I forgot to smooth the normals, that’s why the sphere doesn’t look smooth. So, back to work!

sphere() December 3, 2009

Posted by Andor Saga in Open Source.
add a comment

Testing if my directional light works in Processing.js is difficult without an object. So I threw together the sphere() function. It renders the vertices, but I don’t yet have the normals. So no tests for me yet. However, Anna, another student in my open source class is working on this sphere() function. Once it’s ready, I’ll be able to test my directional lights.

Ambient Triangles December 3, 2009

Posted by Andor Saga in Open Source.
add a comment

Among other functions, I’m working on adding the 3D versions of the triangle() and ambientLight() functions to the Processing.js library. You can see it’s coming along, but a bit slow. The positioning is off because the camera and projection code will be taken care of by a classmate of mine. The ambient lighting is somewhat working, so is the stroke color which I threw in just because. Because I dunno…programming is fun.

WebGLFloatArray vs. CanvasFloatArray December 2, 2009

Posted by Andor Saga in Open Source, webgl.
2 comments

When working with technology which is still in development, you frequently run into interesting problems. I ran into one such problem yesterday. I was trying to use CanvasFloatArray which has been renamed to WebGLFloatArray in WebGL. For more information and a workaround, check out Learning WebGL.

So I updated my demo and now it works on both Minefield and Safari. Thanks Dave!