【问题标题】:How to simulate Ruby's until loop in Elixir?如何在 Elixir 中模拟 Ruby 的 until 循环?
【发布时间】:2016-07-02 12:17:26
【问题描述】:

我正在将一个 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} 元组是令牌的lineposition

这是 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 上的某人建议使用 recursion,但他们没有举例说明。我已经看到了使用累加器等的求和/减少的递归示例。但是,在评估布尔值时,我看不到它是如何应用的。

谁能提供一个使用StringScanner.eos?(scanner) 的工作示例?谢谢。

【问题讨论】:

  • 我想说你问错问题了。请解释您的最终目标是什么,提出一个好的解决方案可能更容易。对我来说,现在的问题真的没有什么意义。
  • 我有一个分词器,它将文本文件拆分为单独的行,然后循环遍历每一行,并给 StringScanner 一行,后者循环遍历行匹配模式。就像 Ruby 版本一样,字符串扫描器在每次扫描匹配时移动一个指针。 eos?如果已到达字符串的末尾,则返回 true。在 Ruby 中,我使用了 until 循环。

标签: recursion elixir


【解决方案1】:

可能是这样的

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/0add_to_acc/2),因为我不知道您的意思是如何实现它们;第一个是为了做scan(line + 1)在Ruby代码中所做的事情,而第二个是为了做&lt;&lt;在Ruby代码中所做的事情(例如,它可以将扫描的东西添加到令牌列表或其他东西中类似)。

【讨论】:

  • 好的。 add_to_acc 将如何工作?在我的例子中,令牌是一个元组列表。例如,令牌可能如下所示:{:new_line, "\n", {1, 1}}。类型规范:@type token :: {:atom, any, {integer, integer}}。我想我不明白它是如何用一个空列表 [] 初始化的,然后在没有声明变量时以列表中的东西结束。
  • 没关系。我在How does recursion work in Elixir 上找到了您的出色答案。我想我现在更好地理解了这一点。我只需要弄清楚如何将其应用到我的代码中...
  • @EdwardJ.Stembler 如果您需要进一步的帮助,请在 #elixir-lang IRC(whatyouide)上联系我 :)
猜你喜欢
  • 1970-01-01
  • 2022-08-19
  • 2012-12-03
  • 2013-08-10
  • 2016-08-20
  • 1970-01-01
  • 1970-01-01
  • 2018-03-16
  • 1970-01-01
相关资源
最近更新 更多