<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                8-模塊 ====== [編譯](#81-%E7%BC%96%E8%AF%91) [腳本模式](#82-%E8%84%9A%E6%9C%AC%E6%A8%A1%E5%BC%8F) [命名函數](#83-%E5%91%BD%E5%90%8D%E5%87%BD%E6%95%B0) [函數捕捉](#84-%E5%87%BD%E6%95%B0%E6%8D%95%E6%8D%89) [默認參數](#85-%E9%BB%98%E8%AE%A4%E5%8F%82%E6%95%B0) Elixir中我們把許多函數組織成一個模塊。我們在前幾章已經提到了許多模塊, 如[String模塊](http://elixir-lang.org/docs/stable/elixir/String.html): ```elixir iex> String.length "hello" 5 ``` 創建自己的模塊,用```defmodule```宏。用```def```宏在其中定義函數: ```elixir iex> defmodule Math do ...> def sum(a, b) do ...> a + b ...> end ...> end iex> Math.sum(1, 2) 3 ``` >像ruby一樣,模塊名大寫起頭 ## 8.1-編譯 通常把模塊寫進文件,這樣可以編譯和重用。假如文件```math.ex```有如下內容: ```elixir defmodule Math do def sum(a, b) do a + b end end ``` 這個文件可以用```elixirc```進行編譯: ```elixir $ elixirc math.ex ``` 這將生成名為```Elixir.Math.beam```的bytecode文件。 如果這時再啟動iex,那么這個模塊就已經可以用了(假如在含有該編譯文件的目錄啟動iex): ```elixir iex> Math.sum(1, 2) 3 ``` Elixir工程通常組織在三個文件夾里: - ebin,包括編譯后的字節碼 - lib,包括Elixir代碼(.ex文件) - test,測試代碼(.exs文件) 實際項目中,構建工具Mix會負責編譯,并且設置好正確的路徑。 而為了學習方便,Elixir也提供了腳本模式,可以更靈活而不用編譯。 ## 8.2-腳本模式 除了.ex文件,Elixir還支持.exs腳本文件。 Elixir對兩種文件一視同仁,唯一區別是.ex文件會保留編譯執行后產出的比特碼文件, 而.exs文件用來作腳本執行,不會留下比特碼文件。例如,如下創建名為math.exs的文件: ```elixir defmodule Math do def sum(a, b) do a + b end end IO.puts Math.sum(1, 2) ``` 執行之: ```sh $ elixir math.exs ``` 像這樣執行腳本文件時,將在內存中編譯和執行,打印出“3”作為結果。沒有比特碼文件生成。 后文中(為了學習和練習方便),推薦使用腳本模式執行學到的代碼。 ## 8.3-命名函數 在某模塊中,我們可以用```def/2```宏定義函數,用```defp/2```定義私有函數。 用```def/2```定義的函數可以被其它模塊中的代碼使用,而私有函數僅在定義它的模塊內使用。 ```elixir defmodule Math do def sum(a, b) do do_sum(a, b) end defp do_sum(a, b) do a + b end end Math.sum(1, 2) #=> 3 Math.do_sum(1, 2) #=> ** (UndefinedFunctionError) ``` 函數聲明也支持使用衛兵或多個子句。 如果一個函數有好多子句,Elixir會匹配每一個子句直到找到一個匹配的。 下面例子檢查參數是否是數字: ```elixir defmodule Math do def zero?(0) do true end def zero?(x) when is_number(x) do false end end Math.zero?(0) #=> true Math.zero?(1) #=> false Math.zero?([1,2,3]) #=> ** (FunctionClauseError) ``` 如果沒有一個子句能匹配參數,會報錯。 ## 8.4-函數捕捉 本教程中提到函數,都是用```name/arity```的形式描述。 這種表示方法可以被用來獲取一個命名函數(賦給一個函數型變量)。 下面用iex執行一下上文定義的math.exs文件: ```elixir $ iex math.exs ``` ```elixir iex> Math.zero?(0) true iex> fun = &Math.zero?/1 &Math.zero?/1 iex> is_function fun true iex> fun.(0) true ``` 用```&<function notation>```通過函數名捕捉一個函數,它本身代表該函數值(函數類型的值)。 它可以不必賦給一個變量,直接用括號來使用該函數。 本地定義的,或者已導入的函數,比如```is_function/1```,可以不用前綴模模塊名: ```elixir iex> &is_function/1 &:erlang.is_function/1 iex> (&is_function/1).(fun) true ``` 這種語法還可以作為快捷方式來創建和使用函數: ```elixir iex> fun = &(&1 + 1) #Function<6.71889879/1 in :erl_eval.expr/5> iex> fun.(1) 2 ``` 代碼中```&1``` 表示傳給該函數的第一個參數。 因此,```&(&1+1)```其實等同于```fn x->x+1 end```。在創建短小函數時,這個很方便。 想要了解更多關于```&```捕捉操作符,參考[Kernel.SpecialForms文檔](http://elixir-lang.org/docs/stable/elixir/Kernel.SpecialForms.html)。 ## 8.5-默認參數 Elixir中,命名函數也支持默認參數: ```elixir defmodule Concat do def join(a, b, sep \\ " ") do a <> sep <> b end end IO.puts Concat.join("Hello", "world") #=> Hello world IO.puts Concat.join("Hello", "world", "_") #=> Hello_world ``` 任何表達式都可以作為默認參數,但是只在函數調用時 **用到了** 才被執行。 (函數定義時,那些表達式只是存在那兒,不執行;函數調用時,沒有用到默認值,也不執行)。 ```elixir defmodule DefaultTest do def dowork(x \\ IO.puts "hello") do x end end ``` ```elixir iex> DefaultTest.dowork 123 123 iex> DefaultTest.dowork hello :ok ``` 如果有默認參數值的函數有了多條子句,推薦先定義一個函數頭(無具體函數體)聲明默認參數: ```elixir defmodule Concat do def join(a, b \\ nil, sep \\ " ") def join(a, b, _sep) when is_nil(b) do a end def join(a, b, sep) do a <> sep <> b end end IO.puts Concat.join("Hello", "world") #=> Hello world IO.puts Concat.join("Hello", "world", "_") #=> Hello_world IO.puts Concat.join("Hello") #=> Hello ``` 使用默認值時,注意對函數重載會有一定影響。考慮下面例子: ```elixir defmodule Concat do def join(a, b) do IO.puts "***First join" a <> b end def join(a, b, sep \\ " ") do IO.puts "***Second join" a <> sep <> b end end ``` 如果將以上代碼保存在文件“concat.ex”中并編譯,Elixir會報出以下警告: ```elixir concat.ex:7: this clause cannot match because a previous clause at line 2 always matches ``` 編譯器是在警告我們,在使用兩個參數調用```join```函數時,總使用第一個函數定義。 只有使用三個參數調用時,才會使用第二個定義: ```elixir $ iex concat.exs ``` ```elixir iex> Concat.join "Hello", "world" ***First join "Helloworld" iex> Concat.join "Hello", "world", "_" ***Second join "Hello_world" ``` 后面幾章將介紹使用命名函數來做循環,如何從別的模塊中導入函數,以及模塊的屬性等。
                  <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>

                              哎呀哎呀视频在线观看