F# kod biçimlendirme yönergeleriF# code formatting guidelines

Bu makalede, F # kodunuzun olması için kodunuzu biçimlendirme yönergeleri sunulmaktadır:This article offers guidelines for how to format your code so that your F# code is:

  • Daha okunaklıMore legible
  • Visual Studio ve diğer düzenleyicilerde biçimlendirme araçları tarafından uygulanan kurallara uygun olarakIn accordance with conventions applied by formatting tools in Visual Studio and other editors
  • Çevrimiçi diğer koda benzerSimilar to other code online

Bu yönergeler, Anh-Dung Phantarafından oluşturulan F # biçimlendirme kurallarına yönelik kapsamlı bir kılavuza dayanır.These guidelines are based on A comprehensive guide to F# Formatting Conventions by Anh-Dung Phan.

Girintileme için genel kurallarGeneral rules for indentation

F # varsayılan olarak önemli boşluk kullanır.F# uses significant white space by default. Aşağıdaki kılavuzlar, bu, uygulayabileceğine dair bazı güçlüklerin nasıl ele alınacağını gösteren yönergeler sağlamaya yöneliktir.The following guidelines are intended to provide guidance as to how to juggle some challenges this can impose.

Boşluk kullanmaUsing spaces

Girintileme gerekli olduğunda, sekmeler değil, boşluk kullanmanız gerekir.When indentation is required, you must use spaces, not tabs. En az bir alan gereklidir.At least one space is required. Kuruluşunuz, girintileme için kullanılacak boşluk sayısını belirtmek için kodlama standartları oluşturabilir; her düzeyde girintileme her zamanki iki, üç veya dört boşluk.Your organization can create coding standards to specify the number of spaces to use for indentation; two, three, or four spaces of indentation at each level where indentation occurs is typical.

Girintileme başına dört boşluk önerilir.We recommend four spaces per indentation.

Bu şekilde, programların girintileme öznel bir önemi olur.That said, indentation of programs is a subjective matter. Çeşitlemeler Tamam, ancak izlemeniz gereken ilk kural girintileme tutarlılığındanoluşur.Variations are OK, but the first rule you should follow is consistency of indentation. Genellikle kabul edilen bir girintileme stili seçin ve kod tabanınızın tamamında sistematik olarak kullanın.Choose a generally accepted style of indentation and use it systematically throughout your codebase.

Boşluk biçimlendirmeFormatting white space

F #, boşluk duyarlıdır.F# is white space sensitive. Beyaz boşluktan çok sayıda anlambilim doğru girintileme kapsamında olmakla birlikte göz önünde bulundurmanız gereken bazı şeyler vardır.Although most semantics from white space are covered by proper indentation, there are some other things to consider.

Aritmetik İfadelerdeki biçimlendirme işleçleriFormatting operators in arithmetic expressions

Her zaman ikili aritmetik ifadelerin etrafında boşluk kullanın:Always use white space around binary arithmetic expressions:

let subtractThenAdd x = x - 1 + 3

Birli - işleçler her zaman, yoksayıdıkları değer tarafından hemen izlenir:Unary - operators should always be immediately followed by the value they are negating:

// OK
let negate x = -x

// Bad
let negateBad x = - x

İşleçten sonra bir boşluk karakteri eklemek, - Diğerlerinin karışıklığına neden olabilir.Adding a white-space character after the - operator can lead to confusion for others.

Özetle, her zaman için önemlidir:In summary, it's important to always:

  • Boşluk ile ikili işleçler çevrelemeSurround binary operators with white space
  • Birli işleçten sonra hiç bir sondaki boşluk yokNever have trailing white space after a unary operator

İkili aritmetik işleç Kılavuzu özellikle önemlidir.The binary arithmetic operator guideline is especially important. -Belirli biçimlendirme seçenekleriyle birleştirildiğinde ikili bir işlecin sarlamaması, tek bir birli olarak yorumlanmasına neden olabilir - .Failing to surround a binary - operator, when combined with certain formatting choices, could lead to interpreting it as a unary -.

Bir özel operatör tanımını boşluk ile çevreleyinSurround a custom operator definition with white space

Her zaman bir operatör tanımını çevrelemek için boşluk kullanın:Always use white space to surround an operator definition:

// OK
let ( !> ) x f = f x

// Bad
let (!>) x f = f x

İle başlayan ve birden fazla karakter içeren herhangi bir özel operatör için * , bir derleyici belirsizliğini önlemek için tanımın başlangıcına boşluk eklemeniz gerekir.For any custom operator that starts with * and that has more than one character, you need to add a white space to the beginning of the definition to avoid a compiler ambiguity. Bu nedenle, tek bir boşluk karakteriyle tüm işleçlerin tanımlarını çevrelemeyi öneririz.Because of this, we recommend that you simply surround the definitions of all operators with a single white-space character.

Boşluk işlevi parametre okları boşluk ileSurround function parameter arrows with white space

