PHPの関数をJavaScriptで使おうプロジェクト – php.js

PHPやPerlなどでおなじみの関数群を、可能な限りJavaScriptで表現しようと言う不思議な取り組みがある。

Functions overview – php.js.

何が意味不明なのかは、それぞれのJavaSCriptで記述された関数の中身を見ればわかる。
どの関数も結構な長さの記述で構成されており、単純な名称のラッピングで済んでいるケースはほとんどない。
JavaScriptとPHP、サーバサイドとクライアント再度、という根本的な生い立ちの違いを超えた言語仕様の不一致をまざまざ感じる、不思議なプロジェクトだ。

代表作として、sprintf()を見てみよう。

sprintf() on JavaScript


function sprintf () {
// Return a formatted string
//
// version: 1109.2015
// discuss at: http://phpjs.org/functions/sprintf
// + original by: Ash Searle (http://hexmen.com/blog/)
// + namespaced by: Michael White (http://getsprink.com)
// + tweaked by: Jack
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + input by: Paulo Freitas
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + input by: Brett Zamir (http://brett-zamir.me)
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// * example 1: sprintf(“%01.2f”, 123.1);
// * returns 1: 123.10
// * example 2: sprintf(“[%10s]”, ‘monkey’);
// * returns 2: ‘[ monkey]’
// * example 3: sprintf(“[%’#10s]”, ‘monkey’);
// * returns 3: ‘[####monkey]’
var regex = /%%|%(\d+\$)?([-+\’#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
var a = arguments,
i = 0,
format = a[i++];

// pad()
var pad = function (str, len, chr, leftJustify) {
if (!chr) {
chr = ‘ ‘;
}
var padding = (str.length >= len) ? ” : Array(1 + len – str.length >>> 0).join(chr);
return leftJustify ? str + padding : padding + str;
};

// justify()
var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {
var diff = minWidth – value.length;
if (diff > 0) {
if (leftJustify || !zeroPad) {
value = pad(value, minWidth, customPadChar, leftJustify);
} else {
value = value.slice(0, prefix.length) + pad(”, diff, ‘0’, true) + value.slice(prefix.length);
}
}
return value;
};

// formatBaseX()
var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
// Note: casts negative numbers to positive ones
var number = value >>> 0;
prefix = prefix && number && {
‘2’: ‘0b’,
‘8’: ‘0’,
’16’: ‘0x’
}[base] || ”;
value = prefix + pad(number.toString(base), precision || 0, ‘0’, false);
return justify(value, prefix, leftJustify, minWidth, zeroPad);
};

// formatString()
var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) {
if (precision != null) {
value = value.slice(0, precision);
}
return justify(value, ”, leftJustify, minWidth, zeroPad, customPadChar);
};

// doFormat()
var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {
var number;
var prefix;
var method;
var textTransform;
var value;

if (substring == ‘%%’) {
return ‘%’;
}

// parse flags
var leftJustify = false,
positivePrefix = ”,
zeroPad = false,
prefixBaseX = false,
customPadChar = ‘ ‘;
var flagsl = flags.length;
for (var j = 0; flags && j < flagsl; j++) { switch (flags.charAt(j)) { case ' ': positivePrefix = ' '; break; case '+': positivePrefix = '+'; break; case '-': leftJustify = true; break; case "'": customPadChar = flags.charAt(j + 1); break; case '0': zeroPad = true; break; case '#': prefixBaseX = true; break; } } // parameters may be null, undefined, empty-string or real valued // we want to ignore null, undefined and empty-string values if (!minWidth) { minWidth = 0; } else if (minWidth == '*') { minWidth = +a[i++]; } else if (minWidth.charAt(0) == '*') { minWidth = +a[minWidth.slice(1, -1)]; } else { minWidth = +minWidth; } // Note: undocumented perl feature: if (minWidth < 0) { minWidth = -minWidth; leftJustify = true; } if (!isFinite(minWidth)) { throw new Error('sprintf: (minimum-)width must be finite'); } if (!precision) { precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == ‘d’) ? 0 : undefined;
} else if (precision == ‘*’) {
precision = +a[i++];
} else if (precision.charAt(0) == ‘*’) {
precision = +a[precision.slice(1, -1)];
} else {
precision = +precision;
}

// grab value using valueIndex if required?
value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];

switch (type) {
case ‘s’:
return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
case ‘c’:
return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
case ‘b’:
return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
case ‘o’:
return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
case ‘x’:
return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
case ‘X’:
return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
case ‘u’:
return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
case ‘i’:
case ‘d’:
number = (+value) | 0;
prefix = number < 0 ? '-' : positivePrefix; value = prefix + pad(String(Math.abs(number)), precision, '0', false); return justify(value, prefix, leftJustify, minWidth, zeroPad); case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': number = +value; prefix = number < 0 ? '-' : positivePrefix; method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())]; textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2]; value = prefix + Math.abs(number)[method](precision); return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform](); default: return substring; } }; return format.replace(regex, doFormat); }[/PHP] printf()がない言語に、sprintf()をアドオンすることがいかに大変かがわかるだろう。 また、mail()やfopen()など、JavaScriptが根本的にはクライアントサイドの言語であることを忘れてしまうかのような関数も用意されている。 (中の実装をみると、「あぁ、なるほどね。そういうことか」と感じることだろう) PHPがグングンのびた時代に、それに乗っかった世代からは重宝がられるかもしれないが、ある意味どんなフレームワークよりもふざけた視点で作られたphpjsは、パフォーマンスなどを考えると実用性は乏しい。 それでもスポット的に使える局面はあるのかもしれない。 ※私も使ったことがある。しかも仕事で。

A4用紙でCDを包む優れた方法

バルクCD制作価格が底値な今、業者がいまだ強気で付けてきているパッケージの制作コストを、この方法ならバルクCD制作価格が底値な今、業者がいまだ強気で付けてきているパッケージの制作コストをバンドヤムービーメイキングチームの努力次第で押さえることができます。
しかも、エレガントに。

動画だとこんな感じ。非常にわかりやすい。
※細かい話、上記画像の方法よりも少しだけリッチです。でも、ほとんど同じです。

リンク先には几帳面な人のためのPDF折り線テンプレートも。
昔から方々でいろんな人が発明した方法があったのですが、ここまで洗練されている方法は珍しいので紹介です。
A4の長辺って、考えてみればCDの径2.5枚分+厚み×2くらいのものなんですよね。あらためて認識したまめ知識でした。この数字のマジックに運命的な何かを感じます。

感じますよね?
あれ?

参考:http://attrip.jp/58475
参考:http://blog.photopierre.com/archives/2009/10/06-2323.html

Koboが来た!|おしゃれガールがKoboやKindleで本を読む時代はくるか

Kobo Rakuten editionが発売され、僕の手元にもついに現物が届きました。
機能的な詳細レポは先行したGizmodeさんに任せて、勝手に所感を述べてみる。

とにかく軽い。動きも軽快です。
動きも意匠も作りさえもちゃっちくて、ページをめくるたびにチカチカうるさかったあのe-Inkのイメージはどこに行ったのでしょう?
セットアップも、指定された http://rakuten.kobosetup.com/ からセットアップ兼運用アプリケーション(いわゆるiTunesみたいなもの)をダウンロードしてきて楽天アカウントを入れれば後はYES連打で完了します。

随所での噂通り、ハードウェア的にはかなり洗練された印象を受けます。
※個人的にはKindleの触感よりスキかも。
とりあえず手元にあったのだめカンタービレの目次をスキャンして取込、表示してみました。
意外にもコミックサイズの吹き出しも読むに耐える解像度を確保しています。

僕はクロを買いましたが、マットなブラックとe-Inkディスプレイのコントラストも良く、製品として完成された印象を受けます。
また、この軽さでブラウザ内蔵というのも、なんか、別にあんまり使わないだろうけどわくわくするのです。

白黒で見たWEBは、なんだか新鮮。
いつものページもなんだか違えて見えます。

他にも手書きメモ機能なんかもあって、これはKoboをUSBでつないだ時にマウントされるフォルダから簡単に取り出す事ができた。
書き味は。。。画像を見て推して知るべし。(with Bamboo Styrus for iPad)

KoboやKindle、iPadやKindle Fireが出てきて、ハードウェア的にはプロトタイプが出そろった感じ。
e-Inkはもうすこしこの流れで洗練され続けて、次の世代あたりが使用感的にも爆発的に受け入れられる予感がします。
今はSony Readerなんかのショボショボの端末から比べればかなりパフォーマンスがあがったとは言え、まだ新し物好きのおもちゃの域を出ない気がします。

なかなかぐずぐずしてる電子書籍端末が普及する鍵はどこにあるんでしょう?
僕は表題の写真のように、おしゃれ女子が優雅に使いこなす絵に似合ってこそ、はじめて人間の「道具」となり得る気がしてます。
あのiPadですら、様々なバランス(重すぎるとか)を考慮した時に、手放しで優雅なひとときに似合うとは言い難い。
e-Ink端末も、iPadの様なリッチで重い端末も、惜しいところで「日常スタイル」でのバランスをとり切れてない。

気は早いかもしれないですが、次の世代でその原型が見られる可能性は充分にある。
Koboを見てるとそんな気がするのです。

自主制作映画「ウシロ」本編 Horror movie USHIRO “The Behind” – YouTube

Art

久しぶりにクオリティの高い動画を見た。
基本はストレートなホラー映画だけど、主演女性がすこぶるかっこよくていい。
YouTubeを使って本気で自主映画を発信する時代になったんだな。
10分程度なので、ちょっとした時間にもどうぞ。

自主制作映画「ウシロ」本編 Horror movie USHIRO "The Behind" – YouTube.

ご丁寧に予告編まであった。
こちらもなかなかのクオリティ。

FaceBook: http://www.facebook.com/pages/GinORFieLD/166858086722914
初監督作品「ウシロ」”The Behind”

出演 古庄未來 新谷妃呂子
監督・脚本・撮影・編集 荻野龍登
制作協力 ロケットランチ http://www.making-indie-movie.com/

sh|shellで条件分岐:case文

シェルでの条件分岐にはcase文が便利。
変数内の文字列で条件分岐する場合はcase、それ以外はif、というところだろうか。

case "$var" in
  "a" ) 処理1 ;;
  "bb" ) 処理1 ;;
  "c c c" ) 処理3 ;;
