質問

Java、Erlang、Lispなどでの方法と同様に、LUAでホットスワップコードをhotでホットスワップコードをすることができることについて、インターネットの周りに抱きしめを聞いたことがありますが、30分間のグーグルは何も現れませんでした。誰かがこれについてかなりのことを読んだことがありますか?誰かがそれをした経験はありますか? Luajitで機能しますか、それとも参照VMでのみ機能しますか?

私は、ライブ環境のアップグレードパスよりも開発/デバッグのショートカットとして、このテクニックにもっと興味があります。

役に立ちましたか?

解決

Lua、およびそのことに関するほとんどのスクリプト言語は、定義するときに最も一般化された「ホットスワッピング」の形式をサポートしていません。つまり、できません 保証します ディスク上のファイルを変更し、その変更が実行されるプログラムに変化します。

ただし、Lua、およびその問題のためのほとんどのスクリプト言語は完全に能力があります 制御 ホットスワッピングの形式。グローバル機能はグローバル機能です。モジュールは単にグローバル関数をロードするだけです(そのように使用する場合)。したがって、モジュールがグローバル関数をロードすると、変更が変更された場合にモジュールを再度リロードでき、これらのグローバル関数参照は新しくロードされた関数に変更されます。

でも, 、Lua、およびそのことに関するほとんどのスクリプト言語は、これについて保証しません。起こっているのは、グローバルな状態データの変化です。誰かが古い関数をローカル変数にコピーした場合でも、それでもアクセスできます。モジュールがローカル状態データを使用している場合、モジュールの新しいバージョンは古いモジュールの状態にアクセスできません。モジュールがメンバー関数を持つオブジェクトを作成する場合、それらのメンバーがグローバルからフェッチされない限り、これらのオブジェクトは常に新しい機能ではなく古い関数を参照します。など。

また、luaは糸が安全ではありません。中断することはできません lua_State ある時点で、モジュールをもう一度ロードしようとします。したがって、材料をチェックして変更されたファイルをリロードするために、特定の時点を設定する必要があります。

だからあなたはそれをすることができますが、それが起こる可能性があるという意味では「サポート」されていません。あなたはそれのために働かなければなりません、そしてあなたはあなたが物事をどのように書くか、そしてあなたが地元の機能とグローバルな機能に何を置くかに注意する必要があります。

他のヒント

ニコルとして 言った, 、言語自体はあなたのためにそれをしません。

あなたがこのようなものを自分で実装したい場合、それはそれほど難しくありません、あなたが「残りの」参照(まだ古いコードを指している)と事実である「残りの」参照を「防ぐ」唯一のものは require その返品値をキャッシュします package.loaded.

私がそれをする方法は、あなたのコードを3つのモジュールに分割することです。

  • エントリポイントでのリロードロジック(main.lua)
  • リロード全体で保存するデータ(data.lua)
  • リロードする実際のコード(payload.lua)、それについての参照を保持しないようにしてください(例えば、いくつかのライブラリにコールバックを与える必要がある場合は不可能な場合があります。以下を参照)。
-- main.lua:
local PL = require("payload")
local D = require("data")

function reload(module)
  package.loaded[module]=nil -- this makes `require` forget about its cache
  return require(module)
end

PL.setX(5)
PL.setY(10)

PL.printX()
PL.printY()

-- .... somehow detect you want to reload:
print "reloading"
PL = reload("payload") -- make sure you don't keep references to PL elsewhere, e.g. as a function upvalue!

PL.printX()
PL.printY()
-- data.lua:
return {} -- this is a pretty dumb module, it's literally just a table stored in `package.loaded.data` to make sure everyone gets the same instance when requiring it.
-- payload.lua:
local D = require("data")
local y = 0
return {
  setX = function(nx) D.x = nx end, -- using the data module is preserved
  setY = function(ny) y = ny end, -- using a local is reset upon reload
  printX = function() print("x:",D.x) end,
  printY = function() print("y:", y) end
}

出力:

x: 5
y: 10
reloading
x: 5
y: 0

あなたは、あなたのために必要/リロードするすべてのものを追跡し、モジュールにアクセスを抽象化する(したがって参照を置き換えることができる)、そして使用して、を使用することで、その論理を少し良くすることができます。 __index そのレジストリでメタテイターティストは、あちこちで醜いゲッターを呼び出すことなく、それをかなり透明にすることができます。これはまた、「1つのライナー」コールバックを提供できることを意味します。これは、サードパーティライブラリが必要な場合に、実際にレジストリを通してテールコールするだけです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top