Можно ли сказать, что закрытие функции-это сохранение состояния в функцию, и каждый раз, когда мы назначаем функции новое состояние, это приведет к появлению новой функции?

#scala #functional-programming #closures

#scala #функциональное программирование #закрытие

Вопрос:

В следующей функции, называемой inc в Scala, которая выполняет операцию приращения.

 def inc(more:Int) = {  def helper(x:Int) = x more  helper _ }  

Всякий раз, когда вызывается функция inc, она возвращает другую функцию, которая связывает переданный ей аргумент. Например, inc(1) вернет другую функцию типа Int =gt; Int, где переменная more связана с 1.

 inc(1) // This is of type Int =gt; Int  

Итак, можем ли мы сказать, что more является переменной состояния возвращаемой функции, и когда мы вызываем inc(1), то 1 присваивается more?

Вот еще несколько уточнений,

Поскольку я исхожу из парадигмы программирования OO, когда я говорю «состояние», я соотносил его с экземпляром класса, который в данный момент времени имеет определенное состояние. Давайте сначала рассмотрим класс в Java call IncHelper следующим образом:

 class IncHelper{  private int more;  public IncHelper(int more){  this.more = more;  }   public int inc(int x){  return x this.more;  } }  

Если я создам другой экземпляр вышеуказанного класса следующим образом:

 IncHelper inc1 = new IncHelper(1);  // This instance will always increase a value by 1 inc1.inc(10); // output will be 11  

Если я создам другой экземпляр вышеуказанного класса следующим образом:

 IncHelper inc2 = new IncHelper(2);  // This instance will always increase a value by 2 inc2.inc(10); // output will be 12  

Таким образом, в приведенных выше двух сценариях два экземпляра inc1 и inc2 содержат два разных значения переменных состояния. И то же самое верно для примера, который я привел для функционального программирования Scala:

 val inc1 = inc(1) inc1(10) // Will return 11  

If I create another value as follows:

 val inc2 = inc(2) inc2(10) // Will return 12  

So in both cases i.e. OO Programming when I created 2 instances of IncHelper, it remembers the variable which is passed while constructing it. Same way, it is true for the two function literals we have created, where the two variables passed while creating the function literals inc1 and inc2 has stored the values.

Ответ №1:

Закрытие функции хранит информацию о контексте — другой вопрос, состоит ли этот контекст из изменяемых и/или неизменяемых данных.

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

В вашем случае:

 def inc(more:Int) = {  def helper(x:Int) = x more  helper _ }  

inc не хранит изменяемые данные. x more возвращает новое значение, не изменяя ни x значения, ни more значения. Если вы это сделаете:

 inc(1) inc(1) inc(1) inc(1)  

вы будете получать один и тот же результат ( Int =gt; Int функцию с одинаковым поведением) каждый раз без побочных эффектов. Таким образом, согласно общепринятой терминологии, inc функция не имеет состояния, и вы не можете сказать, что у нее есть состояние. Тот факт, что в нем хранятся некоторые данные… не имеет значения, потому что каждый фрагмент кода, который вы когда-либо писали, делает это, поэтому все будет называться с сохранением состояния, и различие между состоянием и состоянием без состояния будет практически бесполезным.

Теперь, если вы определили, что вы функционируете как:

 var state = 0 def inc(more:Int) = {  state = state   more  val y = state // binds current value of state  def helper(x:Int) = x   y  helper _ }  

каждый вызов inc с одним и тем же значением приведет к другому значению (здесь: функция Int =gt; Int с другим поведением), так что будет о каком-то состоянии говорить. ( int функция будет иметь сохраненное состояние , в var state то время как возвращаемые функции будут без состояния, поскольку они будут захватывать только неизменяемые значения).

Это состояние было бы независимым от концепции закрытия — закрытие только «говорит», что определение функции использует некоторые данные, предоставленные в момент ее создания, И что функция все еще может получить доступ к этим данным после того, как вы больше не сможете получить доступ извне.

Подводя итог, я бы сказал только, что (конкретное) «закрытие функции сохраняет состояние функции», если в среде было какое-то изменяемое состояние, в котором была создана функция, которая была захвачена (использована) этой функцией. В других случаях я бы этого не сказал, так как не было бы никакого «состояния» для захвата. Однако, поскольку это довольно неточное утверждение (делает ли функция снимок изменяемого состояния, которое само по себе не изменяемо? или захваченная функция ссылается на некоторые изменяемые данные, которые могут быть изменены вне ее?) Я бы вообще этого избегал.

Комментарии:

1. Спасибо Матеушу Кубушоку, так как я больше ориентируюсь на парадигму УПС, следовательно, я соотносил ее с УПС. Я подробно изложил свой вопрос, в котором я попытался сопоставить эти два.

2. «Экземпляр», «объект», «состояние» и т. Д.-Это детали реализации, которые вы можете наблюдать в JVM (что является OO по дизайну). Но те же понятия («функция», «закрытие») может быть реализована по-разному, например, в Haskell вы бы замыканий реализуется с некоторыми низкоуровневыми c-концепции (невидима для программиста), а в C закрытие захвата вполне явной (эту странную [] штуковину) а лямбда может быть встроен в сырых АСМ инструкции без выделения памяти. Восприятие «закрытия» как «состояния» может стать способом полного использования этой концепции.