esac

case_word.sh

#!/bin/bash

# "q" 入力以外で終了しないように無限ループにする。
while :
do
  read key
  case "$key" in
    "a" ) echo "aが入力されました。" ;;
    "bb" ) echo "bbが入力されました。" ;;
    "c c c" ) echo "c c cが入力されました。" ;;
    "q" ) echo "終了します。"
          break ;;
  esac
done

exit 0

このシェルスクリプト case_word.sh の実行結果は、以下の通りとなる。

$ ./case_word.sh
a ←キー入力
aが入力されました。
bb ←キー入力
bbが入力されました。
c c c ←キー入力
c c cが入力されました。
a aaa ←キー入力
b b ←キー入力
ccc ←キー入力
q ←キー入力
終了します。
$

因に条件にはワイルドカード「*」も指定できます。
条件によっては 1つめの条件+2つめの条件と、複数の条件にマッチする場合が出てきますが
最初の条件の処理が実行されますのでご注意ください。

参考:http://shellscript.sunone.me/case.html
参考:http://itpro.nikkeibp.co.jp/article/COLUMN/20060228/231123/

photo by: Alex E. Proimos

sh|shell内で文字列置換

シェルスクリプト内で文字列を置換するのにえらく時間がかかった。。。
結局echoをパイプ実行して代入するという方法に落ち着いた。

aaa=abcdollers
bbb=`echo $aaa | sed -e 's/abc/100/' `
echo bbb

上記方法だと、検出した最初の「abc」を「100」に置き換える。
文字列内全てを置き換えたい場合は

aaa=abcdollers
bbb=`echo $aaa | sed -e 's/abc/100/g' `
echo bbb

とする。
何でもそうだけど、わかっちゃえば簡単。。。。

photo by: Rosa Menkman