[REBOL][HelloWorld] http://www.rebol.com/

 REBOL [
  Title: "Hello, world"
  File: %hello.r
  Date: 2004/12/20
  Author: "Tea"
 ]

 print "Hello, world"

REBOLの決まりで、REBOL の記述は最低限必要。実行時にチェックされます。
一行目に REBOL と書いておくと、vimでREBOLのスクリプトだと判断してくれます。

REBOL は、特殊なおまじない構文ではなく、
これ自身もオブジェクトで、実行環境の様々な情報をもっているオブジェクト。

help REBOL と打ち込むとREBOLについてのヘルプが表示されます。
オブジェクトは木構造を持ち、それぞれの子要素も参照できます。
例えば、help REBOL/schemes でサポートされているプロトコルの一覧表示。

Stackframe

Pythonは、inspectionが優れていて
関数,コード,スタックフレームのオブジェクトにまで
Pythonスクリプト上からアクセスできたりする。

 import inspect
 
 def show_var(varname):
   """
   呼出元のローカル変数を表示
   """
   try:
     frame = inspect.currentframe()
     print "%s : %s" % (varname, frame.f_back.f_locals[varname])
   finally:
     del frame

 if __name__ == "__main__":
   foo = "HiNa"
   show_var("foo") # foo : HiNa

エラーや例外時にでるメッセージは、このframeオブジェクトの情報を参照している。
これを使うと、Perlの caller みたいな関数も定義できる。

def caller(num=1):
  """
  引数は、幾つ前のスタックを辿るかを整数で指定。初期値は1。
  [ 呼出元の名前, 呼出元のファイル, 呼出元の行番号 ]
  """
  assert num > 0, "Stack depth number must be greater than zero."
  try:
    frame = inspect.currentframe()
    for _ in xrange(num-1):
      frame = frame.f_back
    code = frame.f_code
    return [ code.co_name, code.co_filename, frame.f_lineno ]
  finally:
    del frame

Python in parrotで心配になったのは、先にも書いたけど
この code や frame オブジェクトの互換性をどう解決するのか。
いずれも C で実装されていて、Pythonプログラムの実行に深く関わっている。

例えば、関数の引数のフォーマット情報を表示するinspectの関数などは、
関数オブジェクト内のコード・オブジェクトが持つバイトコードの情報を参照している。
当然ながら python bytecode -> parrot bytecodeになると、バイトコードが代わるので、
この部分の変更は避けられない。

また、parrot用に書き直されるとした場合でも、
branchになるので、CPythonとParrotPython版両方の保守が発生する。
開発者でもないのに余計な心配かなとは思うが、実装依存部分を取り除くには手間がかかりそうだ。

[Parrot][Python]

Python/Parrotの実装は現在3つ。


disやinspectモジュールのCPythonとの互換はどうなるのか気になる所。
内部のobjectで言うと、codeやframeオブジェクト・レベルでの互換性。
parrotだとbytecodeが代わるので、co_codeとかそのままでは無理なはず。
frameは、アーキテクチャを考えるとparrotの内側に隠蔽差れそうな気がする。
parrotではframeオブジェクトに対してのアクセスを提供しているのだろうか。

      • -

組み込み向けを除いた主なPythonの実装。

# vyperは、サイトが亡くなっていて現在入手不可能。

      • -

sorted, reversed

式のなかで、リストの並べ変えが出来るようになり、
method chain や 副作用のないFPスタイルでのコードが書き易くなった。

sortがcmd, key, reverseの引数を取るようになっので、
sortedでも第二引数以降にこれらのオプションを設定できる。

[Python] 2.4

Releaseされたので早速インストール。新しい機能のテスト。

Generator Expression

 # 使い方:
 # リスト内包表現 [ ... ] の代わりに ( ... )

 # リスト内包表現では新しいリストを作成して返す為、
 # 巨大なリストをfor文で処理したい場合に、
 # - 一時リストを作成するので非効率、
 # - 又、無限リストを扱えないなどの問題があった。

 # ジェネレータ表現ではジェネレータを返す為、
 # foo in ステートメント内でも遅延評価,リスト内包の両方の利点を活かせる。

 foo = (funcA(x) for x in alist if funcB(x))

 # 上のgenerator expressionで作成されたgenerator fooは、
 # 以下の generator と同じ振舞をする。 

 def _foo():
   for x in alist:
     if funcB(x):
       yield funcA(x)
 foo = _foo()

Decorator

  • 関数を定義する際に、Wrapper関数を適用できる。

classmethod, staticmethodを簡単に定義する際に使える。
(というより主にそっちの目的で付けられた構文が汎用化されて、
デコレーターとして提供されたような気がする。)

class C:
  @classmethod
  def meth(self):
    print "C::meth"

複数のデコレーターを組み合わせる事も出来、
デコレーターを使って AOP での before, after の様なフックも掛ける事が出来る。

def require_int(func):
    def wrapper(arg):
        assert isinstance(arg, int)
        return func(arg)
    return wrapper

def provide_int(func):
    def wrapper(arg):
        result = func(arg)
        assert isinstance(result, int)
        return result
    return wrapper

@require_int
@provide_int
def test(num):
    return num * 2

# 従来のコードに展開すると、test定義後に、
# test = require_int(provide_int(test))

print test(10)
print test("1") # AssertionError, in wrapper in require_int

デコレーターに引数を渡す事も出来るらしい。(書き方がわからなかったのでTODO)