Clojure
I've recently picked up on Clojure, a LISP-dialect that runs on the JVM and I absolutely love it; but like other programming languages, it's difficult to convince others to try a programming language other than c/c++ or PHP.
Many friends are in the blub paradox camp: people view programming languages only in the mental model of his/her favorite programming language. Languages more powerful are deemed "unnecessarily complex", where languages less powerful are viewed as inferior.
In the Programming Languages course, we covered functional programming. The person next to me said:
"c++ can do functional programming, it has function pointers."
For someone that ever passed functions without any messy declarations knows that it's just not quite the same. Ruby is particularly nice with blocks, which is syntactic sugar for passing a function to another function:
with_file('myfile.txt') { |line|
puts line
}
While with_file doesn't really exist in ruby, it can be easily implemented by someone to open a file, iterate it line by line, and close it. On the other hand, c doesn't provide as nice syntax for something like this.
In clojure, syntax is similar, with the (in)famous parenthesizes.
(with-file "myfile.txt" (fn [line] (println line)))
Some people may say that's a lot of parenthesizes, like any other LISP, but they're mostly in different places. Idiomatically, this with-file would be a macro - a function that generates code to compile. A good use of a macro abstracts boilerplate code away: such as the declaration of the function in the example above.
(with-file "myfile.txt" line (println line))
As you can see, lisp deals away with most of the character syntax that other languages have. Macros can do other handy language-abstractions. For example instantiating an object make take several statements:
MyClass obj = new MyClass();
obj.setProperty("value");
obj.doMagic();
obj.checkForErrors();
There's some repetition here. Clojure has interop support with java, and supports java objects without any wrappers. The above code in clojure looks like:
(doto (MyClass.)
(.setProperty "value")
(.doMagic)
(.checkForErrors))
For one more pair of parenthesizes, you get to avoid typing the type of class twice, and the variable you're operating on. All while maintaining the readability of the code. That's a pretty sweet deal if you ask me.
There are more issues Clojure touches upon. No doubt multi-threading is a growing concern as CPU manufacturers add more cores, but multi-threaded applications are difficult to make. Dealing with deadlocks is a perplexing experience many first-time threading programmers. Clojure's immutable data structures and concurrency semantics ensures no deadlocks. It's quite a different experience than worrying about if your code functions properly.
I'll leave it to you to check out clojure. Clojure's creator, Rich Hickey, is probably the better person to look for the design philosophies of clojure via his screencasts.
“Brief” Guide to JavaScript – Part 11
You should check out the previous parts before continuing with this final part:
Ajax
It's part of the "Web 2.0" trend. Ajax, or Asynchronous JavaScript and XML provides a background-styled http request to a URL. This is different from the traditional, "load a new page to perform an action" style. With the ability to essentially load a page in the background, you can let the user interact with the rest of your site while performing an operation by the user.
Pros & Cons
"With great power, comes great responsibility."
Ajax provides some very nice benefits, but there are some issues you should consider before determining to use ajax. A lighter-weight response from the server (instead of a full page reload) which can improve the user experience with ajax. But keep in mind:
- The user's back button won't "undo" the last action. This has to be implemented manually.
- Browsers without JavaScript or Ajax can't perform these actions.
- Search engines & bots usually don't run JavaScript, so content provided via ajax is inaccessible to them.
- Ajax doesn't provide an accessible way for blind people to figure out changes on a page (if any).
Providing a graceful alternative, the traditional page-reload mechanisms, is a good way to combat most of the issues above. Although, it's a good practice to avoid using Ajax for simply displaying content.
XMLHttpRequest
The core behind Ajax is the XMLHttpRequest object in JavaScript. XMLHttpRequest is a functional object that needs to be instantiated, so we do this:
var request;
try{
if(XMLHttpRequest) // for all modern browsers
request = new XMLHttpRequest();
else // for IE prior to 8
request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(error){
request = false;
}
if(request){
// do ajax stuff here...
} else {
// browser doesn't support ajax
}
It's worth noting the both the ActiveXObject & XMLHttpRequest object have the possibility of throwing an exception, so use a try/catch block and handle if the feature is not supported.
Next, we need to configure the request object, the basics:
request.open('get', 'http://google.com', true);
open interface is as follows:
open(method, url, async?, username, password)
- method: usually a string of get or post which describes how additional data should be sent. Identical to the method attribute of form tags.
- url: the url to fetch. Identical to the action attribute of form tags.
- async?: You should usually set this to true. This tells the browser to perform the request asynchronously and not freeze up the browser. The advantage of synchronous is after you perform the request, you can immediately use the results in your next line of code. This cannot be guaranteed with an asynchronous request. (optional - defaults true)
- username & password: is the simple http-supported username & password. This does not work for sites that have a username & password login form, but rather for urls that prompt a login dialog before displaying the page. (optional - defaults to no login credentials)
Of course, doing an async request is useless if we can't handle it when the request is completed, so we add an event handler.
request.onreadystatechanged = function(){
// our code goes here.
};
There's a handful of different cases when this handler will be called. In order to differentiate between the requests, the XMLHttpRequest object has a readyState property which we can use to check the current state the request is in. The values are:
- 0: The xmlhttp object hasn't been initialized
- 1: Xmlhttp object has been initialized
- 2: Xmlhttp object has sent request
- 3: Xmlhttp object is being processed (performing request)
- 4: Xmlhttp object is completed (the request is completed)
Most of the time, you'll be checking to see the readyState property is 4.
Also worth mentioning the status property, for the XMLHttpRequest object, which returns the server response code from the request: 200 for successful request, 404 for missing file, etc.
Finally, there's the responseText property which contains the content of the server request.
Now let's build our onreadystate function body:
request.onreadystatechanged = function(){
// ajax request finished & server returned 200
// (url resource found and returned)
// it's probably a better idea to accept any
// status in the 200's, but for simplicity, we'll
// do this
if(request.readyState == 4 && request.status == 200){
var c = document.getElementById('ajax_content');
c.innerHTML = request.responseText;
}
};
Here we set the interior html of the element with id attribute of ajax_content to whatever the server gave us. After we configured our object, we need to perform the request:
// string contains POST data to send to the server. null indicates no POST data.
request.send(null);
It's worth noting the POST data string should be in a query-string format:
request.send('var1=value1&var2=value2');
That's it, JavaScript ajax in a nutshell. No fancy voodoo magic.
XML / HTML / Text data
Just pinging a URL is definitely not useful, we want to handle the data from the user. There are several typical server responses, but usually you have control over this since ajax is used to improve the user experience of your web app.
For text we simply utilize the responseText property:
request.onreadystatechanged = function(){
if(request.readyState == 4 && request.status == 200){
// request.responseText
}
};
This behavior is similar for XML, except when you need to parse them for specific information, then responseXML will be your friend then.
request.onreadystatechanged = function(){
if(request.readyState == 4 && request.status == 200){
// request.responseXML is like a DOM object, supporting DOM
// traversal techniques.
alert(request.responseXML.getElementsByTagName(‘h1’).length);
}
}
Alternatively, you can manually create the XML parser object:
request.onreadystatechanged = function(){
if(request.readyState == 4 && request.status == 200){
var contents = request.responseText;
var xml = null;
if(window.DOMParser){ // all browsers but IE
var parser = new DOMParser();
xml = parser.parseFromString(contents, ‘text/xml’);
} else { // internet explorer
xml = new ActiveXObject(‘Microsoft.XMLDOM’);
xml.async=’false’;
xml.loadXML(contents);
}
// use xml identically to request.responseXML
}
}
JSON
Another common data-transfer format is JSON (JavaScript Object Notation), which is a subset of JavaScript syntax – specifically the data structures part. The only accepted types of JSON are:
- Numbers – 1, 2.5, –4, –5.2, etc.
- Booleans – true, false
- Null value
- Strings - ‘abc’, “defghi”
- Arrays – [‘a’, 1, 2]
- Objects – {‘key’ : ‘value’} where keys must be strings!
The main advantage is the simple ways to use JSON as true JavaScript values. Given that json_string contains json data – whether from ajax or somewhere else – we can simply do:
var json = eval(‘(‘ + json_string + ‘)’);
To convert it to it’s equivalent data structure in JavaScript. Using eval is not safe parsing unsafe JSON code (eg – from a third party), use the JSON parser at json.org. This is simply because eval interprets a given string as JavaScript: including function calls and prototype definitions.
The json.org parser is also bundled with a stringify function to convert JavaScript data structures into JSON.
The End
(no really)
I’m wrapping up my exhausting JavaScript coverage here. But there’s plenty more things to learn if you’re up to it:
- Debugging your JavaScript in IE, Safari, Firefox (with Firebug), etc.
- Gracefully degrading when the user doesn’t have JavaScript or certain JavaScript features
- JavaScript optimization techniques
- XPath for DOM traversal
- AJAX
- Supporting the back button with AJAX actions
- Modifying/Reading HTTP Headers
With that, I’ll tilt my hat, and walk off. If only I had a cool hat.
- Jeff
“Brief” Guide to JavaScript – Part 10
Yes, this is no longer becoming brief; so check out the growing list of previous parts:
Objects Revisited
Objects are the core of JavaScript, so I'm going to a bit further in-depth than previously mentioned. I didn't say explicitly, but everything is JavaScript is an object, booleans, strings, numbers, arrays, functions, etc. are all objects. Before we talk further, I want to quickly review some terminology of objects:
myobj = {}; // constructor that creates an object; // In this case, an empty object.
myobj.property; // accessing a property
myobj.method(); // calling a function which belongs to an object, aka a method.
// we can also access properties, methods, and references using the// array-styled notation
myobj['property']; // 'property' is called a key
myobj['method'](); // 'method' is the key
myobj['anotherobj']; // 'anotherobj' is the key
References
In contrast to what I initially explain, variables store references to objects. This is slightly different than simply storing data. I feel diagrams explain this the best. Say we do something like this:
var myobj = {'hello': 'world'};
var myobj2 = myobj;
JavaScript engines store the data similar to this:
This means if we change our object, the changes are visible through other variables:
myobj.hello = 'jk';
alert(myobj2.hello); // displays 'jk'
To truly copy an object, we have to manually copy every property:
var myobj2 = {};
for(var p in myobj){
myobj[p] = myobj[p];
}
This assumes that all the properties don't contain their own properties (like an array). Changing the property or variable changes where that property/variable points to. So:
var myvar = true;
var myvar2 = myobj;
myvar = false;
Which produces something like this:
In simplest terms, you can change where the variable points to, but setting one equal to another will share the same data source. This behavior also apply to function parameters. The rule of thumb is: for objects (those you use {}), arrays, and anything created with a new keyword behave as references.
Reflection Basics
Reflection is a programming terminology which a program that is aware of itself (not in the skynet terms): knowing the existence of variables, functions, or properties. This is particularly easy in JavaScript due to array-styled notation:
var css = ['borderColor', 'backgroundColor'];
var el = document.getElementById('header');
for(var style in css){
el.styles[style] = 'transparent'; // remove colors.
}
A bit more practical example is when creating similar functions:
var names = {
'Height': 'height',
'Width': 'width',
'Bgcolor': 'backgroundColor',
'Color': 'color',
'Size': 'fontSize'
};
for(var fnName in names){
(function(n){
window['set'+n] = function(element, value){
element.styles[names[n]] = value;
};
})(fnName);
}
// test it
setColor(document.getElementById('header'), 'red');
As you can see, we can use variables outside our anonymous functions, but you have to beware when the variable is updated in a loop. This is because the function will use the value of the variable at the time of the function call. So after the for loop finished, fnName will be 'Size' and all our functions would be change the 'fontSize' element.
To quickly resolve this, we simply create an anonymous function that accepts the fnName variable. With function calls, non-referenced variables are duplicated (remember: arrays, objects, or things using new are references), so we can use that variable when it was during the function declaration, inside the loop.
This outer scoping of variables is called dynamic scoping, where the values are based on when you call the functions, not when the function was defined.
Classes
Once you start writing larger and larger JavaScript-based applications, you'll may opt to use a more Object-Oriented approach. Classes help provide a "blackbox" approach to stateful widgets/systems. I'm not going to write a lengthy discussing the pros & cons, arguing isn’t my cup of tea
If you haven't used classes much, I'll quickly review some terminology:
- Property: A variable "about” the object. Think of a characteristic/trait of a particular object: like the box’s color – color would be the property. Identical to properties in object definitions.
- Method: A name for functions that belongs to a class. Other words, properties that are functions.
- Class: A "blueprint." Classes define properties and methods. For example: a class would be the architecture's design for a house.
- Instance: A representation of the "blueprint". Instances can have different values for properties. Continuing our example: An instance would be an actual house. One instance could be blue (property color = blue) and another instance could be red.
- Static: Treats the class almost like a namespace. Static properties and methods can be access directly. Unlike regular properties and methods, the static variants can't access the currently operating instance because they don't exist in an instance.
Since JavaScript is a bit unusual for classes, which we'll cover shortly.
Instantiated Classes
So we need to define some classes before we create instances of them. JavaScript classes can be created via functions:
function Person(){
}
Seems like a useless function definition, but this is our bare-minimal class definition! We can instantiate the almost useless class:
var john = new Person;
If you've used Object-Oriented programming in other languages, this is absolutely useless. But in JavaScript, properties can be created after the class has been instantiated.
john.name = "John Doe"; // works.
Why? Class instantiations are identical to creating objects. See these:
var myobj = {};
var myobj2 = new Object; // identical
var myobj3 = new Person; // our class is the same
Although you should use the former over the other alternatives. To make our class a bit better before, let's redefine our person class:
function Person(name, phone){
this.name = name;
this.phone = phone;
}
var john = new Person('john doe', '123 456 7890');
alert(john.name);
alert(john.phone);
Here we utilize our handy this variable which allows us to set properties and methods which we can access when we instantiate the class. The function parameters act as a constructor, which provides some values we can use when instantiating a class.
Of course we can make it more complex; let's add a method:
function Person(name, phone){
this.name = name;
this.phone = phone;
this.shout = function(){
alert('hello! My name is ' + name);
}
}
var john = new Person('john doe', '123 456 7890');
john.shout(); // alerts ‘hello! My name is john doe’
Just like any JavaScript object, just easier to replicate using instances.
Static Classes
Unlike instances, static classes don't require instantiation. Static classes are basically single-instanced classes. The easiest way is to simply define them like namespaces (see previously). But if you want a class to have both static and dynamic properties, simply create the dynamic first:
function Person(name, phone){
// dynamic-class code
this.name = name;
this.phone = phone;
Person.count++; // modifying our static property
}
Person.count = 0; // static property
Why does this work? Because everything are objects in JavaScript, including functions.
Prototypes
If you haven't noticed, there's one problem with the whole instantiated thing see:
function Person(){}
var john = new Person;
john.walkSpeed = 100;
If we wanted all person instances to have the walkSpeed property, we would need to add that property to all instantiated person classes. Not cool. To resolve this, we can use the special property in all objects: prototype. This allows us to assign properties to all instances of our class.
function Person(){}
var john = new Person;
Person.prototype.walkSpeed = 100;
alert(john.walkSpeed); // prints 100
var joe = new Person;
alert(joe.walkSpeed); // prints 100
john.walkSpeed = 10; // only affects john, poor fellow.
Using prototypes, we can implement like traditional object oriented inheritance.
function Person(){ }
function Employee() {}
Employee.prototype = new Person();
If you are observant, you'll notice we have a restriction: the constructor has to have no parameters. Unfortunately, achieving good prototype-based inheritance with constructor-supported inheritance is a tougher problem (out of scope of this article). I'll direct you here for a do-it-yourself implementation or JavaScript frameworks: prototype & mootools are good OO frameworks.
This wraps up this lengthy week. Next up is the trendy AJAX stuff. Oh boy!