代码之家  ›  专栏  ›  技术社区  ›  Stephen A

初学者Ruby教程中未初始化的常量Bot::文字游戏(NameError)

  •  0
  • Stephen A  · 技术社区  · 11 年前

    目前正在阅读Beginning Ruby第12章,它构建了一个对话机器人。当运行basic_client.rb文件时,机器人会加载。当输入“我讨厌电视”时,机器人应该识别带有“讨厌”一词的模式,并根据该模式返回响应。

    相反,它会从bot文件中返回一些名称错误。这些都与wordplay.rb文件有关,但我不确定是什么原因导致的。如果有任何帮助,我们将不胜感激。

    /bot.rb:73:in `block (2 levels) in possible_responses': uninitialized constant Bot::Wordplay (NameError)
    /bot.rb:69:in `collect'
    /bot.rb:69:in `block in possible_responses'
    /bot.rb:59:in `each'
    /bot.rb:59:in `possible_responses'
    /bot.rb:27:in `response_to'
    from basic_client.rb:8:in `<main>'
    

    正在运行的文件:basic_client.rb

    `require './bot'
    
    bot = Bot.new(:name => 'Fred', :data_file => 'fred.bot')
    
    puts bot.greeting
    
    while input = gets and input.chomp != 'end'
    puts '>> ' + bot.response_to(input)
    end
    
    puts bot.farewell`
    

    所需的bot.rb:

    require 'yaml'
    require './wordplay'
    
    class Bot
    attr_reader :name
    
    def initialize(options)
        @name = options[:name]  || "Unnamed Bot"
        begin
            @data = YAML.load(File.read(options[:data_file]))
        rescue
            raise "Can't load bot data"
        end
    end
    
    def greeting
        random_response :greeting
    end
    
    def farewell
        random_response :farewell
    end
    
    def response_to(input)
        prepared_input = preprocess(input.downcase)
        sentence = best_sentence(prepared_input)
        responses = possible_responses(sentence)
        responses[rand(responses.length)]
    end
    
    private
    
    def random_response(key)
        random_index = rand(@data[:responses][key].length)
        @data[:responses][key][random_index].gsub(/\[name\]/, @name)
    end 
    
    def preprocess(input)
        perform_substitutions(input)
    end
    
    def perform_substitutions(input)
        @data[:presubs].each { |s| input.gsub!(s[0], s[1]) }
        input
    end
    
    def best_sentence(input)
        hot_words = @data[:responses].keys.select do |k|
            k.class == String && k =~ /^\w+$/
        end
    
        WordPlay.best_sentence(input.sentences, hot_words)
    end
    
    def possible_responses(sentence)
        responses = []
    
        # Find all patterns to try to match against
        @data[:responses].keys.each do |pattern|
            next unless pattern.is_a?(String)
    
            # For each pattern, see if the supplied sentence contains 
            # a match. Remove substitution symbols (*) before checking.  
            # Push all responses to the responses array.
    
            if sentence.match('\b' + pattern.gsub(/\*/, '') + '\b')
                # If the pattern contains substitution placeholders, perform the substitutions
                if pattern.include?('*')
                    responses << @data[:responses][pattern].collect do |phrase|
                        # Erase everything before the placeholder, leaving everything after it
                        matching_section = sentence.sub(/^.*#{pattern}\s+/, '')
                        # Then substitute the text after the placeholder with the pronouns switched
                        phrase.sub('*', Wordplay.switch_pronouns(matching_section))
                    end
                else
                    responses << @data[:responses][pattern]
                end
            end
        end
    
        # If there were no matches, add the default ones
        responses << @data[:responses][:default] if responses.empty?
        # Flatten the blocks of responses to a flat array
        responses.flatten
    end
    end
    

    文字游戏文件:

    class String
    def sentences
        self.gsub(/\n|\r/, ' ').split(/\.\s*/)
    end
    
    def words
        self.scan(/\w[\w\'\-]*/)
    end
    end
    
    class WordPlay
    def self.switch_pronouns(text)
        text.gsub(/\b(I am|You are|I|You|Your|My|Me)\b/i) do |pronoun|
            case pronoun.downcase
            when "i"
                "you"
            when "you"
                "me"
            when "me"
                "you"
            when "i am"
                "you are"
            when "you are"
                "i am"
            when "your"
                "my"
            when "my"
                "your"
            end
        end.sub(/^me\b/i, 'i')
    end
    
    def self.best_sentence(sentences, desired_words)
        ranked_sentences = sentences.sort_by do |s|
            s.words.length - (s.downcase.words - desired_words).length
        end
    
        ranked_sentences.last
    end
    end
    
    2 回复  |  直到 11 年前
        1
  •  1
  •   scones    11 年前

    ruby语言对其变量和常量区分大小写。

    因此,你需要写下这个词 Wordplay 无论在哪里使用它都是一样的。

    我建议你写 class Wordplay 小写为P。 另一种选择是像Greg Guida建议的那样,用大写字母P来写另一个事件。

        2
  •  0
  •   Anthon    11 年前

    第73行文字游戏中的p应该是大写的