Ruby变量范围正在扼杀我

时间:2010-10-14 00:46:25

标签: ruby scope

我有一个读取文件的解析器。在文件中,您可以声明文件名,然后解析器会读取该文件名,然后在完成后,从中断处继续拾取并继续。这可以发生在你想要的深层次。

到目前为止听起来很简单。我想要做的就是打印出文件名和行号。

我有一个名为FileReader的类,如下所示:

class FileReader
    attr_accessor :filename, :lineNumber
    def initialize(filename)
        @filename = filename
        @lineNumber = 0
    end
    def readFile()
        # pseudocode to make this easy
         open @filename
         while (lines)
             @lineNumber = @lineNumber + 1
             if(line startsWith ('File:'))
                 FileReader.new(line).readFile()
             end
             puts 'read ' + @filename + ' at ' + @lineNumber.to_s()
         end
         puts 'EOF'
    end
end

足够简单。所以假设我有一个引用其他文件的文件。 File1-> File2->文件3。这就是它的样子:

read File1 at 1
read File1 at 2
read File1 at 3
read File2 at 1
read File2 at 2
read File2 at 3
read File2 at 4
read File3 at 1
read File3 at 2
read File3 at 3
read File3 at 4
read File3 at 5
EOF
read File3 at 5
read File3 at 6
read File3 at 7
read File3 at 8
EOF
read File2 at 4
read File2 at 5
read File2 at 6
read File2 at 7
read File2 at 8
read File2 at 9
read File2 at 10
read File2 at 11

这对我没有任何意义。

File 1 has 11 lines
File 2 has 8 lines
File 3 has 4 lines

我认为创建一个新对象会有自己的范围,不会影响父对象。

3 个答案:

答案 0 :(得分:2)

class FileReader
  def initialize(filename)
    @filename = filename
  end

  def read_file
    File.readlines(@filename).map.with_index {|l, i|
      next "read #{@filename} at #{i}" unless l.start_with?('File:')
      FileReader.new(l.gsub('File:', '').chomp).read_file
    }.join("\n") << "\nEOF"
  end
end

puts FileReader.new('File1').read_file

或只是

def File.read_recursively(filename)
  readlines(filename).map.with_index {|l, i|
    next "read #{filename} at #{i}" unless l.start_with?('File:')
    read_recursively(l.gsub('File:', '').chomp)
  }.join("\n") << "\nEOF"
end

puts File.read_recursively('File1')

答案 1 :(得分:0)

我同意您的重写代码中的某些内容会混淆问题。是的,那些实例变量应该是实例的本地变量。

注意代码块或条件块可能返回值并将其分配给实例变量的事情...例如,如果open语句使用下一个块并以某种方式返回文件名... @filename = open(line){}

我这样说是因为文件名在EOF之后显然没有改变

答案 2 :(得分:0)

这就是我想出的。它并不漂亮,但我试图保持尽可能接近你的代码,而Ruby也是如此。

file_reader.rb

#!/usr/bin/env ruby
class FileReader

  attr_accessor :filename, :lineNumber

  def initialize(filename)
      @filename = filename
      @lineNumber = 0
  end

  def read_file
    File.open(@filename,'r') do |file|
      while (line = file.gets)
        line.strip!
        @lineNumber += 1
        if line.match(/^File/)
          FileReader.new(line).read_file()
        end
        puts "read #{@filename} at #{@lineNumber} : Line = #{line}"
      end
    end
    puts 'EOF'
  end
end

fr = FileReader.new("File1")
fr.read_file

File1,File2和File3看起来像:

Line 1
Line 2
Line 3
File2 
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
Line 11

输出:

read File1 at 1 : Line = Line 1
read File1 at 2 : Line = Line 2
read File1 at 3 : Line = Line 3
read File2 at 1 : Line = Line 1
read File2 at 2 : Line = Line 2
read File2 at 3 : Line = Line 3
read File2 at 4 : Line = Line 4
read File3 at 1 : Line = Line 1
read File3 at 2 : Line = Line 2
read File3 at 3 : Line = Line 3
read File3 at 4 : Line = Line 4
EOF
read File2 at 5 : Line = File3
read File2 at 6 : Line = Line 6
read File2 at 7 : Line = Line 7
read File2 at 8 : Line = Line 8
EOF
read File1 at 4 : Line = File2
read File1 at 5 : Line = Line 5
read File1 at 6 : Line = Line 6
read File1 at 7 : Line = Line 7
read File1 at 8 : Line = Line 8
read File1 at 9 : Line = Line 9
read File1 at 10 : Line = Line 10
read File1 at 11 : Line = Line 11
EOF

重申一下,我们必须看到你的代码才能知道问题所在。

我理解你认为它与变量范围有关,所以这个问题对我来说很有意义。

对于其他人。对于想要学习的新手,请多一点。这应该是一个帮助的地方。谢谢。 &LT; /肥皂盒&GT;