Bir işlevin imzasını tanımlarken, simgenin etrafında boşluk kullanın -> :When defining the signature of a function, use white space around the -> symbol:

// OK
type MyFun = int -> int -> string

// Bad
type MyFunBad = int->int->string

Boşluk ile çevreleme işlevi bağımsız değişkenleriSurround function arguments with white space

Bir işlevi tanımlarken, her bağımsız değişken etrafında boşluk kullanın.When defining a function, use white space around each argument.

// OK
let myFun (a: decimal) b c = a + b + c

// Bad
let myFunBad (a:decimal)(b)c = a + b + c

Uzun üye tanımları için parametreleri yeni bir satıra yerleştirPlace parameters on a new line for long member definitions

Çok uzun bir üye tanımınız varsa, parametreleri yeni satırlara yerleştirip bir kapsamı girintileyin.If you have a very long member definition, place the parameters on new lines and indent them one scope.

type C() =
    member _.LongMethodWithLotsOfParameters(
        aVeryLongType: AVeryLongTypeThatYouNeedToUse
        aSecondVeryLongType: AVeryLongTypeThatYouNeedToUse
        aThirdVeryLongType: AVeryLongTypeThatYouNeedToUse) =
        // ... the body of the method follows

Bu, oluşturucular için de geçerlidir:This also applies to constructors:

type C(
    aVeryLongType: AVeryLongTypeThatYouNeedToUse
    aSecondVeryLongType: AVeryLongTypeThatYouNeedToUse
    aThirdVeryLongType: AVeryLongTypeThatYouNeedToUse) =
    // ... the body of the class follows

Tür ek açıklamalarıType annotations

Sağ panel işlevi bağımsız değişken türü ek açıklamalarıRight-pad function argument type annotations

Tür ek açıklamalarıyla bağımsız değişkenler tanımlarken, simgeden sonra boşluk kullanın : :When defining arguments with type annotations, use white space after the : symbol:

// OK
let complexFunction (a: int) (b: int) c = a + b + c

// Bad
let complexFunctionBad (a :int) (b :int) (c:int) = a + b + c

Boşluk içeren surround dönüş türü ek açıklamalarıSurround return type annotations with white space

Bir izin-bağlantılı işlevinde veya değer türü ek açıklamasında (bir işlev durumunda dönüş türü), simgeden önce ve sonra boşluk kullanın : :In a let-bound function or value type annotation (return type in the case of a function), use white space before and after the : symbol:

// OK
let expensiveToCompute : int = 0 // Type annotation for let-bound value
let myFun (a: decimal) b c : decimal = a + b + c // Type annotation for the return type of a function
// Bad
let expensiveToComputeBad1:int = 1
let expensiveToComputeBad2 :int = 2
let myFunBad (a: decimal) b c:decimal = a + b + c

Boş satırları biçimlendirmeFormatting blank lines

  • En üst düzey işlev ve sınıf tanımlarını iki boş satır ile ayırın.Separate top-level function and class definitions with two blank lines.
  • Bir sınıf içindeki yöntem tanımları, tek bir boş satırla ayrılır.Method definitions inside a class are separated by a single blank line.
  • İlgili işlevlerin gruplarını ayırmak için fazladan boş satırlar kullanılabilir (gelişigüzel).Extra blank lines may be used (sparingly) to separate groups of related functions. Bir arada ilgili tek bir grup (örneğin, bir kukla uygulamalar kümesi) arasında boş satırlar atlanabilir.Blank lines may be omitted between a bunch of related one-liners (for example, a set of dummy implementations).
  • Mantıksal bölümleri göstermek için işlevlerde boş satırları gelişigüzel bir şekilde kullanın.Use blank lines in functions, sparingly, to indicate logical sections.

Biçimlendirme açıklamalarıFormatting comments

Genellikle, ML stili blok açıklamaları üzerinde birden çok çift eğik açıklama tercih eder.Generally prefer multiple double-slash comments over ML-style block comments.

// Prefer this style of comments when you want
// to express written ideas on multiple lines.

(*
    ML-style comments are fine, but not a .NET-ism.
    They are useful when needing to modify multi-line comments, though.
*)

Satır içi yorumların ilk harfi büyük harfle yazılmalıdır.Inline comments should capitalize the first letter.

let f x = x + 1 // Increment by one.

Adlandırma kurallarıNaming conventions

Sınıf bağlantılı, ifade ile bağlantılı ve kalıp bağlantılı değerler ve işlevler için camelCase kullanınUse camelCase for class-bound, expression-bound, and pattern-bound values and functions

Yerel değişkenler veya kalıp eşleşmeleri ve işlev tanımları ile bağlantılı tüm adlar için camelCase kullanmak için ortak ve kabul edilen F # stili kullanılır.It is common and accepted F# style to use camelCase for all names bound as local variables or in pattern matches and function definitions.

// OK
let addIAndJ i j = i + j

// Bad
let addIAndJ I J = I+J

