Z-Termっていまいち使い勝手がよくない。
Mac環境下では、Z-Termを利用してシリアル接続していたが、通常のターミナルからscreenコマンドにボーレート引数を渡せばシリアル接続できる事を知りこれは便利。
% screen /dev/tty.XXXXXXX 115200
l'essentiel est invisible pour les yeux
Z-Termっていまいち使い勝手がよくない。
Mac環境下では、Z-Termを利用してシリアル接続していたが、通常のターミナルからscreenコマンドにボーレート引数を渡せばシリアル接続できる事を知りこれは便利。
% screen /dev/tty.XXXXXXX 115200
今日は、第二種電気工事士の締切日でした。
試験日がWWDCの日程とダブルブッキングしている事もしらず、申し込みを完了させている人もいましたが、受験料を振込み無事申し込み完了。第二種電気工事士を取得して、キャリアパスを変更しようと考え中。
そう、Mr.ZigBeeなるブログを始めました。
ZigBeeメン目指します。
Posted by ZigBee Man
Scalaでは、オブジェクトの作成〜オブジェクトのメソッド呼び出しによる初期化のための、シンタックスシュガーが用意されている。コンストラクタでオブジェクトを作成して、その後オブジェクトのメソッドを呼び出してオブジェクトを初期化する事はよく例を一つ紹介。
Jettyのハンドラーの初期化をシンタックスシュガーでコーディングした例。ブロック内のスコープは、オブジェクト内でのスコープと同じになるので、メソッドを呼ぶ事ができる。
before:
val handler = new ResourceHandler
handler.setResourceBase("/webapp")
after:
val handler = new ResourceHandler { setResourceBase("/webapp) }
Scalaでは、Javaの型の多くをラップしたクラスにて再定義している。
byte型 -> scala.Byte
short型 -> scala.Short
int型 -> scala.Int
など。
そのため、ScalaからJavaのライブラリを利用していると、ライブラリのAPIの返り値がJavaの型で、Scalaのラッパークラスではないので変換が必要な事がよくある。例えば、java.util.List型は、ScalaのSeq[A]を継承していないので、enumerableではない。
このため、Scalaの標準ライブラリ中にいくつかの明示的な変換規則を定義してある。例えば、java.util.List[T]からList型への変換などは、scala.collection.jcl.Conversion.convertListを読みこむだけで、後はScalaの言語仕様の明示的な型変換機構により自動的に変換してくれる。
var primNumberList = new java.util.ArrayList[Int](3)
primNumberList.add(1)
primNumberList.add(3)
primNumberList.add(5)
// ScalaのSeq[A]を実装していないのでイテレーターとして扱えない
primNumberList.foreach { println(_) } // ERROR: エラー
// implicit conversionの読みこみ
import scala.collection.jcl.Conversions.convertList
primNumberList.foreach { println(_) }
1
3
5
package scala.collection.jcl
object Conversions {
implicit def convertSet[T](set : java.util.Set[T]) = Set(set)
implicit def convertList[T](set : java.util.List[T]) = Buffer(set)
implicit def convertSortedSet[T](set : java.util.SortedSet[T]) = SortedSet(set)
implicit def convertMap[T,E](set : java.util.Map[T,E]) = Map(set)
implicit def convertSortedMap[T,E](set : java.util.SortedMap[T,E]) = SortedMap(set)
implicit def unconvertSet[T](set : SetWrapper[T]) = set.underlying
implicit def unconvertCollection[T](set : CollectionWrapper[T]) = set.underlying
implicit def unconvertList[T](set : BufferWrapper[T]) = set.underlying
implicit def unconvertSortedSet[T](set : SortedSetWrapper[T]) = set.underlying
implicit def unconvertMap[T,E](set : MapWrapper[T,E]) = set.underlying
implicit def unconvertSortedMap[T,E](set : SortedMapWrapper[T,E]) = set.underlying
}
DreadLocks 0.2を公開しました。今回のアップデートでは、テンプレート中のScala構文中でのタプルとシンボルへの対応とScalaInterpreterの実装をリファクタリングし事が主な変更点です。現在、対応している構文は、if-elseif-elseでの条件分岐、算術式の計算、変数へのメソッドの呼び出し、iterableなSeqやmapに対するループ等です。
Jarファイルは、dreadlocks-0.2.1.jarからダウンロード。
以下のような、タプルの要素への参照を含むforeachのループが書けます。
dreadlocks.txt
Hamburger Cafe:
<?sc cafes.foreach { cafe => ?>
* ${cafe._1} in ${cafe._2}
<?sc } ?>
val tmpl = examplTmplateFile("foreach2.shtml")
val source = Source.fromFile(tmpl).getLines.mkString
val template = Template(source)
val context = Context("cafes" -> List(("Authentic", "Akasaka, Tokyo"), ("FELLOWS", "Komazawa, Tokyo")))
val output = template.render(context)
Console.println(output)
// Hamburger Cafe:
// * Authentic in Akasaka, Tokyo
// * FELLOWS in Komazawa, Tokyo
//
BenchmarkSuite - Scalaのベンチマークライブラリ
ページ中段BenchmarkSuiteよりGitHubへリンクしています。
Jarファイルは、BenchmarkSuite-1.0.jarから。
知ってるんだから。Scalaに標準のベンチマークライブラリscala.testing.Benchmark...が、測定したい対象の度にBenchmarkクラスを継承して実装しないといけないなど、APIがかなり硬派! LLでなまった体には正直キツイです。そこで、コードブロックを対象にベンチマークを測定するライブラリが、BenchmarkSuiteです。現在の所、実行時間のみ計測できるとてもシンプルなライブラリです。
使い方は、次の通りです。Benchmark.runに引数を一つ持つブロックを渡し、ブロック引数に対して、reportメソッドを呼ぶだけです。ラベルや実行回数を指定できます。
import org.scalalites.benchmark.Benchmark
Benchmark.run("Benchmark of ack:") { b =>
def ack(x: Int, y: Int): Int = x match {
case 0 => y + 1
case _ => y match { case 0 => ack(x - 1, 1); case _ => ack(x - 1, ack(x, y - 1))}
}
// run over the test named "ack(3, 2) x 50" 50 times
b.report("ack(3, 4) x 10", 10) { ack(3, 4) }
// If you don't pass second argument run benchmark once.
b.report("ack(3, 2)") { ack(3, 2) }
}
// Output
// Benchmark of ack:
// ack(3, 4) x 10 : 4.730000 sec (avg. 0.473000 sec)
// ack(3, 2) x 1 : 0.029000 sec
DreadLocks - Scalaベースのテンプレートエンジン
Scalaのテンプレートエンジンを探していたけど見つからなかったので、DreadLocksテンプレートエンジンを実装しました。現在は、基本的なScalaの構文のみサポートしています。完全なScalaプログラムのサポートと高速化が次のリリースの目標としています(foreachやif文は実装済み)。ソースコードは、GitHub dreadlocks/trunkで、今後のマイルストーンとロードマップは、TwitterやGoogle Groupsで確認できるので、よければどうぞ。
簡単なサンプルコードは、以下の通り。
hamburgers.txt:
Delicious hamburger restraunts in Japan:
<?sc restraunts.foreach { restraunt => ?>
* ${restraunt}
<?sc } ?>
Side menus:
<?sc if(haveSideMenu) { ?>
* ${sideMenus("potato")}
* ${sideMenus("coleslaw")}
<?sc } ?>
Hamburgers.scala
import org.scalalites.dreadlocks._
// You can specify instance of java.io.File, scala.io.Source or String to constructor of Template class.
val source = Source.fromFile("template_variable.shtml")
val template = Template(source)
val context = Context("restraunts" -> List("Baker Bounce", "Great Burger", "FELLOWS"),
"haveSideMenu" -> true,
"sideMenus" -> HashMap("potato" -> "French fries", "coleslaw" -> "Coleslaw"))
val output = template.render(context)
// Console.println(output)
// Delicious hamburger restraunts in Japan:
// * Baker Bounce
// * Great Burger
// * FELLOWS
//
// Side menus:
// * French fries
// * Coleslaw
scalaの言語仕様に用意されているヒアドキュメントを使用すれば、エスケープシーケンスをエスケープする必要が無いため正規表現が簡単に書ける。
before
var bwh = "90.60.88"
val pat = new Regex("\\d+")
pat.findAllIn(bwg) foreach println
"""\d+""".r.findAllIn("90.60.58") foreach println
Oops, long time no post.
Boost has powerful Graph library named BGL(Boost Graph Library), and serialization libraries, however the library for serialization of boost::subgraph doesn't exist, so i implement simple library to do that.
boost_subgraph_serialize was commited on Github, so you can check out them with git.
% git clone git://github.com/rakuto/boost_subgraph_serialize.git
/**
* Serialization of boost::subgraph
*
* Created by Rakuto Furutani <xri://rakuto/> (rakuto+nospam@gmail.com)
*
* output:
* original:
* 0 <--> 1 2
* 1 <--> 0 4
* 2 <--> 0
* 3 <-->
* 4 <--> 5 5 1
* 5 <--> 4 4
* children num: 1
*
* from file:
* 0 <--> 1 2
* 1 <--> 0 4
* 2 <--> 0
* 3 <-->
* 4 <--> 5 5 1
* 5 <--> 4 4
* children num: 1
*/
#include <fstream>
#include <string>
#include <boost/graph/subgraph.hpp>
#include <boost/graph/graph_utility.hpp>
// arhivers
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include "subgraph_serialize.h"

using namespace boost;
typedef property<vertex_name_t, char> VertexProperty;
typedef property<edge_index_t, uint32_t,
property<edge_weight_t, uint32_t> > EdgeProperty;
typedef subgraph<adjacency_list<listS, vecS, undirectedS, VertexProperty, EdgeProperty> > Graph;
static const char* DAT_FILE_NAME = "subgraph.dat";
int main()
{
enum {A, B, C, D, E, F, N};
const char* node_names = "ABCDEF";
// create root graph
Graph root(N);
property_map<Graph, vertex_name_t>::type vertex_names = get(vertex_name_t(), root);
for(uint32_t i = 0; i < N; ++i) vertex_names[i] = node_names[i];
add_edge(A, B, EdgeProperty(1), root);
add_edge(A, C, EdgeProperty(2), root);
add_edge(E, F, EdgeProperty(3), root);
// create sub graph
enum {B1, E1, F1}; // refering to vertices in sub_g1
Graph& sub_g1 = root.create_subgraph();
add_vertex(B, sub_g1);
add_vertex(E, sub_g1);
add_vertex(F, sub_g1);
add_edge(E1, F1, sub_g1);
add_edge(B1, E1, sub_g1);
std::cout << "original:" << std::endl;
print_graph(root);
std::cout << "children num: " << root.num_children() << std::endl;
// serialize and save graph
std::ofstream ofs(DAT_FILE_NAME, std::ios::out | std::ios::binary);
if(!ofs.is_open()) {
std::cerr << "Can't open " << DAT_FILE_NAME << " file." << std::endl;
return EXIT_FAILURE;
}
archive::binary_oarchive oa(ofs);
oa << root;
ofs.close();
// Try to restore saved graph
Graph g;
std::ifstream ifs(DAT_FILE_NAME, std::ios::in | std::ios::binary);
if(!ifs.is_open()) {
std::cerr << "Can't open " << DAT_FILE_NAME << " file." << std::endl;
return EXIT_FAILURE;
}
archive::binary_iarchive ia(ifs);
ia >> g;
std::cout << "\nfrom file:" << std::endl;
print_graph(g);
std::cout << "children num: " << g.num_children() << std::endl;
return EXIT_SUCCESS;
}
/**
* Serialization of boost::subgraph
*
* Created by Rakuto Furutani <xri://rakuto/> (rakuto+nospam@gmail.com)
*/
#ifndef SUBGRAPH_SELIALIZE_H
#define SUBGRAPH_SELIALIZE_H
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/subgraph.hpp>
namespace boost {
namespace serialization {
template<class Archive, class Graph>
inline void save(Archive& ar,
const subgraph<Graph> graph,
const unsigned int /* file_version*/)
{
typedef typename subgraph<Graph>::vertex_descriptor Vertex;
typedef typename subgraph<Graph>::const_children_iterator ChildrenIter;
// serialize global verticies and edges
size_t num_children = graph.num_children();
bool root = graph.is_root();
ar << BOOST_SERIALIZATION_NVP(root);
ar << BOOST_SERIALIZATION_NVP(num_children);
ar << BOOST_SERIALIZATION_NVP(graph.m_graph);
ChildrenIter ci, ci_end;
tie(ci, ci_end) = graph.children();
for(; ci != ci_end; ++ci) {
ar << *ci;
}
}
template<class Archive, class Graph>
inline void load(
Archive& ar,
subgraph<Graph>& graph,
const unsigned int /* file_version */)
{
typedef typename subgraph<Graph>::vertex_descriptor Vertex;
typedef typename Graph::vertex_iterator VertexIter;
Graph g;
bool root;
size_t num_children;
ar >> BOOST_SERIALIZATION_NVP(root);
ar >> BOOST_SERIALIZATION_NVP(num_children);
ar >> BOOST_SERIALIZATION_NVP(g);
if(root) {
graph.m_graph = g;
} else {
VertexIter vi, vi_end;
tie(vi, vi_end) = vertices(g);
graph.create_subgraph(vi, vi_end);
}
for(size_t i = 0; i < num_children; ++i) {
ar >> BOOST_SERIALIZATION_NVP(graph);
}
}
template<class Archive, class Graph>
inline void serialize(
Archive& ar,
boost::subgraph<Graph>& graph,
const unsigned int file_version)
{
boost::serialization::split_free(ar, graph, file_version);
}
} // namespace serialization
} // namespace boost
#endif
Revision 37555時点で、106の命令コードが実装されていて、103の命令コードについてドキュメントがコメント形式で与えられている。
命令コードドキュメントの生成
% cd /path/to/WebKit/JavaScriptCore
% perl docs/make-bytecode-docs.pl VM/Machine.cpp docs/bytecode.html
var d = new Date();
print(d.getFullYear(), 1 + d.getMonth(), d.getDate());
% ./JavaScriptCore/build/Debug/jsc -d date_test.js
18 instructions; 388 bytes at 0x905b50; 1 parameter(s); 18 callee register(s)
[ 0] enter
[ 1] mov r-14, r0
[ 4] mov r2, r0
[ 7] resolve_global r3, [object global], Date(@id0)
[ 13] get_by_id r4, r3, prototype(@id1)
[ 21] construct r-14, r3, r4, 5, 1, 14
[ 28] construct_verify r-14, r5
[ 31] resolve_func r2, r3, print(@id2)
[ 35] get_by_id r6, r-14, getFullYear(@id3)
[ 43] call r5, r6, r-14, 7, 1, 16
[ 50] mov r7, r1
[ 53] get_by_id r8, r-14, getMonth(@id4)
[ 61] call r9, r8, r-14, 9, 1, 18
[ 68] add r6, r7, r9
[ 73] get_by_id r8, r-14, getDate(@id5)
[ 81] call r7, r8, r-14, 9, 1, 18
[ 88] call r2, r3, r2, 4, 4, 16
[ 95] end r2
Identifiers:
id0 = Date
id1 = prototype
id2 = print
id3 = getFullYear
id4 = getMonth
id5 = getDate
Constants:
r0 = undefined
r1 = 1
StructureIDs:
[ 7] resolve_global: 0x0
[ 13] get_by_id: 0x0
[ 35] get_by_id: 0x0
[ 53] get_by_id: 0x0
[ 73] get_by_id: 0x0
2008 10 13
End: undefined
LEAK: 135 StructureID
%
「recursive callを得意とするV8が、recursive callに比重をおいた、V8 Benchmark Suiteで速い!速い!と語られるのはフェアではない」
今回、正規表現のみに焦点を当ててJavaScriptエンジンを比較してみた。
環境


< dnaInput = dnaInput.replace(k, subs[k], "g")
---
> dnaInput = dnaInput.replace(new RegExp(k, 'g'), subs[k]);
% js
js> 'aaaaa'.replace('a', '_$&_', 'g') # SpiderMonkeyでは、gフラグが有効
_a__a__a__a__a_
% v8-shell
V8 version 0.2.5
> 'aaaaa'.replace('a', '_$&_', 'g') # v8では、gフラグは無効
_a_aaaa
% jsc
> 'aaaaa'.replace('a', '_$&_', 'g') # SFXでも、gフラグは無効
_$&_aaaa
>'aaaaa'.replace(/a/, '_$&_', 'g')
_a_aaaa
JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
{
// 引数の処理
if (pattern->isObject(&RegExpObject::info)) {
// 第一引数がRegExpオブジェクトのケースの処理
}
// 第一引数が文字列の場合
// First arg is a string
UString patternString = pattern->toString(exec);
int matchPos = source.find(patternString);
int matchLen = patternString.size();
// Do the replacement
if (matchPos == -1)
return sourceVal;
if (callType != CallTypeNone) {
ArgList args;
args.append(jsSubstring(exec, source, matchPos, matchLen));
args.append(jsNumber(exec, matchPos));
args.append(sourceVal);
replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec);
}
return jsString(exec, source.substr(0, matchPos) + replacementString + source.substr(matchPos + matchLen));
}
bool WRECParser::parseParentheses(JmpSrcVector&)
{
// FIXME: We don't currently backtrack correctly within parentheses in cases such as
// "c".match(/(.*)c/) so we fall back to PCRE for any regexp containing parentheses.
m_err = TempError_unsupportedParentheses;
return false;
}
> dnaInput = dnaInput.replace(/g*t/g, subs[k]);
% jsc regexp-dna.js
285 (msec)
% js regepx-dna.js
1789 (msec)
> dnaInput = dnaInput.replace(/(g*)t/g, subs[k]);
% jsc regexp-dna.js
1942 (msec)
% js regexp-dna.js
2501 (msec)
おっPythonハカーを多数抱える、煩悩駆動開発で有名なglucose.jpのお手伝いをする機会があり、4年ぶりにPythonを書いた。2.3以来だったので、2.5を眺めているとデコレーターと呼ばれる機能が導入されていた。
デコレーターとクロージャーを組み合わせれば、メソッドの挙動を自由にカスタマイズすることができる。この機能を使用して、関数の結果をmemcachedでキャッシュする機能を付与するデコレーターを作ってみた。
あらかじめ、CACHE変数をmemcachedクライアントで初期化しておく必要がある。
挙動
ソースは、少々ややこしいけど、実行の仕組みは単純。
Step 1:
@cached構文実行時に、ack関数に対して、cached関数が実行され、ack関数がdecorated_funcを呼び出した結果でack関数が置換される。(返り値は、callableなオブジェクトでないといけない。)
Step 2:
decorated_func関数の呼び出し時の引数は、元のack関数。decorated_func関数の内部では、func_with_cacheが定義されており、ack関数に渡した引数を渡して実行される。この関数が、関数呼び出しの結果のキャッシュをチェックする本体となる。
# Decorate methods with capability for caching result
#
# @author Rakuto Furutani <http://raku.to/>
# @version 0.1.0
#
import cPickle
import memcache
import time
import md5
__all__ = ['cached', 'init']
# TODO: CACHE variable and function for initialize move to scope in Devkit.cache.*
# You must define global variable named 'CACHE' with instance of memcache client.
CACHE = None
def init(cache_client):
""" We should initialize this library with this method
examples:
CACHE = memcache.Client(['127.0.0.1:11211'], debug=0)
methods_cache.init(CACHE)
"""
global CACHE
CACHE = cache_client
def cached(d_args):
""" Decorate method with caching capability for caching
All result call the function are cached with cache key generated by function name and parameters.
examples:
@cached({'ttl': 3600})
def havy_complex_func(args):
# do something
# Return whether result call real function or cached result
havy_complex_func()
# You can specify cache key name explicitly
@cached({'ttl': 3600, 'key': 'foo_bar'})
def foo_bar():
# doo something
# You can also decorate one without ttl parameter
@cached
def havy_complex_func(args):
# do something
"""
def cache_key(func, args):
"""Generate unique cache key with funcion name and arguments"""
return "%s_%s" % (func.__name__, md5.new(str(args)).hexdigest())
def call_and_cache(func, args, key):
ret = func(*args)
data = {'ttl': (time.time() + d_args['ttl'] if 'ttl' in d_args else None), 'd': ret}
CACHE.set(key, cPickle.dumps(data))
return ret
def decorated_func(func):
def func_with_cache(*args):
key = d_args['key'] if ('key' in d_args) else cache_key(func, args)
cached_val = CACHE.get(key)
if cached_val is not None:
cached_val = cPickle.loads(cached_val)
if (cached_val['ttl'] is not None) and (cached_val['ttl'] >= time.time()):
return cached_val['d']
return call_and_cache(func, args, key)
return func_with_cache
return decorated_func
if __name__ == '__main__':
import sys
import time
sys.setrecursionlimit(10000)
# Define memcache client
CACHE = memcache.Client(['127.0.0.1:11211'], debug=0)
def _internal_ack(m, n):
if m == 0:
result = n + 1
elif n == 0:
result = ack(m - 1, 1)
else:
result = ack(m - 1, ack(m, n -1))
return result
def ack(m, n):
return _internal_ack(m, n)
@cached({'ttl': 3600})
def ack_with_cache(m, n):
return _internal_ack(m, n)
t = time.time()
ret = ack(3, 4)
print("ack(3, 4) returned %d - %s sec" % (ret, str(time.time() - t)))
ack_with_cache(3, 4) # cached once
t = time.time()
ret = ack_with_cache(3, 4)
print("ack(3, 4) returned %d with cached - %s sec" % (ret, str(time.time() - t)))
ack(3, 4) returned 125 - 0.00920796394348 sec
ack(3, 4) returned 125 with cached - 0.000248908996582 sec

脆弱性。
将来において改善されそうなiPhoneの仕様 or バグの一つが話題になっている。パスコードロックがかかっている画面から緊急電話をクリックした画面でホームボタンをダブルクリックすると「よく使う項目」にアクセスできてしまう。(表示された画面のキャンセルボタンも機能しないし、おそらくバグ)
脆弱性回避のために、
設定 -> 一般 -> ホームボタンで、「よく使う項目にチェックされているフィールドを、「ホーム」にしておく。
P.S.
パスコードロックの画面では、スクリーンショット機能は起動できないが、緊急電話をかけるための画面では、スクリーンショット機能が利用できた。(ただし、実際は、壁紙しか映らなかった。)
関連記事
「机に座り、起動時間が3分程かかる窓のアイコンを眺めつつ、ただ待つ。モデムのスイッチを入れて、PPP接続アシスタントを立ち上げ、青いeのアイコンをクリックする。さぁ、インターネットを始めるぞ!」13年程前か。そんな時代が、随分と懐かしく感じる。
iPhoneの登場が、私達のオフラインでいる時間を無情にも奪う。Firmware 2.0.2でも、電波状況は(まだ)悪いけど、場所を選ばすにSafariが立ち上がり、Google Readerを読めるのはとても魅力的だ。オンラインでいる時間が増えるから、ライフストリーミング系のアプリケーションが盛り上がるわけだ。パーベイシブコンピューティング、インターネットは場所を選ばず利用できるようになりつつある。原丈人氏の言葉で言えば、PUC(パーベイシブユビキタスコミュニケーション)だろうか。GPS, WiFiをiPhone上で使っていて、電池の減りがいつも気になる。iPhoneは、バッテリーの交換が出来ないのに。
瀧内氏と飲んでいる時にも、よく盛り上がる話題の一つが、ワイヤレス給電だ。
WiFi同様に、電力が場所を選ばずに利用できる時代、町中に"パワースポット"が普及するのはいつ頃だろうか?といった内容の話をする。人体に影響を与えず、利用料に応じて課金される従量制。そんな電力スポットの登場が待ち遠しい。
インテル・デベロッパー・フォーラム(IDF)Fall 2008で、MITで研究されているWREL(Resonant Energy Link)のデモが公開された。
via 2050 年までに人間と機械はより一層近づくと講演
ノートブック PC を持って空港や部屋に入るだけで、バッテリーが消耗するどころか充電されるとしたら…。MIT の物理学者の理論をもとに、インテルではワイヤレス共振エネルギー・リンク(Wireless Resonant Energy Link:WREL)の研究を行っています。ラトナーは、電源プラグも電線も使わずに、60 ワットの電球を点灯してみせました。60 ワットは、標準的なノートブック PC の消費電力を上回る電力です。
WREL の素晴らしい点は、電力をワイヤレスで安全かつ効率的に供給できることです。この技術は強結合共振器を使用します。訓練された歌手が声でガラスを割ることができるのとよく似た原理です。これはガラスの固有振動数で音響エネルギーが吸収されることと同じ様に、受信側の共振器の固有振動数と共振することで、エネルギーは効率よく吸収されます。このテクノロジーをノートブック PC などに搭載すれば、送信側の共振器から数十センチの距離に近づけることでバッテリーを充電することが可能になります。
インテルではまた、何百万個もの「catom」と呼ばれる微小なマイクロロボットによって、自在に形状を変えることができる素材の研究を進めています。この素材をコンピューティング機器の筐体やディスプレイ、キーボードの製造に使うことにより、ユーザー固有の形状にすることができます。例えばノートブック PC ならば、ポケットに入れるときは小さくなり、携帯電話として使用するときは受話器の形になり、インターネットを閲覧したり映画を見るときは、大きく薄くなってキーボードも現れる、といったことが可能になります。
海の向こうで話題になっていた時は、その圧倒的な力に感心する程度であったが、実際に日本でもGoogle Street Viewが、リアルクローラーを走らせているとなるとプライバシーが気になる。公共の道路で撮影された映像には、著作権は存在しなく、まずい画像については、モザイクやユーザからの投稿で対応していくとの事だが、土地所有者や人にもrobot.txtを書く権利を与えてくれてもいいだろう。
第三回 Liberty Alliance 技術セミナーで=natさんの基調講演を公聴してきて、OpenID関連の動向を仕入れたのでメモ。
OPとRP間で属性情報を交換するための拡張として、SREGやAXがあるが、AXも今ひとつ普及するに至っていない。(myopenid.comとVeriSignだけ?)また、プライバシポリシーや利用規約の問題もあり、日本企業では、ユーザ属性をサードパーティに公開出来ない事も多い。
基本的に、AXとSREGの違いは、
openid.pape.auth_level.fisc:2
openid.pape.auth_level.ns.fisc: http://www.fisc.or.jp/ex/authlevel
Google anounced about Gears on Rails, see Take your Rails application offline with the Gears on Rails project. We can listen to audio interview. This is Rails plugin to manipulate offline data from RoR.We can install GoR as Rails plugin is as follows:
% sudo gem install json_pure
% rails gor_demo && cd gor_demo
% ruby script /plugin install http://gearsonrails.googlecode.com/svn/trunk/acts_as_local
acts_as_local :except => [:hello]
def create_local
'
post = Post.build(params("post"));
Post.create_local(post);
window.location.reload( false );
'
end
Hmm..,
I spent three hours for a Mnesia's strange error message, so write tips about error I'm confused. The tables on Mnesia often need a time to prepare their tables, and if tables aren't available, then we'll see storange error message.
% db_test.erl
write_db_test() ->
start(), % Start the server, mnesia and create required tables.
?assertMatch({ok, _}, mnesia:transaction(fun() -> #person{name="rakuto"})).
{badmatch,{aborted,{no_exists,ready_queue}}}
write_db_test() ->
start(), % Start the server, mnesia and create required tables.
mnesia:wait_for_tables([person], 3000),
?assertMatch({ok, _}, mnesia:transaction(fun() -> #person{name="rakuto"})).
We usually need to package system and repositories in order to create a big application. Erlware is a repository for Erlang programs and it provides softaware to create a package and release it to the world. There are pretty cool, it is just thing I want to. This entry introduces that how to create an application as package and install to system.
I create a HAVAL bindings for Erlang in order to learn how to create linked-in driver.
See Tutorial for how to create Erlang linked-in driver.
In this entry, I introduce how to create an application provides API for HAVAL bindings for Erlang. We need to install Faxien and Sinan previously.
0. Dicied a names of application and start to development a pakcage.
Create required directories for the application.
% mkdir haval && cd haval && mkdir -p cmds doc bin libCreate directories for HAVAL bindings.
% ls .
bin/ cmds/ doc/ lib/ releases/
%
% mkdir -p lib/haval && cd lib/hava && mkdir src ebin include priv/libConfiguration file named "_build.cfg" for this application.
% cat > _build.cfg1. Create an application
project : {
name : haval
vsn : "1.0.0"
},
repositories : ["http://repo.erlware.org/pub", "http://repo.martinjlogan.com/pub"]
% cd lib/haval/c_src3. Build the application.
% make # Copy haval_drv.so haval/priv/lib
% sinserv # Placed in "/usr/local/erlware/release_packages/sinan-0.10.0.12/bin/sinserv" in my enviromentBuild the application with 'sinan' command. We can see help when '+help' command is passed.
% sinan +helpCreate a package for release. This package is generated underneath "_build/development/apps/" directory.
sinan [args] [task]
local args (+) and server args. local args may be any of the following
+url : The url to connect to and control
+help : This help message
Server args are much more complex. There are always sane defaults so
you shouldn't need them, but you may. To get information about server
args read the sinan documentation.
%
% sinan # Default task is build
starting run
[check_depends] start
[check_depends] stop
[build] start
[build] Building ~/haval-1.0.0/lib/haval/src/haval_server.erl
[build] Building ~/haval-1.0.0/lib/haval/src/haval_sup.erl
[build] Building ~/haval-1.0.0/lib/haval/src/haval_app.erl
[build] Building ~/haval-1.0.0/lib/haval/src/haval.erl
[build] stop
run complete
% ls _build/development/apps/haval-1.0.0 # Generated following sources
c_src/ ebin/ include/ priv/ src/
%
% sinan release4. Install the application locally.
starting run
[check_depends] start
[check_depends] stop
[build] start
[build] stop
[release] start
[release] stop
run complete
%
% mkdir releases/haval-1.0.0/ && mkdir lib
% cp -r _build/development/release releases/haval-1.0.0/
% cp -r _build/development/apps/haval-1.0.0 releases/haval-1.0.0/lib
Run and test.
% faxien install-release releases/haval-1.0.0
ok
% ls /usr/local/erlware/release_packages/haval-1.0.0/
LICENCE README lib/ release/
% erl5. Test the application
Erlang (BEAM) emulator version 5.6.2 [source] [smp:2] [async-threads:0] [kernel-poll:false]
Eshell V5.6.2 (abort with ^G)
1> haval:start().
ok
2> haval:haval_string("test").
"593C9AED973BB51A3C852FB4E051D7C26686B9468B4E405350CB6805DC1B99E6"
3> haval:haval_file("_build.cfg").
"5A114E356FBB0CCCED8C7574B7A71780C8F33D3A9B37B8642126B78429B2988F"
4>
% sinan test
Erlang includes ei library for handling Erlang binary term format. This entry introduces how to use this library.
1. Pass the one string to C driver from Erlang.
It's pretty simple case, and pass one string argument to C driver from Erlang. It should be passed port_control/3 or erlang:port_control/3 after all arguments should be encoded as binary. The "index" variable are used for pointing position in the buffer.
% echo.erl
-define(DRV_ECHO, 1).
echo(Str) ->
control(?DRV_ECHO, Str).
control(Cmd, Data) ->
[{port, Port}| _] = ets:lookup(echo_table, port),
Bin = term_to_binary(Data), % XXX: All arguments will be encoded as binary term format.
Res = port_control(Port, Cmd, Bin),
binary_to_term(Res).
#define DRV_ECHO 1
static int control(ErlDrvData drv_data, unsigned int command, char *buf,
int len, char **buf, int rlen) {
int index, type, size, arity ,ver;
char *arg1;
switch(command) {
case DRV_ECHO:
// It must call ei_decode_version at the beginning when argument is Erlang binary term format.
// All ei_xxx functions return 0 if it will be success, else return -1
ei_decode_version(buf, &index, &ver); // Value of 'index' will become 1.
// Get size of string in order to allocate buffer for argument
ei_get_type(buf, &index, &type, &size); // value of 'type' equal ERL_STRING_EXT
// Allocate memory for buffer
arg1 = new char[size + 1]; // Extra bite is required for NULL string.
/* do something */
}
}
#define ERL_SMALL_INTEGER_EXT 'a'
#define ERL_INTEGER_EXT 'b'
#define ERL_FLOAT_EXT 'c'
#define ERL_ATOM_EXT 'd'
#define ERL_REFERENCE_EXT 'e'
#define ERL_NEW_REFERENCE_EXT 'r'
#define ERL_PORT_EXT 'f'
#define ERL_PID_EXT 'g'
#define ERL_SMALL_TUPLE_EXT 'h'
#define ERL_LARGE_TUPLE_EXT 'i'
#define ERL_NIL_EXT 'j'
#define ERL_STRING_EXT 'k'
#define ERL_LIST_EXT 'l'
#define ERL_BINARY_EXT 'm'
#define ERL_SMALL_BIG_EXT 'n'
#define ERL_LARGE_BIG_EXT 'o'
#define ERL_NEW_FUN_EXT 'p'
#define ERL_FUN_EXT 'u'
#define ERL_NEW_CACHE 'N' /* c nodes don't know these two */
#define ERL_CACHED_ATOM 'C'
-define(DRV_ECHO_LIST, 1).
echo(List) when is_list(List) ->
control(?DRV_ECHO_LIST, List).
control(Cmd, Data) ->
[{port, Port}| _] = ets:lookup(echo_list_table, port),
Bin = term_to_binary(Data), % XXX: All arguments will be encoded as binary term format.
Res = port_control(Port, Cmd, Str),
binary_to_term(Res).
#define DRV_ECHO 1
static int control(ErlDrvData drv_data, unsigned int command, char *buf,
int len, char **buf, int rlen) {
int index, type, size, arity ,ver;
char *arg1;
switch(command) {
case DRV_ECHO_LIST:
// It must call ei_decode_version at the beginning when argument is Erlang binary term format.
// All ei_xxx functions return 0 if it will be success, else return -1
ei_decode_version(buf, &index, &ver); // Value of 'index' will become 1.
// Get size of string in order to allocate buffer for argument
ei_get_type(buf, &index, &type, &size);
// Check the type
if(type == ERL_LIST_EXT) {
// It must be called at the begginning when hanle the list term.
ei_decode_list_header(buf, &index, &arity);
printf("number of elements: %d\n", arity);
// Check the type of first element in the list
ei_get_type(buf, &index, &type, &size);
swithc(type) {
case ERL_SMALL_INTEGER_EXT:
case ERL_INTEGER_EXT:
// do something
break;
case ERL_STRING_EXT:
// do something
break;
}
}
}
}