我正在将Ruby项目转换为Elixir。 Ruby的until循环如何转换为Elixir?
until scanner.eos? do
tokens << scan(line + 1)
end
这是完整的Ruby方法:
def tokenize
@tokens = []
@lines.each_with_index do |text, line|
@scanner = StringScanner.new(text)
until @scanner.eos? do
@tokens << scan(line + 1)
end
end
@tokens
end
@lines
只是一个由新行分割的文本文件。 @lines = text.split("\n")
在Elixir中,我已经转换了string scanner,如下所示:StringScanner.eos?(scanner)
:
@spec eos?(pid) :: boolean
def eos?(pid) when is_pid(pid) do
此外,在Elixir中,令牌是元组:@type token :: {:atom, any, {integer, integer}}
。 {integer, integer}
元组是令牌的line
和position
的位置。
这是Elixir伪造的代码,它不太有效。
@spec scan(String.t, integer) :: token
def scan(text, line) when is_binary(text) and is_integer(line) do
string_scanner = StringScanner.new(text)
until StringScanner.eos?(string_scanner) do
result = Enum.find_value(@scanner_tokenizers, fn {scanner, tokenizer} ->
match = scanner.(string_scanner)
if match do
tokenizer.(string_scanner, match, line)
end
end)
IO.inspect result
end
StringScanner.stop(string_scanner)
result
end
slack channel上有人建议使用递归,但他们没有详细说明示例。我已经看到了使用累加器等求和/缩减的递归示例。但是,我没有看到在评估布尔值时如何应用。
任何人都可以提供使用StringScanner.eos?(scanner)
的工作示例吗?感谢。
答案 0 :(得分:2)
可能类似
def tokens(scanner) do
tokens(scanner, [])
end
defp tokens(scanner, acc) do
if StringScanner.eos?(scanner) do
acc
else
tokens(scanner, add_to_acc(scan_stuff(), acc))
end
end
至少这可能是一般的想法。正如您所看到的那样,我保留了一些非常通用的功能(scan_stuff/0
和add_to_acc/2
),因为我不知道您是如何实现这些功能的;第一个用于执行scan(line + 1)
在Ruby代码中执行的操作,而第二个用于执行<<
在Ruby代码中执行的操作(例如,它可以将扫描的内容添加到列表中令牌或类似的东西)。