// Bad
let AddIAndJ i j = i + j

Sınıflarda yerel olarak bağlantılı işlevler de camelCase kullanmalıdır.Locally bound functions in classes should also use camelCase.

type MyClass() =

    let doSomething () =

    let firstResult = ...

    let secondResult = ...

    member x.Result = doSomething()

Modül bağlantılı ortak işlevler için camelCase kullanınUse camelCase for module-bound public functions

Modül bağlantılı bir işlev ortak bir API 'nin parçasıysa, camelCase kullanmalıdır:When a module-bound function is part of a public API, it should use camelCase:

module MyAPI =
    let publicFunctionOne param1 param2 param2 = ...

    let publicFunctionTwo param1 param2 param3 = ...

İç ve özel modüle yönelik değerler ve işlevler için camelCase kullanınUse camelCase for internal and private module-bound values and functions

Aşağıdakiler de dahil olmak üzere, özel modül bağlantılı değerler için camelCase kullanın:Use camelCase for private module-bound values, including the following:

  • Betiklerdeki geçici işlevlerAd hoc functions in scripts

  • Modül veya türün iç uygulamasını oluşturan değerlerValues making up the internal implementation of a module or type

let emailMyBossTheLatestResults =
    ...

Parametreler için camelCase kullanınUse camelCase for parameters

Tüm parametrelerin, .NET adlandırma kurallarına uygun olarak camelCase kullanması gerekir.All parameters should use camelCase in accordance with .NET naming conventions.

module MyModule =
    let myFunction paramOne paramTwo = ...

type MyClass() =
    member this.MyMethod(paramOne, paramTwo) = ...

Modüller için PascalCase kullanınUse PascalCase for modules

Tüm modüller (üst düzey, iç, özel, iç içe) PascalCase kullanmalıdır.All modules (top-level, internal, private, nested) should use PascalCase.

module MyTopLevelModule

module Helpers =
    module private SuperHelpers =
        ...

    ...

Tür bildirimleri, Üyeler ve Etiketler için PascalCase kullanınUse PascalCase for type declarations, members, and labels

Sınıflar, arabirimler, yapılar, numaralandırmalar, temsilciler, kayıtlar ve ayırt edici birleşimler PascalCase ile adlandırılmalıdır.Classes, interfaces, structs, enumerations, delegates, records, and discriminated unions should all be named with PascalCase. Kayıt ve ayrılmış birleşimler için türler ve Etiketler içindeki Üyeler PascalCase de kullanmalıdır.Members within types and labels for records and discriminated unions should also use PascalCase.

type IMyInterface =
    abstract Something: int

type MyClass() =
    member this.MyMethod(x, y) = x + y

type MyRecord = { IntVal: int; StringVal: string }

type SchoolPerson =
    | Professor
    | Student
    | Advisor
    | Administrator

.NET 'e iç yapılar için PascalCase kullanınUse PascalCase for constructs intrinsic to .NET

Ad alanları, özel durumlar, olaylar ve proje/ .dll adlar PascalCase ' i de kullanmalıdır.Namespaces, exceptions, events, and project/.dll names should also use PascalCase. Bu, diğer .NET dillerinden gelen tüketimin tüketicilere daha doğal bir fikir sunmasına değil, büyük olasılıkla karşılaşabileceğiniz .NET adlandırma kurallarıyla de tutarlıdır.Not only does this make consumption from other .NET languages feel more natural to consumers, it's also consistent with .NET naming conventions that you are likely to encounter.

Adlarda alt çizgileri önleyinAvoid underscores in names

Tarihsel olarak, bazı F # kitaplıklarında adlarda alt çizgiler kullanıldı.Historically, some F# libraries have used underscores in names. Ancak, bu, kısmen kabul edilmez, kısmen de .NET adlandırma kurallarına çakışıyor.However, this is no longer widely accepted, partly because it clashes with .NET naming conventions. Yani, bazı F # programcıları büyük ölçüde, kısmen geçmiş nedenlerle alt çizgi kullanır ve tolerans ve saygı önemli öneme sahiptir.That said, some F# programmers use underscores heavily, partly for historical reasons, and tolerance and respect is important. Bununla birlikte, stilin genellikle onu kullanıp kullanmayacağınızı belirten bir seçeneğe sahip olan diğerlerinin beğenmediğini unutmayın.However, be aware that the style is often disliked by others who have a choice about whether to use it.

Bir özel durum, yerel bileşenlerle birlikte çalışmaya dahildir ve alt çizgilerin ortak olduğu durumdur.One exception includes interoperating with native components, where underscores are common.

Standart F # işleçlerini kullanınUse standard F# operators

