Когда мы должны использовать scala.util.DynamicVariable? - PullRequest
46 голосов
/ 25 февраля 2011

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

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

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

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

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

Ответы [ 3 ]

56 голосов
/ 25 февраля 2011

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 динамических переменных (и, следовательно, привязка к определенному потоку, обрабатывающему запрос) - это просто самый простой способ получить их где-нибудь в коде (не передавая аргументы метода или как-либо ещеиначе явно).

24 голосов
/ 18 марта 2013

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

Предположим, мы должны использовать некоторый код, который использует 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
17 голосов
/ 11 мая 2015

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

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

Вывод будет:

withoutValue
withValue
withoutValue
...