2010-12-11 7 views
5

私はLuaを使い始めました。私が(the Ghosts & Monsters Corona open source)から学んでいる例では、このパターンが繰り返し見られます。これら2つのLuaの違いは何ですか? 1つ良いですか?

local director = require("director") 

local mainGroup = display.newGroup() 

local function main() 

    mainGroup:insert(director.directorView) 

    openfeint = require ("openfeint") 
    openfeint.init("App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here") 

    director:changeScene("loadmainmenu") 

    return true 
end 

main() 

これは大会のいくつかの並べ替えですがLuaのプログラマがお勧めか、それをこのように行うに本物の利点がある経験しましたか?なぜ機能をすべて一緒にスキップしてこれを行うのではないでしょうか:

local director = require("director") 

local mainGroup = display.newGroup() 

mainGroup:insert(director.directorView) 

local openfeint = require ("openfeint") 
openfeint.init("App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here") 

director:changeScene("loadmainmenu") 

第2のスタイルには何らかの暗黙的な利点がありますか?ありがとう!

+0

正しく簡略化しましたか?これらの例のいくつかに完全な形でリンクできますか? – Amber

+1

ええ、あなたが投稿した 'パターン'はまったく意味がないようです。あなたはそれが "たくさん"、例にリンクすることができます参照してください言う? – Mud

+0

私はより完全な例で質問を編集し、完全なソースアーカイブをダウンロードできるところを引用しました。ルアが私が知っている他の言語のようなものであれば、2番目のフォームはlessでより多くのことをするようです。 –

答えて

8

これは、Luaのプログラマーが経験したようなものですか?そういうことに真の利点がありますか?

これは一般的ではありません。利点は、オブジェクトの状態がプライベートであることですが、それはそれを推奨するのに十分ではありません。

このパターンが繰り返し表示されます。

私はこれまで見たことがないし、投稿したソースで一度しか起こりません。

編集:この投稿の下のコメントに質問に対する回答を追加してください。

外部ローカル変数にアクセスする関数は、これらの変数にをバインドし、「クロージャ」と呼ばれます。 Lua(歴史的な理由から)は、それらの結合変数を「上位値」と呼んでいます。たとえば:あなたは出力から見ることができるよう

local function counter() 
    local i = 1 
    return function() 
     print(i) 
     i = i + 1 
    end 
end 

local a, b = counter(), counter() 
a() a() a() b() --> 1 2 3 1 

abはクロージャは、iの異なるコピーにバインドされています。言い換えれば、クロージャーは独自のプライベートステートであると考えることができます。あなたは、オブジェクトをシミュレートするためにこれを使用することができます。

function Point(x,y) 
    local p = {} 
    function p.getX() -- syntax sugar for p.getX = function() 
     return x 
    end 
    function p.setX(x_) 
     x = x_ 
    end 
    -- for brevity, not implementing a setter/getter for y 
    return p 
end 

p1 = Point(10,20) 
p1.setX(50) 
print(p1.getX()) 

Pointそれぞれが地元の人々xyに結合された、クロージャのテーブルを返します。テーブルにはポイントの状態は含まれておらず、クロージャ自体はその上位値によって行われます。重要な点は、Pointが呼び出されるたびに、新しいクロージャが作成されます。これは、大量のオブジェクトがある場合はあまり効率的ではありません。

Luaの中でクラスを作成する別の方法は、状態がテーブルに格納された状態で、最初の引数としてテーブルを取る関数を作成することです:

function Point(x,y) 
    local p = {x=x,y=y} 
    function p:getX() -- syntax sugar for p.getX = function(self) 
     return self.x 
    end 
    function p:setX(x) 
     self.x = x 
    end 
    return p 
end 

p1 = Point(10,20) 
p1:setX(50) -- syntax sugar for p1.setX(p1, 50) 
print(p1:getX()) -- syntax sugar for p1.getX(p1) 

これまでのところ、我々はまだの新しいコピーを作成しています