Aşağıdaki işleçler F # standart kitaplığı 'nda tanımlanmıştır ve eşdeğerleri tanımlamak yerine kullanılmalıdır.The following operators are defined in the F# standard library and should be used instead of defining equivalents. Bu işleçlerin kullanılması, kodun daha okunaklı ve farklı hale getirme eğilimi için önerilir.Using these operators is recommended as it tends to make code more readable and idiomatic. OCaml veya diğer işlevsel programlama dilinde arka plan içeren geliştiriciler farklı ıoms 'ye alışkın olabilir.Developers with a background in OCaml or other functional programming language may be accustomed to different idioms. Aşağıdaki listede önerilen F # işleçleri özetlenmektedir.The following list summarizes the recommended F# operators.

x |> f // Forward pipeline
f >> g // Forward composition
x |> ignore // Discard away a value
x + y // Overloaded addition (including string concatenation)
x - y // Overloaded subtraction
x * y // Overloaded multiplication
x / y // Overloaded division
x % y // Overloaded modulus
x && y // Lazy/short-cut "and"
x || y // Lazy/short-cut "or"
x <<< y // Bitwise left shift
x >>> y // Bitwise right shift
x ||| y // Bitwise or, also for working with “flags” enumeration
x &&& y // Bitwise and, also for working with “flags” enumeration
x ^^^ y // Bitwise xor, also for working with “flags” enumeration

Foo<T>Tercihe sonek sözdizimi () içinde genel türler () için önek sözdizimini T Foo kullanınUse prefix syntax for generics (Foo<T>) in preference to postfix syntax (T Foo)

F #, genel türleri (örneğin, int list ) ve önek .net stili (örneğin,) adlandırmanın SONEK ml stilini devralır list<int> .F# inherits both the postfix ML style of naming generic types (for example, int list) as well as the prefix .NET style (for example, list<int>). Beş özel tür hariç .NET stilini tercih edin:Prefer the .NET style, except for five specific types:

  1. F # listeleri için sonek biçimini kullanın: int list yerine list<int> .For F# Lists, use the postfix form: int list rather than list<int>.
  2. F # seçenekleri için sonek biçimini kullanın: int option yerine option<int> .For F# Options, use the postfix form: int option rather than option<int>.
  3. F # değer seçenekleri için sonek biçimini kullanın: int voption yerine voption<int> .For F# Value Options, use the postfix form: int voption rather than voption<int>.
  4. F # dizileri için veya yerine sözdizimsel adı kullanın int[] int array array<int> .For F# arrays, use the syntactic name int[] rather than int array or array<int>.
  5. Başvuru hücreleri için int ref veya yerine kullanın ref<int> Ref<int> .For Reference Cells, use int ref rather than ref<int> or Ref<int>.

Diğer tüm türler için önek formunu kullanın.For all other types, use the prefix form.

Tanımlama gruplarını biçimlendirmeFormatting tuples

Tanımlama grubu örneklemesi parantez içine alınmalıdır ve içindeki sınırlandırma virgüller tek bir boşluk gelmelidir, örneğin: (1, 2) , (x, y, z) .A tuple instantiation should be parenthesized, and the delimiting commas within it should be followed by a single space, for example: (1, 2), (x, y, z).

Tanımlama gruplarının düzeniyle eşleştirilirken parantezleri atlamak için genellikle kabul edilir:It is commonly accepted to omit parentheses in pattern matching of tuples:

let (x, y) = z // Destructuring
let x, y = z // OK

// OK
match x, y with
| 1, _ -> 0
| x, 1 -> 0
| x, y -> 1

Kayıt düzeni bir işlevin dönüş değeri ise ayraçları atlamak için de kabul edilir:It is also commonly accepted to omit parentheses if the tuple is the return value of a function:

// OK
let update model msg =
    match msg with
    | 1 -> model + 1, []
    | _ -> model, [ msg ]

Özet ' te, parantez içine alınmış demet örneklemeleri tercih eder, ancak kalıp eşleme veya dönüş değeri için tanımlama grupları kullanıldığında, ayraçları önlemek için ince olarak kabul edilir.In summary, prefer parenthesized tuple instantiations, but when using tuples for pattern matching or a return value, it is considered fine to avoid parentheses.

Ayırt edici birleşim bildirimlerini biçimlendirmeFormatting discriminated union declarations

|Tür tanımında dört boşlukla Girintile:Indent | in type definition by four spaces:

// OK
type Volume =
    | Liter of float
    | FluidOunce of float
    | ImperialPint of float

// Not OK
type Volume =
| Liter of float
| USPint of float
| ImperialPint of float

Ayırt edici birleşimleri biçimlendirmeFormatting discriminated unions

Birden çok satıra bölünen oluşturulmuş ayrılmış birleşimler, içerilen verileri girintileme ile yeni bir kapsam olarak vermelidir:Instantiated Discriminated Unions that split across multiple lines should give contained data a new scope with indentation:

let tree1 =
    BinaryNode
        (BinaryNode(BinaryValue 1, BinaryValue 2),
         BinaryNode(BinaryValue 3, BinaryValue 4))

Kapanış parantezi de yeni bir satır üzerinde olabilir:The closing parenthesis can also be on a new line:

