【问题标题】:Why does pattern matching on this string in erlang result in a "string" for the tail and an ascii value for the list?为什么在 erlang 中对这个字符串进行模式匹配会导致尾部的“字符串”和列表的 ascii 值?
【发布时间】:2019-09-17 03:06:42
【问题描述】:

我试图在 erlang 中编写一个模式匹配函数,例如:

to_end("A") -> "Z".

整个想法是使用模式匹配函数将诸如“ABC”之类的字符串转换为诸如“ZYX”之类的不同字符串。它看起来像一个字符串被表示为引擎盖下的一个列表......

我依赖于这样一个事实,即在 erlang 中对“字符串”进行模式匹配会产生单独的字符串字符。但我发现:

21> F="ABC".
22> F.
"ABC"
23> [H | T]=F.
"ABC"
24> H.
65
25> T.
"BC"

为什么列表中这种模式匹配的头部总是产生一个 ASCII 值,而尾部总是产生字母?有没有更好的方法来对“字符串列表”进行模式匹配?

【问题讨论】:

    标签: erlang


    【解决方案1】:

    为什么这种模式匹配的头部总是在列表中 结果是 ASCII 值,尾部是字母?

    在 erlang 中,字符串 "ABC" 是列表 [65,66,67] 的简写符号。该列表的头部是65,而该列表的尾部是列表[66,67],shell 恰好显示为"BC"。哇??!

    shell 在显示字符串/列表时非常糟糕:有时 shell 显示一个列表,有时 shell 显示一个双引号字符串:

    2> [0, 65, 66, 67].
    [0,65,66,67]
    
    3> [65, 66, 67].
    "ABC"
    
    4> 
    

    ...这简直是愚蠢的。每个初级和中级 erlang 程序员在某些时候都会对此感到困惑。

    请记住:当 shell 显示双引号字符串时,它实际上应该显示一个列表,其元素是双引号字符串中每个字符的字符代码。 shell 显示双引号字符串的事实是一个可怕的 ??feature?? erlang,并且在很多情况下很难理解发生了什么。你必须在心里对自己说,“我在 shell 中看到的那个字符串真的是列表……”

    当你想显示一个人的测试分数列表时,shell 会为某些列表显示双引号字符串这一事实真的很糟糕:[88, 97, 92, 70] 和 shell 输出:"Xa\\F"。您可以使用io:format() 方法来解决这个问题:

    6> io:format("~w~n", [[88,97,92,70]]).
    [88,97,92,70]
    ok
    

    但是,如果您只是想暂时查看 shell 显示为字符串的实际整数列表,一种快速而肮脏的方法是将整数 0 添加到列表的头部:

    7> Scores = [88,97,92,70].
    "Xa\\F"
    

    啊?!!

    8> [0|Scores].
    [0,88,97,92,70]
    

    哦,好吧。

    整个想法是将诸如“ABC”之类的字符串转换为某种东西 使用模式匹配函数的不同,例如“ZYX”。

    因为字符串是整数列表的简写,您可以使用加法来更改这些整数:

    -module(my).
    -compile(export_all).
    
    cipher([]) -> [];
    cipher([H|T]) ->
        [H+10|cipher(T)].  %% Add 10 to each character code.
    

    在外壳中:

    ~/erlang_programs$ erl
    Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
    Eshell V9.3  (abort with ^G)
    
    1> c(my).
    my.erl:2: Warning: export_all flag enabled - all functions will be exported
    {ok,my}
    
    2> my:cipher("ABC").
    "KLM"
    
    3>
    

    顺便说一句,所有函数都是“模式匹配”,所以说“模式匹配函数”是多余的,你可以说“一个函数”。

    【讨论】:

      【解决方案2】:

      在 Erlang 中,字符串只是 ascii 值的列表。它还显示整数列表,其中每个整数都是可打印的 ascii 代码,作为字符串。所以[48, 49]会打印出"01",因为48对应0,49对应1。因为你有字符串"ABC",这和[65 | [66 | [67]]]一样,[66, 67]会显示为"BC"

      如果你想编写一个函数来对字符进行模式匹配,你应该使用字符文字语法,即$后跟字符。所以你会写

      to_end($A) -> $Z;
      to_end($B) -> $Y;
      to_end($C) -> $X;
      ...
      to_end($Z) -> $A.
      

      而不是to_end("A") -> "Z"to_end([65]) -> [90] 相同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-19
        • 2013-05-11
        • 1970-01-01
        • 2021-11-06
        • 1970-01-01
        • 2020-04-23
        • 1970-01-01
        相关资源
        最近更新 更多