4

Luaの文字列から(xの)関数を作成しています。私が使用しているコードは

function fcreate(fs)
 return assert(loadstring("return function (x) return " .. fs.." end"))()
end

これはグローバルで機能します。

u=fcreate("math.sin(x)")

正しいことをします。

ただし、ローカル変数は好きではないようです。それで

local c=1
u=fcreate("math.sin(x)+c")

cはローカルであるため、機能しません。

これは修正可能ですか?

4

3 に答える 3

13

"loadstring does not compile with lexical scoping"であるため、いいえ、loadstring呼び出しの外でローカルを参照することはできません。


これは修正可能ですか?

場合によります。そもそもロードストリングを使用する理由は何ですか? Lua はクロージャーをファースト クラスの値としてサポートしているため、例からloadstringが必要な理由がわかりません。

あなたの例:

u = fcreate("math.sin(x)+c")

loadstringまたはfcreate関数を必要とせずに書き換えることができます。

u = function(x) return math.sin(x)+c end

もちろん、これは次と同じです:

function u(x) return math.sin(x) + c end

loadstring他の関数にコンパイルしたいユーザー構成可能な式がある場合のケースを見ることができますが、ローカルcのケースはそうではないことを示唆しています。自家製のラムダ構文を作ろうとしていますか?

于 2012-07-08T04:31:04.090 に答える
2

合理的な方法で行うことはできません。理由の例については、これを見てください。

function makefunction(name)
    local a = 1
    local b = 2
    local c = 3
    -- ...
    return assert(loadstring("return " .. name))
end

local a = 4
local func = makefunction("a")
print(func())

これが機能した場合、何が印刷されますか? 1または4?その関数はもう存在しませんが、関数がロードされた場所から変数をキャプチャしますか? それとも呼ばれたところから調べるのですか?

1 つ目は、関数が作成された場所にレキシカル スコープが設定されることを意味します。関数が終了した後に変数にアクセスできるということは、変数を動的に上位値に昇格する必要があることを意味しますが、これは現時点で Lua が実行できることではありません。現在のように、Lua はコンパイル中にローカル変数へのすべてのアクセスを確認できるため、(パフォーマンス ヒット時に) どの変数を上位値に変換し、どれをローカル変数として保持するかを認識しています。

2 つ目は、'd 関数内の変数アクセスがloadstring、Lua の他のすべてのアクセスとはまったく異なる動作をすることを意味します。Lua は、動的スコープではなく字句スコープを使用します。これは Lua での実装の大幅な変更であり、非常に一貫性のないものです。

したがって、どちらもサポートされていません。Lua 5.1 または Lua 5.2 のパラメーターを使用して、動的にロードされる関数の環境を制御できますが、どちらもローカル変数に自動的にアクセスすることはできません。setfenvenvload(...)

于 2012-07-08T05:55:12.550 に答える
1

ローカル変数を変更する必要がない場合にできることは、それらの値を引数として生成された関数に渡すことです。閉じるには変数を手動で指定する必要がありますが、何もしないよりはましです。

たとえば、クロージャーを次のように構築できます

return (function(a,b,c)
   return function(x) return print(a, x) end
end)(...)

関数を次のように変更することで、それを行うことができます

function fcreate(variables, fs)

  local varnames = {}
  local varvalues = {}
  local nvars = 0
  for n,v in pairs(variables) do
    nvars = nvars + 1
    table.insert(varnames, n)
    table.insert(varvalues, v)
  end

  local chunk_str = (
     'return (function(' .. table.concat(varnames, ',') .. ') ' ..
         'return function(x) return ' .. fs .. ' end ' ..
      'end)(...)'
  )

  return assert( loadstring(chunk_str) )( unpack(varvalues, 1, nvars) )

end

local a = 1;
local f = fcreate({a=a}, 'x+a')
print(f(1), f(2))
于 2012-07-10T20:09:08.213 に答える