let tree1 =
    BinaryNode(
        BinaryNode(BinaryValue 1, BinaryValue 2),
        BinaryNode(BinaryValue 3, BinaryValue 4)
    )

Kayıt bildirimlerini biçimlendirmeFormatting record declarations

{Tür tanımında dört boşlukla girinti yapın ve alan listesini aynı satırda başlatın:Indent { in type definition by four spaces and start the field list on the same line:

// OK
type PostalAddress =
    { Address: string
      City: string
      Zip: string }
    member x.ZipAndCity = sprintf "%s %s" x.Zip x.City

// Not OK
type PostalAddress =
  { Address: string
    City: string
    Zip: string }
    member x.ZipAndCity = sprintf "%s %s" x.Zip x.City

// Unusual in F#
type PostalAddress =
    {
        Address: string
        City: string
        Zip: string
    }

Kayıt üzerinde arabirim uygulamaları veya Üyeler bildirirken, açma belirtecinin yeni bir satıra yerleştirilmesi ve yeni bir satırdaki kapatma belirteci tercih edilir:Placing the opening token on a new line and the closing token on a new line is preferable if you are declaring interface implementations or members on the record:

// Declaring additional members on PostalAddress
type PostalAddress =
    {
        Address: string
        City: string
        Zip: string
    }
    member x.ZipAndCity = sprintf "%s %s" x.Zip x.City

type MyRecord =
    {
        SomeField: int
    }
    interface IMyInterface

Kayıtları biçimlendirmeFormatting records

Kısa kayıtlar tek bir satırda yazılabilir:Short records can be written in one line:

let point = { X = 1.0; Y = 0.0 }

Daha uzun olan kayıtlar, Etiketler için yeni satırları kullanmalıdır:Records that are longer should use new lines for labels:

let rainbow =
    { Boss = "Jeffrey"
      Lackeys = ["Zippy"; "George"; "Bungle"] }

Açma belirtecinin yeni bir satıra yerleştirilmesi, bir kapsam üzerinde sekmeli içerikler ve yeni bir satırdaki kapatma belirteci, şu durumlarda tercih edilir:Placing the opening token on a new line, the contents tabbed over one scope, and the closing token on a new line is preferable if you are:

  • Farklı girintileme kapsamları ile koddaki kayıtları taşımaMoving records around in code with different indentation scopes
  • Bir işleve boru oluşturmaPiping them into a function
let rainbow =
    {
        Boss1 = "Jeffrey"
        Boss2 = "Jeffrey"
        Boss3 = "Jeffrey"
        Boss4 = "Jeffrey"
        Boss5 = "Jeffrey"
        Boss6 = "Jeffrey"
        Boss7 = "Jeffrey"
        Boss8 = "Jeffrey"
        Lackeys = ["Zippy"; "George"; "Bungle"]
    }

type MyRecord =
    {
        SomeField: int
    }
    interface IMyInterface

let foo a =
    a
    |> Option.map (fun x ->
        {
            MyField = x
        })

Liste ve dizi öğeleri için aynı kurallar geçerlidir.The same rules apply for list and array elements.

Copy ve Update kayıt ifadelerini biçimlendirmeFormatting copy-and-update record expressions

Bir kopyalama ve güncelleştirme kayıt ifadesi hala bir kayıt olduğundan benzer yönergeler geçerlidir.A copy-and-update record expression is still a record, so similar guidelines apply.

Kısa ifadeler tek bir satıra uygun olabilir:Short expressions can fit on one line:

let point2 = { point with X = 1; Y = 2 }

Daha uzun ifadeler yeni satırları kullanmalıdır:Longer expressions should use new lines:

let rainbow2 =
    { rainbow with
        Boss = "Jeffrey"
        Lackeys = [ "Zippy"; "George"; "Bungle" ] }

Kayıt kılavuzunda olduğu gibi, küme ayraçları için ayrı satırlar atamak ve bir kapsamın sağına doğru bir kapsamını girintilemek isteyebilirsiniz.And as with the record guidance, you may want to dedicate separate lines for the braces and indent one scope to the right with the expression. Parantez olmadan isteğe bağlı bir değeri sarmalama gibi bazı özel durumlarda, bir satır için bir küme ayracı tutmanız gerekebilir:In some special cases, such as wrapping a value with an optional without parentheses, you may need to keep a brace on one line:

type S = { F1: int; F2: string }
type State = { F:  S option }

let state = { F = Some { F1 = 1; F2 = "Hello" } }
let newState =
    {
        state with
            F = Some {
                    F1 = 0
                    F2 = ""
                }
    }

Listeleri ve dizileri biçimlendirmeFormatting lists and arrays

x :: lİşlecin etrafında boşluk ile yazın :: ( :: Bu nedenle boşluklarla çevrelenmiş bir işleçtir).Write x :: l with spaces around the :: operator (:: is an infix operator, hence surrounded by spaces).

Tek bir satırda tanımlanan liste ve diziler, açma köşeli ayracından sonra ve kapatma parantezinden önce bir boşluk içermelidir:List and arrays declared on a single line should have a space after the opening bracket and before the closing bracket:

let xs = [ 1; 2; 3 ]
let ys = [| 1; 2; 3; |]

Her zaman iki farklı küme ayracı benzeri işleç arasında en az bir boşluk kullanın.Always use at least one space between two distinct brace-like operators. Örneğin, ve arasında bir boşluk bırakın [ { .For example, leave a space between a [ and a {.

// OK
[ { IngredientName = "Green beans"; Quantity = 250 }
  { IngredientName = "Pine nuts"; Quantity = 250 }
  { IngredientName = "Feta cheese"; Quantity = 250 }
  { IngredientName = "Olive oil"; Quantity = 10 }
  { IngredientName = "Lemon"; Quantity = 1 } ]

// Not OK
[{ IngredientName = "Green beans"; Quantity = 250 }
 { IngredientName = "Pine nuts"; Quantity = 250 }
 { IngredientName = "Feta cheese"; Quantity = 250 }
 { IngredientName = "Olive oil"; Quantity = 10 }
 { IngredientName = "Lemon"; Quantity = 1 }]

Aynı kılavuz, tanımlama gruplarının listeleri veya dizileri için geçerlidir.The same guideline applies for lists or arrays of tuples.

Birden çok satıra bölünen listeler ve diziler, kayıt olarak benzer bir kuralı izler:Lists and arrays that split across multiple lines follow a similar rule as records do:

let pascalsTriangle =
    [|
        [| 1 |]
        [| 1; 1 |]
        [| 1; 2; 1 |]
        [| 1; 3; 3; 1 |]
        [| 1; 4; 6; 4; 1 |]
        [| 1; 5; 10; 10; 5; 1 |]
        [| 1; 6; 15; 20; 15; 6; 1 |]
        [| 1; 7; 21; 35; 35; 21; 7; 1 |]
        [| 1; 8; 28; 56; 70; 56; 28; 8; 1 |]
    |]

Kayıtlarda olduğu gibi, açılış ve kapanış köşeli ayracını kendi satırlarıyla birlikte bildirmek, kodun etrafında ve boru işlevlerine daha kolay bir şekilde sahip olmasını sağlar.And as with records, declaring the opening and closing brackets on their own line will make moving code around and piping into functions easier.

Program aracılığıyla diziler ve listeler oluştururken, -> do ... yield her zaman bir değer oluşturulduğunda tercih edin:When generating arrays and lists programmatically, prefer -> over do ... yield when a value is always generated:

// Preferred
let squares = [ for x in 1..10 -> x * x ]

// Not preferred
let squares' = [ for x in 1..10 do yield x * x ]

F # dilinin, yield verilerin koşullu olarak üretilebileceği durumlarda belirtilmesi gerekir veya değerlendirilecek ardışık ifadeler olabilir.Older versions of the F# language required specifying yield in situations where data may be generated conditionally, or there may be consecutive expressions to be evaluated. yieldDaha eski bir F # dil sürümüyle derlemeniz gerekmedikçe bu anahtar sözcüklerin atlanması tercih edin:Prefer omitting these yield keywords unless you must compile with an older F# language version:

// Preferred
let daysOfWeek includeWeekend =
    [
        "Monday"
        "Tuesday"
        "Wednesday"
        "Thursday"
        "Friday"
        if includeWeekend then
            "Saturday"
            "Sunday"
    ]

// Not preferred
let daysOfWeek' includeWeekend =
    [
        yield "Monday"
        yield "Tuesday"
        yield "Wednesday"
        yield "Thursday"
        yield "Friday"
        if includeWeekend then
            yield "Saturday"
            yield "Sunday"
    ]

Bazı durumlarda okunabilirlik konusunda do...yield yardımcı olabilir.In some cases, do...yield may aid in readability. Bu durumlarda, öznel, dikkate alınması gerekir.These cases, though subjective, should be taken into consideration.

İfadeleri biçimlendirmeFormatting if expressions

Koşullular girintileme, bunları yapan ifadelerin boyutlarına bağlıdır.Indentation of conditionals depends on the sizes of the expressions that make them up. cond, e1 Ve kısaysa, e2 bunları tek bir satıra yazmanız yeterlidir:If cond, e1 and e2 are short, simply write them on one line:

if cond then e1 else e2

Ya da cond e1 e2 daha uzunsa ve çok satırlı ise:If either cond, e1 or e2 are longer, but not multi-line:

if cond
then e1
else e2

Deyimlerden herhangi biri çok satırlıdır:If any of the expressions are multi-line:

if cond then
    e1
else
    e2

Ve ile birden çok elif koşul else , ile aynı kapsamda girintilenir if :Multiple conditionals with elif and else are indented at the same scope as the if:

if cond1 then e1
elif cond2 then e2
elif cond3 then e3
else e4

Model eşleştirme yapılarıPattern matching constructs

Bir | eşleşmenin for each yan tümcesini girintileme olmadan kullanın.Use a | for each clause of a match with no indentation. İfade kısaysa, her alt ifade da basit olduğunda tek bir satır kullanmayı düşünebilirsiniz.If the expression is short, you can consider using a single line if each subexpression is also simple.

// OK
match l with
| { him = x; her = "Posh" } :: tail -> x
| _ :: tail -> findDavid tail
| [] -> failwith "Couldn't find David"

// Not OK
match l with
    | { him = x; her = "Posh" } :: tail -> x
    | _ :: tail -> findDavid tail
    | [] -> failwith "Couldn't find David"

Bir düzenin sağ tarafındaki ifade çok büyükse, bu satırı aşağıdaki satıra taşıyın ve ' den bir adım girintilenir match / | .If the expression on the right of the pattern matching arrow is too large, move it to the following line, indented one step from the match/|.

match lam with
| Var v -> 1
| Abs(x, body) ->
    1 + sizeLambda body
| App(lam1, lam2) ->
    sizeLambda lam1 + sizeLambda lam2

Tarafından başlayan anonim işlevlerin örüntüme göre function , genellikle çok uzakta girintisiz.Pattern matching of anonymous functions, starting by function, should generally not indent too far. Örneğin, bir kapsamı aşağıda gösterildiği gibi girintileme iyi bir şekilde belirlenir:For example, indenting one scope as follows is fine:

lambdaList
|> List.map (function
    | Abs(x, body) -> 1 + sizeLambda 0 body
    | App(lam1, lam2) -> sizeLambda (sizeLambda 0 lam1) lam2
    | Var v -> 1)

Ya da tarafından tanımlanan işlevlerde desenler let eşleştirmesi let rec let , function anahtar sözcüğünün kullanılsa bile, başlatıldıktan sonra dört boşluk olmalıdır:Pattern matching in functions defined by let or let rec should be indented four spaces after starting of let, even if function keyword is used:

let rec sizeLambda acc = function
    | Abs(x, body) -> sizeLambda (succ acc) body
    | App(lam1, lam2) -> sizeLambda (sizeLambda acc lam1) lam2
    | Var v -> succ acc

Okları hizalamayı önermiyoruz.We do not recommend aligning arrows.

Try/with ifadelerini biçimlendirmeFormatting try/with expressions

Özel durum türünde model eşleştirme, ile aynı düzeyde girintili olmalıdır with .Pattern matching on the exception type should be indented at the same level as with.

try
    if System.DateTime.Now.Second % 3 = 0 then
        raise (new System.Exception())
    else
        raise (new System.ApplicationException())
with
| :? System.ApplicationException ->
    printfn "A second that was not a multiple of 3"
| _ ->
    printfn "A second that was a multiple of 3"

İşlev parametresi uygulamasını biçimlendirmeFormatting function parameter application

Genellikle, çoğu işlev parametresi uygulaması aynı satırda yapılır.In general, most function parameter application is done on the same line.

Parametreleri yeni bir satırdaki bir işleve uygulamak istiyorsanız, bunları bir kapsama göre girintileyin.If you wish to apply parameters to a function on a new line, indent them by one scope.

// OK
sprintf "\t%s - %i\n\r"
     x.IngredientName x.Quantity

// OK
sprintf
     "\t%s - %i\n\r"
     x.IngredientName x.Quantity

// OK
let printVolumes x =
    printf "Volume in liters = %f, in us pints = %f, in imperial = %f"
        (convertVolumeToLiter x)
        (convertVolumeUSPint x)
        (convertVolumeImperialPint x)

İşlev bağımsız değişkenleri olarak lambda ifadeleri için de aynı yönergeler geçerlidir.The same guidelines apply for lambda expressions as function arguments. Lambda ifadesinin gövdesi ise, gövde başka bir çizgiye sahip olabilir ve bu da bir kapsama göre girintilenirIf the body of a lambda expression, the body can have another line, indented by one scope

let printListWithOffset a list1 =
    List.iter
        (fun elem -> printfn "%d" (a + elem))
        list1

// OK if lambda body is long enough
let printListWithOffset a list1 =
    List.iter
        (fun elem ->
            printfn "%d" (a + elem))
        list1

Ancak, bir lambda ifadesinin gövdesi birden fazla satırsa, bir işleve tek bir bağımsız değişken olarak uygulanan çok satırlı bir yapının olması yerine ayrı bir işleve düzenleme göz önünde bulundurun.However, if the body of a lambda expression is more than one line, consider factoring it out into a separate function rather than have a multi-line construct applied as a single argument to a function.

Hatalı bir şekilde biçimlendirme işleçleriFormatting infix operators

İşleçleri boşluklara göre ayırın.Separate operators by spaces. Bu kuralın belirgin özel durumları ! ve . işleçleridir.Obvious exceptions to this rule are the ! and . operators.

Indüzeltilme ifadeleri aynı sütundaki sıralama için Tamam:Infix expressions are OK to lineup on same column:

acc +
(sprintf "\t%s - %i\n\r"
     x.IngredientName x.Quantity)

let function1 arg1 arg2 arg3 arg4 =
    arg1 + arg2 +
    arg3 + arg4

Biçimlendirme işlem hattı işleçleriFormatting pipeline operators

|>İşlem hattı işleçleri üzerinde çalıştıkları ifadelerin altına gitmelidir.Pipeline |> operators should go underneath the expressions they operate on.

// Preferred approach
let methods2 =
    System.AppDomain.CurrentDomain.GetAssemblies()
    |> List.ofArray
    |> List.map (fun assm -> assm.GetTypes())
    |> Array.concat
    |> List.ofArray
    |> List.map (fun t -> t.GetMethods())
    |> Array.concat

// Not OK
let methods2 = System.AppDomain.CurrentDomain.GetAssemblies()
            |> List.ofArray
            |> List.map (fun assm -> assm.GetTypes())
            |> Array.concat
            |> List.ofArray
            |> List.map (fun t -> t.GetMethods())
            |> Array.concat

Biçimlendirme modülleriFormatting modules

Yerel modüldeki kodun modüle bağlı olması gerekir, ancak üst düzey modüldeki kod girintilenmemelidir.Code in a local module must be indented relative to the module, but code in a top-level module should not be indented. Ad alanı öğelerinin girintili olması gerekmez.Namespace elements do not have to be indented.

// A is a top-level module.
module A

let function1 a b = a - b * b
// A1 and A2 are local modules.
module A1 =
    let function1 a b = a * a + b * b

module A2 =
    let function2 a b = a * a - b * b

Nesne ifadelerini ve arabirimleri biçimlendirmeFormatting object expressions and interfaces

Nesne ifadeleri ve arabirimler, member dört boşluktan sonra girintilenmiş şekilde hizalanmalıdır.Object expressions and interfaces should be aligned in the same way with member being indented after four spaces.

let comparer =
    { new IComparer<string> with
          member x.Compare(s1, s2) =
              let rev (s: String) =
                  new String (Array.rev (s.ToCharArray()))
              let reversed = rev s1
              reversed.CompareTo (rev s2) }

İfadelerde boşluk biçimlendirmeFormatting white space in expressions

F # ifadelerinde gereksiz boşluk kullanmaktan kaçının.Avoid extraneous white space in F# expressions.

// OK
spam (ham.[1])

// Not OK
spam ( ham.[ 1 ] )

Adlandırılmış bağımsız değişkenler de çevreleyen boşluk içermemelidir = :Named arguments should also not have space surrounding the =:

// OK
let makeStreamReader x = new System.IO.StreamReader(path=x)

// Not OK
let makeStreamReader x = new System.IO.StreamReader(path = x)

Biçimlendirme öznitelikleriFormatting attributes

Öznitelikler bir yapının üzerine yerleştirilir:Attributes are placed above a construct:

[<SomeAttribute>]
type MyClass() = ...

[<RequireQualifiedAccess>]
module M =
    let f x = x

[<Struct>]
type MyRecord =
    { Label1: int
      Label2: string }

Parametrelerde öznitelikleri biçimlendirmeFormatting attributes on parameters

Öznitelikler, parametrelere de yerleştirilebilir.Attributes can also be placed on parameters. Bu durumda, daha sonra parametresiyle aynı satıra ve adından önce yerleştirin:In this case, place then on the same line as the parameter and before the name:

// Defines a class that takes an optional value as input defaulting to false.
type C() =
    member _.M([<Optional; DefaultParameterValue(false)>] doSomething: bool)

Birden çok özniteliği biçimlendirmeFormatting multiple attributes

Bir parametre olmayan bir yapı için birden çok öznitelik uygulandığında, her satır için bir öznitelik olması gibi yerleştirilmelidir:When multiple attributes are applied to a construct that is not a parameter, they should be placed such that there is one attribute per line:

[<Struct>]
[<IsByRefLike>]
type MyRecord =
    { Label1: int
      Label2: string }

Bir parametreye uygulandığında, bunların aynı satırda olmaları ve bir ; ayırıcıyla ayrılması gerekir.When applied to a parameter, they must be on the same line and separated by a ; separator.

Sabit değerleri biçimlendirmeFormatting literals

Özniteliği kullanan F # değişmez değerleri Literal özniteliği kendi satırına yerleştirip PascalCase adlandırmayı kullanmalıdır:F# literals using the Literal attribute should place the attribute on its own line and use PascalCase naming:

[<Literal>]
let Path = __SOURCE_DIRECTORY__ + "/" + __SOURCE_FILE__

[<Literal>]
let MyUrl = "www.mywebsitethatiamworkingwith.com"

Özniteliği değeri ile aynı satıra yerleştirmekten kaçının.Avoid placing the attribute on the same line as the value.