FF的正则表达式神奇的负索引属性

March 10th, 2010

查了各种文档,没发现记载,可能是非正式属性
分别对应于正则表达式对象的6个属性
-1 : source
-2 : global
-3 : ignoreCase
-4 : lastIndex
-5 : multiline
-6 : sticky

比如 /a/[-2] 相当于 (/a/).global

admin Uncategorized

erlang的尾递归优化

March 10th, 2010

1. 计算 f(n) = f(n-1)+f(n-2)+f(n-3)
2. 倒序列表L

树形递归:

  1. foo(N) when N < 3 ->
  2.         N;
  3. foo(N) ->
  4.         foo(N - 1) + foo(N - 2) + foo(N - 3).

线性迭代(尾递归优化):

  1. foo(N) when N < 3 ->
  2.         N;
  3. foo(N) ->
  4.         foo_iter(0,1,2,N-3).
  5.  
  6. foo_iter(A,B,C,0) ->
  7.         A + B + C;
  8. foo_iter(A,B,C,Count) ->
  9.         foo_iter(B, C, A + B + C, Count - 1).

线性递归

  1. range(N) when N=:=0 ->
  2.         [];
  3. range(N) ->
  4.         [N-1|range(N-1)].

线性迭代(尾递归)

  1. revc(L) ->
  2.         revc_iter([],L).
  3.  
  4. revc_iter(T, []) ->
  5.         T;
  6. revc_iter(T,[H|L]) ->
  7.         revc_iter([H|T],L).

有兴趣的同学可以测一下,效率可不是差一个两个数量级的~

admin Uncategorized

有趣的“块级作用域”

February 24th, 2010
  1. var i=100;
  2. with({i:0}) for(;i<10;i++){
  3.     alert(i);
  4. }
  5. alert(i);
  1. var i = 100;
  2. ~function(i){
  3.     for(;i<10;i++){
  4.         alert(i);
  5.     }
  6. }(0);
  7. alert(i);

以上两种形式建立块级作用域,当然除了特殊需要很少有人这么去折腾…

admin Uncategorized

函数式编程 2 —— javascript 1.7

February 23rd, 2010

请使用支持JavaScript1.7以上版本的浏览器运行下面的代码

  1. function perms(list){
  2.     if(list.length)
  3.         return Array.concat.apply(
  4.             [],
  5.             [
  6.                 [O.concat(T) for each(T in I)] 
  7.                     for each([O,I] in list.map(function(o,i) [[o],perms(list.slice(0,i).concat(list.slice(i+1)))]))
  8.             ]
  9.         );
  10.     else
  11.         return [[]];
  12. }
  13.  
  14. alert(perms([1,2,3,4]).join("\n"));

JavaScript语法写Functional还是繁琐,上面的这个,用erlang来写的话只要两行——

  1. perms([]) -> [[]];
  2. perms(L) -> [[H|T] || H<-L, T<-perms(L--[H])].

admin Uncategorized

函数式编程

February 23rd, 2010

快速排序

  1. //纯算法,仅供研究,其实在浏览器下不快,js递归效率很差
  2. function qsort(arr){
  3.     if(!arr.length) return [];
  4.     var c = arr.shift();
  5.     return qsort(arr.filter(function(o){return o<=c?o:null}))
  6.         .concat([c])
  7.         .concat(qsort(arr.filter(function(o){return o>c?o:null})));
  8. }
  9. var a = [1,4,3,2,5,1,-1,3,2,4.5];
  10. alert(qsort(a));

admin Uncategorized

trac插件的bug

January 14th, 2010

1、account-mgr 的bug: 找回密码后不能登陆
修改acct_mgr/web_ui.py
if req.path_info != redirect_url: -> if req.href(req.path_info) != redirect_url:
http://trac-hacks.org/attachment/ticket/3233/redirect-fix.patch

2、codereview的bug: 插件设置出错后没有正确的出错信息
http://trac-hacks.org/attachment/ticket/6032/codereview.model.diff

admin Python

函数的可靠性

December 21st, 2009

http://bbs.51js.com/viewthread.php?tid=86342&pid=602059&page=1&extra=page%3D1#pid602059

要设计一个优秀的函数,基本的原则之一是这个函数的表现要可靠,有时候我们不经意间为了实现一个特性而违背了函数的可靠性,给使用者留下了“坑”,这是不应该的

  1. function test(){
  2.         var x = 1;
  3.         test = function(){
  4.             return x++;
  5.         }
  6.         return test();
  7.     }

这个函数之所以这么写,作者是想在函数中利用闭包特性定义一个局部静态变量,但是,这个函数是有问题的

  1. function test(){
  2.         var x = 1;
  3.         test = function(){
  4.             return x++;
  5.         }
  6.         return test();
  7.     }
  8.     var test2 = test; //中招
  9.     alert(test2());alert(test2());alert(test2()); //错了

