2015-01-27 2 views
5

В F # я могу использовать сопоставление образцов во множестве мест в синтаксисе.Как разрушить аргумент конструктора?

Например:

// Given this type... 
type SingleCaseUnion = | SingleCaseUnion of int 

/// ...I can do this: 
let destructureInFunc (SingleCaseUnion n) = 
    printfn "%d" n 

// ...and this: 
type DestructureInMethod() = 
    member t.M(SingleCaseUnion n) = 
     printfn "%d" n 

Но я не могу работать, как это сделать:

type DestructureInCtor(SingleCaseUnion n) = 
    do printfn "%d" n 

// type DestructureInCtor(SingleCaseUnion n) = 
// ---------------------------------------^ 
// 
// stdin(3,40): error FS0010: Unexpected identifier in type definition. Expected ')' or other token. 

У меня есть синтаксис неправильно, или же F # не поддерживает шаблон согласования в параметрах конструктора ? не

+0

Хотя это не работает для * первичных * конструкторов, другие (вторичные) конструкторы позволяют это. * (reposted как комментарий, так как мой ответ стал излишним.) * – Vandroiy

ответ

5

Нет, language spec явно говорит нет:

primary-constr-args : attributesopt accessopt (simple-pat, ... , simplepat) 
simple-pat : 
| ident 
| simple-pat : type 

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

Если F # должно было разрешить сопоставление шаблонов здесь, были бы некоторые шаблоны, которые нарушили бы это однопараметрическое отношение.

type DestructureInCtor(SingleCaseUnion _) = 
    // doesn't declare a private field 

или:

type DestructureInCtor((a:int, b:int)) = 
    // declares two private fields? 

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

+0

В соответствии с разделом 8.6.1.3 спецификации, похоже, не существует взаимно однозначного отношения параметра-поля. Параметры могут оставаться локальными для конструктора в зависимости от их использования, так же, как привязки 'let' в основном конструкторе. * (См. Пример, где «вход y используется только во время построения» в спецификации). Учитывая, что остальная часть основного конструктора допускает шаблоны, я не понимаю, почему они ввели бы слишком много сложностей в списке параметров. – Vandroiy

+0

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

+0

Я сравниваю с let-bindings, а не с параметрами функции. Почему бы 'MyType (pattern) =' просто компилироваться как 'MyType (a) = (newline) let pattern = a'? На первый взгляд, кажется, не слишком много сложностей. – Vandroiy

Смежные вопросы