NSArray map

 Uncategorized  Comments Off on NSArray map
Jun 032012
 

I had an NSArray of objects (all the same). I needed a property out of all of those objects. So I created a Category on NSArray to add this functionality. It loops through each object and performs a selector creating a new array from the results. One important note is that since you can’t put Nil in an NSArray it does a check for Nil and doesn’t add that result. Therefore you do not get a perfect one to one map in all cases :(. The objects returned from the mapping (in my case) also needed to be serialized (a custom serializer I wrote). So I called mapByPerformingSelector again to much success. Then I realized that looping though the array twice was a waste so I created the mapWithBlock method. Simply supplying a block that asks for the needed property and then returning the serialized version of the returned object handled what I needed and only looped through the objects once. Success!

typedef id (^MapResult)(id obj);

@interface NSArray (NSArrayMap)

- (NSMutableArray*)mapByPerformingSelector:(SEL)sel;
- (NSMutableArray*)mapWithBlock:(MapResult)map;

@end
@implementation  NSArray (NSArrayMap)

- (NSMutableArray*)mapByPerformingSelector:(SEL)sel {
    NSMutableArray * new = [NSMutableArray arrayWithCapacity:[self count]];
    
    for (id obj in self) {
        id t = [obj performSelector:sel];
        if (t) {
            [new addObject:t];
        }
    }
    
    return new;
}

- (NSMutableArray*)mapWithBlock:(MapResult)map {
    NSMutableArray * new = [NSMutableArray arrayWithCapacity:[self count]];

    for (id obj in self) {
        id t = map(obj);
        if (t) {
            [new addObject:t];
        }
    }
    
    return new;
}

@end

As you can see these methods return NSMutableArrays… why? it was easier.

Example:

NSMutableArray* results = [sourceArray mapWithBlock:^id(id obj) {
    PropertyType * r = ((ObjectType*)obj).property;
    return [r serialize];
}];

PHP Delayed Invocation Object

 PHP  Comments Off on PHP Delayed Invocation Object
Jul 072011
 

By virtue of PHP’s many Magic functions it is possible and indeed quite easy to create an object that can be used to call a function or object method now, but have it invoked later.

The reason I wrote this function was for lazy loading of data. I had the id’s and information required to acquire the data available in the constructor so I could have loaded it then. I could have saved all those data values and made the DB call later. That would have meant that I would have needed another private function that new how to use the data to pass it off to my model objects. So, why not pretend to call it in the constructor and have it invoked later.

Say that you have a class Blog_Feed and you want to call a method getBlogPostData(id) on it.

$obj = new Blog_Feed();
$data = $obj->getBlogPostData(42);

Using the Invocation class below

$obj = new Blog_Feed();
$inv = new Invocation($obj);
$inv->getBlogPostData(42);
// $data = $inv();

Those two examples are functionally equivalent. The advantage is that if your application has differing code paths where some paths don’t need the blog post data it won’t make that call yet.

class Some_Class {
    $data = null;
    $dataInv = null;

    function __construct(id) {
        $obj = new Blog_Feed();
        $this->dataInv = new Invocation($obj);
        $this->dataInv->getBlogPostData(id);
    }

    function functionThatNeedsData() {
        if (!$this->data) { $inv = $this->dataInv; $this->data = $inv(); }
        // use the data
    }

    .
    .
    .
}

Therefore, if the functionThatNeedsData is never called then the $data is never populated by the getBlogPostData() function.

A quick side note about the line

if (!$this->data) { $inv = $this->dataInv; $this->data = $inv(); }

The instance variable $dataInv is saved out into a local variable before it is invoked because PHP can’t tell the difference syntactically between calling a variable as a function or calling a member function. PHP will assume it’s a function, not be able to find it, and then throw an exception.

$obj->localvar();
$obj->method();

This is the code for the Invocation class.

<?php
class Invocation {
    protected $obj;
    protected $func;
    protected $args;
    
    public function __construct($obj = null) {
        $this->obj = $obj;
    }
    
    public function __invoke() {
        if ($this->func) {
            if ($this->obj) {
                return call_user_func_array(
                    array($this->obj, $this->func), $this->args
                );
            }
            else {
                return call_user_func_array($this->func, $this->args);
            }
        }
    }
    
    public function __call($name, $args) {
        $this->func = $name;
        $this->args = $args;
    }
}

As you can see in the code. The object to have the method invoked on is taken by the constructor. No object needs to be given though, this can be used to call a global free function as well. The __call function saves the function that was called and the arguments passed to that function. The __invoke function uses the data it has to call the function.

This can be easily extended to call multiple functions in succession.

<?php
class Invocation {
    protected $obj;
    protected $func = array();
    protected $args = array();
    protected $multi;
    
    public function __construct($obj = null, $multi = false) {
        $this->obj = $obj;
        $this->multi = $multi;
    }
    
    public function __invoke() {
        while (count($this->func)) {
            $func = array_shift($this->func);
            $args = array_shift($this->args);

            if ($func) {
                if ($this->obj) {
                    return call_user_func_array(
                        array($this->obj, $func), $args
                    );
                }
                else {
                    return call_user_func_array($func, $args);
                }
            }
        }
    }
    
    public function __call($name, $args) {
        if ($this->multi || count($this->func) == 0) {
            $this->func[] = $name;
            $this->args[] = $args;
        }
    }
}

A quick example:

$obj = new Some_Type();
$inv = new Invocation($obj);
$inv->function1('hello', 'world');
$inv->function2(42, PI);
$res = $inv(); // result from function1;
$res = $inv(); // result from function1 again;
$obj = new Some_Type();
$inv = new Invocation($obj, true);
$inv->function1('hello', 'world');
$inv->function2(42, PI);
$res = $inv(); // result from function1;
$res = $inv(); // result from function2;

Delegated AJAX

 JavaScript  Comments Off on Delegated AJAX
Oct 042010
 

About a year ago I needed a quick and easy AJAX library to just grab XML or JSON. At that time I was working heavily in Objective-C on the iPhone which uses a lot of delegation of functionality. I wanted to build something similar for my web application.

In most browsers the XMLHttpRequest object is a native JS object and can be extended with JS’s class prototyping. So I created a function…

XMLHttpRequest.prototype.Request = function(address, postParams, delegate);

The first param is the URL to request, the second is an associative array of values to POST, and the last is a delegate class.

The delegate class can contain any or none of the following functions in the following example.

function MyDelegate() {
    this.onstart = function() {}
    this.onprogress = function(completed, total) {}
    this.onsuccess = function() {}
    this.onerror = function(code, status) {}
    this.onfinish = function() {}
}

The functions sort of speak for themselves in what they do. “onstart” happens first, “onfinish” last, “onprogress” happens while the progress of the request is ongoing, “onerror” when an error occurs, and “onsuccess” when the request succeeds.

Usually only an “onsuccess” is needed. “onerror” is often very useful to handle any errors.

The delegate class definition (“MyDelegate” in the above example) can be defined to take any number of parameters. Via the JS closure paradigm all of the defined event handlers will have direct access to them. This is most handy.

Furthermore, because in the creation of a JS object via function all the code in the function is ran, this gives us the best way to make an AJAX request.

function FetchCurrencyDataDelegate(countryCode) {
    this.onsuccess = function() {
        // handle the return of the data
        var obj = this.responseJSON;

    }

    XMLHttpRequest.Request(
        '/currency.php', { 'countryCode' : countryCode }, this
    );
}

Passing “this” into the Request object uses a closure to ensure that it never leaves scope while the request object exists. The Request function will then use that object reference to make the appropriate event handler function calls when needed.

You might think that XMLHttpRequest.Request shouldn’t work because XMLHttpRequest is a type and not an instantiated object. You are correct. To make that shortcut work needs one more function, a helper.

XMLHttpRequest.Request = function(address, postParams, delegate) {
    var request = new XMLHttpRequest;
    request.Request(address, postParams, delegate);
}

When the AJAX request returns the library code applies all of the XMLHttpRequest objects properties to the delegate and then calls “onsuccess.” In addition, the library creates a “responseJSON” value which is a decoded JS object if the server returns a JSON string.

So, starting the ajax call is now as simple as…

new FetchCurrencyDataDelegate('us');

We don’t care that our current scope doesn’t keep a reference to the new object because the AJAX library’s Request function has a copy of it which will keep it alive. We are now relying on the Delegate to properly handle all UI or storage changes resulting for the AJAX call.

The source code is below. But first there is one more important topic.

This AJAX library works in all major browsers as is except for Internet Explorer 7 or before (which are sadly still widely used and therefore “major”). The reason they don’t work is that they lack a native XMLHttpRequest Object. The fix for that is simple… create one. The second file is also supplied at the end. To use both files, in your html document’s head section include this.

<!--[if lte IE 7]>
<script type="text/javascript" src="/js/XMLHttpRequest.IEFix.js"></script>
<![endif]-->
<script type="text/javascript" src="/js/XMLHttpRequest.Request.js"></script>

The conditional comment, which looks like just a comment to all browsers except IE, will include the IEFix JS file only if the browser version is less than or equal to 7. Note: the IEFix must come before the other file.

These browsers also have one big limitation. The XMLHttpRequest Object’s onreadystatechange doesn’t get called in the scope of the object (“this” does not equal the XMLHttpRequest object). This means a global instance of the object must be kept for the onreadystatechange event to use. This isn’t a huge problem except that it means only one AJAX call can be happening at any given time. Future work on my part may find a work around for this. But I don’t care much for Internet Explorer.

XMLHttpRequest.Request.js

// Verifies that the object is an array.
function isArray(obj) {
	//null test (this is needed to keep the other check from blowing up)
	if(obj == null){
		return false;
	}

	if (obj.constructor.toString().indexOf("Array") == -1){
	   return false;
	}
	else{
	   return true;
	}
}

//this function takes an associative array and turns it into a get (or post) string
XMLHttpRequest.prototype.EncodePOST = function(vars) {
	//if null, return null
	if(!vars == null) return null;

	//if it isn't an array, then we don't want it (right?)
	if (isArray(vars) != false) throw "POST variables need to be submitted as an associative array, please.";

	var str = "";
	//create "get" string
	for(x in vars) {
		str += encodeURIComponent(x) + "=" + encodeURIComponent(vars[x]) + "&";
	}

	//hack off that last &
	return str.substring(0, str.length - 1);
}

XMLHttpRequest.Request = function(address, postParams, delegate) {
	var request = new XMLHttpRequest;
	request.Request(address, postParams, delegate);
}

XMLHttpRequest.prototype.Request = function(address, postParams, delegate) {
	this.onreadystatechange = function() {
		// check the ready state, ignore if we aren't done (for now)
		if (this.readyState != 4) return;

		switch (this.status) {
			case 200:
				// see if we have a function to call
				if (delegate) {
					if (!(this.responseXML && this.responseXML.documentElement)) {
						try {
							// If the return is not XML then see if it is JSON.
							delegate.responseJSON = eval("(" + this.responseText + ")");
						}
						catch (ex) {}
					}
					else {
						// if webkit then hookup events
					}
					// Push property values to the delegate
					delegate.responseXML = this.responseXML;
					delegate.responseText = this.responseText;
					delegate.status = this.status;
					delegate.statusText = this.statusText;

					if (delegate.onsuccess) {
						// notify delegate of success
						delegate.onsuccess.apply(delegate, new Array());
					}
				}
				break;
			// Could handle other error codes here (such as 401 Unauthorized) so that they will be happen for all delegates
			default:
				try {
					// Notify delegate of an error
					delegate.onerror.apply(delegate, new Array(this.status, this.statusText));
				}
				catch (ex) {
					// default error handler... an alert
					alert("Error retrieving server data: " + this.statusText);
				}
				break;
		}

		if (delegate) {
			if (delegate.onfinish) {
				// Notify delegate to update UI of ajax finish
				delegate.onfinish.apply(delegate, null);
			}
		}

		return;
	};

	this.onprogress = function (e) {
		if (delegate) {
			if (delegate.onprogress) {
				// Notify delegate of progress
				delegate.onprogress.apply(delegate, new Array(e.position, e.totalSize));
			}
		}
	}

	var postString = this.EncodePOST(postParams);
	this.open("POST", address, true);
	this.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	if (delegate) {
		if (delegate.onstart) {
			// Call onstart to notify UI of ajax call
			delegate.onstart.apply(delegate, null);
		}
	}
	this.send(postString);
}

XMLHttpRequest.IEFix.js

Request = null;

function XMLHttpRequest() {
	if (!Request && window.ActiveXObject) {
		try {
			this.req = new ActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			try {
				this.req = new ActiveXObject("Microsoft.XMLHTTP");
			} catch(e) {
				this.req = false;
			}
		}
	}

	if (!this.req) return false;

	Request = this;

	this.req.onreadystatechange = function() {
		var r = Request;
		Request.readyState = Request.req.readyState;
		if (Request.readyState == 4) {
			Request.responseXML = Request.req.responseXML;
			Request.responseText = Request.req.responseText;
			Request.status = Request.req.status;
			Request.statusText = Request.req.statusText;

			Request = null;
		}

		r.onreadystatechange();
	}

	this.open = function(method, url, async) {
		this.req.open(method, url, async);
	}
	this.setRequestHeader = function(name, value) {
		this.req.setRequestHeader(name, value);
	}
	this.send = function(postString) {
		this.req.send(postString);
	}
}

JS Generator – Fibonacci Example

 JavaScript  Comments Off on JS Generator – Fibonacci Example
Oct 022010
 
function fibonacci() {
    var i1 = 0, i2 = 1;
    while (true) {
        yield i1;
        var t = i1;
        i1 = i2;
        i2 += t;
    }
}
var g = fibonacci();
for (var i = 0; i < 10; i++) {
    document.write(g.next() + "\n");
}

The function fibonacci contains the keyword “yield” making the function a generator. When the function is called it returns an iterator. The first time the iterator’s next function is called the fibonacci function runs like normal until the yield keyword. Yield works just like return, returning the value specified. The next time “next” is called the function continues on the first statement after the yield. In this example, the while loop adjusts the variables and yields the new value. After that, every time the next function is called it continues to rerun the same looping code, each time yielding the next value in the Fibonacci sequence.

When the generator function ends, instead of yielding then the generator is complete. The Fibonacci example never ends. But a simple addition can give the function an ending point.

function fibonacci(limit) {
    var i1 = 0, i2 = 1;
    while (true) {
        if (limit > 0)
            yield i1;
        else
             break;

        limit--;
        var t = i1;
        i1 = i2;
        i2 += t;
    }
}
var g = fibonacci(15);
for (var i in g) {
    document.write(i + "\n");
}

In this manner, where you know the generator will end, the for in syntax works well.

NOTE: in Firefox the yield keyword doesn’t exist unless the script tag loading the function has a type of “text/javascript;version=1.7”. version must be 1.7 or higher.

First Post: JS Closure Example

 JavaScript  Comments Off on First Post: JS Closure Example
Oct 012010
 

While creating 10 <a> elements, each link pointing at a different id number. In that case, this example makes sense.

for (var i = 0; i < 10; i++) {
    var a = document.getElementById('a');
    a.onclick = function(e) {
        location.href = 'http://www.example.com/?id=' + i;
    };
    document.body.appendChild(a);
}

However, the creation of the anonymous function block encloses a reference to the variable i but the value of i keeps changing as the for loop loops. That ends up yielding all 10 links linking to http://www.example.com/?id=10.

To correct that each anonymous function needs it’s own copy of i. To do that.

for (var i = 0; i < 10; i++) {
    var a = document.getElementById('a');
    a.onclick = (function(internal_i) {
        return function(e) {
            location.href = 'http://www.example.com/?id=' 
                          + internal_i + '&lastId=' + i;
        };
    })(i);
    document.body.appendChild(a);
}

Having the anonymous function block be returned by another anonymous function block that is passing the looping variable into it causes a new copy of i to be created.

Wrapping an anonymous function block in parenthesis allows you to follow it with a parameter list which will call the function immediately and thus return the function event handler with the closure. The event handler has references to both i and it’s outer function’s internal_i.

Enhanced by Zemanta