2008/01/31


デジャブかもしれません
twitterを使ってみんなでアイデアを共有するサービス、ひらめいったーはてなスターサイト上で、twitterユーザのアイコンが表示されるようにするグリモン書いた。

続きを読む...

Posted at by




その1 3桁ごとに区切る - PleasureDelayerDiary はてなブックマーク数


Number.prototype.split3_1 = function() {
    var r = ""; 
    var s = this.toString().split("").reverse();
    for(var i = 0; i < s.length; i++) {
        if(i % 3 == 0 && i != 0 && s[i] != "-") {
            r = s[i] + "," + r
        } else {
            r = s[i] + r;
        }
    }  
    return r;
}

その2 iandeth. - javascriptで数値をカンマ区切り文字列に変換する関数メモ はてなブックマーク数


Number.prototype.split3_2 = function () {
    var to = String(this);
    var tmp = "";
    while (to != (tmp = to.replace(/^([+-]?\d+)(\d\d\d)/,"$1,$2"))){
        to = tmp;
    }
    return to;
}

その3 JavaScriptで数値を3桁ごとに区切る - 0x集積蔵 はてなブックマーク数


Number.prototype.split3_3 = function() {
    var m = (this &lt; 0) ? -1 : 1;
    var str = String(this*m).split('.');
    var arr = String(str[0]).split(''), len = Math.ceil(arr.length/3), res = [];
    for (var i =0;i&lt;len;++i) res.push(arr.splice(-3,3).join(''));
    return (m == -1 ? '-' : '') + res.reverse().join(',') + (str[1] ? '.' + str[1] : '');
};

その4 [JavaScript]数値を3桁ごとに区切る はてなブックマーク数


Number.prototype.split3_ore = function() {
  ('' + this).match(/(-?)([0-9]+)(\.[0-9]*)?/);
  var sp = [RegExp.$1, RegExp.$2, RegExp.$3];
  var x = Math.floor(sp[1].length / 3) * 3;
  var len = sp[1].length;
  return sp[0] + (sp[1].substr(0, len - x)) + (len - x == 0 ? '' : ',') +
         (sp[1].substr(len - x, x).match(/[0-9]{3}/g).join(',')) + sp[2];
}
私ならこう書く。
Number.prototype.split3 = function() {
  var r = "", s = this.toString().split("").reverse().join("").replace(/\d{3}/g,
    function(v){r+=v+',';return ''});
  return (r + s).split("").reverse().join("");
}
alert((1000000).split3()) // 1,000,000
文字列を逆にして、replaceに指定した関数で3桁毎にカンマを入れた結果と、空で置換したsubstituteの結果(あまった結果)を足す。その後文字列を逆にして戻す。
マイナスもたぶんOK。


追記1
しまった。チェック甘すぎ。
Number.prototype.split3 = function() {
  var r = "", s = this.toString().split("").reverse().join("").replace(/\d{3}/g,
    function(v){r+=v+',';return ''});
  if (!s.match(/\d/)) r = r.substr(0, r.length-1);
  return (r + s).split("").reverse().join("");
}
計測してみる!
mattnおそ!www
関数呼び出しコストか?
追記2
うむ。小数か...
Number.prototype.split3_mattn2 = function() {
  var r = '', s = this.toString();
  s.match(/(-?)([0-9]+)(\.[0-9]*)?/);
  var sp = [RegExp.$1, s = parseInt(RegExp.$2), RegExp.$3];
  while(s >= 1000) {
    r = ',' + (s%1000) + r;
    s = parseInt(s/1000);
  }
  return sp[0] + s + r + sp[2];
}
-12345678.2356を3桁ごとに区切るテスト

タイム測定



うむ。それでも遅い。
Posted at by




そうなのか...知らなかった。

The Future of JavaScript
var a = [1,2,3]; var a2 = a.pop; var b = a2() は?
  this のコンテキストが変わってるのでエラーになる
なんでだろ。 メソッド呼び出し時に正しくコンテキストスイッチしてないって事?

例えば var obj = new(function Clazz() {
  var self = this;
  self.value = 0;
  self.plus = function() { self.value++; };
})();
var func_plus = obj.plus;
func_plus();
alert(obj.value);
なら結果は「1」になるよね?それってもしかして var obj = new(function Clazz() {
  this.value = 0;
  this.plus = function() { this.value++; };
})();
var func_plus = obj.plus;
func_plus();
alert(obj.value);
こうなってるって事じゃないの?うむ...それっていいの?
コンテキスト保持しておけば function Clazz() {
  var self = this;
  self.value = 0;
  self.plus = function() { self.value++; };
}
var obj1 = new Clazz();
var obj2 = new Clazz();
var func_plus = obj1.plus;
func_plus();
obj2.plus = func_plus;
obj2.plus();
alert(obj1.value + "," + obj2.value);
こんな事しても、例外出ずに動くよね?obj1.valueがインクリメントされる結果になるけど...

