Подтвердить что ты не робот

Когда мы будем использовать scala.util.DynamicVariable?

Когда я прочитал источник скаляры, я обнаружил, что есть код:

protected val _response   = new DynamicVariable[HttpServletResponse](null)
protected val _request    = new DynamicVariable[HttpServletRequest](null)

Существует интересный класс с именем DynamicVariable. Я просмотрел документ этого класса, но я не знаю, когда и почему мы должны его использовать? Он имеет withValue(), который обычно используется.

Если мы его не используем, то какой код мы должны использовать вместо этого, чтобы решить проблему, которую он решил?

(Я новичок в scala, если вы можете предоставить некоторый код, это будет здорово)

4b9b3361

Ответ 1

DynamicVariable - это реализация шаблонов займов и динамических областей. Пример использования DynamicVariable в значительной степени похож на ThreadLocal в Java (по сути, DynamicVariable использует InheritableThreadLocal за кулисами) - он использовался, когда вам нужно выполнить вычисление в закрытой области, где каждый поток имеет свою собственную копию значения переменной:

dynamicVariable.withValue(value){ valueInContext =>
  // value used in the context
} 

Учитывая, что DynamicVariable использует наследуемый ThreadLocal, значение переменной передается потокам, порожденным в контексте:

dynamicVariable.withValue(value){ valueInContext =>
  spawn{
    // value is passed to the spawned thread
  }
}

DynamicVariableThreadLocal) используется в Scalatra по той же причине, что и во многих других средах (Lift, Spring, Struts и т.д.) - это неинтрузивный способ хранения и передачи контекст (поток) - конкретная информация.

Создание динамических переменных HttpServletResponse и HttpServletRequest (и, таким образом, привязка к определенному потоку, обрабатывающему запрос), - это самый простой способ получить их в любом месте кода (не проходя через аргументы метода или в любом случае явно).

Ответ 2

На это хорошо ответил Василь, но я добавлю еще один простой пример, который может помочь понять.

Предположим, что мы должны использовать некоторый код, который использует println() для записи всего stdout. Мы хотим, чтобы этот вывод попадал в файл журнала, но у нас нет доступа к источнику.

  • println() использует Console.println()
  • Console.println() (к счастью) на основе a DynamicVariable[PrintStream], который по умолчанию равен java.lang.System.out
  • Console определяет withOut, который просто переходит к динамической переменной withValue

Мы можем использовать это, чтобы просто исправить нашу проблему:

def noisy() { println("robot human robot human") }
noisy() // prints to stdout
val ps = new java.io.PrintStream("/tmp/mylog")
scala.Console.withOut(ps) { noisy() } // output now goes to /tmp/mylog file

Ответ 3

Это минимальный фрагмент:

val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
  print
}
print

Выход будет:

withoutValue
withValue
withoutValue