Вопрос о области действия локальных переменных при использовании выражения Let во время рекурсивного вызова функции - PullRequest
0 голосов
/ 13 июня 2019

У меня возникают некоторые проблемы при попытке выяснить текущую динамическую среду во время рекурсивного вызова функции и значений, с которыми связаны локальные переменные в функции. Это не просто проблема, с которой я сталкиваюсь в ML, но даже в JAVAЯ очень запутался по поводу объема переменных во время рекурсивных вызовов.

fun examplefunction(x:int,ys:int list)=
if null (tl ys)
then 0
else
let
  val temp=0
  val temp=temp +(hd ys)
  val tail= (tl ys)
  val k=1
in

  if x>temp andalso temp+(hd tail)>=x

  then k

  else k+examplefunction(x,tl ys)

end

Мне трудно понять, как переменная temp обновляется во время рекурсивного вызова (если я предполагаю, что входной список int достаточно велик).Например, в случае

x = 5 и ys = [2,1,3], и я вызываю функцию с помощью

examplefunction (5, [2,1,3]);

В этом случае (tl ys) в строке 2 не равно нулю

и, следовательно, еще выполняется, а в строке 6 переменная temp связывается с целым числом 0, в следующей строке 7 она получаетзатеняется, и в новом динамическом окружении он становится связанным с 2. Переменная tail связана с int list [1], а переменная k связана с 1.

Теперь в "in" (строка 10)выражение if в строке 12 имеет значение false, поэтому в строке 16 выполняется else, который рекурсивно вызывает функцию

examplefunction (5, [1,3])

Я хочу понять, в какой средеэто вызов функции "examplefunction (5, [1,3])"? *

Когда этот рекурсивный вызов функции получает исключения, в строке 6 временная переменная, равная 2 в предыдущем вызове, затеняется на 0 изатем 0 + hd [1,3] = 0 + 1 = 1.

Это очень смущает меня и действительнобольшое препятствие в написании некоторых функций в задании на домашнее задание.Пожалуйста, дайте мне знать, если вопрос не ясен.

1 Ответ

0 голосов
/ 14 июня 2019

Среда связывает имена, такие как аргументы функции x, ys и аргументы в теле предложения let, temp, tail и k (в данном случае). Каждое объявление val внутри let расширяет среду, связывая имя с подвыражением.

Итак, если посмотреть на examplefunction, среда, в которой вычисляется тело функции, имеет x и ys, связанные с тем, с чем функция была вызвана. В вашем первом примере: x связан с 5, а ys связан с [2,1,3].

При оценке ветви if и ветви then в среду ничего не добавляется. В ветке else есть предложение let, которое добавит несколько новых привязок в среду.

Первый - это temp = 0. На этом этапе выражения среда оценки имеет вид x, ys, а теперь temp.

Далее temp восстанавливается до подвыражения temp + hd ys. На этом этапе окружение не будет иметь никаких новых имен, но выражение, к которому привязан temp, изменилось.

Следующей связью в предложении let является tail для tl ys. Это добавляет новое имя к среде, tail.

Наконец, k связан с 1. В среде теперь есть переменные x, ys, temp, tail и k, связанные с некоторыми подвыражениями. При вызове с аргументами x = 5 и ys = [2,1,3] эти привязки будут следующими: temp = 0 + hd ys = 2, tail = tl ys = [1,3] и k = 1.

Затем вычисляется следующее подвыражение if-then-else, и examplefunction может вызываться или не вызываться рекурсивно в зависимости от того, имеет ли логическое значение x> temp and также temp + (hd tail)> = x значение true или нет.

Важно то, что если он вызывается рекурсивно, среда не будет иметь привязку к temp, tail и k, поскольку они являются локальными для предложения let. Как написано, x будет привязан к x и ys к tl ys в рекурсивном вызове, и мы начнем тот же процесс снова.

Ключевые моменты:

  1. Среда связывает имена с выражениями.
  2. Аргументы функций и объявления val в предложениях let добавляют локальные привязки к среде во время вычисления выражений.
  3. Когда функция вызывается рекурсивно, все, что было связано внутри выражения let внутри тела функции, не будет начинаться при рекурсивном вызове
...