Elixir列表推导式中二进制模式匹配失败问题排查
这个问题的核心是你对Elixir列表推导式的生成器语法理解有点偏差,咱们一步步拆解来看:
首先,先明确'hello'的本质:它是一个字符列表,每个元素都是对应字符的ASCII整数(比如'h'是104,'e'是101,以此类推)。
然后看你写的列表推导式:
for << b1::size(2), b2::size(3), b3::size(3) >> = <<ch>> <- 'hello', do: b1
这里的问题出在生成器部分:<-左边的是用来匹配枚举元素的模式,而你写的<<...>> = <<ch>>是试图把枚举元素(整数)匹配到这个二进制模式上——但整数和二进制是不同的类型,自然匹配失败,所以所有元素都被过滤掉,结果就是空列表[]。
而你单独测试的<< b1::size(2), b2::size(3), b3::size(3) >> = <<100>>能成功,是因为<<100>>是一个单字节的二进制(正好8位),和你的模式总长度(2+3+3=8)完全匹配,所以可以正确绑定变量。
那怎么修改才能得到预期结果呢?有两种常见的写法:
写法1:在过滤条件中完成二进制匹配
先遍历字符列表的每个整数元素,再尝试把它转成单字节二进制后进行模式匹配:
iex()> for ch <- 'hello', <<b1::size(2), b2::size(3), b3::size(3)>> = <<ch>>, do: b1 [1, 1, 1, 1, 1]
这里的逻辑是:对每个ch(整数),先把它包装成<<ch>>(单字节二进制),再用你的模式去匹配,匹配成功就返回b1。
写法2:直接对二进制进行枚举
既然你要处理的是字符对应的二进制,不如直接把字符列表转成二进制字符串("hello"),然后用二进制模式作为生成器:
iex()> for <<b1::size(2), b2::size(3), b3::size(3)>> <- "hello", do: b1 [1, 1, 1, 1, 1]
这种写法更直接,因为"hello"是二进制类型,每个字节正好是8位,和你的模式长度完全契合,推导式会自动逐个字节匹配模式。
本质上,你之前的错误是混淆了“枚举元素的类型”和“模式匹配的目标类型”——枚举的是整数,却用二进制模式去匹配,自然无法成功。调整一下匹配的时机或者枚举的源,就能解决问题啦。
内容的提问来源于stack exchange,提问作者aryndin

