<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 遞歸 現在再強調一次,m4 會將當前宏的展開結果插入到待讀取的輸入流的前端。也就是說,m4 會對當前宏的展開結果再次進行掃描,以處理嵌套的宏調用。這個性質決定了可以寫出讓 m4 累死的遞歸宏。 例如: ~~~ define(`TEST', `TEST') TEST ~~~ 當 m4 試圖對?`TEST`?進行展開時,它就會永無休止的去展開?`TEST`,而每次展開的結果依然是?`TEST`。 既然有遞歸,那么就可以利用遞歸來做一些計算,為了讓遞歸能夠結束,這就需要 m4 能夠支持條件。幸好,我們已經知道 m4 是支持條件的。下面,是一個遞歸版本的 Fibonacci 宏的實現與應用,它可以產生第 47 個 Fibonacci 數: ~~~ divert(-1) define(`FIB', `ifelse(`$1', `0', 0, `ifelse(`$1', `1', 1, `eval(FIB(eval($1 - 1)) + FIB(eval($1-2)))')')') divert(0)dnl FIB(46) ~~~ m4 的展開結果應該是?`1836311903`。也許你要等很久才會看到這個結果。因為遞歸的 Fibonacci 數計算過程中包含著大量的重復計算,效率很低。 不過,迭代版本的 Fibonacci 數計算過程也能寫得出來: ~~~ divert(-1) define(`FIB_ITER', `ifelse(`$3', 0, $2, `FIB_ITER(eval($1 + $2), $1, eval($3 - 1))')') define(`FIB', `FIB_ITER(1, 0, $1)') divert(0)dnl FIB(46) ~~~ 迭代計算很快,在我的機器上只需要 0.002 秒就可以得出?`1836311903`?這個結果。不過,如果想嘗試比 46 更大的數,比如`FIB(47)`,結果就會出現負數。這是因為 m4 目前只支持 32 位的有符號整數,它能表示的最大正整數是 2^31 - 1,而`FIB(47)`?的結果會大于這個數。 ## 循環 既然有遞歸,那么就可以用它來模擬循環。例如: ~~~ define(`for', `ifelse($#, 0, ``$0'', `ifelse(eval($2 <= $3), 1, `pushdef(`$1',$2)$4`'popdef(`$1')$0(`$1', incr($2), $3, `$4')')')') ~~~ 這個?`for`?宏可以像下面這樣調用: ~~~ for(`i', 1, n, `循環內的計算') ~~~ 它類似于 C 語言中的?`for`?循環: ~~~ for(int i = 1; i <= n; i++) { 循環內的計算 } ~~~ 例如,可以用?`for`?宏將 64 個?`-`?符號發送到輸出流: ~~~ for(`i', 1, 64, `-') ~~~ 這個宏的展開結果為: ~~~ ---------------------------------------------------------------- ~~~ 如果你用過 reStructuredText 標記語言,一定會知道怎么用?`for`?宏構建一個協助你構造一個用于快速撰寫 reStructuredText 標題標記的宏。 要理解?`for`?宏的定義,有幾個 m4 小知識需要補習一下。請向下看。 ## 宏參數列表的特征值 我們已經知道?`$1, $2, ..., $9`?對應于宏參數列表中的各個參數(GNU m4 不限定參數的個數,其他 m4 實現最多支持 9 個參數)。如果對 C 或 Bash 有所了解,那么當我說?`$0`?是宏本身,估計不會覺得很奇怪。因此,在上一節?`for`?宏定義中,`$0`?表示引用了宏名?`for`。不妨將?`$0`?改成?`for`?試一下。 `$#`?表示宏參數的個數。例如: ~~~ define(`count', ``$0': $# args') count # -> count: 0 args count() # -> count: 1 args count(1) # -> count: 1 args count(1,) # -> count: 2 args ~~~ > `#`?是注釋符,`->`?后面的文本是 m4 對注釋符號之前的文本處理后發送到輸出流的結果。 值得注意的是,即使?`()`?內什么也沒有,m4 也會認為?`count`?宏是有一個參數的,它是空字串。 `for`?的定義中,第一處條件語句為: ~~~ ifelse($#, 0, ``$0'', ... ...) ~~~ 它的作用就是告訴 m4,遇到?`for`?的調用語句,如果?`for`?的參數個數為 0,那么?`for`?的展開結果為帶引號的字符串: ~~~ `for' ~~~ 要理解為什么在條件語句中,`for`?用兩重引號包圍起來,你需要再認真的復習一次 m4 的宏展開過程。如果用單重引號,那么以無參數的形式調用?`for`?宏時,m4 會陷入對?`for`?宏無限次的展開過程中。 ## 宏的作用域 所有的宏都是全局的。 如果我們需要『局部宏』該怎么做?也就是說,如何將一個宏只在另一個宏的定義中使用?局部宏的意義就類似于編程語言中的局部變量,如果沒有局部宏,那么在一個全局的空間中,很容易出現宏名沖突,導致宏被意外的重定義了。 為了避免宏名沖突,一種可選的方法是在宏名之前加前綴,比如使用?`local`?作為局部宏名的前綴。不過,這種方法對于遞歸宏無效。更好的方法是用棧。 m4 實際上是用一個棧來維護宏的定義的。當前宏的定義位于棧頂。使用?`pushdef`?可以將一個臨時定義的宏壓入棧中,在利用完這個臨時的宏之后,再用?`popdef`?將其彈出棧外。例如: ~~~ define(`USED',1) define(`proc', `pushdef(`USED',10)pushdef(`UNUSED',20)dnl `'`USED' = USED, `UNUSED' = UNUSED`'dnl `'popdef(`USED',`UNUSED')') proc # -> USED = 10, UNUSED = 20 USED # -> 1 ~~~ 如果被壓入棧的宏是未定義的宏,那么?`pushdef`?就相當于?`define`。如果?`popdef`?彈出的宏也是未定義的宏,`popdef`?就相當于?`undefine`,它不會產生任何抱怨。 GNU m4 認為?`define(X, Y)`?與?`popdef(X)pushdef(X, Y)`?等價。其他的 m4 實現會認為?`define(X)`?等價于`undefine(X)define(X, Y)`,也就是說,新的宏的定義會更新整個棧。?`undefine(X)`?就是取消?`X`?宏的定義,使之成為未定義的宏。 ## 讓宏名更安全 m4 有一個?`-P`?選項,它可以強制性的在其內建宏名之前冠以?`m4_`?前綴。例如下面的 M1.m4 文件: ~~~ define(`M1',`text1')M1 # -> define(M1,text1)M1 m4_define(`M1',`text1')M1 # -> text1 ~~~ 直接用 m4 處理,結果為: ~~~ $ m4 M1.m4 text1 # -> define(M1,text1)M1 m4_define(M1,text1)text1 # -> text1 ~~~ 如果用?`m4 -P`?來處理,結果為: ~~~ $ m4 -P test.m4 define(M1,text1)M1 # -> define(M1,text1)M1 text1 # -> text1 ~~~ ## 挑戰 理解?`for`?宏的定義。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看