Lua学習ノート(三)——式

8428 ワード

1数学演算オペレータ
1.1 %オペレータ
Luaの%オペレータとC言語のオペレータはいずれも型取りの意味であるが,型取りの仕方は異なる.C言語では、型取り操作は、2つのオペランドの絶対値を型取りした後、最初のオペランドの記号を追加します.Luaでは、商に対して相対的に負が無限に下に整頓された後の余数にすぎない.
+++
Cでは、
a1 = abs(a);
b1 = abs(b);
c = a1 % b1 = a1 - floor(a1/b1)*b1;

a % b = (a >= 0) ? c : -c;

Luaでは、
a % b == a - math.floor(a/b)*b

Luaは直接型取り定義に基づいて演算を行う.Cは型取り演算を少し処理した.
+++
例:
Cで
int a = 5 % 6;
int b = 5 % -6;
int c = -5 % 6;
int d = -5 % -6;

printf("a,b,c,d");--5,5,-5,-5

Luaの中で
a = 5 % 6
b = 5 % -6
c = -5 % 6
d = -5 % -6

x = {a,b,c,d}

for i,v in ipairs(x) do
    print(i,v)
end


--> 5
--> -1
--> 1
--> -5

2つの言語のモデリング結果は、オペランドが同じ番号の場合にのみ同じであることがわかります.異号の場合、型取り結果の記号と数値は等しくありません.
Luaにおける型取り演算は、a%b、a,bが同番であれば、結果としてa,bの絶対値の型をとる.異号で、結果としてb絶対値と絶対値の型取り後の差をとる.型取り後の値の記号はbと同じです.
2比較オペレータ
比較操作の結果、boolean型、非true、すなわちfalseであった.
サポートされるオペレータは次のとおりです.
< <= ~= == > >=
!オペレータはサポートされていません.
+++ ==操作の場合、演算時に2つの操作数のタイプを比較し、一致しなければfalseとなる.この場合、数値と文字列は自動的に変換されません.
2つのオブジェクトが等しいか否かを比較する場合、同一メモリ領域を指す場合のみ、trueと判定する.
a = 123
b = 233
c = "123"
d = "123"
e = {1,2,3}
f = e
g = {1,2,3}

print(a == b)       --> false
print(a == c)       --> false      --                 
print(c == d)       --> true       
print(e == f)       --> true       --          
print(e == g)       --> false      --       ,        
print(false == nil) --> false      -- false   boolean,nil   nil  

便利なタグで、-->は前の式の結果を表します.
+++ userdatatableとの比較は、メタ方法eqによって変更することができる.
サイズ比較では、数字と文字列の比較はC言語と一致します.他のタイプの値である場合、Luaはメタメソッドltおよびleを呼び出そうと試みる.
3論理オペレータand,or,not falsenilだけが偽とされている.
3.1 not
逆操作notの結果はboolean型であった.(andorの結果は必ずしもbooleanとは限らない)
b = not a           -- a   nil,b   true
c = not not a       -- c   false

3.2 and a and baが偽であればaaが真であればbを返します.
注意、なぜaが偽物の場合aに戻るのですか?何の意味があるの?これは、afalseまたはnilである可能性があります.この2つの値はいずれも偽ですが、違いがあります.
3.3 or a or baが偽であればbaが真であればaを返します.andとは反対です.
+++
ヒント:論理オペレータがboolean型の結果を得るために使用される場合、論理オペレータの操作結果が元の論理的意味に合致するため、論理演算後に誰に戻るかの問題を考慮する必要はありません.
例を挙げる
if (not (a > min and a < max)) then  --    a      ,   
    error() 
end

+++
3.4その他andorは短絡原則に従い、2番目の操作数は必要に応じてのみ評価操作を行う.

a = 5 x = a or jjjj() -- , , 。 print(a) -->5 print(x) -->5

