Могу ли я скопировать закрытие в Scala? - PullRequest
2 голосов
/ 13 июля 2011

Возможно, это недоделанная идея, но могу ли я скопировать среду выражения? Рассмотрим следующий пример:

class foo[T](block: => T) {
  var data = { () => block }
  def run() = { data() }
}

var a = 5

var b = new foo({ a += 1; println(a) })
var c = new foo({ a += 1; println(a) })

b.run()
c.run()
b.run()
c.run()

Я получаю следующий вывод:

6
7
8
9

Но что я действительно хочу, так это:

6
6
7
7

Короче говоря, я хочу, чтобы foo имел копии переменных в блоке вместо того, чтобы ссылаться на них после того, как начальное значение было разрешено. Можно ли это сделать? scala.util.DynamicVariable кажется многообещающим, но мне трудно понять, как я могу использовать его в приведенном выше примере.

Ответы [ 3 ]

6 голосов
/ 13 июля 2011

Если вы хотите сделать копию, то почему бы не сделать копию?

 var c = new foo({ var aa = a + 1; println(aa) })

Если вы хотите взять существующее замыкание, которое ссылается на переменную, и превратить его в замыкание, которое ссылается на копию этой переменной, то, боюсь, это невозможно.

В любом случае изменяемые переменные не должны использоваться, за исключением очень редких случаев и очень контролируемым образом. То есть не жонглировать своими ссылками.

2 голосов
/ 13 июля 2011

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

class bar[T](block: (T) => T, a: T) {
  var cur = a
  def run() = { cur = block(cur); cur }
}

var a = 5

var b = new bar((r: Int) => { val q = r + 1; println(q); q }, a)
var c = new bar((r: Int) => { val q = r + 1; println(q); q }, a)

b.run()
c.run()
b.run()
c.run()

Вывод:

6
6
7
7

Однако учтите, что в отличие от вашего кода это не повлияет на значение переменной aкак он работает.

0 голосов
/ 13 июля 2011

1) Как н.м. уже упоминалось, вы должны предпочесть неизменные понятия при использовании замыканий.

2) С другой стороны, это как раз то, для чего замыкания. Они не фиксируют значение переменной, они сами фиксируют переменную ! Ваш вопрос вроде перевернутый. Вы на самом деле захватываете среду - среду вашей переменной. Если вам не нужна та же переменная, чем скопировать ее как n.m. или Ян Маклаирд соответственно предложил.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...