yajc.js

December 3rd, 2012 Comments off

Just released yajc.js, a jQuery carousel.

Categories: Uncategorized Tags: ,

Y Combinator Function in Bike

September 21st, 2012 3 comments
Categories: bike Tags:

Notify and Memento

July 14th, 2012 Comments off

Announcing my 2 new open-source .NET projects:

  • Notify: data-binding change tracking library
  • Memento: lightweight undo framework

I still work on Bike, Combres, and Fasterflect although very limited (mostly fix bugs and support).

So far all of my major open-source projects are .NET based. While I do contribute a little bit here and there to non-.NET projects, it’s not as much as I want to. My open-source focus in the upcoming period therefore will be around JavaScript and Objective-C.

Revisit Dynamic Event Handler in .NET

July 11th, 2012 Comments off

A while ago I blogged about how to build a catch-all handler for .NET events and delegates. That solution uses LCG to generate CIL for the dynamic delegate. The latest version of Fasterflect however uses Expression Trees to generate the dynamic delegate. So I thought I would post the new solution here for completeness.

defaultdict() and memoization

June 11th, 2012 Comments off

After the previous post, it came across me that member_missing can be used to implement something like Python’s defaultdict. So I thought it’s interesting to code up an example leveraging this ability.

You know the fibonacci calculating algorithm right? This is the fibonacci code (except written in Bike, not Java) that I use to teach my students about recursion in an entry Java programming course:

var fib = func(n) {
  n < 2 ? 1 : fib(n-1) + fib(n-2)
};

Clean and simple! A base case on the left expression of the ternary and a recursive case on the right. Probably among the best to introduce people to the concept of recursion. What I didn't tell my students is that this is extremely inefficient. Pick fib(30) for example. It will invoke fib(29) + fib(28). fib(29) in turn invokes fib(28) + fib(27). Notice something? No? Read again? Still no? fib(28) is executed twice. And this is just the top part of the call tree. As you go down further, this phenomena is phenomenal, i.e. fib(27) is invoked tree times, fib(26) four times and so on! Needless to say, your CPU won't be very happy. Enter memoization.

In a nutshell, we use memoization as a technique to cache result of previous invocations. Assume the function has no side effect (i.e. being idempotent), which should generally be the case in a functional language, we can later reuse the cached result should the function is invoked again with the same arguments. Here's the code to compute fibonacci making use of memoization technique (and member_missing, as defaultdict).

func memoize(f) {
  var cache = {
    member_missing: func() { null }
  };
  return func recur(n) {
    cache[n] || (cache[n] = f(recur, n));
  };
}

var fib = func(n) {
  n < 2 ? 1 : fib(n-1) + fib(n-2)
};

var m_fib = memoize(func(recur, n) {
  n < 2 ? 1 : recur(n-1) + recur(n-2);
});

load 'stopwatch.bk';
var watch = Bike.Stopwatch.create( ).start( );
println('fib(20) = {0} (elapsed: {1}ms)', fib(20), watch.stop());

watch.reset().start();
println('m_fib(20) = {0} (elapsed: {1}ms)', m_fib(20), watch.stop()); 

Run the code and you should notice a significant difference between the run time of the normal fibonacci and one with memoization.

New feature in Bike: member_missing

June 11th, 2012 Comments off

I always like the ability of objects to dynamically respond to a message without having an explicit binding. Something like method_missing in Ruby or DynamicObject in .NET. It would be great for Bike to have that capability. Fortunately, adding this feature was much easier than I thought, thanks to how the interpreter code was already laid out. Please join me welcoming member_missing in Bike! Let’s examine this feature more closely, shall we?

var obj = {
  member_missing: func(name) {
    return "Member: {0}".with(name);
  }
};

println(obj.notExist); # Member: notExist
println(obj.has_member('notExist')); # False

The code above creates an object and defines the special member_missing method, which will be invoked by the runtime whenever it can’t resolve a member. Therefore, when trying to access notExist, methodMissing is invoked with the member name as its only argument and has a chance to decide what to return. In this case, it returns a string showing what member was being accessed.

This works for method invocation as well. When the interpreter attempts to invoke a method, the first thing it does is resolving the method object (Bike.Function) before invoking it. Therefore, member_missing can also do its magic here by returning a method that the runtime will instead invoke.

obj = {
  member_missing: func(name) {
    if (name == "add") {
      return func(a, b) { a + b };
    }
  }
};

println(obj.add(1, 2)); # 3

You see, Bike’s member_missing doesn’t behave exactly like Ruby’s method_missing. I could modify the runtime to instead of invoking the function returned by member_missing, it will invoke something like method_missing (Bike edition!) and pass in the call information (e.g. name, arguments). Maybe that what I should have done for efficiency sake (i.e. avoid creating a function every time!). Then again, maybe later, one thing at a time, eh. For now, those who care about a bit of efficiency here and there, you can cache the generated method, as follow.

obj = {
  member_missing: func(name) {
    if (name == "cache") {
      return this.cache = func() {};
    }
  }
};

obj.cache();
println(obj.has_member('cache')); # True

The next time obj.cache() is invoked, member_missing() isn’t invoke anymore because an explicit binding already exists.

Now, a more interesting example demonstrating the power of member_missing. If this somehow reminds you of RailsActiveRecord, you’re right.

var db = {
  member_missing: func(name) {
    if (name.starts('find')) {
      return db[name] #! cache it !# = func(obj) {
        var sql = 'SELECT * FROM {0}'.with(name.sub(4).upper());
        obj.members(false, true).each_with_index(func(name, index) {
          sql += (index == 0 ? ' WHERE ' : ' AND ') +
                 name.upper() +
                 (obj[name] is Bike.String ? '' : '=') +
                 obj[name]
        });
        println('Executing...{0}{1}', NL, sql);
        return [#! Suppose I'm a product array, yay! !#];
      };
    }
  }
};