上記の例を通して、論理操作に警戒しなければならない.これは、タイムリーに予想できなかったエラーを導入する可能性があるからだ.
4コネクタ..は、2つの文字列(または数値)を接続して新しい文字列になります.他のタイプについては、メタメソッドconcatが呼び出される.
5長さを取るオペレータ#
文字列の場合、長さは文字列の文字数です.
テーブルについては、t[n]がnilではなくt[n+1]がnilである下付きnをテーブルの長さとして探す.
~~他のタイプについては?~~
5.1例
--      
print(#"abc\0")                         --> 4
--    
print(#{[1]=1,[2]=2,[3]=3,x=5,y=6})     --> 3
print(#{[1]=1,[2]=nil,[3]=3,x=5,y=6})   --> 1

6優先度
低~高:
or
and
 <     >     <=    >=    ~=    ==
 ..
 +     -
 *     /     %
 not   #     - (unary)
 ^

べき乗演算>単眼演算>四則演算>コネクタ>比較オペレータ>and>or
7 Table構造
Table構造のBNF定義
tableconstructor ::= `{´ [fieldlist] `}´
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp
fieldsep ::= `,´ | `;´

BNF定義はBNFパターンの概要を参照する.
例:
a = {}
b = {["price"] = 5; cost = 4; 2+5}
c = { [1] = 2+5, [2] = 2, 8, price = "abc", ["cost"] = 4} -- b   c         


print(b["price"])   --> 5
print(b.cost)       --> 4
print(b[1])         --> 7       --       ,      ,    1   

print(c["price"])   --> abc
print(c.cost)       --> 4
print(c[1])         --> 8       
print(c[2])         --> 2       

注意:
  • キー値が与えられていない場合は、下付き文字を順番に割り当て、下付き文字は1から
  • である.
  • テーブルに同じキーがある場合、後ろの値をキーに対応する値
  • とする.
    上記の2つは、上記の例におけるc 1の出力値が8であるように存在する.
    +++
    テーブルに同じキーがある場合は、後ろの値をキーに対応する値とします.
    a = {[1] = 5,[1] = 6} --    a[1] = 6
    

    +++
    テーブルの最後のドメインが式形式であり、関数である場合、この関数のすべての戻り値がテーブルに追加されます.
    a = 1
    function order()
        a = a + 1
        return 1,2,3,4
    end
    
    b = {order(); a; order(); }
    
    c = {order(); a; (order());}
    
    print(b[1])                     --> 1       
    print(b[2])                     --> 2       --                        
    print(b[3])                     --> 1       
    print(b[4])                     --> 2       --             
    
    print(#b)                       --> 6       --       6                 
    print(#c)                       --> 3       --              3
    

    8関数
    関数はfunctionタイプのオブジェクトの値を持つ式です.関数は実行するたびにインスタンス化されます.
    8.1関数定義
    Luaで1つの関数を実現するには、以下の3つの形式がある.
    f = function() [block] end
    local f; f = function() [block] end
    a.f = function() [block] end
    

    Luaは文法糖を提供し、この3つの関数定義をそれぞれ処理する.
    function f() [block] end
    local function f() [block] end
    function a.f() [block] end
    

    +++
    上記のlocal関数の定義がlocal f = function() [block] endではないのは、次のエラーを回避するためです.
    local f = function()
        print("local fun")
        if i==0 then 
            f()             --     :attempt to call global 'f' (a nil value)
            i = i + 1
        end
    end
    

    8.2関数のパラメータ
    パラメータは、実パラメータによってローカル変数に初期化されます.
    パラメータリストの末尾に...を追加すると、関数が不定長パラメータを受け入れることができることを示します.末尾が追加されない場合、関数のパラメータリストの長さは固定されます.
    f(a,b)
    g(a,b,...)
    h(a,...,b)              --     
    
    f(1)                    --> a = 1, b = nil
    f(1,2)                  --> a = 1, b = 2
    f(1,2,3)                --> a = 1, b = 2
    
    g(1,2)                  --> a = 1, b = 2, (nothing)
    g(1,2,3)                --> a = 1, b = 2, (3)
    g(1,f(4,5),3)           --> a = 1, b = 4, (3)
    g(1,f(4,5))             --> a = 1, b = 4, (5)
    
    

    +++
    もう1つのパラメータはselfの関数の定義方法です.
    a.f = function (self, params) [block] end
    

    その文法糖の形式は以下の通りである.
    function a:f(params) [block] end
    

    使用例:
    a = {name = "    "}
    function a:f()
        print(self.name)
    end
    a:f()                       -->        --        a.f(),   self.name        attempt to index local 'self';       a.f(a)
    
    :の役割は、関数の定義と呼び出し時にselfパラメータを1つ少なく書くことができることです.この形式は のシミュレーションである.
    8.3関数呼び出し
    Luaの関数呼び出しのBNF構文は次のとおりです.
    functioncall ::= prefixexp args
    

    prefixexpの値のタイプがfunctionである場合、この関数は与えられたパラメータで呼び出されます.そうでない場合、prefixexpのメタメソッド「call」が呼び出され、callの最初のパラメータがprefixexpの値であり、次にargsパラメータのリストが表示されます(2.8メタテーブル|Metableを参照).
    関数呼び出しは、selfパラメータが入力されたかどうかに応じて、.呼び出しと:呼び出しに分けられる.関数呼び出しは、入力パラメータのタイプに応じて、パラメータリスト呼び出し、テーブル呼び出し、文字列呼び出しに分けられます.
    [改善を待つ]
    8.4関数閉パッケージ
    関数が外部変数にアクセスしている場合は、閉パッケージです.
    関数内部の変数はすべてローカル変数であるため,外部からアクセスできない.この場合,外部が局所変数の値を変更しようとすると,閉パケットを用いてこの目的を達成することができる.具体的な実装過程は大体このようにして,関数内部に局所変数を変えることができるサブ関数があり,関数がこのサブ関数を返すと,外部はこのサブ関数を用いて局所変数を操作することができる.
    例:閉包による局所変数の変更
    --        
    
    function begin(i)
        local cnt = i
    
        return function ()      --         ,        ;         ,          cnt
            cnt = cnt + 1
            return cnt
        end
    end
    
    
    iterator = begin(2)     --           2 ,         
    
    print(iterator())           --     
    print(iterator())
    
    

    ヒント:閉パッケージの詳細については、JavaScript閉パッケージがどのように機能しているかを参照してください.--StackOverflow
    リファレンスリンク
    BNF様式紹介(BNFの簡単な紹介)How do JavaScript closures work?——StackOverflow(Javascriptでの閉パッケージの概念を詳しく紹介)