Literały
W tym artykule przedstawiono tabelę przedstawiającą sposób określania typu literału w języku F#.
Typy literałów
W poniższej tabeli przedstawiono typy literałów w języku F#. Znaki reprezentujące cyfry w notacji szesnastkowej nie są wrażliwe na wielkość liter; znaki identyfikujące typ są wrażliwe na wielkość liter.
Typ | Opis | Sufiks lub prefiks | Przykłady |
---|---|---|---|
sbyte | znakowa 8-bitowa liczba całkowita | y | 86y 0b00000101y |
bajt | niepodpisany 8-bitowy numer naturalny | uy | 86uy 0b00000101uy |
int16 | 16-bitowa liczba całkowita ze znakiem | s | 86s |
uint16 | niepodpisany 16-bitowy numer naturalny | nas | 86us |
Int int32 |
ze znakiem 32-bitowej liczby całkowitej | l lub brak | 86 86l |
uint uint32 |
niepodpisany 32-bitowy numer naturalny | u lub ul | 86u 86ul |
nativeint | natywny wskaźnik do podpisanego numeru naturalnego | n | 123n |
unativeint | natywny wskaźnik jako nieznakowana liczba naturalna | jeden | 0x00002D3Fun |
int64 | znakowana 64-bitowa liczba całkowita | L | 86L |
uint64 | niepodpisany 64-bitowy numer naturalny | UL | 86UL |
pojedynczy, float32 | 32-bitowa liczba zmiennoprzecinkowa | F lub f |
4.14F lub 4.14f lub infinityf lub -infinityf |
Lf | 0x00000000lf |
||
spławik; podwójny | 64-bitowa liczba zmiennoprzecinkowa | żaden |
4.14 lub 2.3E+32 , 2.3e+32 lub infinity lub -infinity |
LF | 0x0000000000000000LF |
||
bigint | Liczba całkowita nie ogranicza się do reprezentacji 64-bitowej | Ja | 9999999999999999999999999999I |
dziesiętny | liczba ułamkowa reprezentowana jako stały punkt lub liczba racjonalna | M lub m |
0.7833M lub 0.7833m |
Char | Znak Unicode | żaden |
'a' lub '\u0061' |
Struna | Ciąg Unicode | żaden | "text\n" lub @"c:\filename" lub """<book title="Paradise Lost">""" lub "string1" + "string2" Zobacz również Łańcuchy. |
bajt | Znak ASCII | B | 'a'B |
byte[] | Ciąg ASCII | B | "text"B |
Ciąg lub bajt[] | ciąg dosłowny | prefiks @ |
@"\\server\share" (Unicode)@"\\server\share"B (ASCII) |
Nazwane literały
Wartości, które mają być stałymi, można oznaczyć atrybutem Literal.
Ten atrybut ma wpływ na kompilowanie wartości jako stałej. W poniższym przykładzie zarówno x
, jak i y
poniżej są niezmienne wartości, ale x
są oceniane w czasie wykonywania, natomiast y
jest stałą czasu kompilacji.
let x = "a" + "b" // evaluated at run-time
[<Literal>]
let y = "a" + "b" // evaluated at compile-time
Notatka
Funkcji nie można używać do obliczania wartości [<Literal>]
, ponieważ literały muszą być określane w czasie kompilacji i nie mogą zależeć od oceny środowiska uruchomieniowego.
Dlaczego funkcje nie mogą obliczać literałów
Atrybut [<Literal>]
wymaga, aby wartości są znane w czasie kompilacji. Funkcje, nawet jeśli wydają się generować stałe dane wyjściowe, są oceniane w czasie wykonywania, co czyni je nieodpowiednimi dla [<Literal>]
. To ograniczenie gwarantuje, że literały mogą być bezpiecznie używane w scenariuszach, takich jak dopasowywanie wzorców, argumenty atrybutów i współdziałanie z funkcjami zewnętrznymi.
Na przykład próba przypisania wyniku funkcji do literału zakończy się niepowodzeniem:
[<Literal>]
let yFunc() = "a" + "b" // error FS0267: this is not a valid constant expression
To rozróżnienie ma również znaczenie podczas wywoływania funkcji zewnętrznej . Na przykład DllImport
jest atrybutem, który musi znać wartość myDLL
podczas kompilacji. Bez deklaracji [<Literal>]
ten kod nie może skompilować:
[<Literal>]
let myDLL = "foo.dll"
[<DllImport(myDLL, CallingConvention = CallingConvention.Cdecl)>]
extern void HelloWorld()
W wyrażeniach dopasowywania wzorców identyfikatory rozpoczynające się od małych liter są zawsze traktowane jako zmienne, które mają być powiązane, a nie jako literały, dlatego podczas definiowania literałów należy zazwyczaj używać początkowych liter.
[<Literal>]
let SomeJson = """{"numbers":[1,2,3,4,5]}"""
[<Literal>]
let Literal1 = "a" + "b"
[<Literal>]
let FileLocation = __SOURCE_DIRECTORY__ + "/" + __SOURCE_FILE__
[<Literal>]
let Literal2 = 1 ||| 64
[<Literal>]
let Literal3 = System.IO.FileAccess.Read ||| System.IO.FileAccess.Write
Przykład zwięzłego dopasowywania wzorca przy użyciu nazwanych literałów
Literały nazwane mogą sprawić, że dopasowanie wzorca będzie bardziej zwięzłe, unikając konieczności klauzuli when
lub dodatkowej logiki. Na przykład:
[<Literal>]
let ErrorCode = 404
let handleResponse code =
match code with
| ErrorCode -> "Not Found"
| _ -> "Other Response"
Uwagi
Nazwane literały są przydatne w następujących celach:
- Dopasowywanie wzorca bez klauzuli
when
. - Argumenty atrybutów.
- Argumenty dostawcy typu statycznego.
Ciągi Unicode mogą zawierać jawne kodowanie, które można określić przy użyciu \u
, a następnie 16-bitowy kod szesnastkowy (0000 — FFFF) lub kodowania UTF-32, które można określić przy użyciu \U
, a następnie 32-bitowy kod szesnastkowy, który reprezentuje dowolny punkt kodu Unicode (000000000 – 0010FFFF).
Użycie operatorów bitowych innych niż |||
nie jest dozwolone.
Liczby całkowite w innych bazach
Podpisane 32-bitowe liczby całkowite można również określić w systemie szesnastkowym, ósemkowym lub binarnym, używając odpowiednio prefiksu 0x
, 0o
lub 0b
.
let numbers = (0x9F, 0o77, 0b1010)
// Result: numbers : int * int * int = (159, 63, 10)
Podkreślenia w literałach liczbowych
Cyfry można oddzielić znakiem podkreślenia (_
).
let value = 0xDEAD_BEEF
let valueAsBits = 0b1101_1110_1010_1101_1011_1110_1110_1111
let exampleSSN = 123_45_6789
Specjalne wartości nieskończoności zmiennoprzecinkowych
Zarówno float
, jak i single
typy liczb zmiennoprzecinkowe mają skojarzone specjalne wartości reprezentujące nieskończoność dodatnią i ujemną.
Wartość F# | Typ języka F# | Odpowiadająca wartość .NET |
---|---|---|
infinity lub +infinity |
float |
PositiveInfinity |
-infinity |
float |
NegativeInfinity |
infinityf lub +infinityf |
single |
PositiveInfinity |
-infinityf |
single |
NegativeInfinity |
Te wartości mogą być używane bezpośrednio lub są zwracane podczas dzielenia przez zero zmiennoprzecinkowe lub liczbę zbyt małą, aby być reprezentowane przez dany typ. Na przykład:
> 1.0/0.0;;
val it: float = infinity
> 1.0/(-0.0);;
val it: float = -infinity
> 1.0/0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
;;
val it: float = infinity