所以,必须要消除这种“坑“,改用下面的写法:

  1. var test = (function(){
  2.     var x = 1;
  3.     return function() {
  4.         alert(x);
  5.         x ++;
  6.     }
  7. })();

最后,总结一下定义带有局部静态作用域的函数范式

  1. var myFunc = (function(){
  2.     var localVariable = "someValue";
  3.     return function(args...){
  4.         //function body
  5.     }
  6. })();

admin 前端技术

一个看似简单的问题

November 22nd, 2009

JavaScript求不大于且最接近于一个整数的偶数:

  1. function f(n){
  2.     return n & -2;
  3. }

admin Uncategorized

神奇的“连续”

August 31st, 2009

先看一段代码:

  1. Function.prototype.$continuous = function(fn){
  2.     var me = this;
  3.     return function(){
  4.         var currentArgs = Array.prototype.slice.call(arguments, 0, me.length);
  5.         var moreArgs = Array.prototype.slice.call(arguments, me.length);
  6.  
  7.         ret = me.apply(this, currentArgs);
  8.  
  9.         if(moreArgs.length > 0){
  10.             ret = fn.call(this, arguments.callee, ret, moreArgs);
  11.         }
  12.  
  13.         return ret;
  14.     }
  15. }

这个函数并不复杂,它的作用是包装一个函数,判断它实际调用的参数个数和形参个数,当实际调用的参数个数大于形参个数时,再用一个闭包进行后续操作,这个闭包有3个参数,分别是包装的函数自身、前次调用的返回值,以及多余的参数。

这个简单的函数其实比想象得有用:

  1. var add = function(x,y){
  2.     return x+y;
  3. }

add显然只是一个简单的两个数相加的程序,如果想让它支持多个数相加呢?

  1. function reducer(target, returnValue, moreArgs){
  2.     return target.apply(this, [returnValue].concat(moreArgs));
  3. }
  4. add = add.$continuous(reducer);
  5. var a = add(1,2,3,4,5)//a = 1+2+3+4+5=15

同样的:

  1. var max = function(x,y){
  2.     return x>y?x:y;
  3. }
  4. max = max.$continuous(reducer);
  5. var a = max(1,2,3,2,1); //a=3

还有别的作用:

  1. function processor(target, returnValue, moreArgs){
  2.     return [returnValue].concat(target.apply(this, moreArgs));
  3. }  
  4. var $ = function(id){
  5.     return document.getElementById(id);
  6. }.$continuous(processor);
  7. var els = $("a","b","c")//得到3个elements(返回数组)

最后总结一下:
$continuous本身很简单,但是它可以被reducer或processor作用,也就是说,返回结果可以被push,也可以被reduce,上面的reducer实际上是先push再reduce,后面的processor我改了一个次序,先reduce再push,就能获得截然不同的用途。

不知道通过上面的叙述,大家对脚本库核心的基本设计和函数式(functional)编程的思想方法有没有新的认识。不管怎样,JavaScript灵活多变的特性,总能让前端开发充满乐趣。 :)

admin 前端技术

JavaScript的大数加法、乘法和乘方

June 2nd, 2009

这里用一个小技巧:|0默认转为数值并取整,因为p和q可能长度不同,有可能会出现p[i]或q[j]成为undefined,|0比parseInt更强,可以自动将undefined的值转为0,这样就不用判断p[i]或q[j]是否为数值了。
可以将/\d{1,N}/g改成N位一次运算,默认是4位一次。

  1. function bigNumMulti(a,b){
  2.     var p = a.match(/\d{1,4}/g).reverse();
  3.     var q = b.match(/\d{1,4}/g).reverse();
  4.     var f1 = 0;
  5.     var result = "0";
  6.  
  7.     for(var i = 0; i < p.length; i++){
  8.         var f2 = 0;
  9.         for(var j = 0; j < q.length; j++){
  10.             var t = (p[i]|0)*(q[j]|0);
  11.             t += new Array(f1+f2+1).join("0");
  12.             result = bigNumAdd(result, t);
  13.             f2 += q[j].length;
  14.         }
  15.         f1 += p[i].length;
  16.     }
  17.     return result;
  18. }
  19. function bigNumAdd(a,b){
  20.     var m = a.split('').reverse();
  21.     var n = b.split('').reverse();
  22.     var ret = [];
  23.     var s = 0;
  24.  
  25.     for(var i = 0; i < a.length || i < b.length; i++){
  26.         var t = (m[i]|0) + (n[i]|0) + s;
  27.  
  28.         ret.push(t%10);
  29.         s = (t/10)|0;
  30.     }
  31.     if(s){
  32.         ret.push(s);
  33.     }
  34.     return ret.reverse().join('');
  35. }
  36.  
  37. function bigNumPow(a,b){
  38.     var ret = "1";
  39.     for(var i = 0; i < b; i++){
  40.         ret = bigNumMulti(ret,a.toString());
  41.     }
  42.     return ret;
  43. }
  44. document.write(bigNumPow(36,16));

admin 前端技术