Почему переменная может быть дважды привязана к шаблону? Обычно F # не допускает, чтобы переменные шаблона выполнялись дважды в одном шаблоне. Но в следующем коде F # не жалуется - это ошибка? type foo = { A: int } let test (x, {A = x}) = x let result = test ("bla", {A = 3}) Ответ 1 Я не думаю, что это ошибка, хотя это кажется запутанным, но это просто способ компиляции компиляции вышеуказанного значения. В разделе 14.6.3 указано, что если определение значения не является одним шаблоном значений (как здесь, здесь), выработанное выражение tmp <typars1… typarsn> = expr ident1 <typars1> = expr1 … identn <typarsn> = exprn где tmp - новый идентификатор, и каждый expri является результатом компиляции паттерна шаблона (§7) против ввода tmp [from spec]. Чтобы узнать, что делает компилятор, мы можем использовать цитату F #, например: <@ let test (x:int, {A = x:int})= x in test (3, {A = 5}) @>;; В строчном формате я получаю (оставляя некоторые вещи): Let (test, Lambda (tupledArg, Let (x, TupleGet (tupledArg, 0), Let (_arg1, TupleGet (tupledArg, 1), Let (x, PropertyGet (Some (_arg1), A, []), x)))), Application (test, NewTuple (Value (3), NewRecord (foo, Value (5))))) поэтому мы получаем "внутренний" x. Я не думаю, что это ошибка, но, возможно, это было бы более последовательным, если бы это вызвало предупреждение.
Ответ 1 Я не думаю, что это ошибка, хотя это кажется запутанным, но это просто способ компиляции компиляции вышеуказанного значения. В разделе 14.6.3 указано, что если определение значения не является одним шаблоном значений (как здесь, здесь), выработанное выражение tmp <typars1… typarsn> = expr ident1 <typars1> = expr1 … identn <typarsn> = exprn где tmp - новый идентификатор, и каждый expri является результатом компиляции паттерна шаблона (§7) против ввода tmp [from spec]. Чтобы узнать, что делает компилятор, мы можем использовать цитату F #, например: <@ let test (x:int, {A = x:int})= x in test (3, {A = 5}) @>;; В строчном формате я получаю (оставляя некоторые вещи): Let (test, Lambda (tupledArg, Let (x, TupleGet (tupledArg, 0), Let (_arg1, TupleGet (tupledArg, 1), Let (x, PropertyGet (Some (_arg1), A, []), x)))), Application (test, NewTuple (Value (3), NewRecord (foo, Value (5))))) поэтому мы получаем "внутренний" x. Я не думаю, что это ошибка, но, возможно, это было бы более последовательным, если бы это вызвало предупреждение.