функции в F # .. почему это не компилируется - PullRequest
0 голосов
/ 13 января 2011

Я написал две версии кода.Первый работает как положено и печатает «Привет».второй выводит мне ошибку, что «блок, следующий за этим, является незаконченным»

1-я версия

#light 

let samplefn() =
            let z = 2
            let z = z * 2
            printfn "hi"

samplefn()

2-я версия

#light 

let samplefn() =
            let z = 2
            let z = z * 2           

samplefn()

Разница только в том, что printfn отсутствуетво второй версии.Я использую Visual Studio 2010 в качестве моей IDE.Я очень плохо знаком с F #, но эта ошибка кажется мне очень странной.Думаю, мне не хватает какой-то очень важной концепции.Пожалуйста, объясните.

Редактировать: Также, если я делаю это вне функции, я получаю ошибку даже с первой версией кода.

#light
let z = 2
let z = z * 2
printfn "Error: Duplicate definition of value z"

Ответы [ 3 ]

7 голосов
/ 13 января 2011

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

Чтобы представить это по-другому, всем функциям в F # требуется возвращаемое значение, которое является значением последнего выполненного выраженияв вашей функции.let не имеет возвращаемого значения, поэтому ваша функция недопустима.Чтобы исправить это, вы можете добавить возвращаемое значение, например:

let samplefn() =
    let z = 2
    let z = z * 2
    ()

, которое определяет функцию, которая абсолютно ничего не делает (возвращает unit).Возможно, лучшим примером является следующий:

let samplefn() =
    let z = 2
    let z = z * 2
    z

, который вернет 4 (значение привязки для метки z).

5 голосов
/ 13 января 2011

Я думаю, что здесь полезно понимать нелегкий синтаксис.Давайте переведем:

1-я версия (пусть выражения связывания)

let samplefn() =
    let z = 2 in
    let z = z * 2 in
    printfn "hi";;

samplefn();;

Здесь важно понять, что все привязки пусть не верхнего уровня на самом деле являются выражениями вида let <variable> = <expression1> in <expression2>где <variable> связан с результатом <expression1> в новой области видимости <expression2>, а <expression2> - это возвращаемое значение всего выражения.Легкий синтаксис заставляет вас верить, что такие привязки let являются переменными присваиваниями / утверждениями, хотя на самом деле действительно верно, что почти все в F # является выражением.

Возможно, следующее иллюстрирует это более четко:

let a = (let b = 3 in b + 2) //a is 5

2-я версия (привязки let верхнего уровня)

let z = 2;;
let z = z * 2;;
printfn "Error: Duplicate definition of value z";;

Привязки let верхнего уровня завершаются с ;;, что указывает на завершение того, что можно считать оператором.Верхний уровень - это одна область, и здесь мы получаем ошибку при попытке дважды связать z в одной и той же области.Принимая во внимание, что используя форму выражения привязок let в Примере 1, мы связываем z заново для каждой подобласти в цепочке выражений.Обратите внимание, что мы можем сделать что-то вроде этого на верхнем уровне:

let z = (let z = 2 in z * 2);;
4 голосов
/ 13 января 2011

A let, который не находится на верхнем уровне (например, ваши с отступами), должен иметь оператор (фактически выражение, как примечания pst), называемый "телом" после присваивания.В первом примере тело - printfn "hi", тогда как во втором примере тело отсутствует.Это то, на что жалуется компилятор.

Обратите внимание, что в определениях вашей функции внутренние выражения let фактически создают вложенные области видимости.То есть let z = z * 2 фактически создает новое значение с именем z и связывает с ним значение внешнего z умноженного на 2, а затем использует его в теле let (которое является printfn вэтот случай).Вложенный let всегда будет иметь тело.Это вложение, которое допускает, казалось бы, дублированное определение.

Поскольку внешнему let тело не нужно, компилятор считает, что вы пытаетесь переопределить z в той же области, что является ошибкой,Вы можете использовать скобки, чтобы указать компилятору, как правильно интерпретировать последний пример:

let z = 2
(let z = z * 2
printfn "z = %d" z)
printfn "z = %d" z

Выше будет напечатано

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