PointClass = {} 
function PointClass:getX() return self.x end 
function PointClass:setX(x) self.x = x end 
function Point(x,y) 
    return { 
     x = x, 
     y = y, 
     getX = PointClass.getX, 
     setX = PointClass.getY, 
    } 
end 

は今の方法は一度作成され、すべてのPointインスタンスは、同じクロージャを共有する:各メソッドは、今私たちは国家のために上位値に頼っていないことを、我々はそれを修正することができます。これを行うためのより良い方法は、新しいPointインスタンスが自動的にインスタンス自体では見られない方法のためにPointClassに見えるようにするのLuaのメタプログラミング機能を使用することです:

PointClass = {} 
PointClass.__index = PointClass -- metamethod 
function PointClass:getX() return self.x end 
function PointClass:setX(x) self.x = x end 
function Point(x,y) 
    return setmetatable({x=x,y=y}, PointClass) 
end 

p1 = Point(10,20) 
-- the p1 table does not itself contain a setX member, but p1 has a metatable, so 
-- when an indexing operation fails, Lua will look in the metatable for an __index 
-- metamethod. If that metamethod is a table, Lua will look for getX in that table, 
-- resolving p1.setX to PointClass.setX. 
p1:setX(50) 

これはLuaの中のクラスを作成するための、より慣用的な方法です。より効率的で柔軟なメモリです(特に、継承を実装するのが簡単です)。それはこの場合には、読みやすさを向上するため

+0

泥、その特定のファイル(main.lua)に1回出現しますが、作成者はコード全体を通してパターンを使用します。アーカイブ内のファイルの多く(レベル* .lua、load * .lua)はこのパターンを利用します。つまり、アーカイブに含まれているが、別の作者によって書かれたdirector.luaはパターンを持たないように見えます。それは、それが幽霊と怪物の作者のスタイルだと私に信じさせます。 –

+0

はい、彼のことです。一般的なコードはそれほど慣用的ではありません。特に、クラスを作成する方法は非常に珍しいことです。すべてのインスタンスメソッドに対して新しいクロージャを作成し、状態をテーブルに格納しているクラスの共有メソッドのセットではなく、上位値に状態を格納します。これはかなり無駄ですが、それは本当にプライベートな状態を作り出す方法でもあります。それは彼がやっていることになるかもしれませんが、彼は州のためにテーブルを使用するコードの他の領域があります(時には同じクラスが状態の値を上位に、テーブルの一部をテーブルに格納しています)。 – Mud

+0

泥、議論のおかげで。繰り返しますが、私がルアを初めて知ったので、あなたが上向きの価値を意味するものを説明してもらえますか?ありがとう! –

0

あなたがそれを示したように、私は最初のスタイルに多くの点を見ません。しかし、下部にif arg then main() endのようなものがあるとすれば、スタンドアロンスクリプトであるだけでなく読み込み可能な "ライブラリ"としても役立つかもしれません。それはを持っていると言いました。私はあなたがそれに疑問を持っていると思います。

3

私は頻繁にこのように私自身のLuaスクリプトを書く:

function main() 
    helper1(helper2(arg[1])) 
    helper3() 
end 

function helper1(foo) 
    print(foo) 
end 

function helper2(bar) 
    return bar*bar 
end 

function helper3() 
    print('hello world!') 
end 

main() 

この方法で「メイン」のコードが先頭にあるが、私はまだ前に必要なグローバル関数を定義することができます実行します。

本当に簡単なトリックです。私は読みやすさの他にこれを行う理由を考えることはできません。

1

最初のスタイルは読みやすさをあまりにも向上させる可能性がありますが、私はむしろメインの代わりに意味のある名前を付けるか、機能を使用しないでください。

ところで、私は、コードのブロックに名前を付けること、つまりそれらを関数やメソッドに入れることは、常に良い方法だと思います。これはコードの意図を説明するのに役立ち、再利用を奨励します。

関連する問題