【问题标题】:Elixir: Configure a mix project to always print charlists as lists?Elixir:将混合项目配置为始终将字符列表打印为列表?
【发布时间】:2021-03-13 05:12:51
【问题描述】:

在测试我的 Phoenix 应用程序时,我经常遇到需要比较预期记录 ID 列表和实际记录 ID 列表的情况。错误解释起来很乏味,因为 Elixir 一直将整数列表打印为字符列表,所以我的测试输出如下所示:

     Assertion with == failed
     code:  assert H.sort(Enum.map(list1, &(&1.id()))) == H.sort(Enum.map(list2, &(&1.id())))
     left:  'stu'
     right: 'st'

这促使我重写我的测试以避免比较整数列表,这是可以容忍的,但只是耸耸肩并寻找这样一种语言的解决方法是一种耻辱。所以我想知道是否有办法告诉 Elixir/Mixalways 将整数列表打印为列表,而不是 charlists/charstrings。我编写了 Ruby 风格的 Elixir,而且我几乎从不使用 charlists,对我来说,它们主要是一个可以解决的问题。

感谢this answer 我知道有一种方法可以将 IEx 配置为始终将整数列表打印为列表。有没有办法在 Mix 中这样做,或者在 Elixir 本身中全局这样做,所以mix test 会采用这种行为?

【问题讨论】:

    标签: elixir


    【解决方案1】:

    这在ExUnit 中是不可配置的,它可以调用Inspect.Algebra.to_doc/2 并将Inspect.Opts 硬编码为%Inspect.Opts{width: width}

    在您自己的代码中,您总是可以在调用 inspect/2 时传递第二个参数,例如

    IO.inspect('ABC', charlists: :as_list)
    #⇒ [65, 66, 67]
    

    【讨论】:

      【解决方案2】:

      charlists 的“人性化”可能是 Elixir 中最令人困惑的问题之一。正如@Aleksei 指出的那样,这在ExUnit 中是不可配置的(尽管您可以通过在.iex.exs 文件中添加IEx.configure(inspect: [charlists: :as_lists]) 来配置iex)。

      但是,您不需要重写测试。请记住,打印值的方式只是数据的视图。它确实影响数据的存储方式

      您的示例断言失败,因为'stu' 不等于'st',正如[115, 116, 117] 不等于[115, 116]

      看下面的代码:

      iex> [115, 116, 117] === 'stu'
      true
      

      左右两边是 100% 完全等价的。单引号只是让人们更容易输入数据。

      在您的特定情况下,您可能需要查看MapSet,尤其是如果您的 ID 列表是唯一的。然后,您可以避免在比较之前进行笨拙/脆弱的排序。使用MapSet,您只需比较两组是否相等。例如:

      expected_ids = MapSet.new([115, 116, 117])
      actual_ids = MapSet.new(some_function_output)
      
      assert MapSet.equal?(actual_ids, expected_ids)
      

      这可能有助于避免繁琐的跟踪由字符列表引起的错误。在您的情况下,另一个选择可能是在映射期间将整数转换为字符串,例如Enum.map(list1, fn x -> to_string(x.id) end)

      【讨论】:

        猜你喜欢
        • 2017-03-12
        • 2018-01-13
        • 2020-07-01
        • 1970-01-01
        • 2019-09-19
        相关资源
        最近更新 更多