LSL Style Guide/zh-Hans

From Second Life Wiki
Jump to navigation Jump to search

用LSL进行有效的编程,开发者需要在格式化和规范他们的脚本方面依照标准进行实践。

这个设计指南由以下这些准则组成。尽管它们不像编译器的规则那样严格,但对编写易于维护的代码仍然非常关键。编程格式最重要的一个方面是你在编写代码过程中使用某种格式的时候,要始终如一。

通用准则

很多自己开始编程的人写出来的程序都,说好听的话,十分难看。它们一般都被写成这样:

<lsl>

   default {state_entry(){llSay(0,"Hello World.");}}

</lsl>

然而,写一个上万字的程序的时候,能被人理解(或者至少能“看懂”)是很重要的。要做到这一点,程序员可以使用的两个主要方法是使用花括号和缩进。

方式一: <lsl>

   default {
       state_entry() {
           llSay(0, "Hello World.");
       }
   }

</lsl>

方式二: <lsl>

   default
   {
       state_entry()
       {
           llSay(0, "Hello World.");
       }
   }

</lsl>

方式一节省了空间,但方式二对初学者来说则更容易阅读。一但某个程序员在实践中使用了特定的格式,阅读那种格式的代码就会变得很容易。前后一致的缩进规则使得两种方式都更容易阅读。在方式一中缩进是标明层次范围的关键标示。

命名规范

在Second Life中,有许多命名规范,下面列出的是最常用的。

全局变量(指在整个程序中都要用到的变量)应该以小写字母g开头。例如:

<lsl>

   integer gSelected = 0;
   string  gMyName = "Please set one";

</lsl>

可变常量(Variable Constants)应全部大写。例如:

<lsl>

   integer CHAT_CHAN = -517265;
   key OWNER_KEY = llGetOwner();

</lsl>

在用户自定义的函数或事件中使用的变量应以下划线开头。例如:

<lsl>

   listen( integer _channel, string _name, key _id, string _message )
   {
       if ( _channel == 1 || _id == llGetOwner() )
       	llOwnerSay("Hello Avatar");
   }

</lsl>

让代码条理清晰

刚开始编程的时候,很多人会在一行代码里调用许多的函数。这使代码变得难以阅读,几乎无法调试除错。下面的例子就是这样的:

<lsl> list lst; integer numDigits = 10; default {

  touch_start(integer n) {
      integer i = 0;
      integer index = llListFindList(lst, [llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1))]);
      if (!~llListFindList(lst, [llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1))]))
          lst += llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1));
      llOwnerSay(llList2CSV(lst));
  }

} </lsl>

再看下面这段代码,功能完全相同,却更简单易懂。比较起来,几乎没人能看懂上面的代码要实现什么目的,而下面的则很容易看懂。

<lsl> list lst; integer numDigits = 10;

default {

   touch_start(integer n) {
       integer i = 0;
       string name = llKey2Name(llDetectedKey(i));
       list nameAsList = llParseString2List(name, [" "], []);
       string firstName = llList2String(nameAsList, 0);
       string startPart = llToLower(llGetSubString(firstName, 0, numDigits - 1));
       integer index = llListFindList(lst, (list)startPart);
       if (!~index)
           lst += startPart;
       llOwnerSay(llList2CSV(lst));
   }

} </lsl>

LSL 缺少一个能够优化代码的编译器。因此,为了得到执行速度更快的代码,有必要在以上两种编程样式中找到平衡。在以多行合并方式对代码进行优化之前,必须确保代码没有漏洞并且执行正常。不恰当的优化会导致错误的结果,要始终对优化过的代码进行彻底测试。

list lst;
integer numDigits = 10;

default {
    touch_start(integer n) {
        integer i = 0;
        string startPart = llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1));
        if (!~llListFindList(lst, (list)startPart))
            lst += startPart;
        llOwnerSay(llList2CSV(lst));
    }
}

脚本结构

LSL脚本由expressions, functions, statements, event handlers以及states构成。LSL编译器为脚本规定了一个明确的结构:

  1. User Defined Variables (参考 LSL_Variables)
  2. User Defined Functions (参考 User-defined_functions)
  3. default State (参考 State)
  4. User Defined States

编辑器

编辑LSL代码文件可以使用许多第三方开发的编辑器。 浏览 LSL Alternate Editors 可以获取详细信息。