# SELECT * FROM PRODUCTS WHERE CATEGORYID=1 AND PRICE>1000
var products = db.findProducts({categoryId: 1, price: '>1000'});

Interested? Have Bike up and running and start hacking. The examples above can be found in GitHub.

Building a Custom Defect Submitter for qTrace

May 10th, 2012 1 comment

Code for my new blog post in QASymphony’s Blog.

Categories: Uncategorized Tags: ,

Bike has a homepage!

May 3rd, 2012 Comments off

Had some fun with Python

May 1st, 2012 Comments off

By now, you should have already known I love programming languages, to the extent that I even created one myself. One of the languages I want to learn this year is Python. My first Python program is a port for the Semicolon language. The code is also available in github with examples.

# coding: utf-8

def tokenize(code):
	import re
	ops = {
	  ';;;':  { 'code': 'push', 'arg': 'signed'},
	  ';;⁏':  { 'code': 'dup' },
	  ';⁏;':  { 'code': 'swap' },
	  ';⁏⁏':  { 'code': 'discard' },
	  '⁏;;':  { 'code': 'add' },
	  '⁏;⁏':  { 'code': 'sub' },
	  '⁏⁏;':  { 'code': 'mul' },
	  '⁏⁏⁏':  { 'code': 'div' },
	  '⁏  ':  { 'code': 'mod' },
	  '; ;':  { 'code': 'store' },
	  '; ⁏':  { 'code': 'retrieve' },
	  ' ;;':  { 'code': 'label', 'arg': 'unsigned' },
	  ' ;⁏':  { 'code': 'call', 'arg': 'unsigned' },
	  ' ; ':  { 'code': 'ret' },
	  ' ⁏ ':  { 'code': 'jump', 'arg': 'unsigned' },
	  ' ⁏;':  { 'code': 'jz', 'arg': 'unsigned' },
	  ' ⁏⁏':  { 'code': 'jn', 'arg': 'unsigned' },
	  '  ;':  { 'code': 'exit' },
	  '⁏ ;;': { 'code': 'outchar' },
	  '⁏ ;⁏': { 'code': 'outnum' },
	  '⁏ ⁏;': { 'code': 'readchar' },
	  '⁏ ⁏⁏': { 'code': 'readnum' },
	}
	
	make_int = lambda str:int(''.join('0' if c == ';' else '1' for c in str), 2)
	while code and code != '\n':
		has_match = False
		for key in ops:
			pattern = (key + (r'([;⁏]*)\n' if 'arg' in ops[key] else '()') + r'(.*)$').decode('utf8')
			match = re.match(pattern, code, re.S)
			if match:
				has_match = True
				code = match.group(2)
				if 'arg' in ops[key]:
					if ops[key]['arg'] == 'unsigned':
						tokens.append([ops[key]['code'], make_int(match.group(1))])
					elif ops[key]['arg'] == 'signed':
						tokens.append([ops[key]['code'], 
									   (1 if match.group(1)[0] == ';' else -1) * make_int(match.group(1)[1:])])
				else: tokens.append([ops[key]['code']])
		if not has_match: 
			raise Exception('Unknown command')

def step():	
	global pc
	op = tokens[pc][0]
	arg = None if len(tokens[pc]) == 1 else tokens[pc][1]
	pc += 1
	if op == 'push':
		stack.append(arg)
		step()
	elif op == 'dup':
		stack.append(stack[-1])
		step()
	elif op == 'swap':
		stack[-1], stack[-2] = stack[-2], stack[-1]
		step()
	elif op == 'discard':
		stack.pop()
		step()
	elif op == 'add' or op == 'sub' or op == 'mul' or op == 'div' or op == 'mod':
		bin_ops = { 'add': '+', 'sub': '-', 'mul': '*', 'div': '/', 'mod': '%' }
		stack.append(eval(str(stack.pop()) + bin_ops[op] + str(stack.pop())))
		step()
	elif op == 'store':
		heap[stack[-2]] = stack[-1]
		stack.pop(); stack.pop()
		step()
	elif op == 'retrieve':
		stack.append(heap[stack.pop()])
		step()
	elif op == 'label':
		step()
	elif op == 'call':	
		call_stack.append(pc)
		jump(arg)
	elif op == 'ret':
		pc = call_stack.pop()
		step()
	elif op == 'jump':	
		jump(arg)
	elif op == 'jz':
		if stack.pop() == 0: jump(arg)
	elif op == 'jn':		
		if stack.pop() < 0: jump(arg)
	elif op == 'exit':
		sys.exit()
	elif op == 'outchar':
		print chr(stack.pop())
		step()
	elif op == 'outnum':
		print str(stack.pop())
		step()
	elif op == 'readchar':
		stack.append(ord(sys.stdin.read(1)))
		step()
	elif op == 'readnum':
		stack.append(int(sys.stdin.readline()))
		step()
	else: raise Exception('Unknown opcode')

def jump(label):
	global pc
	for index, token in enumerate(tokens):
		if token[0] == 'label' and token[1] == label:
			pc = index
			break
	step()
		
import sys
if len(sys.argv) == 2:
	tokens = []; pc = 0; heap = {}; stack = []; call_stack = []
	tokenize(open(sys.argv[1], 'r').read().decode('utf8'))
	step()
else: print 'Usage: python semicolon.py [file.sc]'

Posts on software testing

March 3rd, 2012 1 comment

I’ve written a series of blog posts in my company’s blog.  Links here for references:

Any plugin to automatically synchronize posts between 2 blogs by same author?