F# kod biçimlendirme yönergeleri
Bu makalede, F# kodunuzun şöyle olacak şekilde nasıl biçimlendir kurallarınız olduğu açıklanmıştır:
- Daha okunaklı
- Uygulama ve diğer düzenleyicilerde biçimlendirme araçları tarafından Visual Studio Code kurallara uygun olarak
- Diğer çevrimiçi kodlara benzer
Bu yönergeler, Anh-Dung Phan'ın F# Biçimlendirme Kuralları için kapsamlı bir kılavuzu temel almaktadır.
Ayrıca adlandırma kurallarına da yer alan Kodlama kuralları veBileşen tasarım yönergelerine bakın.
Biçimlendirme için genel kurallar
F# varsayılan olarak önemli miktarda boşluk kullanır ve boşluklara duyarlıdır. Aşağıdaki yönergeler, bunun neden olduğu bazı zorlukların üstesinden nasıl uygulanarak değiştirilene kadar rehberlik sağlamak için tasarlanmıştır.
Sekme değil boşluk kullanma
Girinti gerekli olduğunda sekmeleri değil boşlukları kullanabilirsiniz. F# kodu sekmeleri kullanmaz ve bir dize değişmez değeri veya açıklama dışında bir sekme karakteriyle karşılaşıldı ise derleyici bir hata verir.
Tutarlı girinti kullanma
Girintileme sırasında en az bir boşluk gereklidir. Kurum, girintileme için kaç alan kullandıracaklarını belirtmek için kodlama standartları oluşturabilir; Girintilemenin oluştuğu her düzeyde iki, üç veya dört girinti alanı tipiktir.
Girintileme başına dört boşluk önerilir.
Ancak program girintileme özneser bir konudur. Çeşitlemeler tamam, ancak izlememiz gereken ilk kural girintileme tutarlılığıdır. Genellikle kabul edilen girintileme stilini seçin ve kod tabanınız genelinde sistematik olarak kullanın.
Otomatik kod biçimlendirıcı kullanma
Fantomas kod biçimlendirıcısı, otomatik kod biçimlendirme için F# topluluk standardı aracıdır. Varsayılan ayarlar bu stil kılavuzuna karşılık gelen ayarlardır.
Bu kod biçimlendirıcının kullanılması kesinlikle önerilir. F# ekiplerinin içinde kod biçimlendirme belirtimleri, takım deposuna iade edilirken kod biçimlendiren için üzerinde anlaşmaya varıldı ayarlar dosyası açısından kabul edilmelidir ve kod biçimlendirme belirtimleri ortaklaştırıldı.
Ad uzunluğuna duyarlı biçimlendirmeden kaçının
Adlandırmaya duyarlı girintileme ve hizalamadan kaçının:
// ✔️ OK
let myLongValueName =
someExpression
|> anotherExpression
// ❌ Not OK
let myLongValueName = someExpression
|> anotherExpression
// ✔️ OK
let myOtherVeryLongValueName =
match
someVeryLongExpressionWithManyParameters
parameter1
parameter2
parameter3
with
| Some _ -> ()
| ...
// ❌ Not OK
let myOtherVeryLongValueName =
match someVeryLongExpressionWithManyParameters parameter1
parameter2
parameter3 with
| Some _ -> ()
| ...
// ❌ Still Not OK
let myOtherVeryLongValueName =
match someVeryLongExpressionWithManyParameters
parameter1
parameter2
parameter3 with
| Some _ -> ()
| ...
Bunu önlemenin birincil nedenleri:
- Önemli kod sağa doğru taşındı
- Gerçek kod için daha az genişlik kaldı
- Yeniden değiştirme, hizalamayı bozacak
Fazla boşluktan kaçının
F# kodunda, bu stil kılavuzunda açıklananlar dışında fazla boşluktan kaçının.
// ✔️ OK
spam (ham 1)
// ❌ Not OK
spam ( ham 1 )
Yorumları biçimlendirme
Blok açıklamalarını tercih etmek yerine birden çok çift eğik çizgili açıklama tercih eder.
// Prefer this style of comments when you want
// to express written ideas on multiple lines.
(*
Block comments can be used, but use sparingly.
They are useful when eliding code sections.
*)
Açıklamalar ilk harfi büyük harfle yazarak iyi oluşturulmuş tümcecikler veya tümceler olabilir.
// ✔️ A good comment.
let f x = x + 1 // Increment by one.
// ❌ two poor comments
let f x = x + 1 // plus one
XML belge açıklamalarını biçimlendirmek için aşağıdaki "Biçimlendirme bildirimleri" seçeneğine bakın.
Biçimlendirme ifadeleri
Bu bölümde farklı türdeki biçimlendirme ifadeleri ele almaktadır.
Dize ifadelerini biçimlendirme
Dize değişmezleri ve irdelenmiş dizeler, satırın ne kadar uzun olduğuna bakılmaksızın tek bir satırda bırakılana kadar devam eder.
let serviceStorageConnection =
$"DefaultEndpointsProtocol=https;AccountName=%s{serviceStorageAccount.Name};AccountKey=%s{serviceStorageAccountKey.Value}"
Çok satırlı ilişkilendirmeli ifadeler önerilmez. Bunun yerine, ifade sonucu bir değere bağlayın ve ilişkilendirme dizesinde bunu kullanın.
Tuple ifadelerini biçimlendirme
Bir tuple örneği parantez içinde olmalı ve içindeki sınırlayıcı virgülleri takip eden tek bir boşluk (örneğin, , ) (1, 2) (x, y, z) gerekir.
// ✔️ OK
let pair = (1, 2)
let triples = [ (1, 2, 3); (11, 12, 13) ]
Genellikle, çiftlerin desen eşleştirmesinde parantezlerin at olması kabul edilir:
// ✔️ OK
let (x, y) = z
let x, y = z
// ✔️ OK
match x, y with
| 1, _ -> 0
| x, 1 -> 0
| x, y -> 1
Ayrıca, tül bir işlevin dönüş değeri ise parantezleri atlarsanız da yaygın olarak kabul edilir:
// ✔️ OK
let update model msg =
match msg with
| 1 -> model + 1, []
| _ -> model, [ msg ]
Özetle parantezli kayıt düzeni örneklemeyi tercih edersiniz, ancak desen eşleştirme veya dönüş değeri için çift ayraçlar kullanırken parantezleri önlemek uygun kabul edilir.
Uygulama ifadelerini biçimlendirme
Bir işlev veya yöntem uygulaması biçimlendirken, satır genişliği aşağıdakilere izin verirken bağımsız değişkenler aynı satırda sağlanır:
// ✔️ OK
someFunction1 x.IngredientName x.Quantity
Bağımsız değişkenler gerektirmediği sürece parantezler atlanır:
// ✔️ OK
someFunction1 x.IngredientName
// ❌ Not preferred - parentheses should be omitted unless required
someFunction1(x.IngredientName)
Varsayılan biçimlendirme kurallarında, kısa veya parantez içinde bağımsız değişkenlere küçük harf işlevleri uygularken bir boşluk eklenir:
// ✔️ OK
someFunction2 ()
// ✔️ OK
someFunction3 (x.Quantity1 + x.Quantity2)
// ❌ Not OK, formatting tools will add the extra space by default
someFunction2()
// ❌ Not OK, formatting tools will add the extra space by default
someFunction3(x.IngredientName, x.Quantity)
Varsayılan biçimlendirme kurallarında, eklenen bağımsız değişkenlere büyük harfle yazılmış yöntemler uygularken boşluk eklenmez. Bunun nedeni, bunların genellikle akıcı programlama ile birlikte kullanılmalarıdır:
// ✔️ OK - Methods accepting parenthesize arguments are applied without a space
SomeClass.Invoke()
// ✔️ OK - Methods accepting tuples are applied without a space
String.Format(x.IngredientName, x.Quantity)
// ❌ Not OK, formatting tools will remove the extra space by default
SomeClass.Invoke ()
// ❌ Not OK, formatting tools will remove the extra space by default
String.Format (x.IngredientName, x.Quantity)
Okunabilirlik açısından veya bağımsız değişken listesi ya da bağımsız değişken adları çok uzun olduğundan, yeni bir satırda bir işleve bağımsız değişkenler geçmelisiniz. Bu durumda, bir düzeyi girintileme:
// ✔️ OK
someFunction2
x.IngredientName x.Quantity
// ✔️ OK
someFunction3
x.IngredientName1 x.Quantity2
x.IngredientName2 x.Quantity2
// ✔️ OK
someFunction4
x.IngredientName1
x.Quantity2
x.IngredientName2
x.Quantity2
// ✔️ OK
someFunction5
(convertVolumeToLiter x)
(convertVolumeUSPint x)
(convertVolumeImperialPint x)
İşlev tek bir çok satırlı bağlı bağımsız değişken alırsa, her bağımsız değişkeni yeni bir satıra yer:
// ✔️ OK
someTupledFunction (
478815516,
"A very long string making all of this multi-line",
1515,
false
)
// OK, but formatting tools will reformat to the above
someTupledFunction
(478815516,
"A very long string making all of this multi-line",
1515,
false)
Bağımsız değişken ifadeleri kısa ise bağımsız değişkenleri boşluklarla ayırarak tek satırda tutmanız gerekir.
// ✔️ OK
let person = new Person(a1, a2)
// ✔️ OK
let myRegexMatch = Regex.Match(input, regex)
// ✔️ OK
let untypedRes = checker.ParseFile(file, source, opts)
Bağımsız değişken ifadeleri uzunsa, sol paranteze girintileme yerine yeni çizgileri kullanın ve bir düzey girintileme ekleyin.
// ✔️ OK
let person =
new Person(
argument1,
argument2
)
// ✔️ OK
let myRegexMatch =
Regex.Match(
"my longer input string with some interesting content in it",
"myRegexPattern"
)
// ✔️ OK
let untypedRes =
checker.ParseFile(
fileName,
sourceText,
parsingOptionsWithDefines
)
// ❌ Not OK, formatting tools will reformat to the above
let person =
new Person(argument1,
argument2)
// ❌ Not OK, formatting tools will reformat to the above
let untypedRes =
checker.ParseFile(fileName,
sourceText,
parsingOptionsWithDefines)
Çok satırlı dizeler dahil olmak üzere tek bir çok satırlı bağımsız değişken olsa bile aynı kurallar geçerlidir:
// ✔️ OK
let poemBuilder = StringBuilder()
poemBuilder.AppendLine(
"""
The last train is nearly due
The Underground is closing soon
And in the dark, deserted station
Restless in anticipation
A man waits in the shadows
"""
)
Option.traverse(
create
>> Result.setError [ invalidHeader "Content-Checksum" ]
)
İşlem hattı ifadelerini biçimlendirme
Birden çok satır kullanırken, |> işlem hattı işleçleri üzerinde çalıştır kullanıldıkları ifadelerin altına iner.
// ✔️ 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
// ❌ Not OK, add a line break after "=" and put multi-line pipelines on multiple lines.
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 either
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
Lambda ifadelerini biçimlendirme
Bir lambda ifadesi çok satırlı bir ifadede bağımsız değişken olarak kullanılır ve ardından diğer bağımsız değişkenler geldiğinde, bir lambda ifadesinin gövdesini bir düzey girintili yeni bir satıra koyun:
// ✔️ OK
let printListWithOffset a list1 =
List.iter
(fun elem ->
printfn $"A very long line to format the value: %d{a + elem}")
list1
Lambda bağımsız değişkeni bir işlev uygulamasındaki son bağımsız değişkense, ok aynı satıra gelene kadar tüm bağımsız değişkenleri yer.
// ✔️ OK
Target.create "Build" (fun ctx ->
// code
// here
())
// ✔️ OK
let printListWithOffsetPiped a list1 =
list1
|> List.map (fun x -> x + 1)
|> List.iter (fun elem ->
printfn $"A very long line to format the value: %d{a + elem}")
Match lambda'larını benzer şekilde işle.
// ✔️ OK
functionName arg1 arg2 arg3 (function
| Choice1of2 x -> 1
| Choice2of2 y -> 2)
Lambdadan önce birçok baştaki veya çok satırlı bağımsız değişken olduğunda, tüm bağımsız değişkenleri tek bir düzeyle girintiler.
// ✔️ OK
functionName
arg1
arg2
arg3
(fun arg4 ->
bodyExpr)
// ✔️ OK
functionName
arg1
arg2
arg3
(function
| Choice1of2 x -> 1
| Choice2of2 y -> 2)
Bir lambda ifadesinin gövdesi birden çok satır uzunluğunda ise, bunu yerel olarak kapsamlı bir işlevde yeniden düzenlemeyi göz önünde bulundurmalıdır.
İşlem hatları lambda ifadeleri içerirken, her lambda ifadesi genellikle işlem hattının her aşamasındaki son bağımsız değişkendir:
// ✔️ OK, with 4 spaces indentation
let printListWithOffsetPiped list1 =
list1
|> List.map (fun elem -> elem + 1)
|> List.iter (fun elem ->
// one indent starting from the pipe
printfn $"A very long line to format the value: %d{elem}")
// ✔️ OK, with 2 spaces indentation
let printListWithOffsetPiped list1 =
list1
|> List.map (fun elem -> elem + 1)
|> List.iter (fun elem ->
// one indent starting from the pipe
printfn $"A very long line to format the value: %d{elem}")
Aritmetik ve ikili ifadeleri biçimlendirme
her zaman ikili aritmetik ifadelerin etrafında boşluk kullanın:
// ✔️ OK
let subtractThenAdd x = x - 1 + 3
Belirli biçimlendirme seçenekleriyle - birleştirilen ikili işleç çevrelenelamazsa, birli olarak yorumlanmasına neden - olabilir.
Birli - işleçler her zaman hemen ardından olumsuzlukları olan değer ekilmelidir:
// ✔️ OK
let negate x = -x
// ❌ Not OK
let negateBad x = - x
işlecinin ardından boşluk karakteri - eklemek, diğerlerinde kafa karışıklığına neden olabilir.
İkili işleçleri boşluklara göre ayırma. Sonek ifadeleri aynı sütunda sıralanır:
// ✔️ OK
let function1 () =
acc +
(someFunction
x.IngredientName x.Quantity)
// ✔️ OK
let function1 arg1 arg2 arg3 arg4 =
arg1 + arg2 +
arg3 + arg4
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. Bu işleçlerin kullanılması önerilir çünkü kodu daha okunabilir ve idiomatik hale geldi. Aşağıdaki listede önerilen F# işleçleri özetlenmiştir.
// ✔️ OK
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
Aralık işleç ifadelerini biçimlendirme
Yalnızca tüm ifadeler .. atomik olmayan boşluklar ekler.
Tamsayılar ve tek sözcük tanımlayıcıları atomik olarak kabul edilir.
// ✔️ OK
let a = [ 2..7 ] // integers
let b = [ one..two ] // identifiers
let c = [ ..9 ] // also when there is only one expression
let d = [ 0.7 .. 9.2 ] // doubles
let e = [ 2L .. number / 2L ] // complex expression
let f = [| A.B .. C.D |] // identifiers with dots
let g = [ .. (39 - 3) ] // complex expression
let h = [| 1 .. MyModule.SomeConst |] // not all expressions are atomic
for x in 1..2 do
printfn " x = %d" x
let s = seq { 0..10..100 }
// ❌ Not OK
let a = [ 2 .. 7 ]
let b = [ one .. two ]
Bu kurallar,licing için de geçerlidir:
// ✔️ OK
arr[0..10]
list[..^1]
If ifadelerini biçimlendirme
Koşulluların girintileme boyutuna ve bunları neden olan ifadelerin karmaşıklığına bağlıdır. Şu zaman bunları tek satıra yazın:
cond,e1vee2kısae1vee2if/then/elseifadeleri kendileri değildir.
// ✔️ OK
if cond then e1 else e2
İfadelerden herhangi biri çok satırlı veya ifadeler if/then/else ise.
// ✔️ OK
if cond then
e1
else
e2
ve ile birden elif çok else koşul, tek satır ifadelerinin kurallarına uygun olduğunda ile if aynı kapsamda if/then/else girintili olur.
// ✔️ OK
if cond1 then e1
elif cond2 then e2
elif cond3 then e3
else e4
Koşullardan veya ifadelerden herhangi biri çok satırlı ise if/then/else ifadenin tamamı çok satırlı olur:
// ✔️ OK
if cond1 then
e1
elif cond2 then
e2
elif cond3 then
e3
else
e4
Bir koşul uzunsa anahtar then sözcük yine de ifadenin sonuna yerleştirilir.
// ✔️ OK, but better to refactor, see below
if
complexExpression a b && env.IsDevelopment()
|| someFunctionToCall
aVeryLongParameterNameOne
aVeryLongParameterNameTwo
aVeryLongParameterNameThree then
e1
else
e2
Öte yandan uzun koşulları let bağlaması veya ayrı bir işlev olarak yeniden düzenleme daha iyi bir stildir:
// ✔️ OK
let performAction =
complexExpression a b && env.IsDevelopment()
|| someFunctionToCall
aVeryLongParameterNameOne
aVeryLongParameterNameTwo
aVeryLongParameterNameThree
if performAction then
e1
else
e2
Union case ifadelerini biçimlendirme
Ayrımlı union durumlarının uygulanması, işlev ve yöntem uygulamalarıyla aynı kurallara uyar. Bunun nedeni, adın büyük harfe büyük harfle kod biçimlendirenler bir tuple önce bir boşluk kaldırmasıdır:
// ✔️ OK
let opt = Some("A", 1)
// OK, but code formatters will remove the space
let opt = Some ("A", 1)
İşlev uygulamaları gibi, birden çok satıra bölünmüş yapılarda da girintileme kullanacağız:
// ✔️ OK
let tree1 =
BinaryNode(
BinaryNode (BinaryValue 1, BinaryValue 2),
BinaryNode (BinaryValue 3, BinaryValue 4)
)
Liste ve dizi ifadelerini biçimlendirme
x :: lİşlecin etrafında boşluk ile yazın :: ( :: Bu nedenle boşluklarla çevrelenmiş bir işleçtir).
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:
// ✔️ OK
let xs = [ 1; 2; 3 ]
// ✔️ OK
let ys = [| 1; 2; 3; |]
Her zaman iki farklı küme ayracı benzeri işleç arasında en az bir boşluk kullanın. Örneğin, ve arasında bir boşluk bırakın [ { .
// ✔️ OK
[ { Ingredient = "Green beans"; Quantity = 250 }
{ Ingredient = "Pine nuts"; Quantity = 250 }
{ Ingredient = "Feta cheese"; Quantity = 250 }
{ Ingredient = "Olive oil"; Quantity = 10 }
{ Ingredient = "Lemon"; Quantity = 1 } ]
// ❌ Not OK
[{ Ingredient = "Green beans"; Quantity = 250 }
{ Ingredient = "Pine nuts"; Quantity = 250 }
{ Ingredient = "Feta cheese"; Quantity = 250 }
{ Ingredient = "Olive oil"; Quantity = 10 }
{ Ingredient = "Lemon"; Quantity = 1 }]
Aynı kılavuz, tanımlama gruplarının listeleri veya dizileri için geçerlidir.
Birden çok satıra bölünen listeler ve diziler, kayıt olarak benzer bir kuralı izler:
// ✔️ OK
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.
Program aracılığıyla diziler ve listeler oluştururken, -> do ... yield her zaman bir değer oluşturulduğunda tercih edin:
// ✔️ OK
let squares = [ for x in 1..10 -> x * x ]
// ❌ Not preferred, use "->" when a value is always generated
let squares' = [ for x in 1..10 do yield x * x ]
F # ' ın daha eski sürümleri yield , verilerin koşullu olarak üretilebileceği durumlarda belirtilmesi gerekir veya değerlendirilecek ardışık ifadeler olabilir. yieldDaha eski bir F # dil sürümüyle derlemeniz gerekmedikçe bu anahtar sözcüklerin atlanması tercih edin:
// ✔️ OK
let daysOfWeek includeWeekend =
[
"Monday"
"Tuesday"
"Wednesday"
"Thursday"
"Friday"
if includeWeekend then
"Saturday"
"Sunday"
]
// ❌ Not preferred - omit yield instead
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. Bu durumlarda, öznel, dikkate alınması gerekir.
Kayıt ifadelerini biçimlendirme
Kısa kayıtlar tek bir satırda yazılabilir:
// ✔️ OK
let point = { X = 1.0; Y = 0.0 }
Daha uzun olan kayıtlar, Etiketler için yeni satırları kullanmalıdır:
// ✔️ OK
let rainbow =
{ Boss = "Jeffrey"
Lackeys = ["Zippy"; "George"; "Bungle"] }
Uzun kayıt alanı ifadeleri yeni bir satır kullanmalı ve açma işleminden bir girinti içermelidir { :
{ A = a
B =
someFunctionCall
arg1
arg2
// ...
argX
C = c }
{ } İçeriği girintili olan yeni satırlara ve üzerine yerleştirmek, ancak kod formatlayıcıları bunu varsayılan olarak yeniden biçimlendirebilir:
// ✔️ OK
let rainbow =
{ Boss1 = "Jeffrey"
Boss2 = "Jeffrey"
Boss3 = "Jeffrey"
Lackeys = ["Zippy"; "George"; "Bungle"] }
// ❌ Not preferred, code formatters will reformat to the above by default
let rainbow =
{
Boss1 = "Jeffrey"
Boss2 = "Jeffrey"
Boss3 = "Jeffrey"
Lackeys = ["Zippy"; "George"; "Bungle"]
}
Liste ve dizi öğeleri için aynı kurallar geçerlidir.
Copy ve Update kayıt ifadelerini biçimlendirme
Bir kopyalama ve güncelleştirme kayıt ifadesi hala bir kayıt olduğundan benzer yönergeler geçerlidir.
Kısa ifadeler tek bir satıra uygun olabilir:
// ✔️ OK
let point2 = { point with X = 1; Y = 2 }
Daha uzun ifadeler yeni satırları kullanmalıdır:
// ✔️ OK
let rainbow2 =
{ rainbow with
Boss = "Jeffrey"
Lackeys = [ "Zippy"; "George"; "Bungle" ] }
Küme ayraçları için ayrı satırlar atamak ve bir kapsamın sağına doğru girinti yapmak isteyebilirsiniz, ancak kod biçimleri de olabilir. 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:
// ✔️ OK
let newState =
{ state with
Foo = Some { F1 = 0; F2 = "" } }
// ❌ Not OK, code formatters will reformat to the above by default
let newState =
{
state with
Foo =
Some {
F1 = 0
F2 = ""
}
}
Biçimlendirme deseninin eşleşmesi
Bir | eşleşmenin for each yan tümcesini girintileme olmadan kullanın. İfade kısaysa, her alt ifade da basit olduğunda tek bir satır kullanmayı düşünebilirsiniz.
// ✔️ OK
match l with
| { him = x; her = "Posh" } :: tail -> x
| _ :: tail -> findDavid tail
| [] -> failwith "Couldn't find David"
// ❌ Not OK, code formatters will reformat to the above by default
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 / | .
// ✔️ OK
match lam with
| Var v -> 1
| Abs(x, body) ->
1 + sizeLambda body
| App(lam1, lam2) ->
sizeLambda lam1 + sizeLambda lam2
Bir model eşleşmesi oklarının hizalanmasının kaçınılması gerekir.
// ✔️ OK
match lam with
| Var v -> v.Length
| Abstraction _ -> 2
// ❌ Not OK, code formatters will reformat to the above by default
match lam with
| Var v -> v.Length
| Abstraction _ -> 2
Anahtar sözcüğü kullanılarak tanıtılan model eşleştirme, function önceki satırın başından itibaren bir düzey girintili olmalıdır:
// ✔️ OK
lambdaList
|> List.map (function
| Abs(x, body) -> 1 + sizeLambda 0 body
| App(lam1, lam2) -> sizeLambda (sizeLambda 0 lam1) lam2
| Var v -> 1)
functionYa da tarafından tanımlanan veya genel olarak tanımlanan işlevlerde kullanılması, ' let let rec nin yararına kaçınılması gerekir match . Kullanılıyorsa, model kuralları anahtar sözcüğüyle hizalanmalıdır function :
// ✔️ OK
let rec sizeLambda acc =
function
| Abs(x, body) -> sizeLambda (succ acc) body
| App(lam1, lam2) -> sizeLambda (sizeLambda acc lam1) lam2
| Var v -> succ acc
Try/with ifadelerini biçimlendirme
Özel durum türünde model eşleştirme, ile aynı düzeyde girintili olmalıdır with .
// ✔️ OK
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"
|Yalnızca tek bir yan tümce dışında bir for each yan tümcesi ekleyin:
// ✔️ OK
try
persistState currentState
with ex ->
printfn "Something went wrong: %A" ex
// ✔️ OK
try
persistState currentState
with :? System.ApplicationException as ex ->
printfn "Something went wrong: %A" ex
// ❌ Not OK, see above for preferred formatting
try
persistState currentState
with
| ex ->
printfn "Something went wrong: %A" ex
// ❌ Not OK, see above for preferred formatting
try
persistState currentState
with
| :? System.ApplicationException as ex ->
printfn "Something went wrong: %A" ex
Adlandırılmış bağımsız değişkenleri biçimlendirme
Adlandırılmış bağımsız değişkenler çevreleyen boşluk içermemelidir = :
// ✔️ OK
let makeStreamReader x = new System.IO.StreamReader(path=x)
// ❌ Not OK, no spaces necessary around '=' for named arguments
let makeStreamReader x = new System.IO.StreamReader(path = x)
Ayrılmış birleşimler kullanılarak desen eşleştirilirken, adlandırılmış desenler benzer şekilde biçimlendirilir, örn.
type Data =
| TwoParts of part1: string * part2: string
| OnePart of part1: string
// ✔️ OK
let examineData x =
match data with
| OnePartData(part1=p1) -> p1
| TwoPartData(part1=p1; part2=p2) -> p1 + p2
// ❌ Not OK, no spaces necessary around '=' for named pattern access
let examineData x =
match data with
| OnePartData(part1 = p1) -> p1
| TwoPartData(part1 = p1; part2 = p2) -> p1 + p2
Mutasyon ifadelerini biçimlendirme
Mutasyon ifadeleri location <- expr normalde tek bir satırda biçimlendirilir.
Çok satırlı biçimlendirme gerekliyse, sağ taraftaki ifadeyi yeni bir satıra yerleştirin.
// ✔️ OK
ctx.Response.Headers[HeaderNames.ContentType] <-
Constants.jsonApiMediaType |> StringValues
ctx.Response.Headers[HeaderNames.ContentLength] <-
bytes.Length |> string |> StringValues
// ❌ Not OK, code formatters will reformat to the above by default
ctx.Response.Headers[HeaderNames.ContentType] <- Constants.jsonApiMediaType
|> StringValues
ctx.Response.Headers[HeaderNames.ContentLength] <- bytes.Length
|> string
|> StringValues
Nesne ifadelerini biçimlendirme
Nesne ifadesi üyeleri bir düzey girintili olacak şekilde hizalanmalıdır member .
// ✔️ OK
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) }
Dizin/dilim ifadelerini biçimlendirme
Dizin ifadeleri, açma ve kapatma köşeli ayracın etrafında boşluk içermemelidir.
// ✔️ OK
let v = expr[idx]
let y = myList[0..1]
// ❌ Not OK
let v = expr[ idx ]
let y = myList[ 0 .. 1 ]
Bu, eski sözdizimi için de geçerlidir expr.[idx] .
// ✔️ OK
let v = expr.[idx]
let y = myList.[0..1]
// ❌ Not OK
let v = expr.[ idx ]
let y = myList.[ 0 .. 1 ]
Biçimlendirme bildirimleri
Bu bölümde, farklı türlerdeki biçimlendirme bildirimleri ele alınmaktadır.
Bildirimler arasına boş satırlar ekleyin
Üst düzey işlev ve sınıf tanımlarını tek bir boş satırla ayırın. Örnek:
// ✔️ OK
let thing1 = 1+1
let thing2 = 1+2
let thing3 = 1+3
type ThisThat = This | That
// ❌ Not OK
let thing1 = 1+1
let thing2 = 1+2
let thing3 = 1+3
type ThisThat = This | That
Bir yapının XML belge açıklaması varsa, açıklamadan önce boş bir satır ekleyin.
// ✔️ OK
/// This is a function
let thisFunction() =
1 + 1
/// This is another function, note the blank line before this line
let thisFunction() =
1 + 1
Biçim Let ve üye bildirimleri
Biçimlendirme let ve member Bildirimler olduğunda, bir bağlamanın sağ tarafı bir satıra gider ya da (çok uzunsa) yeni bir satıra bir düzey girintili gider.
Örneğin, aşağıdakiler uyumludur:
// ✔️ OK
let a =
"""
foobar, long string
"""
// ✔️ OK
type File =
member this.SaveAsync(path: string) : Async<unit> =
async {
// IO operation
return ()
}
// ✔️ OK
let c =
{ Name = "Bilbo"
Age = 111
Region = "The Shire" }
// ✔️ OK
let d =
while f do
printfn "%A" x
Aşağıdakiler uyumlu değil:
// ❌ Not OK, code formatters will reformat to the above by default
let a = """
foobar, long string
"""
type File =
member this.SaveAsync(path: string) : Async<unit> = async {
// IO operation
return ()
}
let c = {
Name = "Bilbo"
Age = 111
Region = "The Shire"
}
let d = while f do
printfn "%A" x
Üyeleri tek bir boş satır ve belge ile ayırın ve bir belge açıklaması ekleyin:
// ✔️ OK
/// This is a thing
type ThisThing(value: int) =
/// Gets the value
member _.Value = value
/// Returns twice the value
member _.TwiceValue() = value*2
İlgili işlevlerin gruplarını ayırmak için fazladan boş satırlar kullanılabilir (gelişigüzel). Bir arada ilgili tek bir grup (örneğin, bir kukla uygulamalar kümesi) arasında boş satırlar atlanabilir. Mantıksal bölümleri göstermek için işlevlerde boş satırları gelişigüzel bir şekilde kullanın.
İşlev ve üye bağımsız değişkenlerini biçimlendirme
Bir işlevi tanımlarken, her bağımsız değişken etrafında boşluk kullanın.
// ✔️ OK
let myFun (a: decimal) (b: int) c = a + b + c
// ❌ Not OK, code formatters will reformat to the above by default
let myFunBad (a:decimal)(b:int)c = a + b + c
Uzun bir işlev tanımınız varsa, parametreleri yeni satırlara yerleştirip sonraki parametrenin girintileme düzeyiyle eşleşecek şekilde Girintile.
// ✔️ OK
module M =
let longFunctionWithLotsOfParameters
(aVeryLongParam: AVeryLongTypeThatYouNeedToUse)
(aSecondVeryLongParam: AVeryLongTypeThatYouNeedToUse)
(aThirdVeryLongParam: AVeryLongTypeThatYouNeedToUse)
=
// ... the body of the method follows
let longFunctionWithLotsOfParametersAndReturnType
(aVeryLongParam: AVeryLongTypeThatYouNeedToUse)
(aSecondVeryLongParam: AVeryLongTypeThatYouNeedToUse)
(aThirdVeryLongParam: AVeryLongTypeThatYouNeedToUse)
: ReturnType =
// ... the body of the method follows
let longFunctionWithLongTupleParameter
(
aVeryLongParam: AVeryLongTypeThatYouNeedToUse,
aSecondVeryLongParam: AVeryLongTypeThatYouNeedToUse,
aThirdVeryLongParam: AVeryLongTypeThatYouNeedToUse
) =
// ... the body of the method follows
let longFunctionWithLongTupleParameterAndReturnType
(
aVeryLongParam: AVeryLongTypeThatYouNeedToUse,
aSecondVeryLongParam: AVeryLongTypeThatYouNeedToUse,
aThirdVeryLongParam: AVeryLongTypeThatYouNeedToUse
) : ReturnType =
// ... the body of the method follows
Bu Ayrıca, tanımlama gruplarını kullanan üyeler, oluşturucular ve parametreler için de geçerlidir:
// ✔️ OK
type TypeWithLongMethod() =
member _.LongMethodWithLotsOfParameters
(
aVeryLongParam: AVeryLongTypeThatYouNeedToUse,
aSecondVeryLongParam: AVeryLongTypeThatYouNeedToUse,
aThirdVeryLongParam: AVeryLongTypeThatYouNeedToUse
) =
// ... the body of the method
// ✔️ OK
type TypeWithLongConstructor
(
aVeryLongCtorParam: AVeryLongTypeThatYouNeedToUse,
aSecondVeryLongCtorParam: AVeryLongTypeThatYouNeedToUse,
aThirdVeryLongCtorParam: AVeryLongTypeThatYouNeedToUse
) =
// ... the body of the class follows
Parametreler curried ise, = karakteri herhangi bir dönüş türü ile birlikte yeni bir satıra yerleştirin:
// ✔️ OK
type TypeWithLongCurriedMethods() =
member _.LongMethodWithLotsOfCurriedParamsAndReturnType
(aVeryLongParam: AVeryLongTypeThatYouNeedToUse)
(aSecondVeryLongParam: AVeryLongTypeThatYouNeedToUse)
(aThirdVeryLongParam: AVeryLongTypeThatYouNeedToUse)
: ReturnType =
// ... the body of the method
member _.LongMethodWithLotsOfCurriedParams
(aVeryLongParam: AVeryLongTypeThatYouNeedToUse)
(aSecondVeryLongParam: AVeryLongTypeThatYouNeedToUse)
(aThirdVeryLongParam: AVeryLongTypeThatYouNeedToUse)
=
// ... the body of the method
Bu, çok uzun çizgileri önlemenin bir yoludur (Bu durumda, dönüş türü uzun bir ada sahip olabilir) ve parametreler eklenirken daha az sayıda satır hasarı olabilir.
Biçimlendirme işleci bildirimleri
İsteğe bağlı olarak bir operatör tanımını çevrelemek için boşluk kullanın:
// ✔️ OK
let ( !> ) x f = f x
// ✔️ OK
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. Bu nedenle, tek bir boşluk karakteriyle tüm işleçlerin tanımlarını çevrelemeyi öneririz.
Kayıt bildirimlerini biçimlendirme
Kayıt bildirimleri için, { tür tanımında dört boşlukla girinti yapın, alan listesini aynı satırda başlatın ve belirteci olan tüm üyeleri hizalayın { :
// ✔️ OK
type PostalAddress =
{ Address: string
City: string
Zip: string }
member x.ZipAndCity = $"{x.Zip} {x.City}"
{Türü bildirim satırının sonuna yerleştirmeyin ve with / end gereksiz olan üyeler için kullanmayın.
// ❌ Not OK, code formatters will reformat to the above by default
type PostalAddress = {
Address: string
City: string
Zip: string
}
with
member x.ZipAndCity = $"{x.Zip} {x.City}"
end
Kayıt alanları için XML belgeleri eklendiğinde, girintilendirme ve boşluk ekleme için normal olur:
// ✔️ OK
type PostalAddress =
{
/// The address
Address: string
/// The city
City: string
/// The zip code
Zip: string
}
/// Format the zip code and the city
member x.ZipAndCity = $"{x.Zip} {x.City}"
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:
// ✔️ OK
// Declaring additional members on PostalAddress
type PostalAddress =
{
/// The address
Address: string
/// The city
City: string
/// The zip code
Zip: string
}
member x.ZipAndCity = $"{x.Zip} {x.City}"
type MyRecord =
{
/// The record field
SomeField: int
}
interface IMyInterface
Ayırt edici birleşim bildirimlerini biçimlendirme
Ayrılmış birleşim bildirimleri için | tür tanımında dört boşlukla Girintile:
// ✔️ 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
Tek bir kısa birleşim olduğunda, öndeki boşluğu atlayabilirsiniz | .
// ✔️ OK
type Address = Address of string
Daha uzun veya çok satırlı bir birleşim için, her bir satırın | sonuna kadar olan her birleşim alanını yeni bir satıra yerleştirin * .
// ✔️ OK
[<NoEquality; NoComparison>]
type SynBinding =
| SynBinding of
accessibility: SynAccess option *
kind: SynBindingKind *
mustInline: bool *
isMutable: bool *
attributes: SynAttributes *
xmlDoc: PreXmlDoc *
valData: SynValData *
headPat: SynPat *
returnInfo: SynBindingReturnInfo option *
expr: SynExpr *
range: range *
seqPoint: DebugPointAtBinding
Belge açıklamaları eklendiğinde, her açıklamadan önce boş bir satır kullanın /// .
// ✔️ OK
/// The volume
type Volume =
/// The volume in liters
| Liter of float
/// The volume in fluid ounces
| FluidOunce of float
/// The volume in imperial pints
| ImperialPint of float
Değişmez değer bildirimlerini biçimlendirme
Özniteliği kullanan F # değişmez değerleri Literal özniteliği kendi satırına yerleştirip PascalCase adlandırmayı kullanmalıdır:
// ✔️ OK
[<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.
Modül bildirimlerini biçimlendirme
Yerel modüldeki kodun modüle bağlı olması gerekir, ancak üst düzey modüldeki kod girintilenmemelidir. Ad alanı öğelerinin girintili olması gerekmez.
// ✔️ OK - A is a top-level module.
module A
let function1 a b = a - b * b
// ✔️ OK - 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
Do bildirimleri biçimlendirme
Tür bildirimlerinde, modül bildirimlerinde ve hesaplama ifadelerinde, do veya kullanımı do! bazen yan etkili işlemler için gereklidir.
Bu birden çok satıra yayıldığınızda, Girintiyi ile tutarlı tutmak için girintileme ve yeni bir satır kullanın let / let! . Aşağıda bir sınıfta kullanılan örnek verilmiştir do :
// ✔️ OK
type Foo () =
let foo =
fooBarBaz
|> loremIpsumDolorSitAmet
|> theQuickBrownFoxJumpedOverTheLazyDog
do
fooBarBaz
|> loremIpsumDolorSitAmet
|> theQuickBrownFoxJumpedOverTheLazyDog
// ❌ Not OK - notice the "do" expression is indented one space less than the `let` expression
type Foo () =
let foo =
fooBarBaz
|> loremIpsumDolorSitAmet
|> theQuickBrownFoxJumpedOverTheLazyDog
do fooBarBaz
|> loremIpsumDolorSitAmet
|> theQuickBrownFoxJumpedOverTheLazyDog
Aşağıda, do! iki girinti boşluğu kullanan bir örnek verilmiştir ( do! dört girinti boşluğu kullanırken yaklaşım arasında fark yok tesadüfen):
// ✔️ OK
async {
let! foo =
fooBarBaz
|> loremIpsumDolorSitAmet
|> theQuickBrownFoxJumpedOverTheLazyDog
do!
fooBarBaz
|> loremIpsumDolorSitAmet
|> theQuickBrownFoxJumpedOverTheLazyDog
}
// ❌ Not OK - notice the "do!" expression is indented two spaces more than the `let!` expression
async {
let! foo =
fooBarBaz
|> loremIpsumDolorSitAmet
|> theQuickBrownFoxJumpedOverTheLazyDog
do! fooBarBaz
|> loremIpsumDolorSitAmet
|> theQuickBrownFoxJumpedOverTheLazyDog
}
Hesaplama ifade işlemlerini biçimlendirme
Hesaplama ifadeleriiçin özel işlemler oluştururken, camelCase adlandırması kullanılması önerilir:
// ✔️ OK
type MathBuilder () =
member _.Yield _ = 0
[<CustomOperation("addOne")>]
member _.AddOne (state: int) =
state + 1
[<CustomOperation("subtractOne")>]
member _.SubtractOne (state: int) =
state - 1
[<CustomOperation("divideBy")>]
member _.DivideBy (state: int, divisor: int) =
state / divisor
[<CustomOperation("multiplyBy")>]
member _.MultiplyBy (state: int, factor: int) =
state * factor
let math = MathBuilder()
let myNumber =
math {
addOne
addOne
addOne
subtractOne
divideBy 2
multiplyBy 10
}
Modellenen etki alanı, sonunda adlandırma kuralını kullanmalıdır. Farklı bir kural kullanmak istiyorsanız, bunun yerine bu kural kullanılmalıdır.
Biçimlendirme türleri ve tür ek açıklamaları
Bu bölümde, biçimlendirme türleri ve tür ek açıklamaları açıklanmaktadır. Buna uzantı ile biçimlendirme imza dosyaları dahildir .fsi .
Türler için, genel türler () için önek sözdizimini tercih Foo<T> edin, bazı özel durumlarla
F #, genel türleri (örneğin, int list ) ve önek stilini (örneğin,) yazma için her iki sonek stiline de izin verir list<int> .
Sonek stili yalnızca tek bir tür bağımsız değişkeniyle birlikte kullanılabilir.
Her zaman, beş özel tür hariç .NET stilini tercih edin:
- F # listeleri için sonek biçimini kullanın:
int listyerinelist<int>. - F # seçenekleri için sonek biçimini kullanın:
int optionyerineoption<int>. - F # değer seçenekleri için sonek biçimini kullanın:
int voptionyerinevoption<int>. - F # dizileri için veya yerine sözdizimsel adı kullanın
int[]int arrayarray<int>. - Başvuru hücreleri için
int refveya yerine kullanınref<int>Ref<int>.
Diğer tüm türler için önek formunu kullanın.
İşlev türlerini biçimlendirme
Bir işlevin imzasını tanımlarken, simgenin etrafında boşluk kullanın -> :
// ✔️ OK
type MyFun = int -> int -> string
// ❌ Not OK
type MyFunBad = int->int->string
Biçimlendirme değeri ve bağımsız değişken türü ek açıklamaları
Tür ek açıklamalarıyla değerleri veya bağımsız değişkenleri tanımlarken, simgeden sonra boşluk kullanın : , ancak daha önce değil:
// ✔️ OK
let complexFunction (a: int) (b: int) c = a + b + c
let simpleValue: int = 0 // Type annotation for let-bound value
type C() =
member _.Property: int = 1
// ❌ Not OK
let complexFunctionPoorlyAnnotated (a :int) (b :int) (c:int) = a + b + c
let simpleValuePoorlyAnnotated1:int = 1
let simpleValuePoorlyAnnotated2 :int = 2
Dönüş türü ek açıklamalarını biçimlendirme
İşlev veya üye dönüş türü ek açıklamaları ' nda, simgeden önce ve sonra boşluk kullanın : :
// ✔️ OK
let myFun (a: decimal) b c : decimal = a + b + c
type C() =
member _.SomeMethod(x: int) : int = 1
// ❌ Not OK
let myFunBad (a: decimal) b c:decimal = a + b + c
let anotherFunBad (arg: int): unit = ()
type C() =
member _.SomeMethodBad(x: int): int = 1
İmzalarda biçimlendirme türleri
İmzalara tam işlev türleri yazarken, bazı durumlarda bağımsız değişkenlerin birden çok satıra bölünmesi gerekir. Tupled işlevi için bağımsız değişkenler, * her satırın sonuna yerleştirilmiş olarak ayrılır. Dönüş türü girintili. Örneğin, aşağıdaki uygulamayla bir işlev düşünün:
let SampleTupledFunction(arg1, arg2, arg3, arg4) = ...
İlgili imza dosyasında ( .fsi uzantı), çok satırlı biçimlendirme gerektiğinde işlev aşağıdaki şekilde biçimlendirilebilir:
// ✔️ OK
val SampleTupledFunction:
arg1: string *
arg2: string *
arg3: int *
arg4: int
-> int list
Benzer şekilde bir curried işlevi düşünün:
let SampleCurriedFunction arg1 arg2 arg3 arg4 = ...
Karşılık gelen imza dosyasında,, -> her satırın başlangıcına yerleştirilir:
// ✔️ OK
val SampleCurriedFunction:
arg1: string
-> arg2: string
-> arg3: int
-> arg4: int
-> int list
Benzer şekilde, curried ve tupled bağımsız değişkenlerinin karışımını alan bir işlevi göz önünde bulundurun:
// Typical call syntax:
let SampleMixedFunction
(arg1, arg2)
(arg3, arg4, arg5)
(arg6, arg7)
(arg8, arg9, arg10) = ..
Karşılık gelen imza dosyasında,, -> son dışında her bir bağımsız değişkenin sonuna yerleştirilir:
// ✔️ OK
val SampleMixedFunction:
arg1: string *
arg2: string
-> arg3: string *
arg4: string *
arg5: TType
-> arg6: TType *
arg7: TType *
-> arg8: TType *
arg9: TType *
arg10: TType
-> TType list
Açık genel tür bağımsız değişkenlerini ve kısıtlamalarını biçimlendirme
Aşağıdaki yönergeler işlev tanımları, üye tanımları ve tür tanımları için geçerlidir.
Çok uzun değilse, genel tür bağımsız değişkenlerini ve kısıtlamalarını tek bir satırda tutun:
// ✔️ OK
let f<'T1, 'T2 when 'T1: equality and 'T2: comparison> param =
// function body
Hem genel tür bağımsız değişkenleri/kısıtlamaları hem de işlev parametreleri uygun değilse, ancak tür parametreleri/kısıtlamaları tek başına ise, parametreleri yeni satırlara yerleştirin:
// ✔️ OK
let f<'T1, 'T2 when 'T1 : equality and 'T2 : comparison>
param
=
// function body
Tür parametreleri veya kısıtlamaları çok uzunsa, break ve bunları aşağıda gösterildiği gibi hizalayın. Tür parametrelerinin listesini, uzunluğundan bağımsız olarak işlevle aynı satırda tutun. Kısıtlamalar için when ilk satıra yerleştirin ve her kısıtlamayı, uzunluğundan bağımsız olarak tek bir satırda tutun. >Son satırın sonuna yerleştirin. Kısıtlamaları bir düzey ile girintileyin.
// ✔️ OK
let inline f< ^T1, ^T2
when ^T1 : (static member Foo1: unit -> ^T2)
and ^T2 : (member Foo2: unit -> int)
and ^T2 : (member Foo3: string -> ^T1 option)>
arg1
arg2
=
// function body
Tür parametreleri/kısıtlamaları bozulur, ancak normal işlev parametreleri yoksa, aşağıdakileri göz = önüne alarak yeni bir satıra yerleştirin:
// ✔️ OK
let inline f<^T1, ^T2
when ^T1 : (static member Foo1: unit -> ^T2)
and ^T2 : (member Foo2: unit -> int)
and ^T2 : (member Foo3: string -> ^T1 option)>
=
// function body
Biçimlendirme öznitelikleri
Öznitelikler bir yapının üzerine yerleştirilir:
// ✔️ OK
[<SomeAttribute>]
type MyClass() = ...
// ✔️ OK
[<RequireQualifiedAccess>]
module M =
let f x = x
// ✔️ OK
[<Struct>]
type MyRecord =
{ Label1: int
Label2: string }
XML belgelerinden sonra gitmeleri gerekir:
// ✔️ OK
/// Module with some things in it.
[<RequireQualifiedAccess>]
module M =
let f x = x
Parametrelerde öznitelikleri biçimlendirme
Öznitelikler, parametrelere de yerleştirilebilir. Bu durumda, daha sonra parametresiyle aynı satıra ve adından önce yerleştirin:
// ✔️ OK - 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çimlendirme
Bir parametre olmayan bir yapı için birden çok öznitelik uygulandığında, her satır için bir öznitelik olması gibi yerleştirilmelidir:
// ✔️ OK
[<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.