Ruby:方法返回没有块

时间:2011-04-05 16:25:39

标签: ruby

我试图在没有块的情况下调用此代码。底部的未注释线是我想要返回的。第一个未注释的行应该返回tut,第二行转换为英语,最后一行应该是英语。为什么“put eng”这条线上下而不是以句子形式返回?感谢您的帮助。

这是我的代码:

class Tut
      @@consonants = ["b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z"]

  def is_tut? string
    if string =~ /^(([b-df-hj-np-z]ut)|([aeiou\s])|[[:punct:]])+$/i
      yield
    else
      false
    end
  end

  def self.to_tut string 
    string.each_char do |c|
      c += "ut" if @@consonants.find { |i| i == c.downcase }
        yield c if block_given?
      end
  end

  def self.to_english string
    array = string.split //
    array.each do |c|
      if @@consonants.find { |i| i == c.downcase }
        array.shift
        array.shift
      end
      yield c if block_given?
    end
  end
end

#Tut.to_tut( "Wow! Look at this get converted to Tut!" ) { |c| print c }
# should output : Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!

#puts
#puts

tut = Tut.to_tut( "Wow! Look at this get converted to Tut!" )
puts "from return: #{tut}"

puts

#Tut.to_tut( "Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!" ) { |c| print c }
#should outout : Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!
#puts
#puts

tut = Tut.to_tut( "Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!" )
puts "from return: #{tut}"

#puts

#tut_string = ""
#Tut.to_tut( "I'm in tut but I want to be in english." ) { |c| tut_string += c }
#puts tut_string
# should output : I'mut inut tututut bututut I wutanuttut tuto bute inut enutgutlutisuthut.

puts

#Tut.to_english( tut_string ){ |c| print c }
# should output : I'm in tut but I want to be in english.

lan = Tut.to_english( tut )
puts lan

2 个答案:

答案 0 :(得分:0)

方法to_tutto_english在没有阻止的情况下使用时会给出错误答案。发生这种情况是因为ruby始终返回方法中评估的最后一个值。在您的代码中,string.each_charto_tutarray.eachto_english的结果。在这两种情况下,结果都包含原始输入,因此返回并打印。

对于puts eng,它会打印由array.each to_english返回的数组。

答案 1 :(得分:0)

(打开注释:您通常不希望在迭代时修改Enumerable对象,因为这会使读取代码并调试它变得更加困难。)

你的to_tut不会保留你的修改,因为“c”块变量是字符串切片的副本,而不是对字符串部分的引用(如果它是re​​f,你可以使用< ;<要追加;“+ =”仍然无效,因为它重新分配而不是更改引用)。这就是each_char的工作原理,因为String不包含引用。

如果你想修改字符串,你可能需要向后计数,然后通过字符串#[] =插入'ut'。但这很复杂,所以我会提出几个替补。

工作to_tut#1:

def self.to_tut string
  string.chars.map do |c|
    yield c if block_given?
    # this must be the last expression the block
    if @@consonants.find { |i| i == c.downcase }
      c + 'ut'
    else
      c
    end
  end.join
end

工作to_tut#2 - 这可能是最红宝石的方式:

def self.to_tut string
  string.gsub(/[#{@@consonants.join}]/i) {|match|
    yield match if block_given?
    # this must be the last expression in the block
    match + 'ut'
  }
end

你的to_english不起作用,因为array.shift总是删除数组的第一个元素。相反,您希望跟踪当前索引,并从索引+ 1开始删除2个字符。

work to_english:

def self.to_english2 string
  array = string.split //
  array.each_with_index do |c, idx|
    if @@consonants.find { |i| i == c.downcase }
      array.slice!(idx+1, 2)
    end
    yield c if block_given?
  end
  array.join
end

关于为什么你的“put lan”每行返回一个char - 这是因为你的to_english返回一个数组。你想要调用join来转换它。