10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ElixirAdvent Calendar 2024

Day 11

19時間前にリリースされたElixir 1.18に搭載の「型推論」を試してみたが … 上手く動かせていない

Last updated at Posted at 2024-12-11

この記事は、Elixir Advent Calendar 2024 シリーズ8 の11日目です

昨日は、@RyoWakabayashi さんで 「Advent of code 2024 Day 8 Part 1 & Part 2 を Livebook で楽しむ
でした


piacere です、ご覧いただいてありがとございます :bow:

19時間前にリリースされたElixir 1.18に搭載の「型推論」を試してみます

なお、このコラムが、面白かったり、役に立ったら、image.png をお願いします :bow:

Elixir 1.18のビルドとインストール

Elixir 1.18は、2024/12/11段階で、asdfやapt、Precompiledがリリースされていないため、自前でビルドが必要です

git clone https://github.com/elixir-lang/elixir.git
cd elixir
make

おや? … 上記GitHub公式の手順だと、Elixir 1.19.0-devがインストールされるようですね … ま、いっか :laughing:

image.png

「型推論」を試してみる

CHANGELOG のトップにある、関数呼出と戻り値、パターンマッチにおける型チェックエラーを試してみます

defmodule User do
  defstruct [:age, :car_choice]

  def drive(%User{age: age, car_choice: car}, car_choices) when age >= 18 do
    if car in car_choices do
      {:ok, car}
    else
      {:error, :no_choice}
    end
  end

  def drive(%User{}, _car_choices) do
    {:error, :not_allowed}
  end
end

User.drive({:ok, %User{}}, car_choices)

CHANGELOGによると、下記のような型チェックが走るそうです

Elixir 1.18からは、こうした型推論に基づく型チェックが、型定義をコードに一切書いていないのに可能となるってのは、ワクワクしますね

    warning: incompatible types given to User.drive/2:

        User.drive({:ok, %User{age: nil, car_choice: nil}}, car_choices)

    given types:

        {:ok, %User{age: nil, car_choice: nil}}, empty_list()

    but expected one of:

        dynamic(%User{age: term(), car_choice: term()}), dynamic()

    where "car_choices" was given the type:

        # type: empty_list()
        # from: lib/foo.ex:21:17
        car_choices = []

    typing violation found at:
    
 22      User.drive({:ok, %User{}}, car_choices)
              ~
    
    └─ lib/foo.ex:22:10: Example.run/0

しかし、サンプル通りだと、iexでは下記エラーが出ます

** (FunctionClauseError) no function clause matching in User.drive/2    
    
    The following arguments were given to User.drive/2:
    
        # 1
        {:ok, %User{age: nil, car_choice: nil}}
    
        # 2
        []
    
    iex:7: User.drive/2
    iex:17: (file)

そもそも、関数定義と異なる呼出サンプルのようなので、下記呼び出しに直してみます

User.drive({:ok, %User{}}, car_choices)

そうすると今度は、やはり異なる下記エラーが出ます

    error: undefined variable "car_choices"
    
  2  set -e
     ^^^^^^
    
    └─ iex:2

** (CompileError) cannot compile code (errors have been logged)

まぁ、そりゃ car_choices が未定義なので、そうなりますよね

上記型チェックエラー時に given types:empty_list() と出ているのをヒントに、car_choices を試しに下記のように定義してみます

car_choices = []

この場合は、下記のように普通に通ってしまいました … うーん、どうやって型チェックを起こしたら良いんだろう?

{:error, :no_choice}

また分かったら、続報コラムを書くとします

p.s.このコラムが、面白かったり、役に立ったら…

image.png にて、どうぞ応援よろしくお願いします :bow:


明日は、 私で 「【再戦】19時間前にリリースされたElixir 1.18に搭載の「型推論」が上手くいった(御大José Valimとのやり取りも)」 です

10
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?