В ruby, как мне объявить C ++ эквивалент «статических» переменных функции? - PullRequest
2 голосов
/ 11 февраля 2012

Я пытаюсь сохранить хэш локальным для одной функции, которая запоминает свое состояние между вызовами функции.Но я не знаю, как объявить это без замыкания (как предлагали некоторые пользователи в аналогичной теме).

Я знаю C ++ более тщательно, чем ruby, а в C ++ я бы обычно использовал static локальная переменная, как в первом примере здесь: http://msdn.microsoft.com/en-us/library/s1sb61xd.aspx

Мне удалось взломать что-то вместе в ruby ​​с помощью функции defined?:

def func x
  if not defined? @hash
    @hash = Hash.new
  end

  if @hash[x]
    puts 'spaghetti'
  else
    @hash[x] = true
    puts x.to_s
  end
end

func 1
func 1

Это печатает, следующее,что-то вроде того, что я хочу.Единственная проблема заключается в том, что @hash может быть доступен вне этой функции.

1
spaghetti

Есть ли какой-либо "более чистый", более предпочтительный способ объявления переменной с таким поведением (без фабрики)?Я собирался создать две или три переменные, такие как @hash, поэтому я искал лучший способ выразить это кратко.

1 Ответ

1 голос
/ 11 февраля 2012

То, что вы делаете, довольно часто встречается в Ruby, но также настолько распространено, что вам не нужно сильно суетиться по этому поводу.Все переменные экземпляра типа @ являются локальными только для этого экземпляра.Имейте в виду, что «экземпляр» обычно относится к экземпляру класса, но он также может ссылаться на экземпляр из класса.

Вы можете использовать @@ для ссылки наПеременная экземпляра класса из контекста экземпляра, но на практике это может привести к путанице.

То, что вы хотите сделать, - это одно из следующего.но только в контексте одного экземпляра объекта:

def func(x)
  # Instance variables are always "defined" in the sense that
  # they evaluate as nil by default. You won't get an error
  # for referencing one without declaring it first like you do
  # with regular variables.
  @hash ||= { }

  if @hash[x]
    puts 'spaghetti'
  else
    @hash[x] = true
    puts x.to_s
  end
end

Переменная, которая сохраняется между вызовами методов, но только в контексте всех экземпляров объекта:

def func(x)
  # Instance variables are always "defined" in the sense that
  # they evaluate as nil by default. You won't get an error
  # for referencing one without declaring it first like you do
  # with regular variables.
  @@hash ||= { }

  if @@hash[x]
    puts 'spaghetti'
  else
    @@hash[x] = true
    puts x.to_s
  end
end

Обычно это делается чище, оборачивая @@hash в метод класса.Это имеет вторичный эффект облегчения тестирования:

def self.func_hash
  @func_hash ||= { }
end

def func(x)
  if self.class.func_hash[x]
    puts 'spaghetti'
  else
    self.class.func_hash[x] = true
    puts x.to_s
  end
end
...