F # - Guida rapida
F # è un linguaggio di programmazione funzionale. Per comprendere i costrutti F #, è necessario leggere un paio di righe sul paradigma di programmazione denominatoFunctional Programming.
La programmazione funzionale tratta i programmi per computer come funzioni matematiche. Nella programmazione funzionale, l'attenzione si concentrerebbe su costanti e funzioni, invece che su variabili e stati. Perché le funzioni e le costanti sono cose che non cambiano.
Nella programmazione funzionale, scriverete programmi modulari, cioè i programmi sarebbero costituiti da funzioni che prenderanno altre funzioni come input.
I programmi scritti in un linguaggio di programmazione funzionale tendono ad essere concisi.
Informazioni su F #
Di seguito sono riportate le informazioni di base su F # -
- È stato sviluppato nel 2005 presso Microsoft Research.
- Fa parte della famiglia Microsoft del linguaggio .Net.
- È un linguaggio di programmazione funzionale.
- Si basa sul linguaggio di programmazione funzionale OCaml.
Caratteristiche di F #
È l'implementazione .Net di OCaml.
Compila il codice byte .Net CLI (Common Language Interface) o MSIL (Microsoft Intermediate Language) che gira su CLR (Common Language Runtime).
Fornisce inferenza di tipo.
Fornisce ricchi costrutti di corrispondenza dei modelli.
Ha funzionalità di scripting e debugging interattive.
Consente di scrivere funzioni di ordine superiore.
Fornisce un modello a oggetti ben sviluppato.
Uso di F #
F # viene normalmente utilizzato nelle seguenti aree:
- Fare modello scientifico
- Risoluzione di problemi matematici
- Lavoro di ricerca sull'intelligenza artificiale
- Modellazione finanziaria
- Disegno grafico
- Design della CPU
- Programmazione del compilatore
- Telecommunications
Viene anche utilizzato nelle app CRUD, nelle pagine Web, nei giochi GUI e in altri programmi generici.
Gli strumenti necessari per la programmazione F # sono discussi in questo capitolo.
Ambiente di sviluppo integrato (IDE) per F #
Microsoft fornisce Visual Studio 2013 per la programmazione F #.
La versione gratuita di Visual Studio 2013 Community Edition è disponibile sul sito Web ufficiale di Microsoft. La community di Visual Studio 2013 e versioni successive include gli strumenti di Visual F #. Dettagli di installazione disponibili in Asp.net Tutorial . Gli strumenti di Visual F # includono il compilatore della riga di comando (fsc.exe) e F # Interactive (fsi.exe).
Utilizzando questi strumenti, è possibile scrivere tutti i tipi di programmi F # da semplici applicazioni della riga di comando ad applicazioni più complesse. Puoi anche scrivere file di codice sorgente F # usando un editor di testo di base, come Blocco note, e compilare il codice in assembly usando il compilatore della riga di comando.
Puoi scaricarlo da Microsoft Visual Studio. Viene installato automaticamente nella tua macchina.
Scrittura di programmi F # sui collegamenti
Visitare il sito Web ufficiale di F # per le ultime istruzioni su come ottenere gli strumenti come pacchetto Debian o compilarli direttamente dai sorgenti - https://fsharp.org/use/linux/.
F # è un linguaggio di programmazione funzionale.
In F #, le funzioni funzionano come i tipi di dati. Puoi dichiarare e utilizzare una funzione allo stesso modo di qualsiasi altra variabile.
In generale, un'applicazione F # non dispone di alcun punto di ingresso specifico. Il compilatore esegue tutte le istruzioni di primo livello nel file dall'alto verso il basso.
Tuttavia, per seguire lo stile di programmazione procedurale, molte applicazioni mantengono un'unica istruzione di primo livello che richiama il ciclo principale.
Il codice seguente mostra un semplice programma F # -
open System
(* This is a multi-line comment *)
// This is a single-line comment
let sign num =
if num > 0 then "positive"
elif num < 0 then "negative"
else "zero"
let main() =
Console.WriteLine("sign 5: {0}", (sign 5))
main()
Quando compili ed esegui il programma, restituisce il seguente output:
sign 5: positive
Si prega di notare che -
Un file di codice F # potrebbe iniziare con un numero di open istruzioni utilizzate per importare gli spazi dei nomi.
Il corpo dei file include altre funzioni che implementano la logica di business dell'applicazione.
Il ciclo principale contiene le prime istruzioni eseguibili.
Hai visto la struttura di base di un programma F #, quindi sarà facile capire altri elementi costitutivi di base del linguaggio di programmazione F #.
Gettoni in F #
Un programma F # è costituito da vari token. Un token può essere una parola chiave, un identificatore, una costante, una stringa letterale o un simbolo. Possiamo classificare i token F # in due tipi:
- Keywords
- Simbolo e operatori
Parole chiave F #
La tabella seguente mostra le parole chiave e una breve descrizione delle parole chiave. Discuteremo l'uso di queste parole chiave nei capitoli successivi.
Parola chiave | Descrizione |
---|---|
abstract | Indica un metodo che non ha implementazione nel tipo in cui è dichiarato o che è virtuale e ha un'implementazione predefinita. |
and | Utilizzato in associazioni reciprocamente ricorsive, nelle dichiarazioni di proprietà e con più vincoli su parametri generici. |
as | Usato per dare all'oggetto classe corrente un nome oggetto. Utilizzato anche per dare un nome a un intero pattern all'interno di una corrispondenza di pattern. |
assert | Utilizzato per verificare il codice durante il debug. |
base | Utilizzato come nome dell'oggetto della classe di base. |
begin | Nella sintassi dettagliata, indica l'inizio di un blocco di codice. |
class | Nella sintassi dettagliata, indica l'inizio di una definizione di classe. |
default | Indica un'implementazione di un metodo astratto; utilizzato insieme a una dichiarazione di metodo astratto per creare un metodo virtuale. |
delegate | Utilizzato per dichiarare un delegato. |
do | Utilizzato nei costrutti di ciclo o per eseguire codice imperativo. |
done | Nella sintassi dettagliata, indica la fine di un blocco di codice in un'espressione a ciclo continuo. |
downcast | Utilizzato per convertire in un tipo inferiore nella catena di ereditarietà. |
downto | In un for espressione, usata quando si conta al contrario. |
elif | Utilizzato nella ramificazione condizionale. Una forma breve di else if. |
else | Utilizzato nella ramificazione condizionale. |
end | Nelle definizioni dei tipi e nelle estensioni dei tipi, indica la fine di una sezione delle definizioni dei membri. Nella sintassi dettagliata, utilizzato per specificare la fine di un blocco di codice che inizia con la parola chiave begin. |
exception | Utilizzato per dichiarare un tipo di eccezione. |
extern | Indica che un elemento di programma dichiarato è definito in un altro binario o assembly. |
false | Usato come valore letterale booleano. |
finally | Utilizzato insieme al tentativo di introdurre un blocco di codice che viene eseguito indipendentemente dal fatto che si verifichi un'eccezione. |
for | Utilizzato nei costrutti di ciclo. |
fun | Utilizzato nelle espressioni lambda, note anche come funzioni anonime. |
function | Utilizzato come un'alternativa più breve alla parola chiave fun e un'espressione di corrispondenza in un'espressione lambda che ha la corrispondenza del modello su un singolo argomento. |
global | Utilizzato per fare riferimento allo spazio dei nomi .NET di primo livello. |
if | Utilizzato nei costrutti di ramificazione condizionale. |
in | Utilizzato per le espressioni di sequenza e, nella sintassi dettagliata, per separare le espressioni dalle associazioni. |
inherit | Utilizzato per specificare una classe di base o un'interfaccia di base. |
inline | Utilizzato per indicare una funzione che dovrebbe essere integrata direttamente nel codice del chiamante. |
interface | Utilizzato per dichiarare e implementare le interfacce. |
internal | Utilizzato per specificare che un membro è visibile all'interno di un assieme ma non all'esterno. |
lazy | Utilizzato per specificare un calcolo che deve essere eseguito solo quando è necessario un risultato. |
let | Utilizzato per associare o legare un nome a un valore o una funzione. |
let! | Utilizzato nei flussi di lavoro asincroni per associare un nome al risultato di un calcolo asincrono o, in altre espressioni di calcolo, utilizzato per associare un nome a un risultato, che è del tipo di calcolo. |
match | Utilizzato per ramificare confrontando un valore con un modello. |
member | Utilizzato per dichiarare una proprietà o un metodo in un tipo di oggetto. |
module | Utilizzato per associare un nome a un gruppo di tipi, valori e funzioni correlati, per separarlo logicamente da altro codice. |
mutable | Utilizzato per dichiarare una variabile, ovvero un valore che può essere modificato. |
namespace | Utilizzato per associare un nome a un gruppo di tipi e moduli correlati, per separarlo logicamente da altro codice. |
new | Utilizzato per dichiarare, definire o richiamare un costruttore che crea o che può creare un oggetto. Utilizzato anche nei vincoli di parametri generici per indicare che un tipo deve avere un determinato costruttore. |
not | Non in realtà una parola chiave. Tuttavia, non struct in combinazione viene utilizzato come vincolo di parametro generico. |
null | Indica l'assenza di un oggetto. Utilizzato anche in vincoli di parametri generici. |
of | Utilizzato nelle unioni discriminate per indicare il tipo di categorie di valori e nelle dichiarazioni di delega e di eccezione. |
open | Utilizzato per rendere disponibile il contenuto di uno spazio dei nomi o di un modulo senza qualificazione. |
or | Utilizzato con condizioni booleane come operatore o booleano. Equivalente a ||. Utilizzato anche nei vincoli dei membri. |
override | Utilizzato per implementare una versione di un metodo astratto o virtuale che differisce dalla versione di base. |
private | Limita l'accesso a un membro al codice nello stesso tipo o modulo. |
public | Consente l'accesso a un membro dall'esterno del tipo. |
rec | Utilizzato per indicare che una funzione è ricorsiva. |
return | Utilizzato per indicare un valore da fornire come risultato di un'espressione di calcolo. |
return! | Utilizzato per indicare un'espressione di calcolo che, una volta valutata, fornisce il risultato dell'espressione di calcolo contenitore. |
select | Utilizzato nelle espressioni di query per specificare quali campi o colonne estrarre. Nota che questa è una parola chiave contestuale, il che significa che non è effettivamente una parola riservata e agisce solo come una parola chiave nel contesto appropriato. |
static | Utilizzato per indicare un metodo o una proprietà che può essere chiamata senza un'istanza di un tipo o un membro del valore condiviso tra tutte le istanze di un tipo. |
struct | Utilizzato per dichiarare un tipo di struttura. Utilizzato anche in vincoli di parametri generici. Utilizzato per la compatibilità OCaml nelle definizioni dei moduli. |
then | Utilizzato nelle espressioni condizionali. Utilizzato anche per eseguire effetti collaterali dopo la costruzione di oggetti. |
to | Utilizzato nei cicli for per indicare un intervallo. |
true | Usato come valore letterale booleano. |
try | Utilizzato per introdurre un blocco di codice che potrebbe generare un'eccezione. Usato insieme a o finalmente. |
type | Utilizzato per dichiarare una classe, un record, una struttura, un'unione discriminata, un tipo di enumerazione, un'unità di misura o un'abbreviazione di tipo. |
upcast | Utilizzato per convertire in un tipo che è più alto nella catena di ereditarietà. |
use | Utilizzato invece di let per i valori che richiedono la chiamata di Dispose per liberare risorse. |
use! | Usato invece di lasciare! nei flussi di lavoro asincroni e in altre espressioni di calcolo per i valori che richiedono la chiamata di Dispose per liberare risorse. |
val | Utilizzato in una firma per indicare un valore o in un tipo per dichiarare un membro, in situazioni limitate. |
void | Indica il tipo di vuoto .NET. Utilizzato durante l'interoperabilità con altri linguaggi .NET. |
when | Utilizzato per condizioni booleane (quando sorveglia) sulle corrispondenze di modelli e per introdurre una clausola di vincolo per un parametro di tipo generico. |
while | Introduce un costrutto a ciclo continuo. |
with | Utilizzato insieme alla parola chiave match nelle espressioni di corrispondenza dei pattern. Utilizzato anche in espressioni di oggetti, espressioni di copia di record ed estensioni di tipo per introdurre definizioni di membri e per introdurre gestori di eccezioni. |
yield | Utilizzato in un'espressione di sequenza per produrre un valore per una sequenza. |
yield! | Utilizzato in un'espressione di calcolo per aggiungere il risultato di una data espressione di calcolo a una raccolta di risultati per l'espressione di calcolo contenitore. |
Alcune parole chiave riservate provenivano dalla lingua OCaml -
asr | terra | lor | lsl | lsr | lxor | mod | sig |
Alcune altre parole chiave riservate vengono conservate per la futura espansione di F #.
atomico | rompere | controllato | componente | const | vincolo | constructor |
continue | eager | event | external | fixed | functor | include |
method | mixin | object | parallel | process | protected | pure |
sealed | tailcall | trait | virtual | volatile |
Comments in F#
F# provides two types of comments −
- One line comment starts with // symbol.
- Multi line comment starts with (* and ends with *).
A Basic Program and Application Entry Point in F#
Generally, you don’t have any explicit entry point for F# programs. When you compile an F# application, the last file provided to the compiler becomes the entry point and all top level statements in that file are executed from top to bottom.
A well-written program should have a single top-level statement that would call the main loop of the program.
A very minimalistic F# program that would display ‘Hello World’ on the screen −
(* This is a comment *)
(* Sample Hello World program using F# *)
printfn "Hello World!"
When you compile and execute the program, it yields the following output −
Hello World!
The data types in F# can be classified as follows −
- Integral types
- Floating point types
- Text types
- Other types
Integral Data Type
The following table provides the integral data types of F#. These are basically integer data types.
F# Type | Size | Range | Example | Remarks |
---|---|---|---|---|
sbyte | 1 byte | -128 to 127 | 42y -11y |
8-bit signed integer |
byte | 1 byte | 0 to 255 | 42uy 200uy |
8-bit unsigned integer |
int16 | 2 bytes | -32768 to 32767 | 42s -11s |
16-bit signed integer |
uint16 | 2 bytes | 0 to 65,535 | 42us 200us |
16-bit unsigned integer |
int/int32 | 4 bytes | -2,147,483,648 to 2,147,483,647 | 42 -11 |
32-bit signed integer |
uint32 | 4 bytes | 0 to 4,294,967,295 | 42u 200u |
32-bit unsigned integer |
int64 | 8 bytes | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | 42L -11L |
64-bit signed integer |
uint64 | 8 bytes | 0 to 18,446,744,073,709,551,615 | 42UL 200UL |
64-bit unsigned integer |
bigint | At least 4 bytes | any integer | 42I 1499999 9999999 9999999 9999999 9999I |
arbitrary precision integer |
Example
(* single byte integer *)
let x = 268.97f
let y = 312.58f
let z = x + y
printfn "x: %f" x
printfn "y: %f" y
printfn "z: %f" z
(* unsigned 8-bit natural number *)
let p = 2uy
let q = 4uy
let r = p + q
printfn "p: %i" p
printfn "q: %i" q
printfn "r: %i" r
(* signed 16-bit integer *)
let a = 12s
let b = 24s
let c = a + b
printfn "a: %i" a
printfn "b: %i" b
printfn "c: %i" c
(* signed 32-bit integer *)
let d = 212l
let e = 504l
let f = d + e
printfn "d: %i" d
printfn "e: %i" e
printfn "f: %i" f
When you compile and execute the program, it yields the following output −
x: 1
y: 2
z: 3
p: 2
q: 4
r: 6
a: 12
b: 24
c: 36
d: 212
e: 504
f: 716
Floating Point Data Types
The following table provides the floating point data types of F#.
F# Type | Size | Range | Example | Remarks |
---|---|---|---|---|
float32 | 4 bytes | ±1.5e-45 to ±3.4e38 | 42.0F -11.0F |
32-bit signed floating point number (7 significant digits) |
float | 8 bytes | ±5.0e-324 to ±1.7e308 | 42.0 -11.0 |
64-bit signed floating point number (15-16 significant digits) |
decimal | 16 bytes | ±1.0e-28 to ±7.9e28 | 42.0M -11.0M |
128-bit signed floating point number (28-29 significant digits) |
BigRational | At least 4 bytes | Any rational number. | 42N -11N |
Arbitrary precision rational number. Using this type requires a reference to FSharp.PowerPack.dll. |
Example
(* 32-bit signed floating point number *)
(* 7 significant digits *)
let d = 212.098f
let e = 504.768f
let f = d + e
printfn "d: %f" d
printfn "e: %f" e
printfn "f: %f" f
(* 64-bit signed floating point number *)
(* 15-16 significant digits *)
let x = 21290.098
let y = 50446.768
let z = x + y
printfn "x: %g" x
printfn "y: %g" y
printfn "z: %g" z
When you compile and execute the program, it yields the following output −
d: 212.098000
e: 504.768000
f: 716.866000
x: 21290.1
y: 50446.8
z: 71736.9
Text Data Types
The following table provides the text data types of F#.
F# Type | Size | Range | Example | Remarks |
---|---|---|---|---|
char | 2 bytes | U+0000 to U+ffff | 'x' '\t' |
Single unicode characters |
string | 20 + (2 * string's length) bytes | 0 to about 2 billion characters | "Hello" "World" |
Unicode text |
Example
let choice = 'y'
let name = "Zara Ali"
let org = "Tutorials Point"
printfn "Choice: %c" choice
printfn "Name: %s" name
printfn "Organisation: %s" org
When you compile and execute the program, it yields the following output −
Choice: y
Name: Zara Ali
Organisation: Tutorials Point
Other Data Types
The following table provides some other data types of F#.
F# Type | Size | Range | Example | Remarks |
---|---|---|---|---|
bool | 1 byte | Only two possible values, true or false | true false |
Stores boolean values |
Example
let trueVal = true
let falseVal = false
printfn "True Value: %b" (trueVal)
printfn "False Value: %b" (falseVal)
When you compile and execute the program, it yields the following output −
True Value: true
False Value: false
A variable is a name given to a storage area that our programs can manipulate. Each variable has a specific type, which determines the size and layout of the variable's memory; the range of values that can be stored within that memory; and the set of operations that can be applied to the variable.
Variable Declaration in F#
The let keyword is used for variable declaration −
For example,
let x = 10
It declares a variable x and assigns the value 10 to it.
You can also assign an expression to a variable −
let x = 10
let y = 20
let z = x + y
The following example illustrates the concept −
Example
let x = 10
let y = 20
let z = x + y
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z
When you compile and execute the program, it yields the following output −
x: 10
y: 20
z: 30
Variables in F# are immutable, which means once a variable is bound to a value, it can’t be changed. They are actually compiled as static read-only properties.
The following example demonstrates this.
Example
let x = 10
let y = 20
let z = x + y
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z
let x = 15
let y = 20
let z = x + y
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z
When you compile and execute the program, it shows the following error message −
Duplicate definition of value 'x'
Duplicate definition of value 'Y'
Duplicate definition of value 'Z'
Variable Definition With Type Declaration
A variable definition tells the compiler where and how much storage for the variable should be created. A variable definition may specify a data type and contains a list of one or more variables of that type as shown in the following example.
Example
let x:int32 = 10
let y:int32 = 20
let z:int32 = x + y
printfn "x: %d" x
printfn "y: %d" y
printfn "z: %d" z
let p:float = 15.99
let q:float = 20.78
let r:float = p + q
printfn "p: %g" p
printfn "q: %g" q
printfn "r: %g" r
When you compile and execute the program, it shows the following error message −
x: 10
y: 20
z: 30
p: 15.99
q: 20.78
r: 36.77
Mutable Variables
At times you need to change the values stored in a variable. To specify that there could be a change in the value of a declared and assigned variable, in later part of a program, F# provides the mutable keyword. You can declare and assign mutable variables using this keyword, whose values you will change.
The mutable keyword allows you to declare and assign values in a mutable variable.
You can assign some initial value to a mutable variable using the let keyword. However, to assign new subsequent value to it, you need to use the ← operator.
For example,
let mutable x = 10
x ← 15
The following example will clear the concept −
Example
let mutable x = 10
let y = 20
let mutable z = x + y
printfn "Original Values:"
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z
printfn "Let us change the value of x"
printfn "Value of z will change too."
x <- 15
z <- x + y
printfn "New Values:"
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z
When you compile and execute the program, it yields the following output −
Original Values:
x: 10
y: 20
z: 30
Let us change the value of x
Value of z will change too.
New Values:
x: 15
y: 20
z: 35
An operator is a symbol that tells the compiler to perform specific mathematical or logical manipulations. F# is rich in built-in operators and provides the following types of operators −
- Arithmetic Operators
- Comparison Operators
- Boolean Operators
- Bitwise Operators
Arithmetic Operators
The following table shows all the arithmetic operators supported by F# language. Assume variable A holds 10 and variable B holds 20 then −
Show Example
Operator | Description | Example |
---|---|---|
+ | Adds two operands | A + B will give 30 |
- | Subtracts second operand from the first | A - B will give -10 |
* | Multiplies both operands | A * B will give 200 |
/ | Divides numerator by de-numerator | B / A will give 2 |
% | Modulus Operator and remainder of after an integer division | B % A will give 0 |
** | Exponentiation Operator, raises an operand to the power of another | B**A will give 2010 |
Comparison Operators
The following table shows all the comparison operators supported by F# language. These binary comparison operators are available for integral and floating-point types. These operators return values of type bool.
Assume variable A holds 10 and variable B holds 20, then −
Show Example
Operator | Description | Example |
---|---|---|
= | Checks if the values of two operands are equal or not, if yes then condition becomes true. | (A == B) is not true. |
<> | Checks if the values of two operands are equal or not, if values are not equal then condition becomes true. | (A <> B) is true. |
> | Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. | (A > B) is not true. |
< | Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. | (A < B) is true. |
>= | Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. | (A >= B) is not true. |
<= | Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. | (A <= B) is true. |
Boolean Operators
The following table shows all the Boolean operators supported by F# language. Assume variable A holds true and variable B holds false, then −
Show Example
Operator | Description | Example |
---|---|---|
&& | Called Boolean AND operator. If both the operands are non-zero, then condition becomes true. | (A && B) is false. |
|| | Called Boolean OR Operator. If any of the two operands is non-zero, then condition becomes true. | (A || B) is true. |
not | Called Boolean NOT Operator. Use to reverses the logical state of its operand. If a condition is true then Logical NOT operator will make false. | not (A && B) is true. |
Bitwise Operators
Bitwise operators work on bits and perform bit-by-bit operation. The truth tables for &&& (bitwise AND), ||| (bitwise OR), and ^^^ (bitwise exclusive OR) are as follows −
Show Example
p | q | p &&& q | p ||| q | p ^^^ q |
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
Assume if A = 60; and B = 13; now in binary format they will be as follows −
A = 0011 1100
B = 0000 1101
A&&&B = 0000 1100
A|||B = 0011 1101
A^^^B = 0011 0001
~~~A = 1100 0011
The Bitwise operators supported by F# language are listed in the following table. Assume variable A holds 60 and variable B holds 13, then −
Operator | Description | Example |
---|---|---|
&&& | Binary AND Operator copies a bit to the result if it exists in both operands. | (A &&& B) will give 12, which is 0000 1100 |
||| | Binary OR Operator copies a bit if it exists in either operand. | (A ||| B) will give 61, which is 0011 1101 |
^^^ | Binary XOR Operator copies the bit if it is set in one operand but not both. | (A ^^^ B) will give 49, which is 0011 0001 |
~~~ | Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. | (~~~A) will give -61, which is 1100 0011 in 2's complement form. |
<<< | Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. | A <<< 2 will give 240 which is 1111 0000 |
>>> | Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. | A >>> 2 will give 15 which is 0000 1111 |
Operators Precedence
The following table shows the order of precedence of operators and other expression keywords in the F# language, from lowest precedence to the highest precedence.
Show Example
Operator | Associativity |
---|---|
as | Right |
when | Right |
| (pipe) | Left |
; | Right |
let | Non associative |
function, fun, match, try | Non associative |
if | Non associative |
→ | Right |
:= | Right |
, | Non associative |
or, || | Left |
&, && | Left |
< op, >op, =, |op, &op | Left |
&&& , |||, ^^^, ~~~, <<<, >>> | Left |
^ op | Right |
:: | Right |
:?>, :? | Non associative |
- op, +op, (binary) | Left |
* op, /op, %op | Left |
** op | Right |
f x (function application) | Left |
| (pattern match) | Right |
prefix operators (+op, -op, %, %%, &, &&, !op, ~op) | Left |
. | Left |
f(x) | Left |
f<types> | Left |
Decision making structures require that the programmer specify one or more conditions to be evaluated or tested by the program. It should be along with a statement or statements to be executed if the condition is determined to be true, and optionally, other statements to be executed if the condition is determined to be false.
Following is the general form of a typical decision making structure found in most of the programming languages −
F# programming language provides the following types of decision making statements.
Statement | Description |
---|---|
if /then statement | An if/then statement consists of a Boolean expression followed by one or more statements. |
if/then/ else statement | An if/then statement can be followed by an optional else statement, which executes when the Boolean expression is false. |
if/then/elif/else statement | An if/then/elif/else statement allows you to have multiple else branches. |
nested if statements | You can use one if or else if statement inside another if or else if statement(s). |
Programming languages provide various control structures that allow for more complicated execution paths.
A loop statement allows us to execute a statement or group of statements multiple times and following is the general form of a loop statement in most of the programming languages −
F# provides the following types of loops to handle the looping requirements.
Loop Type | Description |
---|---|
for… to and for… downto expressions | The for...to expression is used to iterate in a loop over a range of values of a loop variable. The for… downto expression reduces the value of loop variable. |
for … in expression | This form of for loop is used to iterate over collections of items i.e., loops over collections and sequences |
While…do loop | Repeats a statement or group of statements while a given condition is true. It tests the condition before executing the loop body. |
nested loops | You can use one or more loop inside any other for or while loop. |
In F#, functions work like data types. You can declare and use a function in the same way like any other variable.
Since functions can be used like any other variables, you can −
- Create a function, with a name and associate that name with a type.
- Assign it a value.
- Perform some calculation on that value.
- Pass it as a parameter to another function or sub-routine.
- Return a function as the result of another function.
Defining a Function
Functions are defined by using the let keyword. A function definition has the following syntax −
let [inline] function-name parameter-list [ : return-type ]
= function-body
Where,
function-name is an identifier that represents the function.
parameter-list gives the list of parameters separated by spaces. You can also specify an explicit type for each parameter and if not specified compiler tends to deduce it from the function body (like variables).
function-body consists of an expression, or a compound expression consisting of a number of expressions. The final expression in the function body is the return value.
return-type is a colon followed by a type and is optional. If the return type is not specified, then the compiler determines it from the final expression in the function body.
Parameters of a Function
You list the names of parameters right after the function name. You can specify the type of a parameter. The type of the parameter should follow the name of the parameter separated by a colon.
If no parameter type is specified, it is inferred by the compiler.
For example −
let doubleIt (x : int) = 2 * x
Calling a Function
A function is called by specifying the function name followed by a space and then any arguments separated by spaces.
For example −
let vol = cylinderVolume 3.0 5.0
The following programs illustrate the concepts.
Example 1
The following program calculates the volume of a cylinder when the radius and length are given as parameters
// the function calculates the volume of
// a cylinder with radius and length as parameters
let cylinderVolume radius length : float =
// function body
let pi = 3.14159
length * pi * radius * radius
let vol = cylinderVolume 3.0 5.0
printfn " Volume: %g " vol
When you compile and execute the program, it yields the following output −
Volume: 141.372
Example 2
The following program returns the larger value of two given parameters −
// the function returns the larger value between two
// arguments
let max num1 num2 : int32 =
// function body
if(num1>num2)then
num1
else
num2
let res = max 39 52
printfn " Max Value: %d " res
When you compile and execute the program, it yields the following output −
Max Value: 52
Example 3
let doubleIt (x : int) = 2 * x
printfn "Double 19: %d" ( doubleIt(19))
When you compile and execute the program, it yields the following output −
Double 19: 38
Recursive Functions
Recursive functions are functions that call themselves.
You define a recursive using the let rec keyword combination.
Syntax for defining a recursive function is −
//Recursive function definition
let rec function-name parameter-list = recursive-function-body
For example −
let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)
Example 1
The following program returns Fibonacci 1 to 10 −
let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)
for i = 1 to 10 do
printfn "Fibonacci %d: %d" i (fib i)
When you compile and execute the program, it yields the following output −
Fibonacci 1: 1
Fibonacci 2: 2
Fibonacci 3: 3
Fibonacci 4: 5
Fibonacci 5: 8
Fibonacci 6: 13
Fibonacci 7: 21
Fibonacci 8: 34
Fibonacci 9: 55
Fibonacci 10: 89
Example 2
The following program returns factorial 8 −
open System
let rec fact x =
if x < 1 then 1
else x * fact (x - 1)
Console.WriteLine(fact 8)
When you compile and execute the program, it yields the following output −
40320
Arrow Notations in F#
F# reports about data type in functions and values, using a chained arrow notation. Let us take an example of a function that takes one int input, and returns a string. In arrow notation, it is written as −
int -> string
Data types are read from left to right.
Let us take another hypothetical function that takes two int data inputs and returns a string.
let mydivfunction x y = (x / y).ToString();;
F# reports the data type using chained arrow notation as −
val mydivfunction : x:int -> y:int -> string
The return type is represented by the rightmost data type in chained arrow notation.
Some more examples −
Notation | Meaning |
---|---|
float → float → float | The function takes two float inputs, returns another float. |
int → string → float | The function takes an int and a string input, returns a float. |
Lambda Expressions
A lambda expression is an unnamed function.
Let us take an example of two functions −
let applyFunction ( f: int -> int -> int) x y = f x y
let mul x y = x * y
let res = applyFunction mul 5 7
printfn "%d" res
When you compile and execute the program, it yields the following output −
35
Now in the above example, if instead of defining the function mul, we could have used lambda expressions as −
let applyFunction ( f: int -> int -> int) x y = f x y
let res = applyFunction (fun x y -> x * y ) 5 7
printfn "%d" res
When you compile and execute the program, it yields the following output −
35
Function Composition and Pipelining
In F#, one function can be composed from other functions.
The following example shows the composition of a function named f, from two functions function1 and function2 −
let function1 x = x + 1
let function2 x = x * 5
let f = function1 >> function2
let res = f 10
printfn "%d" res
When you compile and execute the program, it yields the following output −
55
F# also provides a feature called pipelining of functions. Pipelining allows function calls to be chained together as successive operations.
The following example shows that −
let function1 x = x + 1
let function2 x = x * 5
let res = 10 |> function1 |> function2
printfn "%d" res
When you compile and execute the program, it yields the following output −
55
In F#, the string type represents immutable text as a sequence of Unicode characters.
String Literals
String literals are delimited by the quotation mark (") character.
Some special characters are there for special uses like newline, tab, etc. They are encoded using backslash (\) character. The backslash character and the related character make the escape sequence. The following table shows the escape sequence supported by F#.
Character | Escape sequence |
---|---|
Backspace | \b |
Newline | \n |
Carriage return | \r |
Tab | \t |
Backslash | \\ |
Quotation mark | \" |
Apostrophe | \' |
Unicode character | \uXXXX or \UXXXXXXXX (where X indicates a hexadecimal digit) |
Ways of lgnoring the Escape Sequence
The following two ways makes the compiler ignore the escape sequence −
- Using the @ symbol.
- Enclosing the string in triple quotes.
When a string literal is preceded by the @ symbol, it is called a verbatim string. In that way, all escape sequences in the string are ignored, except that two quotation mark characters are interpreted as one quotation mark character.
When a string is enclosed by triple quotes, then also all escape sequences are ignored, including double quotation mark characters.
Example
The following example demonstrates this technique showing how to work with XML or other structures that include embedded quotation marks −
// Using a verbatim string
let xmldata = @"<book author=""Lewis, C.S"" title=""Narnia"">"
printfn "%s" xmldata
When you compile and execute the program, it yields the following output −
<book author="Lewis, C.S" title="Narnia">
Basic Operators on Strings
The following table shows the basic operations on strings −
Value | Description |
---|---|
collect : (char → string) → string → string | Creates a new string whose characters are the results of applying a specified function to each of the characters of the input string and concatenating the resulting strings. |
concat : string → seq<string> → string | Returns a new string made by concatenating the given strings with a separator. |
exists : (char → bool) → string → bool | Tests if any character of the string satisfies the given predicate. |
forall : (char → bool) → string → bool | Tests if all characters in the string satisfy the given predicate. |
init : int → (int → string) → string | Creates a new string whose characters are the results of applying a specified function to each index and concatenating the resulting strings. |
iter : (char → unit) → string → unit | Applies a specified function to each character in the string. |
iteri : (int → char → unit) → string → unit | Applies a specified function to the index of each character in the string and the character itself. |
length : string → int | Returns the length of the string. |
map : (char → char) → string → string | Creates a new string whose characters are the results of applying a specified function to each of the characters of the input string. |
mapi : (int → char → char) → string → string | Creates a new string whose characters are the results of applying a specified function to each character and index of the input string. |
replicate : int → string → string | Returns a string by concatenating a specified number of instances of a string. |
The following examples demonstrate the uses of some of the above functionalities −
Example 1
The String.collect function builds a new string whose characters are the results of applying a specified function to each of the characters of the input string and concatenating the resulting strings.
let collectTesting inputS =
String.collect (fun c -> sprintf "%c " c) inputS
printfn "%s" (collectTesting "Happy New Year!")
When you compile and execute the program, it yields the following output −
H a p p y N e w Y e a r !
Example 2
The String.concat function concatenates a given sequence of strings with a separator and returns a new string.
let strings = [ "Tutorials Point"; "Coding Ground"; "Absolute Classes" ]
let ourProducts = String.concat "\n" strings
printfn "%s" ourProducts
When you compile and execute the program, it yields the following output −
Tutorials Point
Coding Ground
Absolute Classes
Example 3
The String.replicate method returns a string by concatenating a specified number of instances of a string.
printfn "%s" <| String.replicate 10 "*! "
When you compile and execute the program, it yields the following output −
*! *! *! *! *! *! *! *! *! *!
The option type in F# is used in calculations when there may or may not exist a value for a variable or function. Option types are used for representing optional values in calculations. They can have two possible values − Some(x) or None.
For example, a function performing a division will return a value in normal situation, but will throw exceptions in case of a zero denominator. Using options here will help to indicate whether the function has succeeded or failed.
An option has an underlying type and can hold a value of that type, or it might not have a value.
Using Options
Let us take the example of division function. The following program explains this −
Let us write a function div, and send two arguments to it 20 and 5 −
let div x y = x / y
let res = div 20 5
printfn "Result: %d" res
When you compile and execute the program, it yields the following output −
Result: 4
If the second argument is zero, then the program throws an exception −
let div x y = x / y
let res = div 20 0
printfn "Result: %d" res
When you compile and execute the program, it yields the following output −
Unhandled Exception:
System.DivideByZeroException: Division by zero
In such cases, we can use option types to return Some (value) when the operation is successful or None if the operation fails.
The following example demonstrates the use of options −
Example
let div x y =
match y with
| 0 -> None
| _ -> Some(x/y)
let res : int option = div 20 4
printfn "Result: %A " res
When you compile and execute the program, it yields the following output −
Result: Some 5
Option Properties and Methods
The option type supports the following properties and methods −
Property or method | Type | Description |
---|---|---|
None | 'T option | A static property that enables you to create an option value that has the None value. |
IsNone | bool | Returns true if the option has the None value. |
IsSome | bool | Returns true if the option has a value that is not None. |
Some | 'T option | A static member that creates an option that has a value that is not None. |
Value | 'T | Returns the underlying value, or throws a NullReferenceException if the value is None. |
Example 1
let checkPositive (a : int) =
if a > 0 then
Some(a)
else
None
let res : int option = checkPositive(-31)
printfn "Result: %A " res
When you compile and execute the program, it yields the following output −
Result: <null>
Example 2
let div x y =
match y with
| 0 -> None
| _ -> Some(x/y)
let res : int option = div 20 4
printfn "Result: %A " res
printfn "Result: %A " res.Value
When you compile and execute the program, it yields the following output −
Result: Some 5
Result: 5
Example 3
let isHundred = function
| Some(100) -> true
| Some(_) | None -> false
printfn "%A" (isHundred (Some(45)))
printfn "%A" (isHundred (Some(100)))
printfn "%A" (isHundred None)
When you compile and execute the program, it yields the following output −
false
true
false
UN tupleè una raccolta di valori separati da virgole. Questi vengono utilizzati per creare strutture di dati ad hoc, che raggruppano i valori correlati.
Ad esempio, ("Zara Ali", "Hyderabad", 10) è una tupla tripla con due valori stringa e un valore int, ha il tipo (string * string * int).
Le tuple possono essere coppie, triple e così via, dello stesso tipo o di tipi diversi.
Alcuni esempi sono forniti qui -
// Tuple of two integers.
( 4, 5 )
// Triple of strings.
( "one", "two", "three" )
// Tuple of unknown types.
( a, b )
// Tuple that has mixed types.
( "Absolute Classes", 1, 2.0 )
// Tuple of integer expressions.
( a * 4, b + 7)
Esempio
Questo programma ha una funzione che accetta una tupla di quattro valori float e restituisce la media -
let averageFour (a, b, c, d) =
let sum = a + b + c + d
sum / 4.0
let avg:float = averageFour (4.0, 5.1, 8.0, 12.0)
printfn "Avg of four numbers: %f" avg
Quando compili ed esegui il programma, restituisce il seguente output:
Avg of four numbers: 7.275000
Accesso ai singoli membri della tupla
I singoli membri di una tupla possono essere valutati e stampati utilizzando il pattern matching.
L'esempio seguente illustra il concetto:
Esempio
let display tuple1 =
match tuple1 with
| (a, b, c) -> printfn "Detail Info: %A %A %A" a b c
display ("Zara Ali", "Hyderabad", 10 )
Quando compili ed esegui il programma, restituisce il seguente output:
Detail Info: "Zara Ali" "Hyderabad" 10
F # ha due funzioni incorporate, fst e snd, che restituiscono il primo e il secondo elemento in una doppia tupla.
L'esempio seguente illustra il concetto:
Esempio
printfn "First member: %A" (fst(23, 30))
printfn "Second member: %A" (snd(23, 30))
printfn "First member: %A" (fst("Hello", "World!"))
printfn "Second member: %A" (snd("Hello", "World!"))
let nameTuple = ("Zara", "Ali")
printfn "First Name: %A" (fst nameTuple)
printfn "Second Name: %A" (snd nameTuple)
Quando compili ed esegui il programma, restituisce il seguente output:
First member: 23
Second member: 30
First member: "Hello"
Second member: "World!"
First Name: "Zara"
Second Name: "Ali"
UN recordè simile a una tupla, tuttavia contiene campi denominati. Per esempio,
type website =
{ title : string;
url : string }
Definizione del record
Un record è definito come un tipo utilizzando l'estensione type parola chiave ei campi del record sono definiti come un elenco separato da punti e virgola.
La sintassi per la definizione di un record è:
type recordName =
{ [ fieldName : dataType ] + }
Creazione di un record
È possibile creare un record specificando i campi del record. Ad esempio, creiamo un record del sito web denominato homepage -
let homepage = { Title = "TutorialsPoint"; Url = "www.tutorialspoint.com" }
I seguenti esempi spiegheranno i concetti:
Esempio 1
Questo programma definisce un tipo di record denominato sito web. Quindi crea alcuni record di tipo website e stampa i record.
(* defining a record type named website *)
type website =
{ Title : string;
Url : string }
(* creating some records *)
let homepage = { Title = "TutorialsPoint"; Url = "www.tutorialspoint.com" }
let cpage = { Title = "Learn C"; Url = "www.tutorialspoint.com/cprogramming/index.htm" }
let fsharppage = { Title = "Learn F#"; Url = "www.tutorialspoint.com/fsharp/index.htm" }
let csharppage = { Title = "Learn C#"; Url = "www.tutorialspoint.com/csharp/index.htm" }
(*printing records *)
(printfn "Home Page: Title: %A \n \t URL: %A") homepage.Title homepage.Url
(printfn "C Page: Title: %A \n \t URL: %A") cpage.Title cpage.Url
(printfn "F# Page: Title: %A \n \t URL: %A") fsharppage.Title fsharppage.Url
(printfn "C# Page: Title: %A \n \t URL: %A") csharppage.Title csharppage.Url
Quando compili ed esegui il programma, restituisce il seguente output:
Home Page: Title: "TutorialsPoint"
URL: "www.tutorialspoint.com"
C Page: Title: "Learn C"
URL: "www.tutorialspoint.com/cprogramming/index.htm"
F# Page: Title: "Learn F#"
URL: "www.tutorialspoint.com/fsharp/index.htm"
C# Page: Title: "Learn C#"
URL: "www.tutorialspoint.com/csharp/index.htm"
Esempio 2
type student =
{ Name : string;
ID : int;
RegistrationText : string;
IsRegistered : bool }
let getStudent name id =
{ Name = name; ID = id; RegistrationText = null; IsRegistered = false }
let registerStudent st =
{ st with
RegistrationText = "Registered";
IsRegistered = true }
let printStudent msg st =
printfn "%s: %A" msg st
let main() =
let preRegisteredStudent = getStudent "Zara" 10
let postRegisteredStudent = registerStudent preRegisteredStudent
printStudent "Before Registration: " preRegisteredStudent
printStudent "After Registration: " postRegisteredStudent
main()
Quando compili ed esegui il programma, restituisce il seguente output:
Before Registration: : {Name = "Zara";
ID = 10;
RegistrationText = null;
IsRegistered = false;}
After Registration: : {Name = "Zara";
ID = 10;
RegistrationText = "Registered";
IsRegistered = true;}
In F #, un elenco è una serie ordinata e immutabile di elementi dello stesso tipo. In una certa misura è equivalente a una struttura dati di un elenco collegato.
Il modulo F #, Microsoft.FSharp.Collections.List,ha le operazioni comuni sugli elenchi. Tuttavia F # importa questo modulo automaticamente e lo rende accessibile a ogni applicazione F #.
Creazione e inizializzazione di un elenco
Di seguito sono riportati i vari modi per creare elenchi:
Utilizzando list literals.
Utilizzando cons (: :) operatore.
Usando il List.init metodo del modulo List.
Usandone alcuni syntactic constructs chiamato List Comprehensions.
List Literals
In questo metodo, è sufficiente specificare una sequenza di valori delimitati da punto e virgola tra parentesi quadre. Ad esempio:
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
I contro (: :) Operator
Con questo metodo, puoi aggiungere alcuni valori anteponendo o cons-ingin un elenco esistente utilizzando l'operatore ::. Ad esempio:
let list2 = 1::2::3::4::5::6::7::8::9::10::[];;
[] denota un elenco vuoto.
Metodo di inizializzazione dell'elenco
Il metodo List.init del modulo List viene spesso utilizzato per creare elenchi. Questo metodo ha il tipo -
val init : int -> (int -> 'T) -> 'T list
Il primo argomento è la lunghezza desiderata del nuovo elenco e il secondo argomento è una funzione di inizializzazione, che genera elementi nell'elenco.
Per esempio,
let list5 = List.init 5 (fun index -> (index, index * index, index * index * index))
Qui, la funzione index genera l'elenco.
Comprensioni dell'elenco
Le comprensioni di elenchi sono costrutti sintattici speciali utilizzati per la generazione di elenchi.
La sintassi di comprensione dell'elenco F # è disponibile in due forme: intervalli e generatori.
Gli intervalli hanno i costrutti - [inizio .. fine] e [inizio .. passo .. fine]
Per esempio,
let list3 = [1 .. 10]
I generatori hanno il costrutto - [for x in collection do ... yield expr]
Per esempio,
let list6 = [ for a in 1 .. 10 do yield (a * a) ]
Come la yield parola chiave inserisce un singolo valore in un elenco, la parola chiave, yield!, inserisce una raccolta di valori nell'elenco.
La seguente funzione mostra i metodi precedenti:
Esempio
(* using list literals *)
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The list: %A" list1
(*using cons operator *)
let list2 = 1 :: 2 :: 3 :: []
printfn "The list: %A" list2
(* using range constructs*)
let list3 = [1 .. 10]
printfn "The list: %A" list3
(* using range constructs *)
let list4 = ['a' .. 'm']
printfn "The list: %A" list4
(* using init method *)
let list5 = List.init 5 (fun index -> (index, index * index, index * index * index))
printfn "The list: %A" list5
(* using yield operator *)
let list6 = [ for a in 1 .. 10 do yield (a * a) ]
printfn "The list: %A" list6
(* using yield operator *)
let list7 = [ for a in 1 .. 100 do if a % 3 = 0 && a % 5 = 0 then yield a]
printfn "The list: %A" list7
(* using yield! operator *)
let list8 = [for a in 1 .. 3 do yield! [ a .. a + 3 ] ]
printfn "The list: %A" list8
Quando compili ed esegui il programma, restituisce il seguente output:
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The list: [1; 2; 3]
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The list: ['a'; 'b'; 'c'; 'd'; 'e'; 'f'; 'g'; 'h'; 'i'; 'j'; 'k'; 'l'; 'm']
The list: [(0, 0, 0); (1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64)]
The list: [1; 4; 9; 16; 25; 36; 49; 64; 81; 100]
The list: [15; 30; 45; 60; 75; 90]
The list: [1; 2; 3; 4; 2; 3; 4; 5; 3; 4; 5; 6]
Proprietà del tipo di dati elenco
La tabella seguente mostra varie proprietà del tipo di dati elenco:
Proprietà | genere | Descrizione |
---|---|---|
Testa | 'T | Il primo elemento. |
Vuoto | 'T elenco | Una proprietà statica che restituisce un elenco vuoto del tipo appropriato. |
È vuoto | bool | true se l'elenco non ha elementi. |
Articolo | 'T | L'elemento all'indice specificato (in base zero). |
Lunghezza | int | Il numero di elementi. |
Coda | 'T elenco | L'elenco senza il primo elemento. |
L'esempio seguente mostra l'uso di queste proprietà:
Esempio
let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
// Use of Properties
printfn "list1.IsEmpty is %b" (list1.IsEmpty)
printfn "list1.Length is %d" (list1.Length)
printfn "list1.Head is %d" (list1.Head)
printfn "list1.Tail.Head is %d" (list1.Tail.Head)
printfn "list1.Tail.Tail.Head is %d" (list1.Tail.Tail.Head)
printfn "list1.Item(1) is %d" (list1.Item(1))
Quando compili ed esegui il programma, restituisce il seguente output:
list1.IsEmpty is false
list1.Length is 8
list1.Head is 2
list1.Tail.Head is 4
list1.Tail.Tail.Head is 6
list1.Item(1) is 4
Operatori di base in elenco
La tabella seguente mostra le operazioni di base sul tipo di dati dell'elenco:
Valore | Descrizione |
---|---|
append: 'T list →' T list → 'T list | Restituisce un nuovo elenco che contiene gli elementi del primo elenco seguito dagli elementi del secondo. |
media: lista 'T → ^ T | Restituisce la media degli elementi nell'elenco. |
averageBy: ('T → ^ U) →' T list → ^ U | Restituisce la media degli elementi generati applicando la funzione a ogni elemento della lista. |
scegli: (opzione 'T →' U) → lista 'T → lista' U | Applica la funzione data a ogni elemento dell'elenco. Restituisce l'elenco composto dai risultati per ogni elemento in cui restituisce la funzioneSome. |
collect: ('T →' U list) → 'T list →' U list | Per ogni elemento della lista, applica la funzione data. Concatena tutti i risultati e restituisce l'elenco combinato. |
concat: seq <'T lista> →' T lista | Restituisce un nuovo elenco che contiene gli elementi di ciascuno degli elenchi in ordine. |
vuoto: lista 'T | Restituisce un elenco vuoto del tipo specificato. |
esiste: ('T → bool) →' T list → bool | Verifica se un qualsiasi elemento della lista soddisfa il predicato dato. |
esiste2: ('T1 →' T2 → bool) → 'T1 list →' T2 list → bool | Verifica se una qualsiasi coppia di elementi corrispondenti delle liste soddisfa il predicato dato. |
filtro: ('T → bool) →' T lista → 'T lista | Restituisce una nuova raccolta contenente solo gli elementi della raccolta per cui restituisce il predicato specificato true. |
trova: ('T → bool) →' T list → 'T | Restituisce il primo elemento per il quale restituisce la funzione data true. |
findIndex: ('T → bool) →' T list → int | Restituisce l'indice del primo elemento nell'elenco che soddisfa il predicato dato. |
fold: ('State →' T → 'State) →' State → 'T list →' State | Applica una funzione a ogni elemento della raccolta, inserendo un argomento dell'accumulatore attraverso il calcolo. Questa funzione accetta il secondo argomento e applica la funzione ad esso e al primo elemento della lista. Quindi, passa questo risultato alla funzione insieme al secondo elemento e così via. Infine, restituisce il risultato finale. Se la funzione di input è f e gli elementi sono i0 ... iN, questa funzione calcola f (... (fs i0) i1 ...) iN. |
fold2: ('State →' T1 → 'T2 →' State) → 'State →' T1 list → 'T2 list →' State | Applica una funzione agli elementi corrispondenti di due raccolte, inserendo un argomento dell'accumulatore attraverso il calcolo. Le collezioni devono avere dimensioni identiche. Se la funzione di input è f e gli elementi sono i0 ... iN e j0 ... jN, questa funzione calcola f (... (fs i0 j0) ...) iN jN. |
foldBack: ('T →' State → 'State) →' T list → 'State →' State | Applica una funzione a ogni elemento della raccolta, inserendo un argomento dell'accumulatore attraverso il calcolo. Se la funzione di input isf e gli elementi sono i0 ... iN, calcola f i0 (... (f iN s)). |
foldBack2: ('T1 →' T2 → 'State →' State) → 'T1 list →' T2 list → 'State →' State | Applica una funzione agli elementi corrispondenti di due raccolte, inserendo un argomento dell'accumulatore attraverso il calcolo. Le collezioni devono avere dimensioni identiche. Se la funzione di input è f e gli elementi sono i0 ... iN e j0 ... jN, questa funzione calcola f i0 j0 (... (f iN jN s)). |
forall: ('T → bool) →' T list → bool | Verifica se tutti gli elementi della raccolta soddisfano il predicato specificato. |
forall2: ('T1 →' T2 → bool) → 'T1 list →' T2 list → bool | Verifica se tutti gli elementi corrispondenti della raccolta soddisfano a coppie il predicato specificato. |
head: 'T lista →' T | Restituisce il primo elemento della lista. |
init: int → (int → 'T) →' T list | Crea un elenco chiamando il generatore specificato su ogni indice. |
isEmpty: 'T list → bool | ritorna true se l'elenco non contiene elementi, false altrimenti. |
iter: ('T → unit) →' T list → unit | Applica la funzione data a ogni elemento della raccolta. |
iter2: ('T1 →' T2 → unit) → 'T1 list →' T2 list → unit | Applica la funzione data a due raccolte contemporaneamente. Le collezioni devono avere dimensioni identiche. |
iteri: (int → 'T → unit) →' T list → unit | Applica la funzione data a ogni elemento della raccolta. L'intero passato alla funzione indica l'indice dell'elemento. |
iteri2: (int → 'T1 →' T2 → unit) → 'T1 list →' T2 list → unit | Applica la funzione data a due raccolte contemporaneamente. Le collezioni devono avere dimensioni identiche. L'intero passato alla funzione indica l'indice dell'elemento. |
lunghezza: lista 'T → int | Restituisce la lunghezza dell'elenco. |
map: ('T →' U) → 'T list →' U list | Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data a ciascuno degli elementi della raccolta. |
map2: ('T1 →' T2 → 'U) →' T1 list → 'T2 list →' U list | Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data agli elementi corrispondenti delle due raccolte a coppie. |
map3: ('T1 →' T2 → 'T3 →' U) → 'T1 list →' T2 list → 'T3 list →' U list | Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data agli elementi corrispondenti delle tre raccolte contemporaneamente. |
mapi: (int → 'T →' U) → 'T list →' U list | Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data a ciascuno degli elementi della raccolta. L'indice intero passato alla funzione indica l'indice (da 0) dell'elemento trasformato. |
mapi2: (int → 'T1 →' T2 → 'U) →' T1 list → 'T2 list →' U list | Come List.mapi, ma mappando gli elementi corrispondenti da due elenchi di uguale lunghezza. |
max: 'T lista →' T | Restituisce il più grande di tutti gli elementi dell'elenco, confrontato utilizzando Operators.max. |
maxBy: ('T →' U) → 'T list →' T | Restituisce il più grande di tutti gli elementi dell'elenco, confrontato utilizzando Operators.max sul risultato della funzione. |
min: 'T lista →' T | Restituisce il più basso di tutti gli elementi dell'elenco, confrontato utilizzando Operators.min. |
minBy: ('T →' U) → 'T list →' T | Restituisce il più basso di tutti gli elementi dell'elenco, confrontato utilizzando Operators.min sul risultato della funzione |
nth: 'T list → int →' T | Indici nell'elenco. Il primo elemento ha indice 0. |
ofArray: 'T [] →' T list | Crea un elenco dalla matrice data. |
ofSeq: seq <'T> →' T list | Crea un nuovo elenco dall'oggetto enumerabile specificato. |
partizione: ('T → bool) →' T list * 'T list | Divide la raccolta in due raccolte, contenenti gli elementi per i quali restituisce il predicato specificato true e false rispettivamente. |
permute: (int → int) → 'T list →' T list | Restituisce un elenco con tutti gli elementi permutati secondo la permutazione specificata. |
scegli: (opzione 'T →' U) → lista 'T →' U | Applica la funzione data agli elementi successivi, restituendo il primo risultato dove la funzione ritorna Some per qualche valore. |
ridurre: ('T →' T → 'T) →' T lista → 'T | Applica una funzione a ogni elemento della raccolta, inserendo un argomento dell'accumulatore attraverso il calcolo. Questa funzione applica la funzione specificata ai primi due elementi dell'elenco. Quindi passa questo risultato alla funzione insieme al terzo elemento e così via. Infine, restituisce il risultato finale. Se la funzione di input è f e gli elementi sono i0 ... iN, questa funzione calcola f (... (f i0 i1) i2 ...) iN. |
reduceBack: ('T →' T → 'T) →' T list → 'T | Applica una funzione a ogni elemento della raccolta, inserendo un argomento dell'accumulatore attraverso il calcolo. Se la funzione di input isf e gli elementi sono i0 ... iN, questa funzione calcola f i0 (... (f iN-1 iN)). |
replicare: (int → 'T →' T lista) | Crea un elenco chiamando il generatore specificato su ogni indice. |
rev: 'T lista →' T lista | Restituisce un nuovo elenco con gli elementi in ordine inverso. |
scan: ('State →' T → 'State) →' State → 'T list →' State list | Applica una funzione a ogni elemento della raccolta, inserendo un argomento dell'accumulatore attraverso il calcolo. Questa funzione accetta il secondo argomento e applica ad esso la funzione specificata e il primo elemento dell'elenco. Quindi, passa questo risultato alla funzione insieme al secondo elemento e così via. Infine, restituisce l'elenco dei risultati intermedi e il risultato finale. |
scanBack: ('T →' State → 'State) →' T list → 'State →' State list | Come foldBack, ma restituisce sia i risultati intermedi che quelli finali |
ordina: 'T lista →' T lista | Ordina l'elenco fornito utilizzando Operators.compare. |
sortBy: ('T →' Key) → 'T list →' T list | Ordina l'elenco fornito utilizzando i tasti forniti dalla proiezione data. Le chiavi vengono confrontate utilizzando Operators.compare. |
sortWith: ('T →' T → int) → 'T list →' T list | Ordina l'elenco fornito utilizzando la funzione di confronto data. |
somma: ^ T lista → ^ T | Restituisce la somma degli elementi nell'elenco. |
sumBy: ('T → ^ U) →' T list → ^ U | Restituisce la somma dei risultati generati applicando la funzione a ogni elemento della lista. |
coda: lista 'T → lista' T | Restituisce l'elenco di input senza il primo elemento. |
toArray: 'T list →' T [] | Crea un array dall'elenco fornito. |
toSeq: 'T list → seq <' T> | Visualizza l'elenco fornito come una sequenza. |
tryFind: ('T → bool) →' T list → 'T opzione | Restituisce il primo elemento per il quale restituisce la funzione data true. RitornoNone se tale elemento non esiste. |
tryFindIndex: ('T → bool) →' T list → int opzione | Restituisce l'indice del primo elemento nell'elenco che soddisfa il predicato dato. RitornoNone se tale elemento non esiste. |
tryPick: (opzione 'T →' U) → lista 'T → opzione' U | Applica la funzione data agli elementi successivi, restituendo il primo risultato dove la funzione ritorna Someper qualche valore. Se tale elemento non esiste, ritornaNone. |
unzip: ('T1 *' T2) list → 'T1 list *' T2 list | Divide un elenco di coppie in due elenchi. |
unzip3: ('T1 *' T2 * 'T3) list →' T1 list * 'T2 list *' T3 list | Divide un elenco di triple in tre elenchi. |
zip: 'Elenco T1 →' Elenco T2 → ('T1 *' T2) elenco | Combina i due elenchi in un elenco di coppie. Le due liste devono avere la stessa lunghezza. |
zip3: 'T1 list →' T2 list → 'T3 list → (' T1 * 'T2 *' T3) list | Combina le tre liste in una lista di triple. Gli elenchi devono avere la stessa lunghezza. |
I seguenti esempi dimostrano gli usi delle funzionalità di cui sopra:
Esempio 1
Questo programma mostra l'inversione ricorsiva di un elenco:
let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
printfn "The original list: %A" list1
let reverse lt =
let rec loop acc = function
| [] -> acc
| hd :: tl -> loop (hd :: acc) tl
loop [] lt
printfn "The reversed list: %A" (reverse list1)
Quando compili ed esegui il programma, restituisce il seguente output:
The original list: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]
Tuttavia, puoi usare l'estensione rev funzione del modulo per lo stesso scopo -
let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
printfn "The original list: %A" list1
printfn "The reversed list: %A" (List.rev list1)
Quando compili ed esegui il programma, restituisce il seguente output:
The original list: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]
Esempio 2
Questo programma mostra il filtraggio di un elenco utilizzando il List.filter metodo -
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The list: %A" list1
let list2 = list1 |> List.filter (fun x -> x % 2 = 0);;
printfn "The Filtered list: %A" list2
Quando compili ed esegui il programma, restituisce il seguente output:
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The Filtered list: [2; 4; 6; 8; 10]
Esempio 3
Il List.map metodo mappa un elenco da un tipo a un altro -
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The list: %A" list1
let list2 = list1 |> List.map (fun x -> (x * x).ToString());;
printfn "The Mapped list: %A" list2
Quando compili ed esegui il programma, restituisce il seguente output:
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The Mapped list: ["1"; "4"; "9"; "16"; "25"; "36"; "49"; "64"; "81"; "100"]
Esempio 4
Il List.append metodo e l'operatore @ aggiunge un elenco a un altro -
let list1 = [1; 2; 3; 4; 5 ]
let list2 = [6; 7; 8; 9; 10]
let list3 = List.append list1 list2
printfn "The first list: %A" list1
printfn "The second list: %A" list2
printfn "The appened list: %A" list3
let lt1 = ['a'; 'b';'c' ]
let lt2 = ['e'; 'f';'g' ]
let lt3 = lt1 @ lt2
printfn "The first list: %A" lt1
printfn "The second list: %A" lt2
printfn "The appened list: %A" lt3
Quando compili ed esegui il programma, restituisce il seguente output:
The first list: [1; 2; 3; 4; 5]
The second list: [6; 7; 8; 9; 10]
The appened list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The first list: ['a'; 'b'; 'c']
The second list: ['e'; 'f'; 'g']
The appened list: ['a'; 'b'; 'c'; 'e'; 'f'; 'g']
Esempio 5
Il List.sortmetodo ordina un elenco. IlList.sum fornisce la somma degli elementi nell'elenco e il metodo List.average metodo fornisce la media degli elementi nell'elenco -
let list1 = [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0]
printfn "The list: %A" list1
let list2 = List.sort list1
printfn "The sorted list: %A" list2
let s = List.sum list1
let avg = List.average list1
printfn "The sum: %f" s
printfn "The average: %f" avg
Quando compili ed esegui il programma, restituisce il seguente output:
The list: [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0]
The sorted list: [-10.0; -4.5; 0.0; 2.0; 8.0; 9.0; 11.2]
The sum: 15.700000
The average: 2.242857
Un'operazione di "piegatura" applica una funzione a ciascun elemento in un elenco, aggrega il risultato della funzione in una variabile accumulator e restituisce l'accumulatore come risultato dell'operazione di piegatura.
Esempio 6
Il List.fold metodo applica una funzione a ciascun elemento da sinistra a destra, mentre List.foldBack applica una funzione a ogni elemento da destra a sinistra.
let sumList list = List.fold (fun acc elem -> acc + elem) 0 list
printfn "Sum of the elements of list %A is %d." [ 1 .. 10 ] (sumList [ 1 .. 10 ])
Quando compili ed esegui il programma, restituisce il seguente output:
Sum of the elements of list [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] is 55.
Le sequenze, come gli elenchi, rappresentano anche una raccolta ordinata di valori. Tuttavia, gli elementi in una sequenza o un'espressione di sequenza vengono calcolati quando richiesto. Non vengono calcolati in una volta e per questo motivo vengono utilizzati per rappresentare strutture dati infinite.
Definizione di sequenze
Le sequenze vengono definite utilizzando la seguente sintassi:
seq { expr }
Per esempio,
let seq1 = seq { 1 .. 10 }
Creazione di sequenze ed espressioni di sequenze
Analogamente agli elenchi, puoi creare sequenze utilizzando intervalli e comprensioni.
Le espressioni di sequenza sono le espressioni che puoi scrivere per creare sequenze. Questi possono essere fatti -
- Specificando l'intervallo.
- Specificando l'intervallo con incremento o decremento.
- Utilizzando il yield parola chiave per produrre valori che diventano parte della sequenza.
- Utilizzando l'operatore →.
I seguenti esempi dimostrano il concetto:
Esempio 1
(* Sequences *)
let seq1 = seq { 1 .. 10 }
(* ascending order and increment*)
printfn "The Sequence: %A" seq1
let seq2 = seq { 1 .. 5 .. 50 }
(* descending order and decrement*)
printfn "The Sequence: %A" seq2
let seq3 = seq {50 .. -5 .. 0}
printfn "The Sequence: %A" seq3
(* using yield *)
let seq4 = seq { for a in 1 .. 10 do yield a, a*a, a*a*a }
printfn "The Sequence: %A" seq4
Quando compili ed esegui il programma, restituisce il seguente output:
The Sequence: seq [1; 2; 3; 4; ...]
The Sequence: seq [1; 6; 11; 16; ...]
The Sequence: seq [50; 45; 40; 35; ...]
The Sequence: seq [(1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64); ...]
Esempio 2
Il seguente programma stampa i numeri primi da 1 a 50 -
(* Recursive isprime function. *)
let isprime n =
let rec check i =
i > n/2 || (n % i <> 0 && check (i + 1))
check 2
let primeIn50 = seq { for n in 1..50 do if isprime n then yield n }
for x in primeIn50 do
printfn "%d" x
Quando compili ed esegui il programma, restituisce il seguente output:
1
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
Operazioni di base sulla sequenza
La tabella seguente mostra le operazioni di base sul tipo di dati della sequenza:
Valore | Descrizione |
---|---|
aggiungi: seq <'T> → seq <' T> → seq <'T> | Avvolge le due enumerazioni date come un'unica enumerazione concatenata. |
media: seq <^ T> → ^ T | Restituisce la media degli elementi nella sequenza. |
averageBy: ('T → ^ U) → seq <' T> → ^ U | Restituisce la media dei risultati generati applicando la funzione a ogni elemento della sequenza. |
cache: seq <'T> → seq <' T> | Restituisce una sequenza che corrisponde a una versione memorizzata nella cache della sequenza di input. |
cast: IEnumerable → seq <'T> | Avvolge un sistema a bassa tipizzazione. Sequenza di raccolte come sequenza digitata. |
scegli: (opzione 'T →' U) → seq <'T> → seq <' U> | Applica la funzione data a ogni elemento dell'elenco. Restituisce l'elenco composto dai risultati per ogni elemento in cui restituisce la funzioneSome. |
collect: ('T →' Collection) → seq <'T> → seq <' U> | Applica la funzione data a ciascun elemento della sequenza e concatena tutti i risultati. |
compareCon: ('T →' T → int) → seq <'T> → seq <' T> → int | Confronta due sequenze utilizzando la funzione di confronto data, elemento per elemento. |
concat: seq <'Collection> → seq <' T> | Combina l'enumerazione di enumerazioni data come una singola enumerazione concatenata. |
countBy: ('T →' Key) → seq <'T> → seq <' Key * int> | Applica una funzione di generazione di chiavi a ogni elemento di una sequenza e restituisce una sequenza che fornisce chiavi univoche e il loro numero di occorrenze nella sequenza originale. |
ritardo: (unità → seq <'T>) → seq <' T> | Restituisce una sequenza creata dalla specifica ritardata di una sequenza. |
distinto: seq <'T> → seq <' T> | Restituisce una sequenza che non contiene voci duplicate in base a hash generici e confronti di uguaglianza sulle voci. Se un elemento si verifica più volte nella sequenza, le occorrenze successive vengono eliminate. |
distintoBy: ('T →' Key) → seq <'T> → seq <' T> | Restituisce una sequenza che non contiene voci duplicate in base all'hash generico e ai confronti di uguaglianza sulle chiavi restituite dalla funzione di generazione della chiave specificata. Se un elemento si verifica più volte nella sequenza, le occorrenze successive vengono eliminate. |
vuoto: seq <'T> | Crea una sequenza vuota. |
esattamente Uno: seq <'T> →' T | Restituisce l'unico elemento della sequenza. |
esiste: ('T → bool) → seq <' T> → bool | Verifica se qualsiasi elemento della sequenza soddisfa il predicato dato. |
esiste2: ('T1 →' T2 → bool) → seq <'T1> → seq <' T2> → bool | Verifica se qualsiasi coppia di elementi corrispondenti delle sequenze di input soddisfa il predicato dato. |
filtro: ('T → bool) → seq <' T> → seq <'T> | Restituisce una nuova raccolta contenente solo gli elementi della raccolta per cui restituisce il predicato specificato true. |
trova: ('T → bool) → seq <' T> → 'T | Restituisce il primo elemento per il quale restituisce la funzione data true. |
findIndex: ('T → bool) → seq <' T> → int | Restituisce l'indice del primo elemento per il quale restituisce la funzione data true. |
fold: ('State →' T → 'State) →' State → seq <'T> →' State | Applica una funzione a ogni elemento della raccolta, inserendo un argomento dell'accumulatore attraverso il calcolo. Se la funzione di input è f e gli elementi sono i0 ... iN, questa funzione calcola f (... (fs i0) ...) iN. |
forall: ('T → bool) → seq <' T> → bool | Verifica se tutti gli elementi della sequenza soddisfano il predicato specificato. |
forall2: ('T1 →' T2 → bool) → seq <'T1> → seq <' T2> → bool | Verifica che tutte le coppie di elementi tratte dalle due sequenze soddisfino il predicato dato. Se una sequenza è più breve dell'altra, gli elementi rimanenti della sequenza più lunga vengono ignorati. |
groupBy: ('T →' Key) → seq <'T> → seq <' Key * seq <'T >> | Applica una funzione di generazione di chiavi a ogni elemento di una sequenza e produce una sequenza di chiavi univoche. Ogni chiave univoca contiene anche una sequenza di tutti gli elementi che corrispondono a questa chiave. |
head: seq <'T> →' T | Restituisce il primo elemento della sequenza. |
init: int → (int → 'T) → seq <' T> | Genera una nuova sequenza che, una volta iterata, restituisce elementi successivi chiamando la funzione data, fino al conteggio dato. I risultati della chiamata della funzione non vengono salvati, ovvero la funzione viene riapplicata se necessario per rigenerare gli elementi. Alla funzione viene passato l'indice dell'elemento generato. |
initInfinite: (int → 'T) → seq <' T> | Genera una nuova sequenza che, una volta iterata, restituirà elementi successivi chiamando la funzione data. I risultati della chiamata della funzione non vengono salvati, ovvero la funzione verrà riapplicata se necessario per rigenerare gli elementi. Alla funzione viene passato l'indice dell'elemento generato. |
isEmpty: seq <'T> → bool | Verifica se una sequenza contiene elementi. |
iter: ('T → unit) → seq <' T> → unit | Applica la funzione data a ogni elemento della raccolta. |
iter2: ('T1 →' T2 → unit) → seq <'T1> → seq <' T2> → unit | Applica la funzione data a due raccolte contemporaneamente. Se una sequenza è più breve dell'altra, gli elementi rimanenti della sequenza più lunga vengono ignorati. |
iteri: (int → 'T → unit) → seq <' T> → unit | Applica la funzione data a ogni elemento della raccolta. L'intero passato alla funzione indica l'indice dell'elemento. |
ultimo: seq <'T> →' T | Restituisce l'ultimo elemento della sequenza. |
lunghezza: seq <'T> → int | Restituisce la lunghezza della sequenza. |
mappa: ('T →' U) → seq <'T> → seq <' U> | Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data a ciascuno degli elementi della raccolta. La funzione data verrà applicata quando gli elementi vengono richiesti utilizzando il metodo MoveNext sugli enumeratori recuperati dall'oggetto. |
map2: ('T1 →' T2 → 'U) → seq <' T1> → seq <'T2> → seq <' U> | Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data alle coppie di elementi corrispondenti dalle due sequenze. Se una sequenza di input è più breve dell'altra, gli elementi rimanenti della sequenza più lunga vengono ignorati. |
mapi: (int → 'T →' U) → seq <'T> → seq <' U> | Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data a ciascuno degli elementi della raccolta. L'indice intero passato alla funzione indica l'indice (da 0) dell'elemento trasformato. |
max: seq <'T> →' T | Restituisce il più grande di tutti gli elementi della sequenza, confrontato utilizzando Operators.max. |
maxBy: ('T →' U) → seq <'T> →' T | Restituisce il più grande di tutti gli elementi della sequenza, confrontato utilizzando Operators.max sul risultato della funzione. |
min: seq <'T> →' T | Restituisce il più basso di tutti gli elementi della sequenza, confrontato utilizzando Operators.min. |
minBy: ('T →' U) → seq <'T> →' T | Restituisce il più basso di tutti gli elementi della sequenza, confrontato utilizzando Operators.min sul risultato della funzione. |
ennesimo: int → seq <'T> →' T | Calcola l' ennesimo elemento nella raccolta. |
ofArray: 'T array → seq <' T> | Visualizza la matrice data come una sequenza. |
ofList: 'T list → seq <' T> | Visualizza l'elenco fornito come una sequenza. |
a coppie: seq <'T> → seq <' T * 'T> | Restituisce una sequenza di ogni elemento nella sequenza di input e il suo predecessore, ad eccezione del primo elemento che viene restituito solo come predecessore del secondo elemento. |
scegli: (opzione 'T →' U) → seq <'T> →' U | Applica la funzione data a elementi successivi, restituendo il primo valore in cui la funzione restituisce a Some valore. |
sola lettura: seq <'T> → seq <' T> | Crea un nuovo oggetto sequenza che delega all'oggetto sequenza specificato. Ciò garantisce che la sequenza originale non possa essere riscoperta e modificata da un cast di tipo. Ad esempio, se viene fornito un array, la sequenza restituita restituirà gli elementi dell'array, ma non è possibile eseguire il cast dell'oggetto sequenza restituito su un array. |
ridurre: ('T →' T → 'T) → seq <' T> → 'T | Applica una funzione a ciascun elemento della sequenza, inserendo un argomento dell'accumulatore attraverso il calcolo. Inizia applicando la funzione ai primi due elementi. Quindi inserisci questo risultato nella funzione insieme al terzo elemento e così via. Restituisci il risultato finale. |
scansione: ('State →' T → 'State) →' State → seq <'T> → seq <' State> | Come Seq. Piega, ma calcola su richiesta e restituisce la sequenza dei risultati intermedi e finali. |
singleton: 'T → seq <' T> | Restituisce una sequenza che produce un solo elemento. |
salta: int → seq <'T> → seq <' T> | Restituisce una sequenza che salta un numero specificato di elementi della sequenza sottostante e quindi restituisce gli elementi rimanenti della sequenza. |
skipWhile: ('T → bool) → seq <' T> → seq <'T> | Restituisce una sequenza che, quando iterata, salta gli elementi della sequenza sottostante mentre il predicato dato ritorna true, e quindi restituisce gli elementi rimanenti della sequenza. |
ordina: seq <'T> → seq <' T> | Restituisce una sequenza ordinata per chiavi. |
sortBy: ('T →' Key) → seq <'T> → seq <' T> | Applica una funzione di generazione di chiavi a ogni elemento di una sequenza e produce una sequenza ordinata per chiavi. Le chiavi vengono confrontate utilizzando il confronto generico implementato da Operators.compare. |
somma: seq <^ T> → ^ T | Restituisce la somma degli elementi nella sequenza. |
sumBy | Restituisce la somma dei risultati generati applicando la funzione a ogni elemento della sequenza. |
prendere: int → seq <'T> → seq <' T> | Restituisce i primi elementi della sequenza fino a un conteggio specificato. |
takeWhile: ('T → bool) → seq <' T> → seq <'T> | Restituisce una sequenza che, quando iterata, restituisce elementi della sequenza sottostante mentre il predicato dato ritorna true, e quindi non restituisce ulteriori elementi. |
toArray: seq <'T> →' T [] | Crea un array dalla raccolta data. |
toList: seq <'T> →' T list | Crea un elenco dalla raccolta data. |
troncare: int → seq <'T> → seq <' T> | Restituisce una sequenza che, se enumerata, non restituisce più di un numero di elementi specificato. |
tryFind: ('T → bool) → seq <' T> → 'T opzione | Restituisce il primo elemento per il quale restituisce la funzione data true, o None se tale elemento non esiste. |
tryFindIndex: ('T → bool) → seq <' T> → int opzione | Restituisce l'indice del primo elemento nella sequenza che soddisfa il predicato dato, o None se tale elemento non esiste. |
tryPick: (opzione 'T →' U) → seq <'T> → opzione' U | Applica la funzione data a elementi successivi, restituendo il primo valore in cui la funzione restituisce a Some valore. |
unfold: ('State →' T * 'State opzione) →' State → seq <'T> | Restituisce una sequenza che contiene gli elementi generati dal dato calcolo. |
dove: ('T → bool) → seq <' T> → seq <'T> | Restituisce una nuova raccolta contenente solo gli elementi della raccolta per cui restituisce il predicato specificato true. Un sinonimo di Seq.filter. |
windowed: int → seq <'T> → seq <' T []> | Restituisce una sequenza che produce finestre scorrevoli di elementi contenenti disegnati dalla sequenza di input. Ogni finestra viene restituita come un nuovo array. |
zip: seq <'T1> → seq <' T2> → seq <'T1 *' T2> | Combina le due sequenze in un elenco di coppie. Non è necessario che le due sequenze abbiano la stessa lunghezza: quando una sequenza è esaurita, qualsiasi elemento rimanente nell'altra sequenza viene ignorato. |
zip3: seq <'T1> → seq <' T2> → seq <'T3> → seq <' T1 * 'T2 *' T3> | Combina le tre sequenze in un elenco di triple. Non è necessario che le sequenze abbiano la stessa lunghezza: quando una sequenza è esaurita, gli elementi rimanenti nelle altre sequenze vengono ignorati. |
I seguenti esempi dimostrano gli usi di alcune delle funzionalità di cui sopra:
Esempio 1
Questo programma crea una sequenza vuota e la riempie in seguito -
(* Creating sequences *)
let emptySeq = Seq.empty
let seq1 = Seq.singleton 20
printfn"The singleton sequence:"
printfn "%A " seq1
printfn"The init sequence:"
let seq2 = Seq.init 5 (fun n -> n * 3)
Seq.iter (fun i -> printf "%d " i) seq2
printfn""
(* converting an array to sequence by using cast *)
printfn"The array sequence 1:"
let seq3 = [| 1 .. 10 |] :> seq<int>
Seq.iter (fun i -> printf "%d " i) seq3
printfn""
(* converting an array to sequence by using Seq.ofArray *)
printfn"The array sequence 2:"
let seq4 = [| 2..2.. 20 |] |> Seq.ofArray
Seq.iter (fun i -> printf "%d " i) seq4
printfn""
Quando compili ed esegui il programma, restituisce il seguente output:
The singleton sequence:
seq [20]
The init sequence:
0 3 6 9 12
The array sequence 1:
1 2 3 4 5 6 7 8 9 10
The array sequence 2:
2 4 6 8 10 12 14 16 18 20
Si prega di notare che -
Il metodo Seq.empty crea una sequenza vuota.
Il metodo Seq.singleton crea una sequenza di un solo elemento specificato.
Il metodo Seq.init crea una sequenza per la quale vengono creati gli elementi utilizzando una determinata funzione.
I metodi Seq.ofArray e Seq.ofList <'T> creano sequenze da array ed elenchi.
Il metodo Seq.iter consente l'iterazione attraverso una sequenza.
Esempio 2
Il metodo Seq.unfold genera una sequenza da una funzione di calcolo che assume uno stato e lo trasforma per produrre ogni elemento successivo nella sequenza.
La seguente funzione produce i primi 20 numeri naturali:
let seq1 = Seq.unfold (fun state -> if (state > 20) then None else Some(state, state + 1)) 0
printfn "The sequence seq1 contains numbers from 0 to 20."
for x in seq1 do printf "%d " x
printfn" "
Quando compili ed esegui il programma, restituisce il seguente output:
The sequence seq1 contains numbers from 0 to 20.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Esempio 3
Il metodo Seq.truncate crea una sequenza da un'altra sequenza, ma limita la sequenza a un numero specificato di elementi.
Il metodo Seq.take crea una nuova sequenza che contiene un numero specificato di elementi dall'inizio di una sequenza.
let mySeq = seq { for i in 1 .. 10 -> 3*i }
let truncatedSeq = Seq.truncate 5 mySeq
let takeSeq = Seq.take 5 mySeq
printfn"The original sequence"
Seq.iter (fun i -> printf "%d " i) mySeq
printfn""
printfn"The truncated sequence"
Seq.iter (fun i -> printf "%d " i) truncatedSeq
printfn""
printfn"The take sequence"
Seq.iter (fun i -> printf "%d " i) takeSeq
printfn""
Quando compili ed esegui il programma, restituisce il seguente output:
The original sequence
3 6 9 12 15 18 21 24 27 30
The truncated sequence
3 6 9 12 15
The take sequence
3 6 9 12 15
Un set in F # è una struttura di dati che funge da raccolta di elementi senza mantenere l'ordine in cui vengono inseriti gli elementi. I set non consentono l'inserimento di voci duplicate nella raccolta.
Creazione di set
I set possono essere creati nei seguenti modi:
- Creando un set vuoto utilizzando Set.empty e aggiungendo elementi utilizzando la funzione di aggiunta.
- Conversione di sequenze ed elenchi in insiemi.
Il seguente programma mostra le tecniche:
(* creating sets *)
let set1 = Set.empty.Add(3).Add(5).Add(7). Add(9)
printfn"The new set: %A" set1
let weekdays = Set.ofList ["mon"; "tues"; "wed"; "thurs"; "fri"]
printfn "The list set: %A" weekdays
let set2 = Set.ofSeq [ 1 .. 2.. 10 ]
printfn "The sequence set: %A" set2
Quando compili ed esegui il programma, restituisce il seguente output:
The new set: set [3; 5; 7; 9]
The list set: set ["fri"; "mon"; "thurs"; "tues"; "wed"]
The sequence set: set [1; 3; 5; 7; 9]
Operazioni di base sui set
La tabella seguente mostra le operazioni di base sui set:
Valore | Descrizione |
---|---|
aggiungere: 'T → Set <' T> → Set <'T> | Restituisce un nuovo set con un elemento aggiunto al set. Non viene sollevata alcuna eccezione se l'insieme contiene già l'elemento specificato. |
contiene: 'T → Set <' T> → bool | Valuta a true se l'elemento dato è nell'insieme dato. |
count: Set <'T> → int | Restituisce il numero di elementi nel set. |
differenza: Imposta <'T> → Imposta <' T> → Imposta <'T> | Restituisce un nuovo set con gli elementi del secondo set rimossi dal primo. |
vuoto: imposta <'T> | Il set vuoto per il tipo specificato. |
esiste: ('T → bool) → Set <' T> → bool | Verifica se qualsiasi elemento della raccolta soddisfa il predicato specificato. Se la funzione di input è predicato e gli elementi sono i0 ... iN, questa funzione calcola il predicato i0 o ... o il predicato iN. |
filtro: ('T → bool) → Set <' T> → Set <'T> | Restituisce una nuova raccolta contenente solo gli elementi della raccolta per cui restituisce il predicato specificato true. |
fold: ('State →' T → 'State) →' State → Set <'T> →' State | Applica la funzione di accumulazione data a tutti gli elementi dell'insieme. |
foldBack: ('T →' State → 'State) → Set <' T> → 'State →' State | Applica la funzione di accumulazione data a tutti gli elementi dell'insieme. |
forall: ('T → bool) → Set <' T> → bool | Verifica se tutti gli elementi della raccolta soddisfano il predicato specificato. Se la funzione di input è p e gli elementi sono i0 ... iN, questa funzione calcola p i0 && ... && p iN. |
intersecare: Imposta <'T> → Imposta <' T> → Imposta <'T> | Calcola l'intersezione dei due insiemi. |
intersectMany: seq <Set <'T >> → Set <' T> | Calcola l'intersezione di una sequenza di insiemi. La sequenza non deve essere vuota. |
isEmpty: Set <'T> → bool | ritorna true se il set è vuoto. |
isProperSubset: Set <'T> → Set <' T> → bool | Valuta a true se tutti gli elementi del primo insieme sono nel secondo e almeno un elemento del secondo non è nel primo. |
isProperSuperset: Set <'T> → Set <' T> → bool | Valuta a true se tutti gli elementi del secondo insieme sono nel primo e almeno un elemento del primo non è nel secondo. |
isSubset: Set <'T> → Set <' T> → bool | Valuta a true se tutti gli elementi del primo insieme sono nel secondo. |
isSuperset: Set <'T> → Set <' T> → bool | Valuta a true se tutti gli elementi del secondo insieme sono nel primo. |
iter: ('T → unit) → Set <' T> → unit | Applica la funzione data a ciascun elemento dell'insieme, in ordine in base alla funzione di confronto. |
mappa: ('T →' U) → Imposta <'T> → Imposta <' U> | Restituisce una nuova raccolta contenente i risultati dell'applicazione della funzione data a ciascun elemento del set di input. |
maxElement: Set <'T> →' T | Restituisce l'elemento più alto nel set in base all'ordine utilizzato per il set. |
minElement: Set <'T> →' T | Restituisce l'elemento più basso nel set in base all'ordine utilizzato per il set. |
ofArray: 'T array → Imposta <' T> | Crea un set che contiene gli stessi elementi dell'array specificato. |
ofList: 'T list → Imposta <' T> | Crea un insieme che contiene gli stessi elementi dell'elenco fornito. |
ofSeq: seq <'T> → Imposta <' T> | Crea una nuova raccolta dall'oggetto enumerabile specificato. |
partizione: ('T → bool) → Set <' T> → Set <'T> * Set <' T> | Divide l'insieme in due insiemi contenenti gli elementi per i quali il predicato dato restituisce rispettivamente vero e falso. |
rimuovi: 'T → Imposta <' T> → Imposta <'T> | Restituisce un nuovo set con l'elemento specificato rimosso. Non viene sollevata alcuna eccezione se l'insieme non contiene l'elemento dato. |
singleton: 'T → Set <' T> | L'insieme contenente l'elemento dato. |
toArray: Imposta <'T> →' T array | Crea un array che contiene gli elementi dell'insieme in ordine. |
toList: Imposta <'T> →' T list | Crea un elenco che contiene gli elementi dell'insieme in ordine. |
toSeq: Imposta <'T> → seq <' T> | Restituisce una visualizzazione ordinata della raccolta come oggetto enumerabile. |
unione: Set <'T> → Set <' T> → Set <'T> | Calcola l'unione dei due insiemi. |
unionMany: seq <Set <'T >> → Set <' T> | Calcola l'unione di una sequenza di insiemi. |
L'esempio seguente mostra gli usi di alcune delle funzionalità di cui sopra:
Esempio
let a = Set.ofSeq [ 1 ..2.. 20 ]
let b = Set.ofSeq [ 1 ..3 .. 20 ]
let c = Set.intersect a b
let d = Set.union a b
let e = Set.difference a b
printfn "Set a: "
Set.iter (fun x -> printf "%O " x) a
printfn""
printfn "Set b: "
Set.iter (fun x -> printf "%O " x) b
printfn""
printfn "Set c = set intersect of a and b : "
Set.iter (fun x -> printf "%O " x) c
printfn""
printfn "Set d = set union of a and b : "
Set.iter (fun x -> printf "%O " x) d
printfn""
printfn "Set e = set difference of a and b : "
Set.iter (fun x -> printf "%O " x) e
printfn""
Quando compili ed esegui il programma, restituisce il seguente output:
Set a:
1 3 5 7 9 11 13 15 17 19
Set b:
1 4 7 10 13 16 19
Set c = set intersect of a and b :
1 7 13 19
Set d = set union of a and b :
1 3 4 5 7 9 10 11 13 15 16 17 19
Set e = set difference of a and b :
3 5 9 11 15 17
In F #, una mappa è un tipo speciale di insieme che associa i valori a chiave. Una mappa viene creata in modo simile alla creazione degli insiemi.
Creazione di mappe
Le mappe vengono create creando una mappa vuota utilizzando Map.empty e aggiungendo elementi utilizzando la funzione Aggiungi. Il seguente esempio lo dimostra:
Esempio
(* Create an empty Map *)
let students =
Map.empty. (* Creating an empty Map *)
Add("Zara Ali", "1501").
Add("Rishita Gupta", "1502").
Add("Robin Sahoo", "1503").
Add("Gillian Megan", "1504");;
printfn "Map - students: %A" students
(* Convert a list to Map *)
let capitals =
[ "Argentina", "Buenos Aires";
"France ", "Paris";
"Chili", "Santiago";
"Malaysia", " Kuala Lumpur";
"Switzerland", "Bern" ]
|> Map.ofList;;
printfn "Map capitals : %A" capitals
Quando compili ed esegui il programma, restituisce il seguente output:
Map - students: map
[("Gillian Megan", "1504"); ("Rishita Gupta", "1502"); ("Robin Sahoo", "1503
");
("Zara Ali", "1501")]
Map capitals : map
[("Argentina", "Buenos Aires"); ("Chili", "Santiago"); ("France ", "Paris");
("Malaysia", " Kuala Lumpur"); ("Switzerland", "Bern")]
È possibile accedere ai singoli elementi nella mappa utilizzando la chiave.
Esempio
(* Create an empty Map *)
let students =
Map.empty. (* Creating an empty Map *)
Add("Zara Ali", "1501").
Add("Rishita Gupta", "1502").
Add("Robin Sahoo", "1503").
Add("Gillian Megan", "1504");;
printfn "Map - students: %A" students
(*Accessing an element using key *)
printfn "%A" students.["Zara Ali"]
Quando compili ed esegui il programma, restituisce il seguente output:
Map - students: map
[("Gillian Megan", "1504"); ("Rishita Gupta", "1502"); ("Robin Sahoo", "1503
");
("Zara Ali", "1501")]
"1501"
Operazioni di base sulle mappe
Aggiungi il nome del modulo
La tabella seguente mostra le operazioni di base sulle mappe:
Membro | Descrizione |
---|---|
Inserisci | Restituisce una nuova mappa con l'associazione aggiunta alla mappa data. |
ContainsKey | Verifica se un elemento si trova nel dominio della mappa. |
Contare | Il numero di associazioni nella mappa. |
È vuoto | Restituisce vero se non ci sono associazioni nella mappa. |
Articolo | Cerca un elemento nella mappa. Genera KeyNotFoundException se non esiste alcuna associazione nella mappa. |
Rimuovere | Rimuove un elemento dal dominio della mappa. Non viene sollevata alcuna eccezione se l'elemento non è presente. |
TryFind | Cerca un elemento nella mappa, restituendo un file Some valore se l'elemento è nel dominio della mappa e None altrimenti. |
L'esempio seguente mostra gli usi di alcune delle funzionalità di cui sopra:
Esempio
(* Create an empty Map *)
let students =
Map.empty. (* Creating an empty Map *)
Add("Zara Ali", "1501").
Add("Rishita Gupta", "1502").
Add("Robin Sahoo", "1503").
Add("Gillian Megan", "1504").
Add("Shraddha Dubey", "1505").
Add("Novonil Sarker", "1506").
Add("Joan Paul", "1507");;
printfn "Map - students: %A" students
printfn "Map - number of students: %d" students.Count
(* finding the registration number of a student*)
let found = students.TryFind "Rishita Gupta"
match found with
| Some x -> printfn "Found %s." x
| None -> printfn "Did not find the specified value."
Quando compili ed esegui il programma, restituisce il seguente output:
Map - students: map
[("Gillian Megan", "1504"); ("Joan Paul", "1507"); ("Novonil Sarker", "1506"
);
("Rishita Gupta", "1502"); ("Robin Sahoo", "1503");
("Shraddha Dubey", "1505"); ("Zara Ali", "1501")]
Map - number of students: 7
Found 1502.
Le unioni, o unioni discriminate, consentono di creare strutture di dati complesse che rappresentano un insieme di scelte ben definito. Ad esempio, è necessario creare un'implementazione di una variabile di scelta , che ha due valori sì e no. Usando lo strumento Unions, puoi progettarlo.
Sintassi
Le unioni discriminate vengono definite utilizzando la seguente sintassi:
type type-name =
| case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ]
type2 ...]
| case-identifier2 [of [fieldname3 : ]type3 [ * [ fieldname4 : ]type4 ...]
...
La nostra semplice implementazione di, choice, sarà simile alla seguente:
type choice =
| Yes
| No
L'esempio seguente utilizza la scelta del tipo -
type choice =
| Yes
| No
let x = Yes (* creates an instance of choice *)
let y = No (* creates another instance of choice *)
let main() =
printfn "x: %A" x
printfn "y: %A" y
main()
Quando compili ed esegui il programma, restituisce il seguente output:
x: Yes
y: No
Esempio 1
L'esempio seguente mostra l'implementazione degli stati di tensione che impostano un po 'su alto o basso -
type VoltageState =
| High
| Low
let toggleSwitch = function (* pattern matching input *)
| High -> Low
| Low -> High
let main() =
let on = High
let off = Low
let change = toggleSwitch off
printfn "Switch on state: %A" on
printfn "Switch off state: %A" off
printfn "Toggle off: %A" change
printfn "Toggle the Changed state: %A" (toggleSwitch change)
main()
Quando compili ed esegui il programma, restituisce il seguente output:
Switch on state: High
Switch off state: Low
Toggle off: High
Toggle the Changed state: Low
Esempio 2
type Shape =
// here we store the radius of a circle
| Circle of float
// here we store the side length.
| Square of float
// here we store the height and width.
| Rectangle of float * float
let pi = 3.141592654
let area myShape =
match myShape with
| Circle radius -> pi * radius * radius
| Square s -> s * s
| Rectangle (h, w) -> h * w
let radius = 12.0
let myCircle = Circle(radius)
printfn "Area of circle with radius %g: %g" radius (area myCircle)
let side = 15.0
let mySquare = Square(side)
printfn "Area of square that has side %g: %g" side (area mySquare)
let height, width = 5.0, 8.0
let myRectangle = Rectangle(height, width)
printfn "Area of rectangle with height %g and width %g is %g" height width (area myRectangle)
Quando compili ed esegui il programma, restituisce il seguente output:
Area of circle with radius 12: 452.389
Area of square that has side 15: 225
Area of rectangle with height 5 and width 8 is 40
Le variabili in F # sono immutable,il che significa che una volta che una variabile è associata a un valore, non può essere modificata. In realtà vengono compilati come proprietà statiche di sola lettura.
Il seguente esempio lo dimostra.
Esempio
let x = 10
let y = 20
let z = x + y
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z
let x = 15
let y = 20
let z = x + y
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z
Quando compili ed esegui il programma, viene visualizzato il seguente messaggio di errore:
Duplicate definition of value 'x'
Duplicate definition of value 'Y'
Duplicate definition of value 'Z'
Variabili mutabili
A volte è necessario modificare i valori memorizzati in una variabile. Per specificare che potrebbe esserci un cambiamento nel valore di una variabile dichiarata e assegnata nella parte successiva di un programma, F # fornisce ilmutableparola chiave. Puoi dichiarare e assegnare variabili mutabili utilizzando questa parola chiave, i cui valori cambierai.
Il mutable parola chiave consente di dichiarare e assegnare valori in una variabile mutabile.
È possibile assegnare un valore iniziale a una variabile mutabile utilizzando il letparola chiave. Tuttavia, per assegnargli un nuovo valore successivo, è necessario utilizzare il<- operatore.
Per esempio,
let mutable x = 10
x <- 15
Il seguente esempio chiarirà il concetto:
Esempio
let mutable x = 10
let y = 20
let mutable z = x + y
printfn "Original Values:"
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z
printfn "Let us change the value of x"
printfn "Value of z will change too."
x <- 15
z <- x + y
printfn "New Values:"
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z
Quando compili ed esegui il programma, restituisce il seguente output:
Original Values:
x: 10
y: 20
z: 30
Let us change the value of x
Value of z will change too.
New Values:
x: 15
y: 20
z: 35
Usi di dati mutabili
I dati mutabili sono spesso richiesti e utilizzati nell'elaborazione dei dati, in particolare con la struttura dei dati dei record. Il seguente esempio lo dimostra:
open System
type studentData =
{ ID : int;
mutable IsRegistered : bool;
mutable RegisteredText : string; }
let getStudent id =
{ ID = id;
IsRegistered = false;
RegisteredText = null; }
let registerStudents (students : studentData list) =
students |> List.iter(fun st ->
st.IsRegistered <- true
st.RegisteredText <- sprintf "Registered %s" (DateTime.Now.ToString("hh:mm:ss"))
Threading.Thread.Sleep(1000) (* Putting thread to sleep for 1 second to simulate processing overhead. *))
let printData (students : studentData list) =
students |> List.iter (fun x -> printfn "%A" x)
let main() =
let students = List.init 3 getStudent
printfn "Before Process:"
printData students
printfn "After process:"
registerStudents students
printData students
Console.ReadKey(true) |> ignore
main()
Quando compili ed esegui il programma, restituisce il seguente output:
Before Process:
{ID = 0;
IsRegistered = false;
RegisteredText = null;}
{ID = 1;
IsRegistered = false;
RegisteredText = null;}
{ID = 2;
IsRegistered = false;
RegisteredText = null;}
After process:
{ID = 0;
IsRegistered = true;
RegisteredText = "Registered 05:39:15";}
{ID = 1;
IsRegistered = true;
RegisteredText = "Registered 05:39:16";}
{ID = 2;
IsRegistered = true;
RegisteredText = "Registered 05:39:17";}
Gli array sono raccolte di dimensioni fisse, a base zero e modificabili di elementi di dati consecutivi che sono tutti dello stesso tipo.
Creazione di array
È possibile creare array utilizzando varie sintassi e modi o utilizzando le funzioni dal modulo Array. In questa sezione, discuteremo la creazione di array senza utilizzare le funzioni del modulo.
Esistono tre modi sintattici per creare array senza funzioni:
- Elencando valori consecutivi compresi tra [| e |] e separati da punto e virgola.
- Mettendo ogni elemento su una riga separata, nel qual caso il separatore punto e virgola è facoltativo.
- Utilizzando espressioni di sequenza.
È possibile accedere agli elementi dell'array utilizzando un operatore punto (.) E parentesi ([e]).
L'esempio seguente mostra la creazione di array:
//using semicolon separator
let array1 = [| 1; 2; 3; 4; 5; 6 |]
for i in 0 .. array1.Length - 1 do
printf "%d " array1.[i]
printfn" "
// without semicolon separator
let array2 =
[|
1
2
3
4
5
|]
for i in 0 .. array2.Length - 1 do
printf "%d " array2.[i]
printfn" "
//using sequence
let array3 = [| for i in 1 .. 10 -> i * i |]
for i in 0 .. array3.Length - 1 do
printf "%d " array3.[i]
printfn" "
Quando compili ed esegui il programma, restituisce il seguente output:
1 2 3 4 5 6
1 2 3 4 5
1 4 9 16 25 36 49 64 81 100
Operazioni di base sugli array
Il modulo libreria Microsoft.FSharp.Collections.Array supporta operazioni su array unidimensionali.
La tabella seguente mostra le operazioni di base sugli array:
Valore | Descrizione |
---|---|
aggiungi: 'T [] →' T [] → 'T [] | Crea un array che contiene gli elementi di un array seguito dagli elementi di un altro array. |
media: ^ T [] → ^ T | Restituisce la media degli elementi in una matrice. |
mediaBy: ('T → ^ U) →' T [] → ^ U | Restituisce la media degli elementi generati applicando una funzione a ogni elemento di un array. |
blit: 'T [] → int →' T [] → int → int → unit | Legge un intervallo di elementi da un array e li scrive in un altro. |
scegli: (opzione 'T → U) →' T [] → 'U [] | Applica una funzione fornita a ogni elemento di un array. Restituisce un array che contiene i risultati x per ogni elemento per il quale la funzione restituisce Some (x). |
raccogliere: ('T →' U []) → T [] → 'U [] | Applica la funzione fornita a ogni elemento di una matrice, concatena i risultati e restituisce la matrice combinata. |
concat: seq <'T []> →' T [] | Crea un array che contiene gli elementi di ciascuna delle sequenze di array fornite. |
copia: 'T →' T [] | Crea un array che contiene gli elementi dell'array fornito. |
creare: int → 'T →' T [] | Crea un array i cui elementi sono tutti inizialmente il valore fornito. |
vuoto: "T [] | Restituisce un array vuoto del tipo specificato. |
esiste: ('T → bool) →' T [] → bool | Verifica se qualsiasi elemento di un array soddisfa il predicato fornito. |
esiste2: ('T1 →' T2 → bool) → 'T1 [] →' T2 [] → bool | Verifica se qualsiasi coppia di elementi corrispondenti di due array soddisfa la condizione fornita. |
riempimento: 'T [] → int → int →' T → unit | Riempie un intervallo di elementi di una matrice con il valore fornito. |
filtro: ('T → bool) →' T [] → 'T [] | Restituisce una raccolta che contiene solo gli elementi della matrice fornita per cui restituisce la condizione fornita true. |
trova: ('T → bool) →' T [] → 'T | Restituisce il primo elemento per il quale restituisce la funzione fornita true. Genera KeyNotFoundException se non esiste alcun elemento di questo tipo. |
findIndex: ('T → bool) →' T [] → int | Restituisce l'indice del primo elemento in un array che soddisfa la condizione fornita. Genera KeyNotFoundException se nessuno degli elementi soddisfa la condizione. |
fold: ('State →' T → 'State) →' State → 'T [] →' State | Applica una funzione a ogni elemento di un array, inserendo un argomento dell'accumulatore attraverso il calcolo. Se la funzione di input è f e gli elementi dell'array sono i0 ... iN, questa funzione calcola f (... (fs i0) ...) iN. |
fold2: ('State →' T1 → 'T2 →' State) → 'State →' T1 [] → 'T2 [] →' State | Applica una funzione a coppie di elementi da due array forniti, da sinistra a destra, inserendo un argomento dell'accumulatore attraverso il calcolo. I due array di input devono avere la stessa lunghezza; in caso contrario, viene generata ArgumentException. |
foldBack: ('T →' State → 'State) →' T [] → 'State →' State | Applica una funzione a ogni elemento di un array, inserendo un argomento dell'accumulatore attraverso il calcolo. Se la funzione di input è f e gli elementi dell'array sono i0 ... iN, questa funzione calcola f i0 (... (f iN s)). |
foldBack2: ('T1 →' T2 → 'State →' State) → 'T1 [] →' T2 [] → 'State →' State | Applica una funzione a coppie di elementi da due array forniti, da destra a sinistra, inserendo un argomento dell'accumulatore attraverso il calcolo. I due array di input devono avere la stessa lunghezza; in caso contrario, viene generata ArgumentException. |
forall: ('T → bool) →' T [] → bool | Verifica se tutti gli elementi di un array soddisfano la condizione fornita. |
forall2: ('T1 →' T2 → bool) → 'T1 [] →' T2 [] → bool | Verifica se tutti gli elementi corrispondenti di due array forniti soddisfano una condizione fornita. |
ottieni: 'T [] → int →' T | Ottiene un elemento da una matrice. |
init: int → (int → 'T) →' T [] | Utilizza una funzione fornita per creare un array della dimensione fornita. |
isEmpty: 'T [] → bool | Verifica se un array contiene elementi. |
iter: ('T → unit) →' T [] → unit | Applica la funzione fornita a ogni elemento di un array. |
iter2: ('T1 →' T2 → unità) → 'T1 [] →' T2 [] → unità) | Applica la funzione fornita a una coppia di elementi da indici corrispondenti in due matrici. I due array devono avere la stessa lunghezza; in caso contrario, viene generata ArgumentException. |
iteri: (int → 'T → unit) →' T [] → unit | Applica la funzione fornita a ogni elemento di un array. L'intero passato alla funzione indica l'indice dell'elemento. |
iteri2: (int → 'T1 →' T2 → unit) → 'T1 [] →' T2 [] → unit | Applica la funzione fornita a una coppia di elementi da indici corrispondenti in due matrici, passando anche l'indice degli elementi. I due array devono avere la stessa lunghezza; in caso contrario, viene generata un'eccezione ArgumentException. |
lunghezza: 'T [] → int | Restituisce la lunghezza di un array. La proprietà Length fa la stessa cosa. |
mappa: ('T →' U) → 'T [] →' U [] | Crea un array i cui elementi sono il risultato dell'applicazione della funzione fornita a ciascuno degli elementi di un array fornito. |
map2: ('T1 →' T2 → 'U) →' T1 [] → 'T2 [] →' U [] | Crea un array i cui elementi sono il risultato dell'applicazione della funzione fornita agli elementi corrispondenti di due array forniti. I due array di input devono avere la stessa lunghezza; in caso contrario, viene generata ArgumentException. |
mapi: (int → 'T →' U) → 'T [] →' U [] | Crea un array i cui elementi sono il risultato dell'applicazione della funzione fornita a ciascuno degli elementi di un array fornito. Un indice intero passato alla funzione indica l'indice dell'elemento trasformato. |
mapi2: (int → 'T1 →' T2 → 'U) →' T1 [] → 'T2 [] →' U [] | Crea un array i cui elementi sono il risultato dell'applicazione della funzione fornita agli elementi corrispondenti delle due collezioni a coppie, passando anche l'indice degli elementi. I due array di input devono avere la stessa lunghezza; in caso contrario, viene generata ArgumentException. |
max: 'T [] →' T | Restituisce il più grande di tutti gli elementi di un array. Operators.max viene utilizzato per confrontare gli elementi. |
maxBy: ('T →' U) → 'T [] →' T | Restituisce il più grande di tutti gli elementi di un array, confrontato tramite Operators.max sul risultato della funzione. |
min: ('T [] →' T | Restituisce il più piccolo di tutti gli elementi di un array. Operators.min viene utilizzato per confrontare gli elementi. |
minBy: ('T →' U) → 'T [] →' T | Restituisce il più piccolo di tutti gli elementi di un array. Operators.min viene utilizzato per confrontare gli elementi. |
ofList: 'T list →' T [] | Crea un array dall'elenco fornito. |
ofSeq: seq <'T> →' T [] | Crea un array dall'oggetto enumerabile fornito. |
partizione: ('T → bool) →' T [] → 'T [] *' T [] | Divide un array in due array, uno contenente gli elementi per i quali restituisce la condizione fornita true, e l'altra contenente quelli per cui ritorna false. |
permuto: (int → int) → 'T [] →' T [] | Permuta gli elementi di un array in base alla permutazione specificata. |
scegli: (opzione 'T →' U) → 'T [] →' U | Applica la funzione fornita agli elementi successivi di un array fornito, restituendo il primo risultato in cui la funzione restituisce Some (x) per alcuni x. Se la funzione non restituisce mai Some (x), viene generata KeyNotFoundException. |
ridurre: ('T →' T → 'T) →' T [] → 'T | Applica una funzione a ogni elemento di un array, inserendo un argomento dell'accumulatore attraverso il calcolo. Se la funzione di input è f e gli elementi dell'array sono i0 ... iN, questa funzione calcola f (... (f i0 i1) ...) iN. Se la matrice ha dimensione zero, viene generata ArgumentException. |
reduceBack: ('T →' T → 'T) →' T [] → 'T | Applica una funzione a ogni elemento di un array, inserendo un argomento dell'accumulatore attraverso il calcolo. Se la funzione di input è f e gli elementi sono i0 ... iN, questa funzione calcola f i0 (... (f iN-1 iN)). Se la matrice ha dimensione zero, viene generata ArgumentException. |
rev: 'T [] →' T [] | Inverte l'ordine degli elementi in una matrice fornita. |
scansione: ('State →' T → 'State) →' State → 'T [] →' State []) | Si comporta come la piega, ma restituisce i risultati intermedi insieme ai risultati finali. |
scanBack: ('T →' State → 'State) →' T [] → 'State →' State [] | Si comporta come foldBack, ma restituisce i risultati intermedi insieme ai risultati finali. |
impostare: 'T [] → int →' T → unità | Imposta un elemento di un array. |
ordina: 'T [] →' T [] | Ordina gli elementi di un array e restituisce un nuovo array. Operators.compare viene utilizzato per confrontare gli elementi. |
sortBy: ('T →' Key) → 'T [] →' T [] | Ordina gli elementi di un array utilizzando la funzione fornita per trasformare gli elementi nel tipo su cui si basa l'operazione di ordinamento e restituisce un nuovo array. Operators.compare viene utilizzato per confrontare gli elementi. |
sortInPlace: 'T [] → unit | Ordina gli elementi di un array modificando l'array in posizione, utilizzando la funzione di confronto fornita. Operators.compare viene utilizzato per confrontare gli elementi. |
sortInPlaceBy: ('T →' Key) → 'T [] → unit | Ordina gli elementi di un array modificando l'array in posizione, utilizzando la proiezione fornita per le chiavi. Operators.compare viene utilizzato per confrontare gli elementi. |
sortInPlaceWith: ('T →' T → int) → 'T [] → unit | Ordina gli elementi di una matrice utilizzando la funzione di confronto fornita per modificare la matrice in posizione. |
sortWith: ('T →' T → int) → 'T [] →' T [] | Ordina gli elementi di un array utilizzando la funzione di confronto fornita e restituisce un nuovo array. |
sub: 'T [] → int → int →' T [] | Crea un array che contiene il sottointervallo fornito, specificato dall'indice iniziale e dalla lunghezza. |
somma: 'T [] → ^ T | Restituisce la somma degli elementi nell'array. |
sumBy: ('T → ^ U) →' T [] → ^ U | Restituisce la somma dei risultati generati applicando una funzione a ogni elemento di un array. |
toList: 'T [] →' T list | Converte la matrice fornita in un elenco. |
toSeq: 'T [] → seq <' T> | Visualizza l'array fornito come una sequenza. |
tryFind: ('T → bool) →' T [] → 'T opzione | Restituisce il primo elemento dell'array fornito per il quale restituisce la funzione fornita true. ritornaNone se tale elemento non esiste. |
tryFindIndex: ('T → bool) →' T [] → int opzione | Restituisce l'indice del primo elemento in un array che soddisfa la condizione fornita. |
tryPick: (opzione 'T →' U) → 'T [] → opzione' U | Applica la funzione fornita agli elementi successivi dell'array fornito e restituisce il primo risultato in cui la funzione restituisce Some (x) per alcuni x. Se la funzione non restituisce mai Some (x),None viene restituito. |
decomprimere: ('T1 *' T2) [] → 'T1 [] *' T2 [] | Divide un array di coppie di tuple in una tupla di due array. |
unzip3: ('T1 *' T2 * 'T3) [] →' T1 [] * 'T2 [] *' T3 [] | Divide una matrice di tuple di tre elementi in una tupla di tre matrici. |
zeroCreate: int → 'T [] | Crea un array i cui elementi sono inizialmente impostati sul valore predefinito Unchecked.defaultof <'T>. |
zip: "T1 [] →" T2 [] → ("T1 *" T2) [] | Combina due array in un array di tuple che hanno due elementi. I due array devono avere la stessa lunghezza; in caso contrario, viene generata ArgumentException. |
zip3: 'T1 [] →' T2 [] → 'T3 [] → (' T1 * 'T2 * 113' T3) [] | Combina tre array in un array di tuple che hanno tre elementi. I tre array devono avere la stessa lunghezza; in caso contrario, viene generata ArgumentException. |
Nella sezione seguente vedremo gli usi di alcune di queste funzionalità.
Creazione di array utilizzando le funzioni
Il modulo Array fornisce diverse funzioni che creano un array da zero.
Il Array.empty la funzione crea un nuovo array vuoto.
Il Array.create funzione crea un array di una dimensione specificata e imposta tutti gli elementi su valori dati.
Il Array.init funzione crea un array, data una dimensione e una funzione per generare gli elementi.
Il Array.zeroCreate funzione crea un array in cui tutti gli elementi vengono inizializzati al valore zero.
Il Array.copy funzione crea un nuovo array che contiene gli elementi che vengono copiati da un array esistente.
Il Array.sub la funzione genera un nuovo array da un sottointervallo di un array.
Il Array.append funzione crea un nuovo array combinando due array esistenti.
Il Array.choose la funzione seleziona gli elementi di un array da includere in un nuovo array.
Il Array.collect funzione esegue una funzione specificata su ogni elemento dell'array di un array esistente, quindi raccoglie gli elementi generati dalla funzione e li combina in un nuovo array.
Il Array.concat funzione prende una sequenza di array e li combina in un singolo array.
Il Array.filter funzione accetta una funzione di condizione booleana e genera un nuovo array che contiene solo quegli elementi dell'array di input per i quali la condizione è vera.
Il Array.rev la funzione genera un nuovo array invertendo l'ordine di un array esistente.
I seguenti esempi dimostrano queste funzioni:
Esempio 1
(* using create and set *)
let array1 = Array.create 10 ""
for i in 0 .. array1.Length - 1 do
Array.set array1 i (i.ToString())
for i in 0 .. array1.Length - 1 do
printf "%s " (Array.get array1 i)
printfn " "
(* empty array *)
let array2 = Array.empty
printfn "Length of empty array: %d" array2.Length
let array3 = Array.create 10 7.0
printfn "Float Array: %A" array3
(* using the init and zeroCreate *)
let array4 = Array.init 10 (fun index -> index * index)
printfn "Array of squares: %A" array4
let array5 : float array = Array.zeroCreate 10
let (myZeroArray : float array) = Array.zeroCreate 10
printfn "Float Array: %A" array5
Quando compili ed esegui il programma, restituisce il seguente output:
0 1 2 3 4 5 6 7 8 9
Length of empty array: 0
Float Array: [|7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0|]
Array of squares: [|0; 1; 4; 9; 16; 25; 36; 49; 64; 81|]
Float Array: [|0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0|]
Esempio 2
(* creating subarray from element 5 *)
(* containing 15 elements thereon *)
let array1 = [| 0 .. 50 |]
let array2 = Array.sub array1 5 15
printfn "Sub Array:"
printfn "%A" array2
(* appending two arrays *)
let array3 = [| 1; 2; 3; 4|]
let array4 = [| 5 .. 9 |]
printfn "Appended Array:"
let array5 = Array.append array3 array4
printfn "%A" array5
(* using the Choose function *)
let array6 = [| 1 .. 20 |]
let array7 = Array.choose (fun elem -> if elem % 3 = 0 then
Some(float (elem))
else
None) array6
printfn "Array with Chosen elements:"
printfn "%A" array7
(*using the Collect function *)
let array8 = [| 2 .. 5 |]
let array9 = Array.collect (fun elem -> [| 0 .. elem - 1 |]) array8
printfn "Array with collected elements:"
printfn "%A" array9
Quando compili ed esegui il programma, restituisce il seguente output:
Sub Array:
[|5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19|]
Appended Array:
[|1; 2; 3; 4; 5; 6; 7; 8; 9|]
Array with Chosen elements:
[|3.0; 6.0; 9.0; 12.0; 15.0; 18.0|]
Array with collected elements:
[|0; 1; 0; 1; 2; 0; 1; 2; 3; 0; 1; 2; 3; 4|]
Ricerca di array
Il Array.find function accetta una funzione booleana e restituisce il primo elemento per il quale la funzione restituisce true, altrimenti solleva un'eccezione KeyNotFoundException.
Il Array.findIndex la funzione funziona in modo simile tranne che restituisce l'indice dell'elemento invece dell'elemento stesso.
Il seguente esempio lo dimostra.
Microsoft fornisce questo interessante esempio di programma, che trova il primo elemento nell'intervallo di un dato numero che è sia un quadrato perfetto che un cubo perfetto -
let array1 = [| 2 .. 100 |]
let delta = 1.0e-10
let isPerfectSquare (x:int) =
let y = sqrt (float x)
abs(y - round y) < delta
let isPerfectCube (x:int) =
let y = System.Math.Pow(float x, 1.0/3.0)
abs(y - round y) < delta
let element = Array.find (fun elem -> isPerfectSquare elem && isPerfectCube elem) array1
let index = Array.findIndex (fun elem -> isPerfectSquare elem && isPerfectCube elem) array1
printfn "The first element that is both a square and a cube is %d and its index is %d." element index
Quando compili ed esegui il programma, restituisce il seguente output:
The first element that is both a square and a cube is 64 and its index is 62.
Il List<'T> class rappresenta un elenco fortemente tipizzato di oggetti a cui è possibile accedere tramite indice.
È una controparte mutevole della classe List. È simile agli array, poiché è possibile accedervi da un indice, tuttavia, a differenza degli array, gli elenchi possono essere ridimensionati. Pertanto non è necessario specificare una dimensione durante la dichiarazione.
Creazione di un elenco modificabile
Gli elenchi vengono creati utilizzando il newparola chiave e chiamando il costruttore dell'elenco. Il seguente esempio lo dimostra:
(* Creating a List *)
open System.Collections.Generic
let booksList = new List<string>()
booksList.Add("Gone with the Wind")
booksList.Add("Atlas Shrugged")
booksList.Add("Fountainhead")
booksList.Add("Thornbirds")
booksList.Add("Rebecca")
booksList.Add("Narnia")
booksList |> Seq.iteri (fun index item -> printfn "%i: %s" index booksList.[index])
Quando compili ed esegui il programma, restituisce il seguente output:
0: Gone with the Wind
1: Atlas Shrugged
2: Fountainhead
3: Thornbirds
4: Rebecca
5: Narnia
La classe List (T)
La classe List (T) rappresenta un elenco di oggetti fortemente tipizzato a cui è possibile accedere tramite indice. Fornisce metodi per cercare, ordinare e manipolare gli elenchi.
Le seguenti tabelle forniscono le proprietà, i costruttori ei metodi della classe List (T) -
Proprietà
Proprietà | Descrizione |
---|---|
Capacità | Ottiene o imposta il numero totale di elementi che la struttura dati interna può contenere senza ridimensionamento. |
Contare | Ottiene il numero di elementi contenuti in List (T). |
Articolo | Ottiene o imposta l'elemento in corrispondenza dell'indice specificato. |
Costruttori
Costruttore | Descrizione |
---|---|
Elenco (T) () | Inizializza una nuova istanza della classe List (T) che è vuota e ha la capacità iniziale predefinita. |
Elenco (T) (IEnumerable (T)) | Inizializza una nuova istanza della classe List (T) che contiene elementi copiati dalla raccolta specificata e ha una capacità sufficiente per contenere il numero di elementi copiati. |
Elenco (T) (Int32) | Inizializza una nuova istanza della classe List (T) che è vuota e ha la capacità iniziale specificata. |
Metodo
Metodi | Descrizione |
---|---|
Inserisci | Aggiunge un oggetto alla fine della lista (T). |
AddRange | Aggiunge gli elementi della raccolta specificata alla fine di List (T). |
AsReadOnly | Restituisce un wrapper IList (T) di sola lettura per la raccolta corrente. |
BinarySearch (T) | Cerca un elemento nell'intero elenco ordinato (T) utilizzando l'operatore di confronto predefinito e restituisce l'indice in base zero dell'elemento. |
BinarySearch (T, IComparer (T)) | Cerca un elemento nell'intero elenco ordinato (T) utilizzando l'operatore di confronto specificato e restituisce l'indice in base zero dell'elemento. |
BinarySearch (Int32, Int32, T, IComparer (T)) | Cerca un elemento in un intervallo di elementi nell'elenco ordinato (T) utilizzando l'operatore di confronto specificato e restituisce l'indice in base zero dell'elemento. |
Chiaro | Rimuove tutti gli elementi dall'elenco (T). |
Contiene | Determina se un elemento si trova nell'elenco (T). |
ConvertAll (TOutput) | Converte gli elementi nell'elenco corrente (T) in un altro tipo e restituisce un elenco contenente gli elementi convertiti. |
Copia a (T []) | Copia l'intero List (T) in una matrice unidimensionale compatibile, a partire dall'inizio della matrice di destinazione. |
Copia a (T [], Int32) | Copia l'intero List (T) in una matrice unidimensionale compatibile, a partire dall'indice specificato della matrice di destinazione. |
CopyTo (Int32, T [], Int32, Int32) | Copia un intervallo di elementi da List (T) a una matrice unidimensionale compatibile, a partire dall'indice specificato della matrice di destinazione. |
Uguale a (oggetto) | Determina se l'oggetto specificato è uguale all'oggetto corrente. (Ereditato da Object.) |
Esiste | Determina se List (T) contiene elementi che soddisfano le condizioni definite dal predicato specificato. |
Finalizza | Consente a un oggetto di provare a liberare risorse ed eseguire altre operazioni di pulizia prima che venga recuperato dalla procedura di Garbage Collection (Ereditato da Object). |
Trova | Cerca un elemento che soddisfi le condizioni definite dal predicato specificato e restituisce la prima occorrenza all'interno dell'intero List (T). |
Trova tutto | Recupera tutti gli elementi che soddisfano le condizioni definite dal predicato specificato. |
FindIndex (Predicate (T)) | Cerca un elemento che soddisfi le condizioni definite dal predicato specificato e restituisce l'indice in base zero della prima occorrenza all'interno dell'intero List (T). |
FindIndex (Int32, Predicate (T)) | Cerca un elemento che soddisfi le condizioni definite dal predicato specificato e restituisce l'indice in base zero della prima occorrenza all'interno dell'intervallo di elementi nell'elenco (T) che si estende dall'indice specificato all'ultimo elemento. |
FindIndex (Int32, Int32, Predicate (T)) | Cerca un elemento che soddisfi le condizioni definite dal predicato specificato e restituisce l'indice in base zero della prima occorrenza all'interno dell'intervallo di elementi nell'elenco (T) che inizia dall'indice specificato e contiene il numero di elementi specificato. |
FindLast | Cerca un elemento che soddisfi le condizioni definite dal predicato specificato e restituisce l'ultima occorrenza all'interno dell'intero List (T). |
FindLastIndex (Predicate (T)) | Cerca un elemento che soddisfi le condizioni definite dal predicato specificato e restituisce l'indice in base zero dell'ultima occorrenza all'interno dell'intero List (T). |
FindLastIndex (Int32, Predicate (T)) | Cerca un elemento che soddisfi le condizioni definite dal predicato specificato e restituisce l'indice in base zero dell'ultima occorrenza all'interno dell'intervallo di elementi nell'elenco (T) che si estende dal primo elemento all'indice specificato. |
FindLastIndex (Int32, Int32, Predicate (T)) | Cerca un elemento che soddisfi le condizioni definite dal predicato specificato e restituisce l'indice in base zero dell'ultima occorrenza all'interno dell'intervallo di elementi nell'elenco (T) che contiene il numero di elementi specificato e termina in corrispondenza dell'indice specificato. |
Per ciascuno | Esegue l'azione specificata su ogni elemento di List (T). |
GetEnumerator | Restituisce un enumeratore che itera attraverso List (T). |
GetHashCode | Serve come funzione hash predefinita. (Ereditato da Object.) |
GetRange | Crea una copia superficiale di un intervallo di elementi nell'elenco di origine (T). |
GetType | Ottiene il Type dell'istanza corrente. (Ereditato da Object.) |
IndexOf (T) | Cerca l'oggetto specificato e restituisce l'indice in base zero della prima occorrenza all'interno dell'intero List (T). |
IndexOf (T, Int32) | Cerca l'oggetto specificato e restituisce l'indice in base zero della prima occorrenza all'interno dell'intervallo di elementi nell'elenco (T) che si estende dall'indice specificato all'ultimo elemento. |
IndexOf (T, Int32, Int32) | Cerca l'oggetto specificato e restituisce l'indice in base zero della prima occorrenza all'interno dell'intervallo di elementi nell'elenco (T) che inizia dall'indice specificato e contiene il numero di elementi specificato. |
Inserire | Inserisce un elemento in List (T) all'indice specificato. |
InsertRange | Inserisce gli elementi di una raccolta in List (T) in corrispondenza dell'indice specificato. |
LastIndexOf (T) | Cerca l'oggetto specificato e restituisce l'indice in base zero dell'ultima occorrenza all'interno dell'intero List (T). |
LastIndexOf (T, Int32) | Cerca l'oggetto specificato e restituisce l'indice in base zero dell'ultima occorrenza all'interno dell'intervallo di elementi nell'elenco (T) che si estende dal primo elemento all'indice specificato. |
LastIndexOf (T, Int32, Int32) | Cerca l'oggetto specificato e restituisce l'indice in base zero dell'ultima occorrenza all'interno dell'intervallo di elementi nell'elenco (T) che contiene il numero di elementi specificato e termina all'indice specificato. |
MemberwiseClone | Crea una copia superficiale dell'oggetto Object corrente. (Ereditato da Object.) |
Rimuovere | Rimuove la prima occorrenza di un oggetto specifico dall'elenco (T). |
Rimuovi tutto | Rimuove tutti gli elementi che soddisfano le condizioni definite dal predicato specificato. |
RemoveAt | Rimuove l'elemento in corrispondenza dell'indice specificato di List (T). |
RemoveRange | Rimuove un intervallo di elementi dall'elenco (T). |
Inversione() | Inverte l'ordine degli elementi nell'intera lista (T). |
Reverse (Int32, Int32) | Inverte l'ordine degli elementi nell'intervallo specificato. |
Ordinare() | Ordina gli elementi nell'intero List (T) utilizzando l'operatore di confronto predefinito. |
Ordina (Confronto (T)) | Ordina gli elementi nell'intero List (T) utilizzando il System specificato. Confronto (T). |
Ordina (IComparer (T)) | Ordina gli elementi nell'intero List (T) utilizzando l'operatore di confronto specificato. |
Ordina (Int32, Int32, IComparer (T)) | Ordina gli elementi in un intervallo di elementi in List (T) utilizzando l'operatore di confronto specificato. |
ToArray | Copia gli elementi di List (T) in un nuovo array. |
Accordare | Restituisce una stringa che rappresenta l'oggetto corrente. (Ereditato da Object.) |
TrimExcess | Imposta la capacità sul numero effettivo di elementi nell'elenco (T), se tale numero è inferiore a un valore di soglia. |
TrueForAll | Determina se ogni elemento in List (T) soddisfa le condizioni definite dal predicato specificato. |
Esempio
(* Creating a List *)
open System.Collections.Generic
let booksList = new List<string>()
booksList.Add("Gone with the Wind")
booksList.Add("Atlas Shrugged")
booksList.Add("Fountainhead")
booksList.Add("Thornbirds")
booksList.Add("Rebecca")
booksList.Add("Narnia")
printfn"Total %d books" booksList.Count
booksList |> Seq.iteri (fun index item -> printfn "%i: %s" index booksList.[index])
booksList.Insert(2, "Roots")
printfn("after inserting at index 2")
printfn"Total %d books" booksList.Count
booksList |> Seq.iteri (fun index item -> printfn "%i: %s" index booksList.[index])
booksList.RemoveAt(3)
printfn("after removing from index 3")
printfn"Total %d books" booksList.Count
booksList |> Seq.iteri (fun index item -> printfn "%i: %s" index booksList.[index])
Quando compili ed esegui il programma, restituisce il seguente output:
Total 6 books
0: Gone with the Wind
1: Atlas Shrugged
2: Fountainhead
3: Thornbirds
4: Rebecca
5: Narnia
after inserting at index 2
Total 7 books
0: Gone with the Wind
1: Atlas Shrugged
2: Roots
3: Fountainhead
4: Thornbirds
5: Rebecca
6: Narnia
after removing from index 3
Total 6 books
0: Gone with the Wind
1: Atlas Shrugged
2: Roots
3: Thornbirds
4: Rebecca
5: Narnia
Il Dictionary<'TKey, 'TValue> class è l'analogo mutabile della struttura dati della mappa F # e contiene molte delle stesse funzioni.
Ricapitolando dal capitolo Mappa in F #, una mappa è un tipo speciale di insieme che associa i valori alla chiave.
Creazione di un dizionario mutevole
I dizionari modificabili vengono creati utilizzando il newparola chiave e chiamando il costruttore dell'elenco. Il seguente esempio lo dimostra:
open System.Collections.Generic
let dict = new Dictionary<string, string>()
dict.Add("1501", "Zara Ali")
dict.Add("1502","Rishita Gupta")
dict.Add("1503","Robin Sahoo")
dict.Add("1504","Gillian Megan")
printfn "Dictionary - students: %A" dict
Quando compili ed esegui il programma, restituisce il seguente output:
Dictionary - students: seq
[[1501, Zara Ali]; [1502, Rishita Gupta]; [1503, Robin Sahoo];
[1504, Gillian Megan]]
La classe Dictionary (TKey, TValue)
La classe Dictionary (TKey, TValue) rappresenta una raccolta di chiavi e valori.
Le seguenti tabelle forniscono le proprietà, i costruttori ei metodi della classe List (T) -
Proprietà
Proprietà | Descrizione |
---|---|
Comparer | Ottiene l'oggetto IEqualityComparer (T) utilizzato per determinare l'uguaglianza delle chiavi per il dizionario. |
Contare | Ottiene il numero di coppie chiave / valore contenute nel Dictionary (TKey, TValue). |
Articolo | Ottiene o imposta il valore associato alla chiave specificata. |
Chiavi | Ottiene una raccolta contenente le chiavi nel dizionario (TKey, TValue). |
Valori | Ottiene una raccolta contenente i valori in Dictionary (TKey, TValue). |
Costruttori
Costruttori | Descrizione |
---|---|
Dizionario (TKey, TValue) () | Inizializza una nuova istanza di Dictionary(TKey, TValue) classe che è vuota, ha la capacità iniziale predefinita e utilizza l'operatore di confronto di uguaglianza predefinito per il tipo di chiave. |
Dizionario (TKey, TValue) (IDictionary (TKey, TValue)) | Inizializza una nuova istanza di Dictionary(TKey, TValue) classe che contiene elementi copiati dal file specificato IDictionary(TKey, TValue) e utilizza l'operatore di confronto di uguaglianza predefinito per il tipo di chiave. |
Dizionario (TKey, TValue) (IEqualityComparer (TKey)) | Inizializza una nuova istanza di Dictionary(TKey, TValue) che è vuota, ha la capacità iniziale predefinita e utilizza la classe IEqualityComparer(T). |
Dizionario (TKey, TValue) (Int32) | Inizializza una nuova istanza di Dictionary(TKey, TValue) class che è vuota, ha la capacità iniziale specificata e utilizza l'operatore di confronto di uguaglianza predefinito per il tipo di chiave. |
Dizionario (TKey, TValue) (IDictionary (TKey, TValue), IEqualityComparer (TKey)) | Inizializza una nuova istanza di Dictionary(TKey, TValue) classe che contiene elementi copiati dal file specificato IDictionary(TKey, TValue) e utilizza il file IEqualityComparer(T). |
Dizionario (TKey, TValue) (Int32, IEqualityComparer (TKey)) | Inizializza una nuova istanza di Dictionary(TKey, TValue) che è vuota, ha la capacità iniziale specificata e utilizza la classe IEqualityComparer(T). |
Dizionario (TKey, TValue) (SerializationInfo, StreamingContext) | Inizializza una nuova istanza di ictionary(TKey, TValue) classe con dati serializzati. |
Metodi
Metodo | Descrizione |
---|---|
Inserisci | Aggiunge la chiave e il valore specificati al dizionario. |
Chiaro | Rimuove tutte le chiavi e i valori dal dizionario (TKey, TValue). |
ContainsKey | Determina se il Dictionary (TKey, TValue) contiene la chiave specificata. |
ContainsValue | Determina se il dizionario (TKey, TValue) contiene un valore specifico. |
Uguale a (oggetto) | Determina se l'oggetto specificato è uguale all'oggetto corrente. (Ereditato da Object.) |
Finalizza | Consente a un oggetto di provare a liberare risorse ed eseguire altre operazioni di pulizia prima che venga recuperato dalla procedura di Garbage Collection. (Ereditato da Object.) |
GetEnumerator | Restituisce un enumeratore che itera nel Dictionary (TKey, TValue). |
GetHashCode | Serve come funzione hash predefinita. (Ereditato da Object.) |
GetObjectData | Implementa l'interfaccia System.Runtime.Serialization.ISerializable e restituisce i dati necessari per serializzare l'istanza Dictionary (TKey, TValue). |
GetType | Ottiene il Type dell'istanza corrente. (Ereditato da Object.) |
MemberwiseClone | Crea una copia superficiale dell'oggetto Object corrente. (Ereditato da Object.) |
OnDeserialization | Implementa l'interfaccia System.Runtime.Serialization.ISerializable e genera l'evento di deserializzazione quando la deserializzazione è completa. |
Rimuovere | Rimuove il valore con la chiave specificata dal dizionario (TKey, TValue). |
Accordare | Restituisce una stringa che rappresenta l'oggetto corrente. (Ereditato da Object.) |
TryGetValue | Ottiene il valore associato alla chiave specificata. |
Esempio
open System.Collections.Generic
let dict = new Dictionary<string, string>()
dict.Add("1501", "Zara Ali")
dict.Add("1502","Rishita Gupta")
dict.Add("1503","Robin Sahoo")
dict.Add("1504","Gillian Megan")
printfn "Dictionary - students: %A" dict
printfn "Total Number of Students: %d" dict.Count
printfn "The keys: %A" dict.Keys
printf"The Values: %A" dict.Values
Quando compili ed esegui il programma, restituisce il seguente output:
Dictionary - students: seq
[[1501, Zara Ali]; [1502, Rishita Gupta]; [1503, Robin Sahoo];
[1504, Gillian Megan]]
Total Number of Students: 4
The keys: seq ["1501"; "1502"; "1503"; "1504"]
The Values: seq ["Zara Ali"; "Rishita Gupta"; "Robin Sahoo"; "Gillian Megan"]
L'uscita di ingresso di base include:
- Leggere e scrivere nella console.
- Lettura e scrittura su file.
Modulo Core.Printf
Abbiamo usato le funzioni printf e printfn per scrivere nella console. In questa sezione, esamineremo i dettagli diPrintf modulo di F #.
Oltre alle funzioni precedenti, il modulo Core.Printf di F # dispone di vari altri metodi per la stampa e la formattazione utilizzando% marker come segnaposto. La tabella seguente mostra i metodi con una breve descrizione:
Valore | Descrizione |
---|---|
bprintf: StringBuilder → BuilderFormat <'T> →' T | Stampa su un StringBuilder. |
eprintf: TextWriterFormat <'T> →' T | Stampa l'output formattato su stderr. |
eprintfn: TextWriterFormat <'T> →' T | Stampa l'output formattato su stderr, aggiungendo una nuova riga. |
failwithf: StringFormat <'T,' Result> → 'T | Stampa su un buffer di stringa e solleva un'eccezione con il risultato dato. |
fprintf: TextWriter → TextWriterFormat <'T> →' T | Stampa su uno scrittore di testo. |
fprintfn: TextWriter → TextWriterFormat <'T> →' T | Stampa su uno scrittore di testo, aggiungendo una nuova riga. |
kbprintf: (unità → 'Risultato) → StringBuilder → BuilderFormat <' T, 'Risultato> →' T | Come bprintf, ma chiama la funzione specificata per generare il risultato. |
kfprintf: (unità → 'Risultato) → TextWriter → TextWriterFormat <' T, 'Risultato> →' T | Come fprintf, ma chiama la funzione specificata per generare il risultato. |
kprintf: (stringa → 'Risultato) → StringFormat <' T, 'Risultato> →' T | Come printf, ma chiama la funzione specificata per generare il risultato. Ad esempio, questi consentono alla stampa di forzare uno scarico dopo che tutto l'output è stato immesso nel canale, ma non prima. |
ksprintf: (stringa → 'Risultato) → StringFormat <' T, 'Risultato> →' T | Come sprintf, ma chiama la funzione specificata per generare il risultato. |
printf: TextWriterFormat <'T> →' T | Stampa l'output formattato su stdout. |
printfn: TextWriterFormat <'T> →' T | Stampa l'output formattato su stdout, aggiungendo una nuova riga. |
sprintf: StringFormat <'T> →' T | Stampa su una stringa utilizzando un buffer di stringa interno e restituisce il risultato come stringa. |
Specifiche di formato
Le specifiche di formato vengono utilizzate per formattare l'input o l'output, in base alle necessità dei programmatori.
Si tratta di stringhe con marcatori% che indicano segnaposto di formato.
La sintassi di un segnaposto di formato è:
%[flags][width][.precision][type]
Il type è interpretato come -
genere | Descrizione |
---|---|
% b | Formati a bool, formattato come true o false. |
% c | Formatta un carattere. |
%S | Formati a string, formattato come contenuto, senza interpretare alcun carattere di escape. |
% d,% i | Formatta qualsiasi tipo intero di base formattato come intero decimale, con segno se il tipo intero di base è firmato. |
% u | Formatta qualsiasi tipo intero di base formattato come numero intero decimale senza segno. |
%X | Formatta qualsiasi tipo intero di base formattato come intero esadecimale senza segno, utilizzando lettere minuscole da a a f. |
%X | Formatta qualsiasi tipo intero di base formattato come intero esadecimale senza segno, utilizzando le lettere maiuscole dalla A alla F. |
% o | Formatta qualsiasi tipo intero di base formattato come intero ottale senza segno. |
% e,% E,% f,% F,% g,% G | Formatta qualsiasi tipo di virgola mobile di base (float, float32) formattato utilizzando specifiche di formato a virgola mobile in stile C. |
% e,% E | Formatta un valore con segno avente la forma [-] d.dddde [segno] ddd dove d è una singola cifra decimale, dddd è una o più cifre decimali, ddd è esattamente tre cifre decimali e il segno è + o -. |
% f | Formatta un valore con segno avente la forma [-] dddd.dddd, dove dddd è una o più cifre decimali. Il numero di cifre prima della virgola decimale dipende dalla grandezza del numero e il numero di cifre dopo la virgola decimale dipende dalla precisione richiesta. |
% g,% G | Formatta un valore con segno stampato in formato f o e, a seconda di quale sia più compatto per il valore e la precisione dati. |
% M | Formatta un valore Decimal. |
% O | Formatta qualsiasi valore, stampato inscatolando l'oggetto e usando il suo ToString metodo. |
% A,% + A | Formatta qualsiasi valore, stampato con le impostazioni di layout predefinite. Usa% + A per stampare la struttura dei sindacati discriminati con rappresentazioni interne e private. |
%un | Un identificatore di formato generale, richiede due argomenti. Il primo argomento è una funzione che accetta due argomenti: primo, un parametro di contesto del tipo appropriato per la funzione di formattazione data (ad esempio, un TextWriter) e secondo, un valore da stampare e che restituisce o restituisce il testo appropriato. Il secondo argomento è il valore particolare da stampare. |
% t | Un identificatore di formato generale richiede un argomento: una funzione che accetta un parametro di contesto del tipo appropriato per la funzione di formattazione data (aTextWriter) e che restituisce o restituisce il testo appropriato. I tipi interi di base sonobyte, sbyte, int16, uint16, int32, uint32, int64, uint64, nativeint, e unativeint. I tipi di virgola mobile di base sono float e float32. |
Il widthè un parametro opzionale. È un numero intero che indica la larghezza minima del risultato. Ad esempio,% 5d stampa un numero intero con almeno spazi di 5 caratteri.
Valido flags sono descritti nella tabella seguente -
Valore | Descrizione |
---|---|
0 | Specifica di aggiungere zeri invece di spazi per ottenere la larghezza richiesta. |
- | Specifica di giustificare a sinistra il risultato entro la larghezza specificata. |
+ | Specifica di aggiungere un carattere + se il numero è positivo (per far corrispondere un segno - per i numeri negativi). |
' ' (spazio) | Specifica di aggiungere uno spazio extra se il numero è positivo (per far corrispondere un segno - per i numeri negativi). |
# | Non valido. |
Esempio
printf "Hello "
printf "World"
printfn ""
printfn "Hello "
printfn "World"
printf "Hi, I'm %s and I'm a %s" "Rohit" "Medical Student"
printfn "d: %f" 212.098f
printfn "e: %f" 504.768f
printfn "x: %g" 212.098f
printfn "y: %g" 504.768f
printfn "x: %e" 212.098f
printfn "y: %e" 504.768f
printfn "True: %b" true
Quando compili ed esegui il programma, restituisce il seguente output:
Hello World
Hello
World
Hi, I'm Rohit and I'm a Medical Studentd: 212.098000
e: 504.768000
x: 212.098
y: 504.768
x: 2.120980e+002
y: 5.047680e+002
True: true
La classe della console
Questa classe fa parte del framework .NET. Rappresenta i flussi di input, output e errore standard per le applicazioni della console.
Fornisce vari metodi per leggere e scrivere nella console. La tabella seguente mostra i metodi:
Metodo | Descrizione |
---|---|
Beep () | Riproduce il suono di un segnale acustico attraverso l'altoparlante della console. |
Beep (Int32, Int32) | Riproduce il suono di un segnale acustico di una frequenza e una durata specificate attraverso l'altoparlante della console. |
Chiaro | Cancella il buffer della console e la finestra della console corrispondente delle informazioni di visualizzazione. |
MoveBufferArea (Int32, Int32, Int32, Int32, Int32, Int32) | Copia un'area di origine specificata del buffer dello schermo in un'area di destinazione specificata. |
MoveBufferArea (Int32, Int32, Int32, Int32, Int32, Int32, Char, ConsoleColor, ConsoleColor) | Copia un'area di origine specificata del buffer dello schermo in un'area di destinazione specificata. |
OpenStandardError () | Acquisisce il flusso di errore standard. |
OpenStandardError (Int32) | Acquisisce il flusso di errore standard, che è impostato su una dimensione del buffer specificata. |
OpenStandardInput () | Acquisisce il flusso di input standard. |
OpenStandardInput (Int32) | Acquisisce il flusso di input standard, che è impostato su una dimensione del buffer specificata. |
OpenStandardOutput () | Acquisisce il flusso di output standard. |
OpenStandardOutput (Int32) | Acquisisce il flusso di output standard, che è impostato su una dimensione del buffer specificata. |
Leggere | Legge il carattere successivo dal flusso di input standard. |
ReadKey () | Ottiene il carattere o il tasto funzione successivo premuto dall'utente. Il tasto premuto viene visualizzato nella finestra della console. |
ReadKey (booleano) | Ottiene il carattere o il tasto funzione successivo premuto dall'utente. Il tasto premuto viene visualizzato facoltativamente nella finestra della console. |
Linea di lettura | Legge la riga di caratteri successiva dal flusso di input standard. |
ResetColor | Imposta i colori di primo piano e di sfondo della console sui valori predefiniti. |
SetBufferSize | Imposta l'altezza e la larghezza dell'area del buffer dello schermo sui valori specificati. |
SetCursorPosition | Imposta la posizione del cursore. |
SetError | Imposta la proprietà Error sull'oggetto TextWriter specificato . |
SetIn | Imposta la proprietà In sull'oggetto TextReader specificato . |
SetOut | Imposta la proprietà Out sull'oggetto TextWriter specificato . |
SetWindowPosition | Imposta la posizione della finestra della console rispetto al buffer dello schermo. |
SetWindowSize | Imposta l'altezza e la larghezza della finestra della console sui valori specificati. |
Scrivi (booleano) | Scrive la rappresentazione testuale del valore booleano specificato nel flusso di output standard. |
Scrivi (Char) | Scrive il valore del carattere Unicode specificato nel flusso di output standard. |
Scrivi (Char []) | Scrive la matrice specificata di caratteri Unicode nel flusso di output standard. |
Scrivi (decimale) | Scrive la rappresentazione testuale del valore Decimal specificato nel flusso di output standard. |
Scrivi (doppia) | Scrive la rappresentazione testuale del valore a virgola mobile e precisione doppia specificato nel flusso di output standard. |
Scrivi (Int32) | Scrive la rappresentazione testuale del valore intero con segno a 32 bit specificato nel flusso di output standard. |
Scrivi (Int64) | Scrive la rappresentazione testuale del valore intero con segno a 64 bit specificato nel flusso di output standard. |
Scrivi (oggetto) | Scrive la rappresentazione testuale dell'oggetto specificato nel flusso di output standard. |
Scrivi (singolo) | Scrive la rappresentazione testuale del valore a virgola mobile a precisione singola specificato nel flusso di output standard. |
Scrivi (stringa) | Scrive il valore di stringa specificato nel flusso di output standard. |
Scrivi (UInt32) | Scrive la rappresentazione testuale del valore intero senza segno a 32 bit specificato nel flusso di output standard. |
Scrivi (UInt64) | Scrive la rappresentazione testuale del valore intero senza segno a 64 bit specificato nel flusso di output standard. |
Scrivi (stringa, oggetto) | Scrive la rappresentazione testuale dell'oggetto specificato nel flusso di output standard utilizzando le informazioni sul formato specificate. |
Scrivi (stringa, oggetto []) | Scrive la rappresentazione testuale della matrice di oggetti specificata nel flusso di output standard utilizzando le informazioni sul formato specificate. |
Scrivi (Char [], Int32, Int32) | Scrive il sottoarray specificato di caratteri Unicode nel flusso di output standard. |
Scrivi (stringa, oggetto, oggetto) | Scrive la rappresentazione testuale degli oggetti specificati nel flusso di output standard utilizzando le informazioni sul formato specificate. |
Scrivi (stringa, oggetto, oggetto, oggetto) | Scrive la rappresentazione testuale degli oggetti specificati nel flusso di output standard utilizzando le informazioni sul formato specificate. |
Scrivi (stringa, oggetto, oggetto, oggetto, oggetto) | Scrive la rappresentazione testuale degli oggetti specificati e l'elenco dei parametri di lunghezza variabile nel flusso di output standard utilizzando le informazioni sul formato specificato. |
Linea di scrittura() | Scrive il terminatore di riga corrente nel flusso di output standard. |
WriteLine (Boolean) | Scrive la rappresentazione testuale del valore booleano specificato, seguita dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (Char) | Scrive il carattere Unicode specificato, seguito dal terminatore di riga corrente, valore nel flusso di output standard. |
WriteLine (Char []) | Scrive la matrice specificata di caratteri Unicode, seguita dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (decimale) | Scrive la rappresentazione testuale del valore Decimal specificato, seguita dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (Double) | Scrive la rappresentazione testuale del valore a virgola mobile e precisione doppia specificato, seguita dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (Int32) | Scrive la rappresentazione testuale del valore intero con segno a 32 bit specificato, seguita dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (Int64) | Scrive la rappresentazione testuale del valore intero con segno a 64 bit specificato, seguita dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (oggetto) | Scrive la rappresentazione testuale dell'oggetto specificato, seguita dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (Single) | Scrive la rappresentazione testuale del valore a virgola mobile a precisione singola specificato, seguita dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (stringa) | Scrive il valore di stringa specificato, seguito dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (UInt32) | Scrive la rappresentazione testuale del valore intero senza segno a 32 bit specificato, seguita dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (UInt64) | Scrive la rappresentazione testuale del valore intero senza segno a 64 bit specificato, seguito dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (String, Object) | Scrive la rappresentazione testuale dell'oggetto specificato, seguita dal terminatore di riga corrente, nel flusso di output standard utilizzando le informazioni sul formato specificato. |
WriteLine (String, Object []) | Scrive la rappresentazione testuale della matrice di oggetti specificata, seguita dal terminatore di riga corrente, nel flusso di output standard utilizzando le informazioni sul formato specificato. |
WriteLine (Char [], Int32, Int32) | Scrive il sottoarray specificato di caratteri Unicode, seguito dal terminatore di riga corrente, nel flusso di output standard. |
WriteLine (String, Object, Object) | Scrive la rappresentazione testuale degli oggetti specificati, seguita dal terminatore di riga corrente, nel flusso di output standard utilizzando le informazioni sul formato specificato. |
WriteLine (String, Object, Object, Object) | Scrive la rappresentazione testuale degli oggetti specificati, seguita dal terminatore di riga corrente, nel flusso di output standard utilizzando le informazioni sul formato specificato. |
WriteLine (String, Object, Object, Object, Object) | Scrive la rappresentazione testuale degli oggetti specificati e l'elenco dei parametri di lunghezza variabile, seguita dal terminatore di riga corrente, nel flusso di output standard utilizzando le informazioni sul formato specificato. |
L'esempio seguente mostra la lettura dalla console e la scrittura in essa:
Esempio
open System
let main() =
Console.Write("What's your name? ")
let name = Console.ReadLine()
Console.Write("Hello, {0}\n", name)
Console.WriteLine(System.String.Format("Big Greetings from {0} and {1}", "TutorialsPoint", "Absoulte Classes"))
Console.WriteLine(System.String.Format("|{0:yyyy-MMM-dd}|", System.DateTime.Now))
main()
Quando compili ed esegui il programma, restituisce il seguente output:
What's your name? Kabir
Hello, Kabir
Big Greetings from TutorialsPoint and Absoulte Classes
|2015-Jan-05|
Lo spazio dei nomi System.IO
Lo spazio dei nomi System.IO contiene una varietà di classi utili per eseguire operazioni di I / O di base.
Contiene tipi o classi che consentono la lettura e la scrittura su file e flussi di dati e tipi che forniscono supporto di base per file e directory.
Classi utili per lavorare con il file system -
- La classe System.IO.File viene utilizzata per creare, aggiungere ed eliminare file.
- La classe System.IO.Directory viene utilizzata per creare, spostare ed eliminare le directory.
- La classe System.IO.Path esegue operazioni sulle stringhe, che rappresentano i percorsi dei file.
- La classe System.IO.FileSystemWatcher consente agli utenti di ascoltare le modifiche in una directory.
Classi utili per lavorare con i flussi (sequenza di byte) -
- La classe System.IO.StreamReader viene utilizzata per leggere i caratteri da un flusso.
- La classe System.IO.StreamWriter viene utilizzata per scrivere caratteri in un flusso.
- La classe System.IO.MemoryStream crea un flusso di byte in memoria.
La tabella seguente mostra tutte le classi fornite nello spazio dei nomi insieme a una breve descrizione:
Classe | Descrizione |
---|---|
BinaryReader | Legge i tipi di dati primitivi come valori binari in una codifica specifica. |
BinaryWriter | Scrive tipi primitivi in binario in un flusso e supporta la scrittura di stringhe in una codifica specifica. |
BufferedStream | Aggiunge un livello di buffering per leggere e scrivere operazioni su un altro flusso. |
Directory | Espone metodi statici per la creazione, lo spostamento e l'enumerazione di directory e sottodirectory. |
DirectoryInfo | Espone i metodi di istanza per la creazione, lo spostamento e l'enumerazione tramite directory e sottodirectory. |
DirectoryNotFoundException | Eccezione generata quando non è possibile trovare una parte di un file o di una directory. |
DriveInfo | Fornisce accesso alle informazioni su un'unità. |
DriveNotFoundException | Eccezione generata quando si tenta di accedere a un'unità o una condivisione non disponibile. |
EndOfStreamException | Eccezione generata quando si tenta di leggere oltre la fine di un flusso. |
ErrorEventArgs | Fornisce dati per l'evento FileSystemWatcher.Error. |
File | Fornisce metodi statici per la creazione, la copia, l'eliminazione, lo spostamento e l'apertura di un singolo file e aiuta nella creazione di oggetti FileStream. |
FileFormatException | L'eccezione generata quando un file di input o un flusso di dati che dovrebbe essere conforme a una determinata specifica del formato di file non è corretto. |
FileInfo | Fornisce proprietà e metodi di istanza per la creazione, la copia, l'eliminazione, lo spostamento e l'apertura di file e aiuta nella creazione di oggetti FileStream. |
FileLoadException | Eccezione generata quando viene trovato un assembly gestito ma non può essere caricato. |
FileNotFoundException | Eccezione generata quando un tentativo di accedere a un file che non esiste su disco fallisce. |
FileStream | Espone un flusso attorno a un file, supportando operazioni di lettura e scrittura sincrone e asincrone. |
FileSystemEventArgs | Fornisce dati per gli eventi della directory: modificati, creati, eliminati. |
FileSystemInfo | Fornisce la classe base per gli oggetti FileInfo e DirectoryInfo. |
FileSystemWatcher | Ascolta le notifiche di modifica del file system e genera eventi quando una directory, o un file in una directory, cambia. |
InternalBufferOverflowException | Eccezione generata quando il buffer interno è in overflow. |
InvalidDataException | Eccezione generata quando un flusso di dati è in un formato non valido. |
IODescriptionAttribute | Imposta la descrizione che i designer di oggetti visivi possono visualizzare quando fanno riferimento a un evento, un extender o una proprietà. |
IOException | Eccezione generata quando si verifica un errore di I / O. |
MemoryStream | Crea un flusso il cui archivio di backup è la memoria. |
Sentiero | Esegue operazioni su istanze String che contengono informazioni sul percorso di file o directory. Queste operazioni vengono eseguite in modo multipiattaforma. |
PathTooLongException | Eccezione generata quando un percorso o un nome file è più lungo della lunghezza massima definita dal sistema. |
PipeException | Generato quando si verifica un errore all'interno di una named pipe. |
RenamedEventArgs | Fornisce dati per l'evento Renamed. |
Stream | Fornisce una visualizzazione generica di una sequenza di byte. Questa è una classe astratta. |
StreamReader | Implementa un TextReader che legge i caratteri da un flusso di byte in una particolare codifica. |
StreamWriter | Implementa un TextWriter per scrivere caratteri in un flusso in una particolare codifica. Per esplorare il codice sorgente di .NET Framework per questo tipo, vedere la fonte di riferimento. |
StringReader | Implementa un TextReader che legge da una stringa. |
StringWriter | Implementa un TextWriter per scrivere informazioni su una stringa. Le informazioni vengono archiviate in uno StringBuilder sottostante. |
TextReader | Rappresenta un lettore in grado di leggere una serie sequenziale di caratteri. |
TextWriter | Rappresenta uno scrittore in grado di scrivere una serie sequenziale di caratteri. Questa classe è astratta. |
UnmanagedMemoryAccessor | Fornisce accesso casuale a blocchi di memoria non gestiti dal codice gestito. |
UnmanagedMemoryStream | Fornisce accesso a blocchi di memoria non gestiti dal codice gestito. |
WindowsRuntimeStorageExtensions | Contiene metodi di estensione per le interfacce IStorageFile e IStorageFolder in Windows Runtime durante lo sviluppo di app di Windows Store. |
WindowsRuntimeStreamExtensions | Contiene metodi di estensione per la conversione tra flussi in Windows Runtime e flussi gestiti nelle app .NET per Windows Store. |
Esempio
L'esempio seguente crea un file chiamato test.txt, vi scrive un messaggio, legge il testo dal file e lo stampa sulla console.
Note - La quantità di codice necessaria per farlo è sorprendentemente inferiore!
open System.IO // Name spaces can be opened just as modules
File.WriteAllText("test.txt", "Hello There\n Welcome to:\n Tutorials Point")
let msg = File.ReadAllText("test.txt")
printfn "%s" msg
Quando compili ed esegui il programma, restituisce il seguente output:
Hello There
Welcome to:
Tutorials Point
I generici consentono di ritardare la specifica del tipo di dati degli elementi di programmazione in una classe o in un metodo, fino a quando non viene effettivamente utilizzato nel programma. In altre parole, i generici ti consentono di scrivere una classe o un metodo che può funzionare con qualsiasi tipo di dati.
Si scrivono le specifiche per la classe o il metodo, con parametri sostitutivi per i tipi di dati. Quando il compilatore incontra un costruttore per la classe o una chiamata di funzione per il metodo, genera codice per gestire il tipo di dati specifico.
In F #, i valori di funzione, i metodi, le proprietà e i tipi di aggregazione come classi, record e unioni discriminate possono essere generici.
I costrutti generici contengono almeno un parametro di tipo. Le funzioni ei tipi generici consentono di scrivere codice che funziona con una varietà di tipi senza ripetere il codice per ogni tipo.
Sintassi
La sintassi per scrivere un costrutto generico è la seguente:
// Explicitly generic function.
let function-name<type-parameters> parameter-list =
function-body
// Explicitly generic method.
[ static ] member object-identifer.method-name<type-parameters> parameter-list [ return-type ] =
method-body
// Explicitly generic class, record, interface, structure,
// or discriminated union.
type type-name<type-parameters> type-definition
Esempi
(* Generic Function *)
let printFunc<'T> x y =
printfn "%A, %A" x y
printFunc<float> 10.0 20.0
Quando compili ed esegui il programma, restituisce il seguente output:
10.0, 20.0
Puoi anche rendere generica una funzione utilizzando la sintassi delle virgolette singole:
(* Generic Function *)
let printFunction (x: 'a) (y: 'a) =
printfn "%A %A" x y
printFunction 10.0 20.0
Quando compili ed esegui il programma, restituisce il seguente output:
10.0 20.0
Si noti che quando si utilizzano funzioni o metodi generici, potrebbe non essere necessario specificare gli argomenti del tipo. Tuttavia, in caso di ambiguità, è possibile fornire argomenti di tipo tra parentesi angolari come abbiamo fatto nel primo esempio.
Se hai più di un tipo, separa più argomenti di tipo con virgole.
Classe generica
Come le funzioni generiche, puoi anche scrivere classi generiche. Il seguente esempio lo dimostra:
type genericClass<'a> (x: 'a) =
do printfn "%A" x
let gr = new genericClass<string>("zara")
let gs = genericClass( seq { for i in 1 .. 10 -> (i, i*i) } )
Quando compili ed esegui il programma, restituisce il seguente output:
"zara"
seq [(1, 1); (2, 4); (3, 9); (4, 16); ...]
Un delegato è una variabile del tipo di riferimento che contiene il riferimento a un metodo. Il riferimento può essere modificato in fase di esecuzione. I delegati F # sono simili ai puntatori alle funzioni, in C o C ++.
Dichiarazione dei delegati
La dichiarazione del delegato determina i metodi a cui può fare riferimento il delegato. Un delegato può fare riferimento a un metodo, che ha la stessa firma di quella del delegato.
La sintassi per la dichiarazione del delegato è:
type delegate-typename = delegate of type1 -> type2
Ad esempio, considera i delegati:
// Delegate1 works with tuple arguments.
type Delegate1 = delegate of (int * int) -> int
// Delegate2 works with curried arguments.
type Delegate2 = delegate of int * int -> int
Entrambi i delegati possono essere utilizzati per fare riferimento a qualsiasi metodo che abbia due parametri int e restituisca una variabile di tipo int .
Nella sintassi -
type1 rappresenta il / i tipo / i di argomento.
type2 rappresenta il tipo restituito.
Nota:
I tipi di argomenti vengono automaticamente selezionati.
I delegati possono essere associati a valori di funzione e metodi statici o di istanza.
I valori della funzione F # possono essere passati direttamente come argomenti ai costruttori delegati.
Per un metodo statico, il delegato viene chiamato utilizzando il nome della classe e il metodo. Per un metodo di istanza, viene utilizzato il nome dell'istanza di oggetto e del metodo.
Il metodo Invoke sul tipo delegato chiama la funzione incapsulata.
Inoltre, i delegati possono essere passati come valori di funzione facendo riferimento al nome del metodo Invoke senza parentesi.
Il seguente esempio dimostra il concetto:
Esempio
type Myclass() =
static member add(a : int, b : int) =
a + b
static member sub (a : int) (b : int) =
a - b
member x.Add(a : int, b : int) =
a + b
member x.Sub(a : int) (b : int) =
a - b
// Delegate1 works with tuple arguments.
type Delegate1 = delegate of (int * int) -> int
// Delegate2 works with curried arguments.
type Delegate2 = delegate of int * int -> int
let InvokeDelegate1 (dlg : Delegate1) (a : int) (b: int) =
dlg.Invoke(a, b)
let InvokeDelegate2 (dlg : Delegate2) (a : int) (b: int) =
dlg.Invoke(a, b)
// For static methods, use the class name, the dot operator, and the
// name of the static method.
let del1 : Delegate1 = new Delegate1( Myclass.add )
let del2 : Delegate2 = new Delegate2( Myclass.sub )
let mc = Myclass()
// For instance methods, use the instance value name, the dot operator, and the instance method name.
let del3 : Delegate1 = new Delegate1( mc.Add )
let del4 : Delegate2 = new Delegate2( mc.Sub )
for (a, b) in [ (400, 200); (100, 45) ] do
printfn "%d + %d = %d" a b (InvokeDelegate1 del1 a b)
printfn "%d - %d = %d" a b (InvokeDelegate2 del2 a b)
printfn "%d + %d = %d" a b (InvokeDelegate1 del3 a b)
printfn "%d - %d = %d" a b (InvokeDelegate2 del4 a b)
Quando compili ed esegui il programma, restituisce il seguente output:
400 + 200 = 600
400 - 200 = 200
400 + 200 = 600
400 - 200 = 200
100 + 45 = 145
100 - 45 = 55
100 + 45 = 145
100 - 45 = 55
Un'enumerazione è un insieme di costanti intere denominate.
In F #, enumerations, conosciuto anche come enums,sono tipi integrali in cui le etichette sono assegnate a un sottoinsieme di valori. Puoi usarli al posto dei letterali per rendere il codice più leggibile e gestibile.
Dichiarazione di enumerazioni
La sintassi generale per dichiarare un'enumerazione è:
type enum-name =
| value1 = integer-literal1
| value2 = integer-literal2
...
L'esempio seguente dimostra l'uso di enumerazioni:
Esempio
// Declaration of an enumeration.
type Days =
| Sun = 0
| Mon = 1
| Tues = 2
| Wed = 3
| Thurs = 4
| Fri = 5
| Sat = 6
// Use of an enumeration.
let weekend1 : Days = Days.Sat
let weekend2 : Days = Days.Sun
let weekDay1 : Days = Days.Mon
printfn "Monday: %A" weekDay1
printfn "Saturday: %A" weekend1
printfn "Sunday: %A" weekend2
Quando compili ed esegui il programma, restituisce il seguente output:
Monday: Mon
Saturday: Sat
Sunday: Sun
La corrispondenza dei modelli consente di "confrontare i dati con una o più strutture logiche, scomporre i dati in parti costituenti o estrarre informazioni dai dati in vari modi".
In altri termini, fornisce un modo più flessibile e potente per testare i dati rispetto a una serie di condizioni ed eseguire alcuni calcoli basati sulla condizione soddisfatta.
Concettualmente, è come una serie di affermazioni if ... then.
Sintassi
In termini di alto livello, la corrispondenza dei modelli segue questa sintassi in F # -
match expr with
| pat1 - result1
| pat2 -> result2
| pat3 when expr2 -> result3
| _ -> defaultResult
Dove,
- Ogni | il simbolo definisce una condizione.
- Il simbolo -> significa "se la condizione è vera, restituisci questo valore ...".
- Il simbolo _ fornisce il modello predefinito, il che significa che corrisponde a tutte le altre cose come un carattere jolly.
Esempio 1
L'esempio seguente calcola i numeri di Fibonacci utilizzando la sintassi del pattern matching:
let rec fib n =
match n with
| 0 -> 0
| 1 -> 1
| _ -> fib (n - 1) + fib (n - 2)
for i = 1 to 10 do
printfn "Fibonacci %d: %d" i (fib i)
Quando compili ed esegui il programma, restituisce il seguente output:
Fibonacci 1: 1
Fibonacci 2: 1
Fibonacci 3: 2
Fibonacci 4: 3
Fibonacci 5: 5
Fibonacci 6: 8
Fibonacci 7: 13
Fibonacci 8: 21
Fibonacci 9: 34
Fibonacci 10: 55
Puoi anche concatenare più condizioni, che restituiscono lo stesso valore. Ad esempio:
Esempio 2
let printSeason month =
match month with
| "December" | "January" | "February" -> printfn "Winter"
| "March" | "April" -> printfn "Spring"
| "May" | "June" -> printfn "Summer"
| "July" | "August" -> printfn "Rainy"
| "September" | "October" | "November" -> printfn "Autumn"
| _ -> printfn "Season depends on month!"
printSeason "February"
printSeason "April"
printSeason "November"
printSeason "July"
Quando compili ed esegui il programma, restituisce il seguente output:
Winter
Spring
Autumn
Rainy
Funzioni di corrispondenza dei modelli
F # consente di scrivere funzioni di corrispondenza dei modelli usando il function parola chiave -
let getRate = function
| "potato" -> 10.00
| "brinjal" -> 20.50
| "cauliflower" -> 21.00
| "cabbage" -> 8.75
| "carrot" -> 15.00
| _ -> nan (* nan is a special value meaning "not a number" *)
printfn "%g"(getRate "potato")
printfn "%g"(getRate "brinjal")
printfn "%g"(getRate "cauliflower")
printfn "%g"(getRate "cabbage")
printfn "%g"(getRate "carrot")
Quando compili ed esegui il programma, restituisce il seguente output:
10
20.5
21
8.75
15
Aggiunta di filtri o protezioni ai modelli
Puoi aggiungere filtri, o protezioni, ai pattern utilizzando when parola chiave.
Esempio 1
let sign = function
| 0 -> 0
| x when x < 0 -> -1
| x when x > 0 -> 1
printfn "%d" (sign -20)
printfn "%d" (sign 20)
printfn "%d" (sign 0)
Quando compili ed esegui il programma, restituisce il seguente output:
-1
1
0
Esempio 2
let compareInt x =
match x with
| (var1, var2) when var1 > var2 -> printfn "%d is greater than %d" var1 var2
| (var1, var2) when var1 < var2 -> printfn "%d is less than %d" var1 var2
| (var1, var2) -> printfn "%d equals %d" var1 var2
compareInt (11,25)
compareInt (72, 10)
compareInt (0, 0)
Quando compili ed esegui il programma, restituisce il seguente output:
11 is less than 25
72 is greater than 10
0 equals 0
Pattern Matching con tuple
L'esempio seguente mostra la corrispondenza del modello con le tuple:
let greeting (name, subject) =
match (name, subject) with
| ("Zara", _) -> "Hello, Zara"
| (name, "English") -> "Hello, " + name + " from the department of English"
| (name, _) when subject.StartsWith("Comp") -> "Hello, " + name + " from the department of Computer Sc."
| (_, "Accounts and Finance") -> "Welcome to the department of Accounts and Finance!"
| _ -> "You are not registered into the system"
printfn "%s" (greeting ("Zara", "English"))
printfn "%s" (greeting ("Raman", "Computer Science"))
printfn "%s" (greeting ("Ravi", "Mathematics"))
Quando compili ed esegui il programma, restituisce il seguente output:
Hello, Zara
Hello, Raman from the department of Computer Sc.
You are not registered into the system
Pattern Matching con i record
L'esempio seguente mostra la corrispondenza del modello con i record:
type Point = { x: float; y: float }
let evaluatePoint (point: Point) =
match point with
| { x = 0.0; y = 0.0 } -> printfn "Point is at the origin."
| { x = xVal; y = 0.0 } -> printfn "Point is on the x-axis. Value is %f." xVal
| { x = 0.0; y = yVal } -> printfn "Point is on the y-axis. Value is %f." yVal
| { x = xVal; y = yVal } -> printfn "Point is at (%f, %f)." xVal yVal
evaluatePoint { x = 0.0; y = 0.0 }
evaluatePoint { x = 10.0; y = 0.0 }
evaluatePoint { x = 0.0; y = 10.0 }
evaluatePoint { x = 10.0; y = 10.0 }
Quando compili ed esegui il programma, restituisce il seguente output:
Point is at the origin.
Point is on the x-axis. Value is 10.000000.
Point is on the y-axis. Value is 10.000000.
Point is at (10.000000, 10.000000).
Un'eccezione è un problema che sorge durante l'esecuzione di un programma. Un'eccezione F # è una risposta a una circostanza eccezionale che si verifica durante l'esecuzione di un programma, ad esempio un tentativo di divisione per zero.
Le eccezioni forniscono un modo per trasferire il controllo da una parte all'altra di un programma. La gestione delle eccezioni F # fornisce i seguenti costrutti:
Costruire | Descrizione |
---|---|
aumentare expr | Genera l'eccezione data. |
failwith expr | Alza il System.Exception eccezione. |
prova expr con le regole | Cattura le espressioni che corrispondono alle regole del modello. |
prova infine expr expr | Esecuzione del finally espressione sia quando il calcolo ha esito positivo sia quando viene sollevata un'eccezione. |
| :? ArgumentException | Una regola che corrisponde al tipo di eccezione .NET specificato. |
| :? ArgumentException come e | Una regola che corrisponde al tipo di eccezione .NET specificato, che lega il nome e al valore dell'oggetto eccezione. |
| Errore (msg) → expr | Una regola che corrisponde all'eccezione F # di trasporto dati specificata. |
| exn → expr | Una regola che corrisponde a qualsiasi eccezione, vincolando il nome exn al valore dell'oggetto eccezione. |
| exn quando expr → expr | Una regola che corrisponde all'eccezione alla condizione data, vincolando il nome exn al valore dell'oggetto eccezione. |
Cominciamo con la sintassi di base della gestione delle eccezioni.
Sintassi
La sintassi di base per il blocco di gestione delle eccezioni F # è:
exception exception-type of argument-type
Dove,
exception-type è il nome di un nuovo tipo di eccezione F #.
argument-type rappresenta il tipo di un argomento che può essere fornito quando si solleva un'eccezione di questo tipo.
È possibile specificare più argomenti utilizzando un tipo di tupla per il tipo di argomento.
Il try...with espressione viene utilizzata per la gestione delle eccezioni nel linguaggio F #.
La sintassi per il tentativo ... con l'espressione è -
try
expression1
with
| pattern1 -> expression2
| pattern2 -> expression3
...
Il try...finally espressione consente di eseguire il codice di ripulitura anche se un blocco di codice genera un'eccezione.
Sintassi per il tentativo ... finalmente l'espressione è -
try
expression1
finally
expression2
Il raiseviene utilizzata per indicare che si è verificato un errore o una condizione eccezionale. Cattura anche le informazioni sull'errore in un oggetto eccezione.
La sintassi per la funzione raise è -
raise (expression)
Il failwith la funzione genera un'eccezione F #.
La sintassi per la funzione failwith è:
failwith error-message-string
Il invalidArg la funzione genera un'eccezione di argomento.
invalidArg parameter-name error-message-string
Esempio di gestione delle eccezioni
Esempio 1
Il seguente programma mostra la gestione delle eccezioni di base con un semplice tentativo ... con blocco -
let divisionprog x y =
try
Some (x / y)
with
| :? System.DivideByZeroException -> printfn "Division by zero!"; None
let result1 = divisionprog 100 0
Quando compili ed esegui il programma, restituisce il seguente output:
Division by zero!
Esempio 2
F # fornisce un file exceptiontipo per la dichiarazione delle eccezioni. È possibile utilizzare un tipo di eccezione direttamente nei filtri in un filetry...with espressione.
Il seguente esempio lo dimostra:
exception Error1 of string
// Using a tuple type as the argument type.
exception Error2 of string * int
let myfunction x y =
try
if x = y then raise (Error1("Equal Number Error"))
else raise (Error2("Error Not detected", 100))
with
| Error1(str) -> printfn "Error1 %s" str
| Error2(str, i) -> printfn "Error2 %s %d" str i
myfunction 20 10
myfunction 5 5
Quando compili ed esegui il programma, restituisce il seguente output:
Error2 Error Not detected 100
Error1 Equal Number Error
Esempio 3
L'esempio seguente mostra la gestione delle eccezioni annidate:
exception InnerError of string
exception OuterError of string
let func1 x y =
try
try
if x = y then raise (InnerError("inner error"))
else raise (OuterError("outer error"))
with
| InnerError(str) -> printfn "Error:%s" str
finally
printfn "From the finally block."
let func2 x y =
try
func1 x y
with
| OuterError(str) -> printfn "Error: %s" str
func2 100 150
func2 100 100
func2 100 120
Quando compili ed esegui il programma, restituisce il seguente output:
From the finally block.
Error: outer error
Error:inner error
From the finally block.
From the finally block.
Error: outer error
Esempio 4
La seguente funzione mostra il failwith funzione -
let divisionFunc x y =
if (y = 0) then failwith "Divisor cannot be zero."
else
x / y
let trydivisionFunc x y =
try
divisionFunc x y
with
| Failure(msg) -> printfn "%s" msg; 0
let result1 = trydivisionFunc 100 0
let result2 = trydivisionFunc 100 4
printfn "%A" result1
printfn "%A" result2
Quando compili ed esegui il programma, restituisce il seguente output:
Divisor cannot be zero.
0
25
Esempio 5
Il invalidArgla funzione genera un'eccezione di argomento. Il seguente programma lo dimostra:
let days = [| "Sunday"; "Monday"; "Tuesday"; "Wednesday"; "Thursday"; "Friday"; "Saturday" |]
let findDay day =
if (day > 7 || day < 1)
then invalidArg "day" (sprintf "You have entered %d." day)
days.[day - 1]
printfn "%s" (findDay 1)
printfn "%s" (findDay 5)
printfn "%s" (findDay 9)
Quando compili ed esegui il programma, restituisce il seguente output:
Sunday
Thursday
Unhandled Exception:
System.ArgumentException: You have entered 9.
…
Verranno visualizzate anche alcune altre informazioni sul file e sulla variabile che causano l'errore nel sistema, a seconda del sistema.
Le classi sono tipi che rappresentano oggetti che possono avere proprietà, metodi ed eventi. "Sono utilizzati per modellare azioni, processi e qualsiasi entità concettuale nelle applicazioni".
Sintassi
La sintassi per definire un tipo di classe è la seguente:
// Class definition:
type [access-modifier] type-name [type-params] [access-modifier] ( parameter-list ) [ as identifier ] =
[ class ]
[ inherit base-type-name(base-constructor-args) ]
[ let-bindings ]
[ do-bindings ]
member-list
...
[ end ]
// Mutually recursive class definitions:
type [access-modifier] type-name1 ...
and [access-modifier] type-name2 ...
...
Dove,
Il type-nameè un identificatore valido. Il modificatore di accesso predefinito per questo èpublic.
Il type-params descrive parametri di tipo generico facoltativo.
Il parameter-listdescrive i parametri del costruttore. Il modificatore di accesso predefinito per il costruttore principale èpublic.
Il identifier utilizzato con l'opzionale as parola chiave dà un nome alla variabile di istanza, o self-identifier, che può essere utilizzato nella definizione del tipo per fare riferimento all'istanza del tipo.
Il inherit parola chiave consente di specificare la classe di base per una classe.
Il let i collegamenti consentono di dichiarare campi o valori di funzioni locali alla classe.
Il do-bindings la sezione include il codice da eseguire sulla costruzione dell'oggetto.
Il member-list è costituito da costruttori aggiuntivi, dichiarazioni di istanze e metodi statici, dichiarazioni di interfaccia, associazioni astratte e dichiarazioni di proprietà ed eventi.
Le parole chiave class e end che segnano l'inizio e la fine della definizione sono facoltativi.
Costruttore di una classe
Il costruttore è il codice che crea un'istanza del tipo di classe.
In F #, i costruttori funzionano in modo leggermente diverso dagli altri linguaggi .Net. Nella definizione della classe, gli argomenti del costruttore principale sono descritti come elenco di parametri.
Il corpo del costruttore è costituito da let e do attacchi.
È possibile aggiungere ulteriori costruttori utilizzando la nuova parola chiave per aggiungere un membro:
new (argument-list) = constructor-body
L'esempio seguente illustra il concetto:
Esempio
Il seguente programma crea una classe di linea insieme a un costruttore che calcola la lunghezza della linea mentre viene creato un oggetto della classe -
type Line = class
val X1 : float
val Y1 : float
val X2 : float
val Y2 : float
new (x1, y1, x2, y2) as this =
{ X1 = x1; Y1 = y1; X2 = x2; Y2 = y2;}
then
printfn " Creating Line: {(%g, %g), (%g, %g)}\nLength: %g"
this.X1 this.Y1 this.X2 this.Y2 this.Length
member x.Length =
let sqr x = x * x
sqrt(sqr(x.X1 - x.X2) + sqr(x.Y1 - x.Y2) )
end
let aLine = new Line(1.0, 1.0, 4.0, 5.0)
Quando compili ed esegui il programma, restituisce il seguente output:
Creating Line: {(1, 1), (4, 5)}
Length: 5
Lascia che Bindings
Le associazioni let in una definizione di classe consentono di definire campi privati e funzioni private per le classi F #.
type Greetings(name) as gr =
let data = name
do
gr.PrintMessage()
member this.PrintMessage() =
printf "Hello %s\n" data
let gtr = new Greetings("Zara")
Quando compili ed esegui il programma, restituisce il seguente output:
Hello Zara
Si prega di notare l'uso dell'autoidentificatore gr per la classe Greetings .
Una struttura in F # è un tipo di dati di tipo valore. Ti aiuta a creare una singola variabile, a conservare i dati correlati di vari tipi di dati. Ilstruct la parola chiave viene utilizzata per creare una struttura.
Sintassi
La sintassi per definire una struttura è la seguente:
[ attributes ]
type [accessibility-modifier] type-name =
struct
type-definition-elements
end
// or
[ attributes ]
[<StructAttribute>]
type [accessibility-modifier] type-name =
type-definition-elements
Esistono due sintassi. La prima sintassi viene utilizzata principalmente, perché, se si utilizza l'estensionestruct e end parole chiave, puoi omettere il StructAttribute attributo.
Gli elementi di definizione della struttura forniscono:
- Dichiarazioni e definizioni dei membri.
- Costruttori e campi mutabili e immutabili.
- Membri e implementazioni dell'interfaccia.
A differenza delle classi, le strutture non possono essere ereditate e non possono contenere associazioni let o do. Da allora, le strutture non hanno lasciato legami; è necessario dichiarare i campi nelle strutture utilizzando ilval parola chiave.
Quando si definisce un campo e il suo tipo utilizzando valparola chiave, non è possibile inizializzare il valore del campo, ma vengono inizializzati a zero o null. Quindi, per una struttura con un costruttore implicito, ilval le dichiarazioni devono essere annotate con il DefaultValue attributo.
Esempio
Il seguente programma crea una struttura a linee insieme a un costruttore. Il programma calcola la lunghezza di una linea utilizzando la struttura -
type Line = struct
val X1 : float
val Y1 : float
val X2 : float
val Y2 : float
new (x1, y1, x2, y2) =
{X1 = x1; Y1 = y1; X2 = x2; Y2 = y2;}
end
let calcLength(a : Line)=
let sqr a = a * a
sqrt(sqr(a.X1 - a.X2) + sqr(a.Y1 - a.Y2) )
let aLine = new Line(1.0, 1.0, 4.0, 5.0)
let length = calcLength aLine
printfn "Length of the Line: %g " length
Quando compili ed esegui il programma, restituisce il seguente output:
Length of the Line: 5
È possibile ridefinire o sovraccaricare la maggior parte degli operatori incorporati disponibili in F #. Pertanto un programmatore può utilizzare anche operatori con tipi definiti dall'utente.
Gli operatori sono funzioni con nomi speciali, racchiusi tra parentesi. Devono essere definiti come membri di una classe statica. Come qualsiasi altra funzione, un operatore sovraccarico ha un tipo restituito e un elenco di parametri.
L'esempio seguente mostra un operatore + su numeri complessi -
//overloading + operator
static member (+) (a : Complex, b: Complex) =
Complex(a.x + b.x, a.y + b.y)
La funzione precedente implementa l'operatore di addizione (+) per una classe Complex definita dall'utente. Aggiunge gli attributi di due oggetti e restituisce l'oggetto Complex risultante.
Implementazione del sovraccarico dell'operatore
Il seguente programma mostra l'implementazione completa:
//implementing a complex class with +, and - operators
//overloaded
type Complex(x: float, y : float) =
member this.x = x
member this.y = y
//overloading + operator
static member (+) (a : Complex, b: Complex) =
Complex(a.x + b.x, a.y + b.y)
//overloading - operator
static member (-) (a : Complex, b: Complex) =
Complex(a.x - b.x, a.y - b.y)
// overriding the ToString method
override this.ToString() =
this.x.ToString() + " " + this.y.ToString()
//Creating two complex numbers
let c1 = Complex(7.0, 5.0)
let c2 = Complex(4.2, 3.1)
// addition and subtraction using the
//overloaded operators
let c3 = c1 + c2
let c4 = c1 - c2
//printing the complex numbers
printfn "%s" (c1.ToString())
printfn "%s" (c2.ToString())
printfn "%s" (c3.ToString())
printfn "%s" (c4.ToString())
Quando compili ed esegui il programma, restituisce il seguente output:
7 5
4.2 3.1
11.2 8.1
2.8 1.9
Uno dei concetti più importanti nella programmazione orientata agli oggetti è quello dell'ereditarietà. L'ereditarietà ci consente di definire una classe in termini di un'altra classe, il che semplifica la creazione e la manutenzione di un'applicazione. Ciò offre anche l'opportunità di riutilizzare la funzionalità del codice e tempi di implementazione rapidi.
Quando si crea una classe, invece di scrivere membri dati e funzioni membro completamente nuovi, il programmatore può designare che la nuova classe erediti i membri di una classe esistente. Questa classe esistente viene chiamata classe base e la nuova classe viene definita classe derivata.
L'idea di eredità implementa la relazione IS-A. Ad esempio, il mammifero è un animale, il cane è un mammifero quindi anche il cane è un animale e così via.
Classe di base e sottoclasse
Una sottoclasse è derivata da una classe base, che è già definita. Una sottoclasse eredita i membri della classe di base e dispone dei propri membri.
Una sottoclasse viene definita utilizzando il inherit parola chiave come mostrato di seguito -
type MyDerived(...) =
inherit MyBase(...)
In F # una classe può avere al massimo una classe base diretta. Se non si specifica una classe di base utilizzando ilinherit parola chiave, la classe eredita implicitamente da Object.
Nota:
I metodi ei membri della classe base sono disponibili per gli utenti della classe derivata come i membri diretti della classe derivata.
Lascia che i collegamenti ei parametri del costruttore siano privati di una classe e, pertanto, non è possibile accedervi dalle classi derivate.
La parola chiave basesi riferisce all'istanza della classe base. È usato come l'identificatore di sé.
Esempio
type Person(name) =
member x.Name = name
member x.Greet() = printfn "Hi, I'm %s" x.Name
type Student(name, studentID : int) =
inherit Person(name)
let mutable _GPA = 0.0
member x.StudentID = studentID
member x.GPA
with get() = _GPA
and set value = _GPA <- value
type Teacher(name, expertise : string) =
inherit Person(name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Expertise = expertise
//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")
p.Greet()
st.Greet()
tr.Greet()
Quando compili ed esegui il programma, restituisce il seguente output:
Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam
Metodi di sostituzione
È possibile sovrascrivere un comportamento predefinito di un metodo della classe base e implementarlo in modo diverso nella sottoclasse o nella classe derivata.
I metodi in F # non possono essere sovrascritti per impostazione predefinita.
Per sovrascrivere i metodi in una classe derivata, devi dichiarare il tuo metodo come sovrascrivibile usando il abstract e default parole chiave come segue:
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
Ora, il metodo Greet della classe Person può essere sovrascritto nelle classi derivate. Il seguente esempio lo dimostra:
Esempio
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
type Student(name, studentID : int) =
inherit Person(name)
let mutable _GPA = 0.0
member x.StudentID = studentID
member x.GPA
with get() = _GPA
and set value = _GPA <- value
override x.Greet() = printfn "Student %s" x.Name
type Teacher(name, expertise : string) =
inherit Person(name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Expertise = expertise
override x.Greet() = printfn "Teacher %s." x.Name
//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")
//default Greet
p.Greet()
//Overriden Greet
st.Greet()
tr.Greet()
Quando compili ed esegui il programma, restituisce il seguente output:
Hi, I'm Mohan
Student Zara
Teacher Mariam.
Classe astratta
A volte è necessario fornire un'implementazione incompleta di un oggetto, che non dovrebbe essere implementata nella realtà. Successivamente, qualche altro programmatore dovrebbe creare sottoclassi della classe astratta per un'implementazione completa.
Ad esempio, la classe Persona non sarà necessaria in un sistema di gestione scolastica. Tuttavia, sarà necessaria la classe Studente o Insegnante. In questi casi, puoi dichiarare la classe Person come classe astratta.
Il AbstractClass attributo dice al compilatore che la classe ha alcuni membri astratti.
Non è possibile creare un'istanza di una classe astratta perché la classe non è completamente implementata.
Il seguente esempio lo dimostra:
Esempio
[<AbstractClass>]
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
type Student(name, studentID : int) =
inherit Person(name)
let mutable _GPA = 0.0
member x.StudentID = studentID
member x.GPA
with get() = _GPA
and set value = _GPA <- value
override x.Greet() = printfn "Student %s" x.Name
type Teacher(name, expertise : string) =
inherit Person(name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Expertise = expertise
override x.Greet() = printfn "Teacher %s." x.Name
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")
//Overriden Greet
st.Greet()
tr.Greet()
Quando compili ed esegui il programma, restituisce il seguente output:
Student Zara
Teacher Mariam.
Le interfacce forniscono un modo astratto per scrivere i dettagli di implementazione di una classe. È un modello che dichiara i metodi che la classe deve implementare ed esporre pubblicamente.
Sintassi
Un'interfaccia specifica i set di membri correlati implementati da altre classi. Ha la seguente sintassi:
// Interface declaration:
[ attributes ]
type interface-name =
[ interface ]
[ inherit base-interface-name ...]
abstract member1 : [ argument-types1 -> ] return-type1
abstract member2 : [ argument-types2 -> ] return-type2
...
[ end ]
// Implementing, inside a class type definition:
interface interface-name with
member self-identifier.member1 argument-list = method-body1
member self-identifier.member2 argument-list = method-body2
// Implementing, by using an object expression:
[ attributes ]
let class-name (argument-list) =
{ new interface-name with
member self-identifier.member1 argument-list = method-body1
member self-identifier.member2 argument-list = method-body2
[ base-interface-definitions ]
}
member-list
Nota:
In una dichiarazione di interfaccia i membri non sono implementati.
I membri sono astratti, dichiarati dal abstractparola chiave. Tuttavia è possibile fornire un'implementazione predefinita utilizzando ildefault parola chiave.
È possibile implementare le interfacce utilizzando espressioni di oggetti o utilizzando tipi di classe.
Nell'implementazione di una classe o di un oggetto, è necessario fornire i corpi dei metodi per i metodi astratti dell'interfaccia.
Le parole chiave interface e end, che segnano l'inizio e la fine della definizione, sono facoltativi.
Per esempio,
type IPerson =
abstract Name : string
abstract Enter : unit -> unit
abstract Leave : unit -> unit
Richiamo dei metodi di interfaccia
I metodi di interfaccia vengono chiamati tramite l'interfaccia, non tramite l'istanza della classe o il tipo che implementa l'interfaccia. Per chiamare un metodo di interfaccia, eseguire il cast al tipo di interfaccia utilizzando il:> operatore (operatore upcast).
Per esempio,
(s :> IPerson).Enter()
(s :> IPerson).Leave()
L'esempio seguente illustra il concetto:
Esempio
type IPerson =
abstract Name : string
abstract Enter : unit -> unit
abstract Leave : unit -> unit
type Student(name : string, id : int) =
member this.ID = id
interface IPerson with
member this.Name = name
member this.Enter() = printfn "Student entering premises!"
member this.Leave() = printfn "Student leaving premises!"
type StuffMember(name : string, id : int, salary : float) =
let mutable _salary = salary
member this.Salary
with get() = _salary
and set(value) = _salary <- value
interface IPerson with
member this.Name = name
member this.Enter() = printfn "Stuff member entering premises!"
member this.Leave() = printfn "Stuff member leaving premises!"
let s = new Student("Zara", 1234)
let st = new StuffMember("Rohit", 34, 50000.0)
(s :> IPerson).Enter()
(s :> IPerson).Leave()
(st :> IPerson).Enter()
(st :> IPerson).Leave()
Quando compili ed esegui il programma, restituisce il seguente output:
Student entering premises!
Student leaving premises!
Stuff member entering premises!
Stuff member leaving premises!
Ereditarietà dell'interfaccia
Le interfacce possono ereditare da una o più interfacce di base.
L'esempio seguente mostra il concetto:
type Interface1 =
abstract member doubleIt: int -> int
type Interface2 =
abstract member tripleIt: int -> int
type Interface3 =
inherit Interface1
inherit Interface2
abstract member printIt: int -> string
type multiplierClass() =
interface Interface3 with
member this.doubleIt(a) = 2 * a
member this.tripleIt(a) = 3 * a
member this.printIt(a) = a.ToString()
let ml = multiplierClass()
printfn "%d" ((ml:>Interface3).doubleIt(5))
printfn "%d" ((ml:>Interface3).tripleIt(5))
printfn "%s" ((ml:>Interface3).printIt(5))
Quando compili ed esegui il programma, restituisce il seguente output:
10
15
5
Gli eventi consentono alle classi di inviare e ricevere messaggi tra loro.
Nella GUI, gli eventi sono azioni dell'utente come la pressione di un tasto, i clic, i movimenti del mouse, ecc. O alcuni eventi come le notifiche generate dal sistema. Le applicazioni devono rispondere agli eventi quando si verificano. Ad esempio, interrompe. Gli eventi vengono utilizzati per la comunicazione tra processi.
Gli oggetti comunicano tra loro tramite il passaggio di messaggi sincrono.
Gli eventi sono associati ad altre funzioni; registro oggetticallback funzioni a un evento e questi callback vengono eseguiti quando (e se) l'evento viene attivato da un oggetto.
La classe di eventi e il modulo di eventi
La classe Control.Event <'T> aiuta nella creazione di un oggetto o evento osservabile.
Ha i seguenti membri di istanza per lavorare con gli eventi:
Membro | Descrizione |
---|---|
Pubblicare | Pubblica un'osservazione come valore di prima classe. |
Trigger | Attiva un'osservazione utilizzando i parametri forniti. |
Il modulo Control.Event fornisce funzioni per la gestione dei flussi di eventi:
Valore | Descrizione |
---|---|
aggiungi: ('T → unit) → Event <' Del, 'T> → unit | Esegue la funzione data ogni volta che viene attivato l'evento specificato. |
scegli: (opzione 'T →' U) → IEvent <'Del,' T> → IEvent <'U> | Restituisce un nuovo evento che si attiva su una selezione di messaggi dall'evento originale. La funzione di selezione trasforma un messaggio originale in un nuovo messaggio opzionale. |
filtro: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> | Restituisce un nuovo evento che ascolta l'evento originale e attiva l'evento risultante solo quando l'argomento dell'evento supera la funzione data. |
mappa: ('T →' U) → IEvent <'Del,' T> → IEvent <'U> | Restituisce un nuovo evento che passa valori trasformati dalla funzione data. |
unione: IEvent <'Del1,' T> → IEvent <'Del2,' T> → IEvent <'T> | Genera l'evento di output quando uno degli eventi di input viene attivato. |
pairwise: IEvent <'Del,' T> → IEvent <'T *' T> | Restituisce un nuovo evento che si attiva alla seconda e successiva attivazione dell'evento di input. IlNth l'attivazione dell'evento di input passa gli argomenti dal file N-1th e Nthinnescando in coppia. L'argomento è passato alN-1th l'attivazione viene mantenuta in uno stato interno nascosto fino a quando il Nth si verifica il trigger. |
partizione: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> * IEvent <'T> | Restituisce un nuovo evento che ascolta l'evento originale e attiva il primo evento risultante se l'applicazione del predicato agli argomenti dell'evento ha restituito true e il secondo evento se ha restituito false. |
scansione: ('U →' T → 'U) →' U → IEvent <'Del,' T> → IEvent <'U> | Restituisce un nuovo evento costituito dai risultati dell'applicazione della funzione di accumulazione data a valori successivi attivati sull'evento di input. Un elemento di stato interno registra il valore corrente del parametro di stato. Lo stato interno non è bloccato durante l'esecuzione della funzione di accumulazione, quindi è necessario prestare attenzione che l'ingresso IEvent non venga attivato da più thread contemporaneamente. |
split: ('T → Choice <' U1, 'U2>) → IEvent <' Del, 'T> → IEvent <' U1> * IEvent <'U2> | Restituisce un nuovo evento che ascolta l'evento originale e attiva il primo evento risultante se l'applicazione della funzione agli argomenti dell'evento ha restituito un Choice1Of2 e il secondo evento se restituisce un Choice2Of2. |
Creazione di eventi
Gli eventi vengono creati e utilizzati tramite Eventclasse. Il costruttore di eventi viene utilizzato per creare un evento.
Esempio
type Worker(name : string, shift : string) =
let mutable _name = name;
let mutable _shift = shift;
let nameChanged = new Event<unit>() (* creates event *)
let shiftChanged = new Event<unit>() (* creates event *)
member this.Name
with get() = _name
and set(value) = _name <- value
member this.Shift
with get() = _shift
and set(value) = _shift <- value
Dopodiché devi esporre il campo nameChanged come membro pubblico, in modo che gli ascoltatori possano agganciarsi all'evento per il quale, usi il Publish proprietà dell'evento -
type Worker(name : string, shift : string) =
let mutable _name = name;
let mutable _shift = shift;
let nameChanged = new Event<unit>() (* creates event *)
let shiftChanged = new Event<unit>() (* creates event *)
member this.NameChanged = nameChanged.Publish (* exposed event handler *)
member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)
member this.Name
with get() = _name
and set(value) = _name <- value
nameChanged.Trigger() (* invokes event handler *)
member this.Shift
with get() = _shift
and set(value) = _shift <- value
shiftChanged.Trigger() (* invokes event handler *)
Successivamente, aggiungi i callback ai gestori di eventi. Ogni gestore di eventi ha il tipo IEvent <'T>, che fornisce diversi metodi:
Metodo | Descrizione |
---|---|
val Aggiungi: evento :( 'T → unit) → unit | Collega una funzione listener all'evento. Il listener verrà richiamato quando l'evento viene attivato. |
val AddHandler: 'del → unit | Connette un oggetto delegato del gestore all'evento. Un gestore può essere successivamente rimosso utilizzando RemoveHandler. Il listener verrà richiamato quando l'evento viene attivato. |
val RemoveHandler: 'del → unit | Rimuove un delegato listener da un archivio listener di eventi. |
La sezione seguente fornisce un esempio completo.
Esempio
Il seguente esempio dimostra il concetto e le tecniche discusse sopra:
type Worker(name : string, shift : string) =
let mutable _name = name;
let mutable _shift = shift;
let nameChanged = new Event<unit>() (* creates event *)
let shiftChanged = new Event<unit>() (* creates event *)
member this.NameChanged = nameChanged.Publish (* exposed event handler *)
member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)
member this.Name
with get() = _name
and set(value) =
_name <- value
nameChanged.Trigger() (* invokes event handler *)
member this.Shift
with get() = _shift
and set(value) =
_shift <- value
shiftChanged.Trigger() (* invokes event handler *)
let wk = new Worker("Wilson", "Evening")
wk.NameChanged.Add(fun () -> printfn "Worker changed name! New name: %s" wk.Name)
wk.Name <- "William"
wk.NameChanged.Add(fun () -> printfn "-- Another handler attached to NameChanged!")
wk.Name <- "Bill"
wk.ShiftChanged.Add(fun () -> printfn "Worker changed shift! New shift: %s" wk.Shift)
wk.Shift <- "Morning"
wk.ShiftChanged.Add(fun () -> printfn "-- Another handler attached to ShiftChanged!")
wk.Shift <- "Night"
Quando compili ed esegui il programma, restituisce il seguente output:
Worker changed name! New name: William
Worker changed name! New name: Bill
-- Another handler attached to NameChanged!
Worker changed shift! New shift: Morning
Worker changed shift! New shift: Night
-- Another handler attached to ShiftChanged!
Come per la libreria MSDN, un modulo F # è un raggruppamento di costrutti di codice F #, ad esempio tipi, valori, valori di funzione e codice in associazioni do. È implementato come una classe CLR (Common Language Runtime) che ha solo membri statici.
A seconda della situazione se l'intero file è incluso nel modulo, ci sono due tipi di dichiarazioni del modulo:
- Dichiarazione del modulo di primo livello
- Dichiarazione del modulo locale
In una dichiarazione di modulo di primo livello, l'intero file è incluso nel modulo. In questo caso, la prima dichiarazione nel file è la dichiarazione del modulo. Non è necessario indentare le dichiarazioni in un modulo di primo livello.
In una dichiarazione di modulo locale, solo le dichiarazioni rientrate in quella dichiarazione di modulo fanno parte del modulo.
Sintassi
La sintassi per la dichiarazione del modulo è la seguente:
// Top-level module declaration.
module [accessibility-modifier] [qualified-namespace.]module-name
declarations
// Local module declaration.
module [accessibility-modifier] module-name =
declarations
Tieni presente che il modificatore di accessibilità può essere uno dei seguenti: pubblico, privato, interno. L'impostazione predefinita èpublic.
I seguenti esempi dimostreranno i concetti:
Esempio 1
Il file del modulo Arithmetic.fs -
module Arithmetic
let add x y =
x + y
let sub x y =
x - y
let mult x y =
x * y
let div x y =
x / y
Il file di programma main.fs -
// Fully qualify the function name.
open Arithmetic
let addRes = Arithmetic.add 25 9
let subRes = Arithmetic.sub 25 9
let multRes = Arithmetic.mult 25 9
let divRes = Arithmetic.div 25 9
printfn "%d" addRes
printfn "%d" subRes
printfn "%d" multRes
printfn "%d" divRes
Quando compili ed esegui il programma, restituisce il seguente output:
34
16
225
2
110
90
1000
10
Esempio 2
// Module1
module module1 =
// Indent all program elements within modules that are declared with an equal sign.
let value1 = 100
let module1Function x =
x + value1
// Module2
module module2 =
let value2 = 200
// Use a qualified name to access the function.
// from module1.
let module2Function x =
x + (module1.module1Function value2)
let result = module1.module1Function 25
printfn "%d" result
let result2 = module2.module2Function 25
printfn "%d" result2
Quando compili ed esegui il programma, restituisce il seguente output:
125
325
UN namespaceè progettato per fornire un modo per mantenere un insieme di nomi separato da un altro. I nomi delle classi dichiarati in uno spazio dei nomi non entreranno in conflitto con gli stessi nomi delle classi dichiarati in un altro.
Secondo la libreria MSDN, a namespace consente di organizzare il codice in aree di funzionalità correlate consentendo di allegare un nome a un raggruppamento di elementi del programma.
Dichiarazione di uno spazio dei nomi
Per organizzare il codice in uno spazio dei nomi, è necessario dichiarare lo spazio dei nomi come prima dichiarazione nel file. Il contenuto dell'intero file diventa quindi parte dello spazio dei nomi.
namespace [parent-namespaces.]identifier
L'esempio seguente illustra il concetto:
Esempio
namespace testing
module testmodule1 =
let testFunction x y =
printfn "Values from Module1: %A %A" x y
module testmodule2 =
let testFunction x y =
printfn "Values from Module2: %A %A" x y
module usermodule =
do
testmodule1.testFunction ( "one", "two", "three" ) 150
testmodule2.testFunction (seq { for i in 1 .. 10 do yield i * i }) 200
Quando compili ed esegui il programma, restituisce il seguente output:
Values from Module1: ("one", "two", "three") 150
Values from Module2: seq [1; 4; 9; 16; ...] 200