【问题标题】:What's with PCALL or is Wowwiki wrong?PCALL 是怎么回事,或者 Wowwiki 有什么问题?
【发布时间】:2010-10-18 11:18:24
【问题描述】:

这是一个 WoW(魔兽世界)lua 脚本问题。没有多少人在这里被问到,但我无处可去,而 Stackoverflow 是程序员的绿洲。

问题:

Wowwiki 声明第 2、3、4 个参数是您调用函数的第 1、2、3 个参数。我不认为这是真的。我发现第 3、第 4、第 5 个参数最终成为第 1、第 2、第 3 个参数。

链接:http://www.wowwiki.com/API_pcall

功能:

function myTest(arg1) 
  return arg1 .. 10; 
end 

问题:

local retOK, ret1 = pcall(myTest,"string value"); 

当我尝试示例时,我收到“尝试在本地 'arg1'(零值)上执行连接”的错误。如果我将代码更改为:

local retOK, ret1 = pcall(myTest,"string value", "bob"); 

然后我得到“bob10”的输出。第二个参数去哪里了,它是干什么用的?

更多测试:

function BobsToolbox:RunTest() 
  local test1, value1 = pcall(BobsToolbox.Test1, "string value"); 
  SharpDeck:Print("Test1: " .. tostring(test1) .. " Value: " .. tostring(value1)); 
end 

function BobsToolbox:Test1(arg1) 
  return arg1 .. "10"; 
end 

结果:尝试连接本地 'arg1'(一个 nil 值)

function BobsToolbox:RunTest() 
  local test1, value1 = pcall(Test1, "string value"); 
  SharpDeck:Print("Test1: " .. tostring(test1) .. " Value: " .. tostring(value1)); 
end 

function Test1(arg1) 
  return arg1 .. "10"; 
end 

结果:字符串值10

我是 lua 新手,我不明白为什么这些不同。

新问题:

以下代码有效,但为什么?

function BobsToolbox:RunTest()
  local test1, value1 = pcall(BobsToolbox.Test1, "string value");
  SharpDeck:Print("Test1: " .. tostring(test1) .. " Value: " .. tostring(value1));
end

function BobsToolbox.Test1(arg1)
  return arg1 .. "10";
end

以下有什么区别:("." vs ":")

  • 函数 BobsToolbox.Test1(arg1)
  • 函数 BobsToolbox:Test1(arg1)

【问题讨论】:

    标签: lua world-of-warcraft


    【解决方案1】:

    Lua 文档:

    http://www.lua.org/pil/16.html

    self 参数的这种使用是任何面向对象语言的中心点。大多数 OO 语言都对程序员部分隐藏了这种机制,因此她不必声明这个参数(尽管她仍然可以在方法中使用 selfthis 一词)。 Lua 也可以隐藏这个参数,使用冒号操作符。我们可以将之前的方法定义改写为

    function Account:withdraw (v) 
        self.balance = self.balance - v 
    end 
    

    方法调用为

    a:withdraw(100.00) 
    

    冒号的作用是在方法定义中增加一个额外的隐藏参数,在方法调用中增加一个额外的参数。冒号只是一种句法工具,虽然很方便;这里没有什么新东西。我们可以用点语法定义一个函数,用冒号语法调用它,反之亦然,只要我们正确处理了额外的参数:

    Account = { balance=0,
        withdraw = function (self, v) 
            self.balance = self.balance - v 
        end 
    } 
    
    function Account:deposit (v) 
        self.balance = self.balance + v 
    end 
    
    Account.deposit(Account, 200.00) 
    Account:withdraw(100.00) 
    

    可能的结论:

    考虑到这一点,我假设当使用“pcall”调用“:”函数时,您必须提供“self”参数。

    【讨论】:

    • 是的,看来您已经找到了答案!当您创建函数 BobsToolbox:Test1(arg1) 时,使用 pcall 的函数名称之后的第一个参数应该是要操作的对象。之后的参数是您实际要使用的参数。
    【解决方案2】:

    相关:WoW 有很好的实时代码编辑器。我曾经使用过 LuaSlinger,但后来发现它已不再开发,开发人员推荐使用 Hack

    但是,您可能会在这里遇到冒号方法调用语法只是语法糖,方法定义也是如此,IIRC。基本上,如果你做foo:bar("quux!"),其中 foo 是一个对象,你实际上只是在做foo.bar(foo, "quux!")

    希望有帮助!

    【讨论】:

    • 我很抱歉,但我想我遗漏了需要的信息。当时我认为这并不重要。如果可以的话,我想看看你是否同意我的条目。
    【解决方案3】:

    嗯,我不认为 WoWWiki 是错误的。这是我正在使用的代码:

    function myTest(arg1) return arg1 .. 10; end 
    
    local retOK, ret1 = pcall(myTest,"string value"); 
    DEFAULT_CHAT_FRAME:AddMessage(ret1);
    
    local retOK, ret1 = pcall(myTest,"string value", "bob"); 
    DEFAULT_CHAT_FRAME:AddMessage(ret1);
    

    这是我在常规聊天框中得到的输出:

    string value10
    string value10
    

    您如何尝试示例代码?我只是将我的代码粘贴到现有的 mod lua 文件中,并确保在选择我的角色并登录之前在插件窗口中启用了 mod。我对源 lua 文件进行了一些更改并输入:

    /console reloadui

    尝试新的更改并将结果输出到我的屏幕。我没有太多的建议可以给你,因为我没有对魔兽插件做过太多的工作。您是否在空白插件中尝试过此代码以确保没有其他干扰?你真的尝试过游戏中的代码吗?如果您可以提供更多信息或希望我尝试其他任何方法,请告诉我!

    更新:决定尝试更多测试。以下是测试(功能相同):

    local retOK, ret1 = pcall(myTest,""); 
    DEFAULT_CHAT_FRAME:AddMessage(ret1);
    
    local retOK, ret1 = pcall(myTest, nil, "bob"); 
    DEFAULT_CHAT_FRAME:AddMessage(ret1);
    

    结果:

    10
    attempt to concatenate local 'arg1' (a nil value)
    

    有趣的是,我在 arg1 为 nil 时看到的错误与您看到的错误略有不同。我很想知道你是如何测试你的代码的。或者,也许您没有逐字复制错误?我想您也可以尝试清除您的 WTF 文件夹并禁用其余的插件来测试此功能。如果有影响,那么您可以一次启用它们,直到找到问题为止。

    【讨论】:

    • 我很抱歉,但我想我遗漏了需要的信息。当时我认为这并不重要。如果可以的话,我想看看你是否同意我的条目。
    猜你喜欢
    • 2011-11-10
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 2013-07-06
    • 2012-03-09
    • 1970-01-01
    相关资源
    最近更新 更多