これってperlなら #!/usr/bin/perl

use strict;
use warnings;

package Clazz;
sub new {
  my $class = shift;
  my $self = { value => 0 };
  return bless $self, $class;
}
sub plus {
  my $self = shift;
  ++$self->{value};
  1;
}

my $obj1 = Clazz->new;
my $obj2 = Clazz->new;

my $func_plus = *Clazz::plus;
warn "func_plus=".$func_plus."\n";
$func_plus->($obj1);
warn sprintf "obj1->{value}=%d, obj2->{value}=%d\n",
    $obj1->{value}, $obj2->{value};

$obj2->{plus} = $func_plus;
$obj2->plus();
warn sprintf "obj1->{value}=%d, obj2->{value}=%d\n",
    $obj1->{value}, $obj2->{value};
こんなサンプルかな。実行結果は func_plus=*Clazz::plus
obj1->{value}=1, obj2->{value}=0
obj1->{value}=1, obj2->{value}=1
サブルーチンにはselfを渡すのはインスタンス自身になるから問題無く動くね。javascriptのようにfunctionの参照自身がインスタンス参照を保持しちゃってる訳じゃなので問題は発生しないか...

pythonなら class Clazz:
  def __init__(self):
    self.value = 0

  def plus(self):
    self.value = self.value + 1

obj1 = Clazz()
obj2 = Clazz()

func_plus = obj1.plus
print "func_plus=%s" % func_plus
func_plus()
print "obj1.value=%d, obj2.value=%d" % (obj1.value, obj2.value)

obj2.plus = func_plus
obj2.plus()
print "obj1.value=%d, obj2.value=%d" % (obj1.value, obj2.value)
こんなサンプルかな?実行結果は func_plus=<bound method Clazz.plus of <__main__.Clazz instance at 0xb7ef828c>>
obj1.value=1, obj2.value=0
obj1.value=2, obj2.value=0
pythonの場合は関数の参照自身がインスタンスの参照も保持しているから、いくらobj2.plusを上書きしてもobj2.valueが更新される訳じゃない。

rubyなら class Clazz
    def initialize() @value = 0 end
    def plus() @value += 1 end
    attr_accessor :value
end

obj1 = Clazz::new
obj2 = Clazz::new
func_plus = Clazz.instance_method :plus
puts "func_plus=%s" % func_plus
func_plus.bind(obj1).call
printf("obj1.value=%d, obj2.value=%d\n", obj1.value, obj2.value)
func_plus.bind(obj2).call
printf("obj1.value=%d, obj2.value=%d\n", obj1.value, obj2.value)
こんな感じ?実行結果は func_plus=#<UnboundMethod: Clazz#plus>
obj1.value=1, obj2.value=0
obj1.value=1, obj2.value=1
rubyの場合はperlぽいけど、UnboundMethodの呼び出しはまずインスタンスをbindしてから呼ぶ事になるので問題は発生しない。ちなみにobj1.plusを取得してobj2.plusに代入できないかやってみたけど、私の力足らずなのか出来なかった。

luaなら function Clazz()
  return {
    value = 0,
    plus = function(self)
      self.value = self.value + 1
    end
  }
end
local obj1 = Clazz()
local obj2 = Clazz()
local func_plus = obj1.plus
print("func_plus", func_plus)
func_plus(obj1)
func_plus(obj2)
print("obj1.value=", obj1.value)
print("obj2.value=", obj2.value)
こんな感じ?実行結果は func_plus   function: 0x8f36270
obj1.value= 1
obj2.value= 1
luaも結局selfを渡す事になるので、問題は派生しない。
ちなみにC++なら #include <stdio.h>

class Clazz {
private:
  int _value;
public:
  Clazz() : _value(0) {}
  void plus() { _value++; }
  int value() { return _value; }
};

int
main(int argc, char* argv[])
{
    Clazz* obj1 = new Clazz();
    Clazz* obj2 = new Clazz();

    typedef void (Clazz::*def_func_plus)();
    def_func_plus func_plus = &Clazz::plus;
    printf("func_plus=%p\n", func_plus);
    (obj1->*func_plus)();
    printf("obj1->value=%d, obj2->value=%d\n",
            obj1->value(), obj2->value());

    // obj2->plus = func_plus; # compile error

    return 0;
}
こんな感じ?実行結果は func_plus=0x8048574
obj1->value=1, obj2->value=0
まぁ、無茶すればobj2->plusも置き換えられない事はないけど、結果は見えてるからいいでしょ...

つまり、著名な言語で問題が発生しているのはjavascriptだけって事か...
それって...

まずくない?
Posted at by