Skip to content

Instantly share code, notes, and snippets.

@umegaya
Created August 2, 2012 08:30
Show Gist options
  • Save umegaya/3235433 to your computer and use it in GitHub Desktop.
Save umegaya/3235433 to your computer and use it in GitHub Desktop.
Lua: hot topics

Lua - hot features and topics

Agenda

Luaの仕様

  • metatable
  • environment
  • upvalue (と closure)

最近のLua界隈のホットなトピック

  • LuaJIT ffi
  • Luvit (とcoroutine)

Luaの未来

Luaって?

ゲーム業界で使われているスクリプト言語で、

  • ANSI C 準拠で依存関係が少ないため、ポータビリティが高い
  • メモリ使用量が少ない
  • 高速に動作する
  • C/C++で書かれたコードとの連携がとても簡単

=> っていうのは聞いたことありますよね。今日は別の側面からLuaを紹介したいと思います。

Famous first words

"Javascriptと同じで、Luaのオブジェクト指向は内臓が見えている"

{% left %} {% end %} {% right %} まつもとゆきひろ、rubyの作者 {% end %}

Famous first words

実際のところ、Luaの内臓はJSよりずっとまるだしです

内臓が見えているってどういうことか

以下のLuaの仕様を見ていくとわかってくるかも

  • metatable
  • environment
  • upvalue

注意!最新のLuaは5.2ですが、以下はLua 5.1な話です。

  • 重要なvariantである、LuaJITが5.1ベースなため

metatable

JS prototype + PHP magic method + C++ operator overload

-- metatable はluaの基本データ型'table'にすぎません
local mt = {
        -- like JS prototype,
        baz = "var",

        -- like PHP magic method, "__get" or ruby's method_missing
        __index = function (t, k)
                return '' .. k .. k
        end,

        -- like C++ operator + ()
        __add = function (o1, o2)
                return o1.name .. ' and ' .. o2.name .. ' are forever friends'
        end,
}
-- それをsetmetatableというAPIを使って他のテーブルに対して設定します
local o1 = setmetatable({ foo = 'foo', name = 'zynga' }, mt)
local o2 = setmetatable({ baz = "hoge", name = 'facebook' }, mt)

print(o1.foo, o1.bar, o1.baz) --> foo barbar  var
print(o2.foo, o2.bar, o2.baz) --> foofoo      barbar  hoge

print(o1 + o2) --> zynga and facebook are forever friends

metatable

metatableをセットされたtableをクラスのインスタンス、metatableをクラス定義、と考えると、setmetatable({..}, mt)はクラスの生成そのものです

  • 例えば継承はmetatableにmetatableを設定することで実現される(JSと同じですね!)
  • mt1 =(is metatable of)=> mt2 =(is metatable of)=> mt3

他の動的言語におけるclass ****みたいな記述は、mtの定義やsetmetatableにsyntax sugarを与えているといえる

  • Luaでクラスベースのオブジェクト指向を書いていると、そのことにとても意識的になる

environment

これも要約すると、あるコードブロックにおける変数のスコープをコントロールする仕様

global = nil
sandbox = {}

function modify_global()
	global = 'modify global should sandboxed'
end

modify_global()

print(global) --> modify global should sandboxed
print(sandbox.global) --> nil

global = nil
setfenv(modify_global, sandbox)
modify_global()

print(global) --> nil
print(sandbox.global) --> modify global should sandboxed

upvalue

"a function together with a referencing environment for the non-local variables of that function."

function factory(num)
	local seps = '|'
	return function(str)
		return (string.rep((str .. seps),num - 1) .. str)
	end
end

f = factory(3)
print(f('abc')) --> abc|abc|abc

"local seps" はその変数のスコープ(factory)から抜けた後もfactoryが返した関数(f)内で参照ができる

Luaではこのsepsのように参照されている変数を、参照している関数のupvalueと呼びます

upvalue

upvalueのLuaにおける実装は、closureとなる関数と、特定のhash table (upvalue scope)を結びつけること

(referred variable) <=(referred from)= (upvalue scope) <=(referred from)= (refer function)

Luaはこのupvalueを読み書きするための機能を提供している

function factory(num)
        local seps = '|'
        return function(str)
                return (string.rep((str .. seps),num - 1) .. str)
        end
end

f = factory(3)
print(f('abc')) --> abc|abc|abc

print(debug.getupvalue(f,1)) --> seps	| Luaは多値を返すことができます
print(debug.setupvalue(f,1,'/')) --> seps
print(f('abc')) --> abc/abc/abc

再び:Luaの内臓

クラスの継承やmix-in, closureなど現代の動的言語に要求されている機能は基本的に連想配列を言語の基本データ型に関連づけることで実現される

  • もっと著名な動的言語rubyやpythonなども、高速化の工夫ののぞけば、本質的には同じことを行っていて、それに文法という名のsyntax sugarを与えているだけといえる。
  • Luaでは、直接にその部分をプログラマーがコントロールするため、本質的な部分が見えやすい

これが内臓が見えているという意味だと思います

LuaJIT ffi

LuaのコードからダイレクトにCの関数を呼び出す。さらにCと同じメモリレイアウトのオブジェクトを直接操作できる

  • バインディング書かなくていい!(つまりオーバーヘッドもない)
  • JIT compileが有効な場合、ダイレクトなC関数呼び出しや、Cの構造体操作などはCのコンパイラと同じマシンコードを生成する
  • 実用的な例でも、ほぼC/C++と同等な速度が出ている

TLC (Tiny Lua Cocos bridge)

  • Cocosというより、Obj-C自体をLuaJIT ffiを使ってbindしたような実装
  • Cocosのクラスごとにbindingなんか書かなくていい

Luvit (and coroutine)

LuaJITを使ったnode.jsの再実装

  • x2 - x4 faster than node.js (symple hello world http server)

Rackspaceはクラウドモニタリングサービスのコンポーネントとして、すでに商用で利用している

Luaのcoroutineを使うことでcallbackスタイルのプログラミングを使わなくてもいいようにしようとしている?

  • ただ、現状の実装ではmeteorのfiberみたいなものなので、本質的ではない。
  • いちどあきらめてたみたいだけど、LuaJITのcoroutineがかなり低コストだと知って、もう一度考え直すってMLでいってた。
  • これは期待

future of Lua

電話やタブレット以外のもっとたくさんのデバイス(組み込み系とか)がインターネットにつながるようになる

  • Luaは組み込み系のスクリプト言語ではかなり有力
  • 組み込みデバイスではブラウザみたいなでかいコンポーネントなんていらない
  • OSの上でLuaを使ってシンプルにwebアクセスする形で機能を実装するというのはかなりリーズナブルな選択に見える

より複雑で大規模な計算がクラウドで行われる

  • zstats,MapReduceのような離散的な計算だけでなく、気象シミュレーションのような連続量をあつかう大規模計算が必要になってくるはず
  • クラウド側におけるGPUコンピューティングはさけられないように思う
  • LuaJIT、特にffiはローレベルプログラミングとの親和性の高さから科学計算のロジック部分を記述するためのプラットフォームとなりうる。
  • 実際、LuaJITを科学計算のフロントエンドとして使うフレームワークについての研究ってたくさんある(SPLAYとか)

未来においては

  • 多数の組み込み機器の中でLuaが動き、
  • 多数のGPUクラウドマシンの中でLuaが動く

Luaはコンピューティングの世界を支配するかも!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment