F #-퀵 가이드
F #은 함수형 프로그래밍 언어입니다. F # 구문을 이해하려면 다음과 같은 프로그래밍 패러다임에 대한 몇 줄을 읽어야합니다.Functional Programming.
함수형 프로그래밍은 컴퓨터 프로그램을 수학 함수로 취급합니다. 함수형 프로그래밍에서 초점은 변수와 상태 대신 상수와 함수에 있습니다. 함수와 상수는 변하지 않는 것들이기 때문입니다.
함수형 프로그래밍에서는 모듈 식 프로그램을 작성합니다. 즉, 프로그램은 다른 함수를 입력으로받는 함수로 구성됩니다.
함수형 프로그래밍 언어로 작성된 프로그램은 간결한 경향이 있습니다.
F # 정보
다음은 F #에 대한 기본 정보입니다.
- 2005 년 Microsoft Research에서 개발되었습니다.
- Microsoft의 .Net 언어 제품군의 일부입니다.
- 함수형 프로그래밍 언어입니다.
- 함수형 프로그래밍 언어 인 OCaml을 기반으로합니다.
F #의 특징
OCaml의 .Net 구현입니다.
.Net CLI (공용 언어 인터페이스) 바이트 코드 또는 CLR (공용 언어 런타임)에서 실행되는 MSIL (Microsoft Intermediate Language)을 컴파일합니다.
유형 추론을 제공합니다.
풍부한 패턴 일치 구조를 제공합니다.
대화 형 스크립팅 및 디버깅 기능이 있습니다.
고차 함수를 작성할 수 있습니다.
잘 개발 된 개체 모델을 제공합니다.
F # 사용
F #은 일반적으로 다음 영역에서 사용됩니다.
- 과학적 모델 만들기
- 수학적 문제 해결
- 인공 지능 연구 작업
- 재무 모델링
- 그래픽 디자인
- CPU 설계
- 컴파일러 프로그래밍
- Telecommunications
또한 CRUD 앱, 웹 페이지, GUI 게임 및 기타 범용 프로그램에서도 사용됩니다.
이 장에서는 F # 프로그래밍에 필요한 도구에 대해 설명합니다.
F # 용 IDE (통합 개발 환경)
Microsoft는 F # 프로그래밍을위한 Visual Studio 2013을 제공합니다.
무료 Visual Studio 2013 Community Edition은 Microsoft의 공식 웹 사이트에서 구할 수 있습니다. Visual Studio 2013 Community 이상은 Visual F # 도구와 함께 제공됩니다. Asp.net Tutorial 에서 제공하는 설치 세부 정보 . Visual F # 도구에는 명령 줄 컴파일러 (fsc.exe) 및 F # Interactive (fsi.exe)가 포함됩니다.
이러한 도구를 사용하면 간단한 명령 줄 응용 프로그램에서 더 복잡한 응용 프로그램에 이르기까지 모든 종류의 F # 프로그램을 작성할 수 있습니다. 메모장과 같은 기본 텍스트 편집기를 사용하여 F # 소스 코드 파일을 작성하고 명령 줄 컴파일러를 사용하여 코드를 어셈블리로 컴파일 할 수도 있습니다.
Microsoft Visual Studio에서 다운로드 할 수 있습니다. 컴퓨터에 자동으로 설치됩니다.
링크에 F # 프로그램 작성
도구를 데비안 패키지로 가져 오거나 소스에서 직접 컴파일하는 방법에 대한 최신 지침을 보려면 F # 공식 웹 사이트를 방문하십시오. https://fsharp.org/use/linux/.
F #은 함수형 프로그래밍 언어입니다.
F #에서 함수는 데이터 형식처럼 작동합니다. 다른 변수와 같은 방식으로 함수를 선언하고 사용할 수 있습니다.
일반적으로 F # 응용 프로그램에는 특정 진입 점이 없습니다. 컴파일러는 파일의 모든 최상위 문을 위에서 아래로 실행합니다.
그러나 절차 적 프로그래밍 스타일을 따르기 위해 많은 응용 프로그램은 주 루프를 호출하는 단일 최상위 문을 유지합니다.
다음 코드는 간단한 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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
sign 5: positive
유의하십시오-
F # 코드 파일은 여러 open 네임 스페이스를 가져 오는 데 사용되는 문.
파일 본문에는 응용 프로그램의 비즈니스 논리를 구현하는 다른 기능이 포함됩니다.
메인 루프에는 실행 가능한 최상위 문이 포함되어 있습니다.
F # 프로그램의 기본 구조를 살펴 보았으므로 F # 프로그래밍 언어의 다른 기본 구성 요소를 쉽게 이해할 수 있습니다.
F #의 토큰
F # 프로그램은 다양한 토큰으로 구성됩니다. 토큰은 키워드, 식별자, 상수, 문자열 리터럴 또는 기호 일 수 있습니다. F # 토큰을 두 가지 유형으로 분류 할 수 있습니다.
- Keywords
- 기호 및 연산자
F # 키워드
다음 표는 키워드와 키워드에 대한 간략한 설명을 보여줍니다. 다음 장에서 이러한 키워드의 사용에 대해 설명합니다.
예어 | 기술 |
---|---|
abstract | 선언 된 형식에 구현이 없거나 가상이고 기본 구현이있는 메서드를 나타냅니다. |
and | 상호 재귀 바인딩, 속성 선언 및 일반 매개 변수에 대한 여러 제약 조건에 사용됩니다. |
as | 현재 클래스 개체에 개체 이름을 지정하는 데 사용됩니다. 또한 패턴 일치 내에서 전체 패턴에 이름을 지정하는 데 사용됩니다. |
assert | 디버깅 중에 코드를 확인하는 데 사용됩니다. |
base | 기본 클래스 개체의 이름으로 사용됩니다. |
begin | 자세한 구문에서 코드 블록의 시작을 나타냅니다. |
class | 자세한 구문에서 클래스 정의의 시작을 나타냅니다. |
default | 추상 메서드의 구현을 나타냅니다. 가상 메서드를 만들기 위해 추상 메서드 선언과 함께 사용됩니다. |
delegate | 대리자를 선언하는 데 사용됩니다. |
do | 루핑 구문 또는 명령형 코드를 실행하는 데 사용됩니다. |
done | 자세한 구문에서 루핑 표현식에서 코드 블록의 끝을 나타냅니다. |
downcast | 상속 체인에서 더 낮은 유형으로 변환하는 데 사용됩니다. |
downto | 안에 for 식, 역으로 계산할 때 사용됩니다. |
elif | 조건부 분기에 사용됩니다. else if의 짧은 형식입니다. |
else | 조건부 분기에 사용됩니다. |
end | 유형 정의 및 유형 확장에서 멤버 정의 섹션의 끝을 나타냅니다. 자세한 구문에서 begin 키워드로 시작하는 코드 블록의 끝을 지정하는 데 사용됩니다. |
exception | 예외 유형을 선언하는 데 사용됩니다. |
extern | 선언 된 프로그램 요소가 다른 바이너리 또는 어셈블리에 정의되어 있음을 나타냅니다. |
false | 부울 리터럴로 사용됩니다. |
finally | 예외 발생 여부에 관계없이 실행되는 코드 블록을 도입하려고 시도와 함께 사용됩니다. |
for | 반복 구조에 사용됩니다. |
fun | 익명 함수라고도하는 람다 식에 사용됩니다. |
function | 단일 인수에 대한 패턴 일치가있는 람다 식에서 fun 키워드 및 일치 식에 대한 더 짧은 대안으로 사용됩니다. |
global | 최상위 .NET 네임 스페이스를 참조하는 데 사용됩니다. |
if | 조건부 분기 구문에 사용됩니다. |
in | 시퀀스 식에 사용되며 자세한 구문에서 바인딩과 식을 구분합니다. |
inherit | 기본 클래스 또는 기본 인터페이스를 지정하는 데 사용됩니다. |
inline | 호출자의 코드에 직접 통합되어야하는 함수를 나타내는 데 사용됩니다. |
interface | 인터페이스를 선언하고 구현하는 데 사용됩니다. |
internal | 멤버가 어셈블리 내부에는 표시되지만 외부에는 표시되지 않도록 지정하는 데 사용됩니다. |
lazy | 결과가 필요할 때만 수행 할 계산을 지정하는 데 사용됩니다. |
let | 이름을 값 또는 함수에 연결하거나 바인딩하는 데 사용됩니다. |
let! | 비동기 워크 플로에서 이름을 비동기 계산 결과에 바인딩하거나 다른 계산 식에서 이름을 계산 유형 인 결과에 바인딩하는 데 사용됩니다. |
match | 값을 패턴과 비교하여 분기하는 데 사용됩니다. |
member | 객체 유형에서 속성 또는 메서드를 선언하는 데 사용됩니다. |
module | 이름을 관련 유형, 값 및 함수 그룹과 연결하여 다른 코드와 논리적으로 구분하는 데 사용됩니다. |
mutable | 변수, 즉 변경할 수있는 값을 선언하는 데 사용됩니다. |
namespace | 이름을 관련 유형 및 모듈 그룹과 연결하여 다른 코드와 논리적으로 구분하는 데 사용됩니다. |
new | 개체를 만들거나 만들 수있는 생성자를 선언, 정의 또는 호출하는 데 사용됩니다. 또한 형식에 특정 생성자가 있어야 함을 나타 내기 위해 일반 매개 변수 제약 조건에서 사용됩니다. |
not | 실제로 키워드가 아닙니다. 그러나 조합되지 않은 구조체는 일반 매개 변수 제약 조건으로 사용됩니다. |
null | 개체가 없음을 나타냅니다. 일반 매개 변수 제약에도 사용됩니다. |
of | 값의 범주 유형을 나타 내기 위해 구분 된 공용체와 대리자 및 예외 선언에 사용됩니다. |
open | 자격없이 네임 스페이스 또는 모듈의 내용을 사용할 수 있도록하는 데 사용됩니다. |
or | 부울 또는 연산자로 부울 조건과 함께 사용됩니다. ||와 같습니다. 멤버 제약에서도 사용됩니다. |
override | 기본 버전과 다른 추상 또는 가상 메서드 버전을 구현하는 데 사용됩니다. |
private | 멤버에 대한 액세스를 동일한 유형 또는 모듈의 코드로 제한합니다. |
public | 유형 외부에서 구성원에 대한 액세스를 허용합니다. |
rec | 함수가 재귀임을 나타내는 데 사용됩니다. |
return | 계산 식의 결과로 제공 할 값을 나타내는 데 사용됩니다. |
return! | 계산할 때 포함하는 계산 식의 결과를 제공하는 계산 식을 나타내는 데 사용됩니다. |
select | 추출 할 필드 또는 열을 지정하기 위해 쿼리 표현식에 사용됩니다. 이것은 문맥 키워드이므로 실제로 예약어가 아니며 적절한 문맥에서 키워드처럼 작동합니다. |
static | 형식의 인스턴스없이 호출 할 수있는 메서드 나 속성 또는 형식의 모든 인스턴스간에 공유되는 값 멤버를 나타내는 데 사용됩니다. |
struct | 구조 유형을 선언하는 데 사용됩니다. 일반 매개 변수 제약에도 사용됩니다. 모듈 정의에서 OCaml 호환성에 사용됩니다. |
then | 조건식에 사용됩니다. 또한 객체 생성 후 부작용을 수행하는 데 사용됩니다. |
to | 범위를 나타 내기 위해 for 루프에서 사용됩니다. |
true | 부울 리터럴로 사용됩니다. |
try | 예외를 생성 할 수있는 코드 블록을 도입하는 데 사용됩니다. with 또는 finally 와 함께 사용됩니다 . |
type | 클래스, 레코드, 구조, 구별 된 공용체, 열거 유형, 측정 단위 또는 유형 약어를 선언하는 데 사용됩니다. |
upcast | 상속 체인에서 더 높은 유형으로 변환하는 데 사용됩니다. |
use | 리소스를 해제하기 위해 Dispose를 호출해야하는 값에 대해 let 대신 사용됩니다. |
use! | let 대신 사용! 리소스를 해제하기 위해 Dispose를 호출해야하는 값에 대한 비동기 워크 플로 및 기타 계산 식. |
val | 제한된 상황에서 값을 나타 내기 위해 서명에 사용되거나 멤버를 선언하는 형식에 사용됩니다. |
void | .NET void 유형을 나타냅니다. 다른 .NET 언어와 상호 운용 할 때 사용됩니다. |
when | 패턴 일치에 대한 부울 조건 (가드시) 에 사용되며 일반 유형 매개 변수에 대한 제약 조건 절을 도입합니다. |
while | 루핑 구조를 소개합니다. |
with | 패턴 일치 표현식에서 match 키워드와 함께 사용됩니다. 또한 멤버 정의를 도입하고 예외 처리기를 도입하기 위해 개체 식, 레코드 복사 식 및 형식 확장에 사용됩니다. |
yield | 시퀀스에 대한 값을 생성하기 위해 시퀀스 표현식에서 사용됩니다. |
yield! | 계산 표현식에서 주어진 계산 표현식의 결과를 포함하는 계산 표현식에 대한 결과 모음에 추가하는 데 사용됩니다. |
일부 예약 키워드는 OCaml 언어에서 나왔습니다.
asr | 나라 | lor | lsl | lsr | lxor | 모드 | 시그 |
다른 일부 예약 된 키워드는 향후 F # 확장을 위해 유지됩니다.
원자 | 단절 | 확인 | 구성 요소 | const | 강제 | 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
ㅏ tuple쉼표로 구분 된 값 모음입니다. 이들은 관련 값을 함께 그룹화하는 임시 데이터 구조를 만드는 데 사용됩니다.
예를 들어, ( "Zara Ali", "Hyderabad", 10)은 두 개의 문자열 값과 하나의 int 값이있는 3- 튜플이며 유형은 (string * string * int)입니다.
튜플은 동일하거나 다른 유형의 쌍, 트리플 등이 될 수 있습니다.
여기에 몇 가지 예가 제공됩니다.
// 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)
예
이 프로그램은 4 개의 float 값의 튜플을 받아 평균을 반환하는 함수를 가지고 있습니다.
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Avg of four numbers: 7.275000
개별 튜플 멤버에 액세스
튜플의 개별 멤버는 패턴 일치를 사용하여 평가되고 인쇄 될 수 있습니다.
다음 예제는 개념을 설명합니다-
예
let display tuple1 =
match tuple1 with
| (a, b, c) -> printfn "Detail Info: %A %A %A" a b c
display ("Zara Ali", "Hyderabad", 10 )
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Detail Info: "Zara Ali" "Hyderabad" 10
F #에는 두 가지 기본 제공 함수가 있습니다. fst 과 snd, 2- 튜플의 첫 번째 항목과 두 번째 항목을 반환합니다.
다음 예제는 개념을 설명합니다-
예
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)
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
First member: 23
Second member: 30
First member: "Hello"
Second member: "World!"
First Name: "Zara"
Second Name: "Ali"
ㅏ record튜플과 비슷하지만 명명 된 필드가 포함되어 있습니다. 예를 들면
type website =
{ title : string;
url : string }
기록 정의
레코드는 다음을 사용하여 유형으로 정의됩니다. type 키워드 및 레코드 필드는 세미콜론으로 구분 된 목록으로 정의됩니다.
레코드를 정의하는 구문은 다음과 같습니다.
type recordName =
{ [ fieldName : dataType ] + }
기록 생성
레코드의 필드를 지정하여 레코드를 만들 수 있습니다. 예를 들어, 우리가 만들 수있는 웹 사이트의 기록이라는 홈페이지를 -
let homepage = { Title = "TutorialsPoint"; Url = "www.tutorialspoint.com" }
다음 예는 개념을 설명합니다.
예 1
이 프로그램은 website라는 레코드 유형을 정의합니다. 그런 다음 웹 사이트 유형의 일부 레코드를 만들고 레코드를 인쇄합니다.
(* 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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"
예 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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Before Registration: : {Name = "Zara";
ID = 10;
RegistrationText = null;
IsRegistered = false;}
After Registration: : {Name = "Zara";
ID = 10;
RegistrationText = "Registered";
IsRegistered = true;}
F #에서 목록은 동일한 형식의 순서가 지정되고 변경할 수없는 일련의 요소입니다. 링크드리스트 데이터 구조와 어느 정도 동일합니다.
F # 모듈, Microsoft.FSharp.Collections.List,목록에 대한 일반적인 작업이 있습니다. 그러나 F #은이 모듈을 자동으로 가져와 모든 F # 응용 프로그램에서 액세스 할 수 있도록합니다.
목록 생성 및 초기화
다음은 목록을 만드는 다양한 방법입니다-
목록 사용 literals.
사용 cons (::) 운영자.
사용 List.init List 모듈의 방법.
일부 사용 syntactic constructs 전화 List Comprehensions.
리터럴 나열
이 방법에서는 세미콜론으로 구분 된 값 시퀀스를 대괄호로 지정하기 만하면됩니다. 예를 들면-
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
단점 (: :) 연산자
이 방법을 사용하면 앞에 또는 cons-ing:: 연산자를 사용하여 기존 목록에 추가합니다. 예를 들면-
let list2 = 1::2::3::4::5::6::7::8::9::10::[];;
[]는 빈 목록을 나타냅니다.
초기화 방법 나열
List 모듈의 List.init 메서드는 종종 목록을 만드는 데 사용됩니다. 이 방법은 유형이 있습니다-
val init : int -> (int -> 'T) -> 'T list
첫 번째 인수는 새 목록의 원하는 길이이고 두 번째 인수는 목록에 항목을 생성하는 이니셜 라이저 함수입니다.
예를 들면
let list5 = List.init 5 (fun index -> (index, index * index, index * index * index))
여기서 index 함수는 목록을 생성합니다.
목록 이해
목록 이해는 목록을 생성하는 데 사용되는 특수 구문 구조입니다.
F # 목록 이해 구문은 범위와 생성기의 두 가지 형태로 제공됩니다.
범위에는 [시작 .. 끝] 및 [시작 .. 단계 .. 끝] 구조가 있습니다.
예를 들면
let list3 = [1 .. 10]
생성기는 다음과 같은 구조를 가지고 있습니다.-[for x in collection do ... yield expr]
예를 들면
let list6 = [ for a in 1 .. 10 do yield (a * a) ]
로 yield 키워드는 단일 값을 목록, 키워드, yield!, 값 모음을 목록으로 푸시합니다.
다음 함수는 위의 방법을 보여줍니다-
예
(* 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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]
목록 데이터 유형의 속성
다음 표는 목록 데이터 유형의 다양한 속성을 보여줍니다-
특성 | 유형 | 기술 |
---|---|---|
머리 | '티 | 첫 번째 요소. |
빈 | 'T 목록 | 적절한 유형의 빈 목록을 반환하는 정적 속성입니다. |
비었다 | 부울 | true 목록에 요소가없는 경우. |
안건 | '티 | 지정된 인덱스 (0부터 시작)의 요소입니다. |
길이 | int | 요소 수입니다. |
꼬리 | 'T 목록 | 첫 번째 요소가없는 목록입니다. |
다음 예제는 이러한 속성의 사용을 보여줍니다-
예
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))
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
목록의 기본 연산자
다음 표는 목록 데이터 유형에 대한 기본 작업을 보여줍니다-
값 | 기술 |
---|---|
추가 : 'T 목록 →'T 목록 → 'T 목록 | 첫 번째 목록의 요소와 두 번째 요소의 순서를 포함하는 새 목록을 반환합니다. |
평균 : 'T리스트 → ^ T | 목록에있는 요소의 평균을 반환합니다. |
averageBy : ( 'T → ^ U) →'T 목록 → ^ U | 목록의 각 요소에 함수를 적용하여 생성 된 요소의 평균을 반환합니다. |
선택 : ( 'T →'U 옵션) → 'T 목록 →'U 목록 | 목록의 각 요소에 주어진 함수를 적용합니다. 함수가 반환하는 각 요소에 대한 결과로 구성된 목록을 반환합니다.Some. |
수집 : ( 'T →'U리스트) → 'T리스트 →'U리스트 | 목록의 각 요소에 대해 주어진 함수를 적용합니다. 모든 결과를 연결하고 결합 된 목록을 반환합니다. |
concat : seq < 'T 목록> →'T 목록 | 각 목록의 요소를 순서대로 포함하는 새 목록을 반환합니다. |
비어 있음 : 'T 목록 | 주어진 유형의 빈 목록을 반환합니다. |
존재 : ( 'T → bool) →'T list → bool | 목록의 요소가 주어진 술어를 만족하는지 테스트합니다. |
exist2 : ( 'T1 →'T2 → bool) → 'T1 목록 →'T2 목록 → bool | 목록의 해당 요소 쌍이 주어진 술어를 충족하는지 테스트합니다. |
필터 : ( 'T → 부울) →'T리스트 → 'T리스트 | 주어진 술어가 리턴하는 콜렉션의 요소 만 포함하는 새 콜렉션을 리턴합니다. true. |
찾기 : ( 'T → bool) →'T 목록 → 'T | 주어진 함수가 반환하는 첫 번째 요소를 반환합니다. true. |
findIndex : ( 'T → bool) →'T 목록 → int | 목록에서 주어진 술어를 만족하는 첫 번째 요소의 색인을 리턴합니다. |
fold : ( 'State →'T → 'State) →'State → 'T list →'State | 컬렉션의 각 요소에 함수를 적용하여 계산을 통해 누산기 인수를 스레딩합니다. 이 함수는 두 번째 인수를 가져 와서 그 함수와 목록의 첫 번째 요소를 적용합니다. 그런 다음이 결과를 두 번째 요소와 함께 함수에 전달합니다. 마지막으로 최종 결과를 반환합니다. 입력 함수가 f이고 요소가 i0 ... iN이면이 함수는 f (... (fs i0) i1 ...) iN을 계산합니다. |
fold2 : ( 'State →'T1 → 'T2 →'State) → 'State →'T1 목록 → 'T2 목록 →'State | 두 컬렉션의 해당 요소에 함수를 적용하여 계산을 통해 누산기 인수를 스레딩합니다. 컬렉션의 크기는 동일해야합니다. 입력 함수가 f이고 요소가 i0 ... iN 및 j0 ... jN이면이 함수는 f (... (fs i0 j0) ...) iN jN을 계산합니다. |
foldBack : ( 'T →'상태 → '상태) →'T 목록 → '상태 →'상태 | 컬렉션의 각 요소에 함수를 적용하여 계산을 통해 누산기 인수를 스레딩합니다. 입력 함수가 f이고 요소가 i0 ... iN이면 f i0 (... (f iN s))를 계산합니다. |
foldBack2 : ( 'T1 →'T2 → '상태 →'상태) → 'T1 목록 →'T2 목록 → '상태 →'상태 | 두 컬렉션의 해당 요소에 함수를 적용하여 계산을 통해 누산기 인수를 스레딩합니다. 컬렉션의 크기는 동일해야합니다. 입력 함수가 f이고 요소가 i0 ... iN 및 j0 ... jN이면이 함수는 f i0 j0 (... (f iN jN s))를 계산합니다. |
forall : ( 'T → bool) →'T list → bool | 컬렉션의 모든 요소가 주어진 조건자를 만족하는지 테스트합니다. |
forall2 : ( 'T1 →'T2 → bool) → 'T1 목록 →'T2 목록 → bool | 컬렉션의 모든 해당 요소가 주어진 조건자를 쌍으로 충족하는지 테스트합니다. |
head : 'T리스트 →'T | 목록의 첫 번째 요소를 반환합니다. |
init : int → (int → 'T) →'T 목록 | 각 인덱스에서 지정된 생성기를 호출하여 목록을 만듭니다. |
isEmpty : 'T리스트 → 부울 | 보고 true 목록에 요소가 없으면 false 그렇지 않으면. |
iter : ( 'T → 단위) →'T 목록 → 단위 | 컬렉션의 각 요소에 주어진 함수를 적용합니다. |
iter2 : ( 'T1 →'T2 → 단위) → 'T1 목록 →'T2 목록 → 단위 | 주어진 함수를 두 개의 컬렉션에 동시에 적용합니다. 컬렉션의 크기는 동일해야합니다. |
iteri : (int → 'T → unit) →'T list → unit | 컬렉션의 각 요소에 주어진 함수를 적용합니다. 함수에 전달 된 정수는 요소의 인덱스를 나타냅니다. |
iteri2 : (int → 'T1 →'T2 → 단위) → 'T1 목록 →'T2 목록 → 단위 | 주어진 함수를 두 개의 컬렉션에 동시에 적용합니다. 컬렉션의 크기는 동일해야합니다. 함수에 전달 된 정수는 요소의 인덱스를 나타냅니다. |
길이 : 'T 목록 → 정수 | 목록의 길이를 반환합니다. |
map : ( 'T →'U) → 'T리스트 →'U리스트 | 컬렉션의 각 요소에 지정된 함수를 적용한 결과 인 요소가있는 새 컬렉션을 만듭니다. |
map2 : ( 'T1 →'T2 → 'U) →'T1 목록 → 'T2 목록 →'U 목록 | 지정된 함수를 쌍으로 두 컬렉션의 해당 요소에 적용한 결과 인 요소가있는 새 컬렉션을 만듭니다. |
map3 : ( 'T1 →'T2 → 'T3 →'U) → 'T1 목록 →'T2 목록 → 'T3 목록 →'U 목록 | 주어진 함수를 세 컬렉션의 해당 요소에 동시에 적용한 결과 인 요소가있는 새 컬렉션을 만듭니다. |
mapi : (int → 'T →'U) → 'T리스트 →'U리스트 | 컬렉션의 각 요소에 지정된 함수를 적용한 결과 인 요소가있는 새 컬렉션을 만듭니다. 함수에 전달 된 정수 인덱스는 변환되는 요소의 인덱스 (0부터)를 나타냅니다. |
mapi2 : (int → 'T1 →'T2 → 'U) →'T1 목록 → 'T2 목록 →'U 목록 | List.mapi와 비슷하지만 길이가 같은 두 목록에서 해당 요소를 매핑합니다. |
max : 'T리스트 →'T | Operators.max를 사용하여 비교 한 목록의 모든 요소 중 가장 큰 요소를 반환합니다. |
maxBy : ( 'T →'U) → 'T 목록 →'T | 함수 결과에 Operators.max를 사용하여 비교하여 목록의 모든 요소 중 가장 큰 요소를 반환합니다. |
min : 'T리스트 →'T | Operators.min을 사용하여 비교 한 목록의 모든 요소 중 가장 낮은 값을 반환합니다. |
minBy : ( 'T →'U) → 'T리스트 →'T | 함수 결과에 Operators.min을 사용하여 비교하여 목록의 모든 요소 중 가장 낮은 값을 반환합니다. |
nth : 'T리스트 → int →'T | 목록에 색인을 생성합니다. 첫 번째 요소에는 인덱스 0이 있습니다. |
ofArray : 'T [] →'T리스트 | 주어진 배열에서 목록을 만듭니다. |
ofSeq : seq < 'T> →'T리스트 | 주어진 열거 가능한 개체에서 새 목록을 만듭니다. |
파티션 : ( 'T → bool) →'T 목록 * 'T 목록 | 주어진 술어가 리턴하는 요소를 포함하는 두 개의 콜렉션으로 콜렉션을 분할합니다. true 과 false 각기. |
permute : (int → int) → 'T 목록 →'T 목록 | 지정된 순열에 따라 순열 된 모든 요소가있는 목록을 반환합니다. |
선택 : ( 'T →'U 옵션) → 'T 목록 →'U | 주어진 함수를 연속 요소에 적용하여 함수가 반환하는 첫 번째 결과를 반환합니다. Some 어떤 가치를 위해. |
축소 : ( 'T →'T → 'T) →'T 목록 → 'T | 컬렉션의 각 요소에 함수를 적용하여 계산을 통해 누산기 인수를 스레딩합니다. 이 함수는 지정된 함수를 목록의 처음 두 요소에 적용합니다. 그런 다음이 결과를 세 번째 요소와 함께 함수에 전달합니다. 마지막으로 최종 결과를 반환합니다. 입력 함수가 f이고 요소가 i0 ... iN이면이 함수는 f (... (f i0 i1) i2 ...) iN을 계산합니다. |
reduceBack : ( 'T →'T → 'T) →'T 목록 → 'T | 컬렉션의 각 요소에 함수를 적용하여 계산을 통해 누산기 인수를 스레딩합니다. 입력 함수가 f이고 요소가 i0 ... iN이면이 함수는 f i0 (... (f iN-1 iN))을 계산합니다. |
복제 : (int → 'T →'T 목록) | 각 인덱스에서 지정된 생성기를 호출하여 목록을 만듭니다. |
rev : 'T리스트 →'T리스트 | 역순으로 요소가있는 새 목록을 반환합니다. |
스캔 : ( '상태 →'T → '상태) →'상태 → 'T 목록 →'상태 목록 | 컬렉션의 각 요소에 함수를 적용하여 계산을 통해 누산기 인수를 스레딩합니다. 이 함수는 두 번째 인수를 취하고 지정된 함수를이 인수와 목록의 첫 번째 요소에 적용합니다. 그런 다음이 결과를 두 번째 요소와 함께 함수에 전달합니다. 마지막으로 중간 결과 목록과 최종 결과를 반환합니다. |
scanBack : ( 'T →'상태 → '상태) →'T 목록 → '상태 →'상태 목록 | foldBack과 비슷하지만 중간 및 최종 결과를 모두 반환합니다. |
정렬 : 'T리스트 →'T리스트 | Operators.compare를 사용하여 주어진 목록을 정렬합니다. |
sortBy : ( 'T →'키) → 'T 목록 →'T 목록 | 주어진 프로젝션에 의해 주어진 키를 사용하여 주어진 목록을 정렬합니다. Operators.compare를 사용하여 키를 비교합니다. |
sortWith : ( 'T →'T → int) → 'T 목록 →'T 목록 | 주어진 비교 함수를 사용하여 주어진 목록을 정렬합니다. |
합계 : ^ T 목록 → ^ T | 목록에있는 요소의 합계를 반환합니다. |
sumBy : ( 'T → ^ U) →'T 목록 → ^ U | 목록의 각 요소에 함수를 적용하여 생성 된 결과의 합계를 반환합니다. |
tail : 'T 목록 →'T 목록 | 첫 번째 요소가없는 입력 목록을 반환합니다. |
toArray : 'T 목록 →'T [] | 주어진 목록에서 배열을 만듭니다. |
toSeq : 'T 목록 → seq <'T> | 주어진 목록을 시퀀스로 봅니다. |
tryFind : ( 'T → bool) →'T 목록 → 'T 옵션 | 주어진 함수가 반환하는 첫 번째 요소를 반환합니다. true. 반환None 그러한 요소가 존재하지 않는 경우. |
tryFindIndex : ( 'T → bool) →'T 목록 → int 옵션 | 목록에서 주어진 술어를 만족하는 첫 번째 요소의 색인을 리턴합니다. 반환None 그러한 요소가 존재하지 않는 경우. |
tryPick : ( 'T →'U 옵션) → 'T 목록 →'U 옵션 | 주어진 함수를 연속 요소에 적용하여 함수가 반환하는 첫 번째 결과를 반환합니다. Some어떤 가치를 위해. 그러한 요소가 없으면 다음을 반환합니다.None. |
unzip : ( 'T1 *'T2) 목록 → 'T1 목록 *'T2 목록 | 쌍 목록을 두 목록으로 분할합니다. |
unzip3 : ( 'T1 *'T2 * 'T3) 목록 →'T1 목록 * 'T2 목록 *'T3 목록 | 트리플 목록을 세 개의 목록으로 분할합니다. |
zip : 'T1 목록 →'T2 목록 → ( 'T1 *'T2) 목록 | 두 목록을 쌍 목록으로 결합합니다. 두 목록은 길이가 같아야합니다. |
zip3 : 'T1 목록 →'T2 목록 → 'T3 목록 → ('T1 * 'T2 *'T3) 목록 | 세 목록을 트리플 목록으로 결합합니다. 목록의 길이는 같아야합니다. |
다음 예제는 위의 기능의 사용을 보여줍니다-
예 1
이 프로그램은 목록을 재귀 적으로 뒤집는 것을 보여줍니다-
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)
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
The original list: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]
그러나 rev 동일한 목적을위한 모듈의 기능-
let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
printfn "The original list: %A" list1
printfn "The reversed list: %A" (List.rev list1)
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
The original list: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]
예 2
이 프로그램은 List.filter 방법-
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The Filtered list: [2; 4; 6; 8; 10]
예제 3
그만큼 List.map 메소드는 한 유형에서 다른 유형으로 목록을 매핑합니다-
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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"]
예 4
그만큼 List.append 메소드와 @ 연산자는 한 목록을 다른 목록에 추가합니다.
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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']
예 5
그만큼 List.sort메소드는 목록을 정렬합니다. 그만큼List.sum 메소드는 목록의 요소 합계를 제공하고 List.average 방법은 목록에있는 요소의 평균을 제공합니다-
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
"접기"연산은 목록의 각 요소에 함수를 적용하고 누산기 변수의 함수 결과를 집계 한 다음 접기 연산의 결과로 누산기를 반환합니다.
예제 6
그만큼 List.fold 메서드는 왼쪽에서 오른쪽으로 각 요소에 함수를 적용하는 반면 List.foldBack 오른쪽에서 왼쪽으로 각 요소에 함수를 적용합니다.
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 ])
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Sum of the elements of list [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] is 55.
목록과 같은 시퀀스는 순서가 지정된 값 모음을 나타냅니다. 그러나 시퀀스 또는 시퀀스 식의 요소는 필요할 때 계산됩니다. 한 번에 계산되지 않으므로 무한한 데이터 구조를 나타내는 데 사용됩니다.
시퀀스 정의
시퀀스는 다음 구문을 사용하여 정의됩니다-
seq { expr }
예를 들면
let seq1 = seq { 1 .. 10 }
시퀀스 및 시퀀스 표현식 생성
목록과 유사하게 범위와 이해력을 사용하여 시퀀스를 만들 수 있습니다.
시퀀스 표현식은 시퀀스 생성을 위해 작성할 수있는 표현식입니다. 이것들은 할 수 있습니다-
- 범위를 지정하여.
- 증가 또는 감소로 범위를 지정합니다.
- 사용하여 yield 시퀀스의 일부가되는 값을 생성하는 키워드입니다.
- → 연산자를 사용합니다.
다음 예제는 개념을 보여줍니다-
예 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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); ...]
예 2
다음 프로그램은 1에서 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
1
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
시퀀스에 대한 기본 작업
다음 테이블은 시퀀스 데이터 유형에 대한 기본 작업을 보여줍니다-
값 | 기술 |
---|---|
추가 : seq < 'T> → seq <'T> → seq < 'T> | 주어진 두 열거를 하나의 연결된 열거로 래핑합니다. |
평균 : seq <^ T> → ^ T | 시퀀스에있는 요소의 평균을 반환합니다. |
averageBy : ( 'T → ^ U) → seq <'T> → ^ U | 시퀀스의 각 요소에 함수를 적용하여 생성 된 결과의 평균을 반환합니다. |
캐시 : seq < 'T> → seq <'T> | 입력 시퀀스의 캐시 된 버전에 해당하는 시퀀스를 반환합니다. |
캐스트 : IEnumerable → seq < 'T> | 느슨한 유형의 시스템을 감 쌉니다. 입력 된 시퀀스로 컬렉션 시퀀스. |
선택 : ( 'T →'U 옵션) → seq < 'T> → seq <'U> | 목록의 각 요소에 주어진 함수를 적용합니다. 함수가 반환하는 각 요소에 대한 결과로 구성된 목록을 반환합니다.Some. |
collect : ( 'T →'컬렉션) → seq < 'T> → seq <'U> | 주어진 함수를 시퀀스의 각 요소에 적용하고 모든 결과를 연결합니다. |
compareWith : ( 'T →'T → int) → seq < 'T> → seq <'T> → int | 주어진 비교 함수를 사용하여 요소별로 두 시퀀스를 비교합니다. |
concat : seq < '컬렉션> → seq <'T> | 지정된 열거 형을 하나의 연결된 열거로 결합합니다. |
countBy : ( 'T →'Key) → seq < 'T> → seq <'Key * int> | 시퀀스의 각 요소에 키 생성 함수를 적용하고 원래 시퀀스에서 고유 키와 해당 발생 횟수를 생성하는 시퀀스를 반환합니다. |
지연 : (단위 → seq < 'T>) → seq <'T> | 시퀀스의 지정된 지연된 사양에서 빌드 된 시퀀스를 반환합니다. |
구별 : seq < 'T> → seq <'T> | 항목에 대한 일반 해시 및 같음 비교에 따라 중복 항목이없는 시퀀스를 반환합니다. 요소가 시퀀스에서 여러 번 발생하면 이후 발생은 버려집니다. |
distinctBy : ( 'T →'키) → seq < 'T> → seq <'T> | 주어진 키 생성 함수에 의해 반환 된 키에 대한 일반 해시 및 동일성 비교에 따라 중복 항목이없는 시퀀스를 반환합니다. 요소가 시퀀스에서 여러 번 발생하면 이후 발생은 버려집니다. |
비어 있음 : seq < 'T> | 빈 시퀀스를 만듭니다. |
exactOne : seq < 'T> →'T | 시퀀스의 유일한 요소를 반환합니다. |
존재 : ( 'T → bool) → seq <'T> → bool | 시퀀스의 요소가 주어진 술어를 만족하는지 테스트합니다. |
exist2 : ( 'T1 →'T2 → bool) → seq < 'T1> → seq <'T2> → bool | 입력 시퀀스의 해당 요소 쌍이 주어진 조건자를 충족하는지 테스트합니다. |
필터 : ( 'T → bool) → seq <'T> → seq < 'T> | 주어진 술어가 리턴하는 콜렉션의 요소 만 포함하는 새 콜렉션을 리턴합니다. true. |
찾기 : ( 'T → bool) → seq <'T> → 'T | 주어진 함수가 반환하는 첫 번째 요소를 반환합니다. true. |
findIndex : ( 'T → bool) → seq <'T> → int | 주어진 함수가 반환하는 첫 번째 요소의 인덱스를 반환합니다. true. |
fold : ( 'State →'T → 'State) →'State → seq < 'T> →'State | 컬렉션의 각 요소에 함수를 적용하여 계산을 통해 누산기 인수를 스레딩합니다. 입력 함수가 f이고 요소가 i0 ... iN이면이 함수는 f (... (fs i0) ...) iN을 계산합니다. |
forall : ( 'T → bool) → seq <'T> → bool | 시퀀스의 모든 요소가 주어진 조건자를 충족하는지 테스트합니다. |
forall2 : ( 'T1 →'T2 → bool) → seq < 'T1> → seq <'T2> → bool | 두 시퀀스에서 가져온 모든 요소 쌍이 주어진 술어를 충족하는지 테스트합니다. 한 시퀀스가 다른 시퀀스보다 짧으면 긴 시퀀스의 나머지 요소는 무시됩니다. |
groupBy : ( 'T →'키) → seq < 'T> → seq <'Key * seq < 'T >> | 시퀀스의 각 요소에 키 생성 기능을 적용하고 고유 한 키 시퀀스를 생성합니다. 각 고유 키에는이 키와 일치하는 모든 요소의 시퀀스도 포함됩니다. |
헤드 : seq < 'T> →'T | 시퀀스의 첫 번째 요소를 반환합니다. |
init : int → (int → 'T) → seq <'T> | 반복 될 때 주어진 개수까지 주어진 함수를 호출하여 연속 요소를 반환하는 새 시퀀스를 생성합니다. 함수 호출 결과는 저장되지 않습니다. 즉, 요소를 재생성하는 데 필요한 함수가 다시 적용됩니다. 함수는 생성중인 항목의 색인을 전달합니다. |
initInfinite : (int → 'T) → seq <'T> | 반복 할 때 지정된 함수를 호출하여 연속 요소를 반환하는 새 시퀀스를 생성합니다. 함수 호출 결과는 저장되지 않습니다. 즉, 요소를 재생성하는 데 필요한 함수가 다시 적용됩니다. 함수는 생성중인 항목의 색인을 전달합니다. |
isEmpty : seq < 'T> → bool | 시퀀스에 요소가 있는지 여부를 테스트합니다. |
iter : ( 'T → 단위) → seq <'T> → 단위 | 컬렉션의 각 요소에 주어진 함수를 적용합니다. |
iter2 : ( 'T1 →'T2 → 단위) → seq < 'T1> → seq <'T2> → 단위 | 주어진 함수를 두 개의 컬렉션에 동시에 적용합니다. 한 시퀀스가 다른 시퀀스보다 짧으면 긴 시퀀스의 나머지 요소는 무시됩니다. |
iteri : (int → 'T → unit) → seq <'T> → unit | 컬렉션의 각 요소에 주어진 함수를 적용합니다. 함수에 전달 된 정수는 요소의 인덱스를 나타냅니다. |
마지막 : seq < 'T> →'T | 시퀀스의 마지막 요소를 반환합니다. |
길이 : seq < 'T> → int | 시퀀스의 길이를 반환합니다. |
맵 : ( 'T →'U) → seq < 'T> → seq <'U> | 컬렉션의 각 요소에 지정된 함수를 적용한 결과 인 요소가있는 새 컬렉션을 만듭니다. 지정된 함수는 개체에서 검색된 열거 자에 대해 MoveNext 메서드를 사용하여 요소가 요구 될 때 적용됩니다. |
map2 : ( 'T1 →'T2 → 'U) → seq <'T1> → seq < 'T2> → seq <'U> | 두 시퀀스의 해당 요소 쌍에 지정된 함수를 적용한 결과 인 요소가있는 새 컬렉션을 만듭니다. 한 입력 시퀀스가 다른 시퀀스보다 짧으면 더 긴 시퀀스의 나머지 요소는 무시됩니다. |
mapi : (int → 'T →'U) → seq < 'T> → seq <'U> | 컬렉션의 각 요소에 지정된 함수를 적용한 결과 인 요소가있는 새 컬렉션을 만듭니다. 함수에 전달 된 정수 인덱스는 변환되는 요소의 인덱스 (0부터)를 나타냅니다. |
최대 : seq < 'T> →'T | Operators.max를 사용하여 비교 한 시퀀스의 모든 요소 중 가장 큰 요소를 반환합니다. |
maxBy : ( 'T →'U) → seq < 'T> →'T | 함수 결과에 Operators.max를 사용하여 비교 한 시퀀스의 모든 요소 중 가장 큰 요소를 반환합니다. |
min : seq < 'T> →'T | Operators.min을 사용하여 비교 한 시퀀스의 모든 요소 중 가장 낮은 값을 반환합니다. |
minBy : ( 'T →'U) → seq < 'T> →'T | 함수 결과에서 Operators.min을 사용하여 비교 한 시퀀스의 모든 요소 중 가장 낮은 값을 반환합니다. |
nth : int → seq < 'T> →'T | 컬렉션 의 n 번째 요소를 계산합니다 . |
ofArray : 'T 배열 → seq <'T> | 주어진 배열을 시퀀스로 봅니다. |
ofList : 'T리스트 → seq <'T> | 주어진 목록을 시퀀스로 봅니다. |
쌍으로 : seq < 'T> → seq <'T * 'T> | 두 번째 요소의 선행 요소로만 반환되는 첫 번째 요소를 제외하고 입력 시퀀스 및 해당 선행 요소의 각 요소 시퀀스를 반환합니다. |
선택 : ( 'T →'U 옵션) → seq < 'T> →'U | 연속 요소에 주어진 함수를 적용하여 함수가 a를 반환하는 첫 번째 값을 반환합니다. Some 값. |
읽기 전용 : seq < 'T> → seq <'T> | 지정된 시퀀스 개체에 위임하는 새 시퀀스 개체를 만듭니다. 이렇게하면 원본 시퀀스가 유형 캐스트에 의해 재발견 및 변형 될 수 없습니다. 예를 들어, 배열이 주어지면 반환 된 시퀀스는 배열의 요소를 반환하지만 반환 된 시퀀스 객체를 배열로 캐스팅 할 수 없습니다. |
줄이기 : ( 'T →'T → 'T) → seq <'T> → 'T | 계산을 통해 누산기 인수를 스레딩하여 시퀀스의 각 요소에 함수를 적용합니다. 처음 두 요소에 함수를 적용하여 시작하십시오. 그런 다음이 결과를 세 번째 요소와 함께 함수에 입력합니다. 최종 결과를 반환합니다. |
스캔 : ( 'State →'T → 'State) →'State → seq < 'T> → seq <'State> | Seq.fold와 비슷하지만 요청시 계산하고 중간 및 최종 결과의 순서를 반환합니다. |
싱글 톤 : 'T → seq <'T> | 하나의 항목 만 생성하는 시퀀스를 반환합니다. |
스킵 : int → seq < 'T> → seq <'T> | 기본 시퀀스의 지정된 요소 수를 건너 뛰고 시퀀스의 나머지 요소를 생성하는 시퀀스를 반환합니다. |
skipWhile : ( 'T → bool) → seq <'T> → seq < 'T> | 반복 될 때 주어진 술어가 리턴하는 동안 기본 시퀀스의 요소를 건너 뛰는 시퀀스를 리턴합니다. true, 그런 다음 시퀀스의 나머지 요소를 생성합니다. |
정렬 : seq < 'T> → seq <'T> | 키로 정렬 된 시퀀스를 생성합니다. |
sortBy : ( 'T →'키) → seq < 'T> → seq <'T> | 시퀀스의 각 요소에 키 생성 기능을 적용하고 키로 정렬 된 시퀀스를 생성합니다. Operators.compare에서 구현 한 일반 비교를 사용하여 키를 비교합니다. |
합계 : seq <^ T> → ^ T | 시퀀스에있는 요소의 합계를 반환합니다. |
sumBy | 시퀀스의 각 요소에 함수를 적용하여 생성 된 결과의 합계를 반환합니다. |
take : int → seq < 'T> → seq <'T> | 시퀀스의 첫 번째 요소를 지정된 개수까지 반환합니다. |
takeWhile : ( 'T → bool) → seq <'T> → seq < 'T> | 반복 될 때 주어진 술어가 리턴하는 동안 기본 시퀀스의 요소를 생성하는 시퀀스를 리턴합니다. true, 그런 다음 더 이상 요소를 반환하지 않습니다. |
toArray : seq < 'T> →'T [] | 지정된 컬렉션에서 배열을 만듭니다. |
toList : seq < 'T> →'T리스트 | 주어진 컬렉션에서 목록을 만듭니다. |
자르기 : int → seq < 'T> → seq <'T> | 열거 될 때 지정된 수의 요소 만 반환하는 시퀀스를 반환합니다. |
tryFind : ( 'T → bool) → seq <'T> → 'T 옵션 | 주어진 함수가 반환하는 첫 번째 요소를 반환합니다. true, 또는 None 그러한 요소가 존재하지 않는 경우. |
tryFindIndex : ( 'T → bool) → seq <'T> → int 옵션 | 시퀀스에서 주어진 술어를 만족하는 첫 번째 요소의 인덱스를 반환합니다. None 그러한 요소가 존재하지 않는 경우. |
tryPick : ( 'T →'U 옵션) → seq < 'T> →'U 옵션 | 연속 요소에 주어진 함수를 적용하여 함수가 a를 반환하는 첫 번째 값을 반환합니다. Some 값. |
펼치기 : ( 'State →'T * 'State 옵션) →'State → seq < 'T> | 주어진 계산에 의해 생성 된 요소를 포함하는 시퀀스를 반환합니다. |
여기서 : ( 'T → bool) → seq <'T> → seq < 'T> | 주어진 술어가 리턴하는 콜렉션의 요소 만 포함하는 새 콜렉션을 리턴합니다. true. Seq.filter의 동의어입니다. |
창 : int → seq < 'T> → seq <'T []> | 입력 시퀀스에서 가져온 요소를 포함하는 슬라이딩 윈도우를 생성하는 시퀀스를 반환합니다. 각 창은 새로운 배열로 반환됩니다. |
zip : seq < 'T1> → seq <'T2> → seq < 'T1 *'T2> | 두 시퀀스를 쌍 목록으로 결합합니다. 두 시퀀스의 길이가 같을 필요는 없습니다. 한 시퀀스가 소진되면 다른 시퀀스의 나머지 요소는 무시됩니다. |
zip3 : seq < 'T1> → seq <'T2> → seq < 'T3> → seq <'T1 * 'T2 *'T3> | 세 시퀀스를 트리플 목록으로 결합합니다. 시퀀스의 길이가 같을 필요는 없습니다. 하나의 시퀀스가 소진되면 다른 시퀀스의 나머지 요소는 무시됩니다. |
다음 예제는 위의 일부 기능의 사용을 보여줍니다-
예 1
이 프로그램은 빈 시퀀스를 생성하고 나중에 채 웁니다.
(* 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""
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
유의하십시오-
Seq.empty 메서드는 빈 시퀀스를 만듭니다.
Seq.singleton 메서드는 지정된 요소 하나의 시퀀스를 만듭니다.
Seq.init 메서드는 주어진 함수를 사용하여 요소가 생성되는 시퀀스를 생성합니다.
Seq.ofArray 및 Seq.ofList < 'T> 메서드는 배열과 목록에서 시퀀스를 만듭니다.
Seq.iter 메서드를 사용하면 시퀀스를 반복 할 수 있습니다.
예 2
Seq.unfold 메서드는 상태를 가져 와서 시퀀스의 각 후속 요소를 생성하도록 변환하는 계산 함수에서 시퀀스를 생성합니다.
다음 함수는 처음 20 개의 자연수를 생성합니다.
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" "
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
예제 3
Seq.truncate 메서드는 다른 시퀀스에서 시퀀스를 생성하지만 시퀀스를 지정된 요소 수로 제한합니다.
Seq.take 메서드는 시퀀스 시작부터 지정된 수의 요소를 포함하는 새 시퀀스를 만듭니다.
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""
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
F #의 집합은 항목이 삽입되는 순서를 유지하지 않고 항목 컬렉션 역할을하는 데이터 구조입니다. 집합은 컬렉션에 중복 항목을 삽입 할 수 없습니다.
세트 생성
세트는 다음과 같은 방법으로 만들 수 있습니다.
- Set.empty를 사용하여 빈 집합을 만들고 add 함수를 사용하여 항목을 추가합니다.
- 시퀀스와 목록을 세트로 변환합니다.
다음 프로그램은 기술을 보여줍니다-
(* 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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]
세트에 대한 기본 작업
다음 표는 세트에 대한 기본 작업을 보여줍니다-
값 | 기술 |
---|---|
추가 : 'T → Set <'T> → Set < 'T> | 집합에 요소가 추가 된 새 집합을 반환합니다. 세트에 이미 주어진 요소가 포함되어 있으면 예외가 발생하지 않습니다. |
포함 : 'T → Set <'T> → bool | 평가 true 주어진 요소가 주어진 세트에있는 경우. |
개수 : Set < 'T> → int | 집합의 요소 수를 반환합니다. |
차이 : Set < 'T> → Set <'T> → Set < 'T> | 두 번째 집합의 요소가 첫 번째 집합에서 제거 된 새 집합을 반환합니다. |
비어 있음 : 설정 < 'T> | 지정된 유형에 대한 빈 세트입니다. |
존재 : ( 'T → bool) → Set <'T> → bool | 컬렉션의 요소가 주어진 조건자를 만족하는지 테스트합니다. 입력 함수가 술어이고 요소가 i0 ... iN이면이 함수는 술어 i0 또는 ... 또는 술어 iN을 계산합니다. |
필터 : ( 'T → bool) → Set <'T> → Set < 'T> | 주어진 술어가 리턴하는 콜렉션의 요소 만 포함하는 새 콜렉션을 리턴합니다. true. |
fold : ( 'State →'T → 'State) →'State → Set < 'T> →'State | 주어진 누적 함수를 세트의 모든 요소에 적용합니다. |
foldBack : ( 'T →'상태 → '상태) → 설정 <'T> → '상태 →'상태 | 주어진 누적 함수를 세트의 모든 요소에 적용합니다. |
forall : ( 'T → bool) → Set <'T> → bool | 컬렉션의 모든 요소가 주어진 조건자를 만족하는지 테스트합니다. 입력 함수가 p이고 요소가 i0 ... iN이면이 함수는 p i0 && ... && p iN을 계산합니다. |
교차 : Set < 'T> → Set <'T> → Set < 'T> | 두 세트의 교차점을 계산합니다. |
intersectMany : seq <Set < 'T >> → Set <'T> | 세트 시퀀스의 교차점을 계산합니다. 시퀀스는 비어 있지 않아야합니다. |
isEmpty : Set < 'T> → bool | 보고 true 세트가 비어있는 경우. |
isProperSubset : Set < 'T> → Set <'T> → bool | 평가 true 첫 번째 세트의 모든 요소가 두 번째에 있고 두 번째의 적어도 하나의 요소가 첫 번째에없는 경우. |
isProperSuperset : Set < 'T> → Set <'T> → bool | 평가 true 두 번째 세트의 모든 요소가 첫 번째 요소에 있고 첫 번째 요소 중 하나 이상이 두 번째 요소에없는 경우 |
isSubset : Set < 'T> → Set <'T> → bool | 평가 true 첫 번째 세트의 모든 요소가 두 번째에있는 경우 |
isSuperset : Set < 'T> → Set <'T> → bool | 평가 true 두 번째 세트의 모든 요소가 첫 번째에있는 경우 |
iter : ( 'T → 단위) → Set <'T> → 단위 | 비교 함수에 따라 지정된 함수를 집합의 각 요소에 순서대로 적용합니다. |
맵 : ( 'T →'U) → Set < 'T> → Set <'U> | 입력 집합의 각 요소에 지정된 함수를 적용한 결과가 포함 된 새 컬렉션을 반환합니다. |
maxElement : Set < 'T> →'T | 집합에 사용되는 순서에 따라 집합에서 가장 높은 요소를 반환합니다. |
minElement : Set < 'T> →'T | 집합에 사용되는 순서에 따라 집합에서 가장 낮은 요소를 반환합니다. |
ofArray : 'T 배열 → Set <'T> | 주어진 배열과 동일한 요소를 포함하는 집합을 만듭니다. |
ofList : 'T리스트 → Set <'T> | 주어진 목록과 동일한 요소를 포함하는 집합을 만듭니다. |
ofSeq : seq < 'T> → Set <'T> | 지정된 열거 가능한 개체에서 새 컬렉션을 만듭니다. |
파티션 : ( 'T → bool) → Set <'T> → Set < 'T> * Set <'T> | 주어진 술어가 각각 true 및 false를 리턴하는 요소를 포함하는 두 세트로 세트를 분할합니다. |
제거 : 'T → 설정 <'T> → 설정 < 'T> | 지정된 요소가 제거 된 새 집합을 반환합니다. 세트에 주어진 요소가 포함되어 있지 않으면 예외가 발생하지 않습니다. |
싱글 톤 : 'T → Set <'T> | 주어진 요소를 포함하는 집합입니다. |
toArray : Set < 'T> →'T 배열 | 집합의 요소를 순서대로 포함하는 배열을 만듭니다. |
toList : Set < 'T> →'T리스트 | 집합의 요소를 순서대로 포함하는 목록을 만듭니다. |
toSeq : Set < 'T> → seq <'T> | 컬렉션의 정렬 된 뷰를 열거 가능한 개체로 반환합니다. |
union : Set < 'T> → Set <'T> → Set < 'T> | 두 세트의 합집합을 계산합니다. |
unionMany : seq <Set < 'T >> → Set <'T> | 집합 시퀀스의 합집합을 계산합니다. |
다음 예제는 위의 일부 기능의 사용을 보여줍니다-
예
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""
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
F #에서 맵은 값을 키와 연결하는 특수한 종류의 집합입니다. 세트가 생성되는 것과 유사한 방식으로 맵이 생성됩니다.
지도 만들기
Map.empty를 사용하여 빈지도를 만들고 Add 기능을 사용하여 항목을 추가하여지도를 만듭니다. 다음 예제는 이것을 보여줍니다-
예
(* 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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")]
키를 사용하여지도의 개별 요소에 액세스 할 수 있습니다.
예
(* 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"]
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Map - students: map
[("Gillian Megan", "1504"); ("Rishita Gupta", "1502"); ("Robin Sahoo", "1503
");
("Zara Ali", "1501")]
"1501"
지도의 기본 작업
모듈 이름 추가
다음 표는지도에 대한 기본 작업을 보여줍니다-
회원 | 기술 |
---|---|
더하다 | 지정된지도에 바인딩이 추가 된 새지도를 반환합니다. |
ContainsKey | 요소가지도의 도메인에 있는지 테스트합니다. |
카운트 | 맵의 바인딩 수입니다. |
비었다 | 맵에 바인딩이 없으면 true를 반환합니다. |
안건 | 지도에서 요소를 찾습니다. 맵에 바인딩이없는 경우 KeyNotFoundException을 발생시킵니다. |
없애다 | 지도의 도메인에서 요소를 제거합니다. 요소가 없으면 예외가 발생하지 않습니다. |
TryFind | 지도에서 요소를 조회하여 Some 요소가지도의 도메인에 있고 None 그렇지 않다면. |
다음 예제는 위의 일부 기능의 사용을 보여줍니다-
예
(* 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."
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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.
공용체 또는 구별 된 공용체를 사용하면 잘 정의 된 선택 세트를 나타내는 복잡한 데이터 구조를 구축 할 수 있습니다. 예를 들어, yes 및 no 값이 두 개인 선택 변수 의 구현을 빌드해야합니다 . Unions 도구를 사용하여 이것을 디자인 할 수 있습니다.
통사론
차별 공용체는 다음 구문을 사용하여 정의됩니다-
type type-name =
| case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ]
type2 ...]
| case-identifier2 [of [fieldname3 : ]type3 [ * [ fieldname4 : ]type4 ...]
...
, choice 의 간단한 구현은 다음과 같습니다.
type choice =
| Yes
| No
다음 예제는 유형 선택을 사용합니다-
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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
x: Yes
y: No
예 1
다음 예제는 높거나 낮은 비트를 설정하는 전압 상태의 구현을 보여줍니다.
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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Switch on state: High
Switch off state: Low
Toggle off: High
Toggle the Changed state: Low
예 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)
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
F #의 변수는 다음과 같습니다. immutable,즉, 변수가 값에 바인딩되면 변경할 수 없습니다. 실제로 정적 읽기 전용 속성으로 컴파일됩니다.
다음 예제는이를 보여줍니다.
예
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
프로그램을 컴파일하고 실행하면 다음과 같은 오류 메시지가 표시됩니다.
Duplicate definition of value 'x'
Duplicate definition of value 'Y'
Duplicate definition of value 'Z'
가변 변수
때때로 변수에 저장된 값을 변경해야합니다. 프로그램의 뒷부분에서 선언되고 할당 된 변수의 값이 변경 될 수 있음을 지정하기 위해 F #은mutable예어. 값을 변경할이 키워드를 사용하여 변경 가능한 변수를 선언하고 할당 할 수 있습니다.
그만큼 mutable 키워드를 사용하면 가변 변수에 값을 선언하고 할당 할 수 있습니다.
다음을 사용하여 변경 가능한 변수에 초기 값을 할당 할 수 있습니다. let예어. 그러나 새로운 후속 값을 할당하려면<- 운영자.
예를 들면
let mutable x = 10
x <- 15
다음 예제는 개념을 지울 것입니다-
예
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
가변 데이터의 사용
변경 가능한 데이터는 특히 레코드 데이터 구조와 함께 데이터 처리에 필요하고 사용됩니다. 다음 예제는 이것을 보여줍니다-
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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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";}
배열은 모두 동일한 유형 인 연속 데이터 요소의 고정 크기, 0 기반, 변경 가능한 컬렉션입니다.
배열 생성
다양한 구문과 방법을 사용하거나 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" "
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
1 2 3 4 5 6
1 2 3 4 5
1 4 9 16 25 36 49 64 81 100
배열에 대한 기본 작업
라이브러리 모듈 Microsoft.FSharp.Collections.Array는 1 차원 배열에 대한 작업을 지원합니다.
다음 표는 배열에 대한 기본 작업을 보여줍니다-
값 | 기술 |
---|---|
추가 : 'T [] →'T [] → 'T [] | 한 배열의 요소와 다른 배열의 요소를 포함하는 배열을 만듭니다. |
평균 : ^ T [] → ^ T | 배열에있는 요소의 평균을 반환합니다. |
averageBy : ( 'T → ^ U) →'T [] → ^ U | 배열의 각 요소에 함수를 적용하여 생성 된 요소의 평균을 반환합니다. |
blit : 'T [] → int →'T [] → int → int → 단위 | 한 배열에서 요소 범위를 읽고 다른 배열에 씁니다. |
선택 : ( 'T → U 옵션) →'T [] → 'U [] | 제공된 함수를 배열의 각 요소에 적용합니다. 함수가 Some (x)를 반환하는 각 요소에 대한 결과 x를 포함하는 배열을 반환합니다. |
수집 : ( 'T →'U []) → T [] → 'U [] | 제공된 함수를 배열의 각 요소에 적용하고 결과를 연결하고 결합 된 배열을 반환합니다. |
연결 : seq < 'T []> →'T [] | 제공된 각 배열 시퀀스의 요소를 포함하는 배열을 만듭니다. |
복사 : 'T →'T [] | 제공된 배열의 요소를 포함하는 배열을 만듭니다. |
생성 : int → 'T →'T [] | 요소가 모두 초기에 제공된 값인 배열을 만듭니다. |
비어 있음 : 'T [] | 주어진 유형의 빈 배열을 반환합니다. |
존재 : ( 'T → bool) →'T [] → bool | 배열의 요소가 제공된 조건자를 충족하는지 여부를 테스트합니다. |
exist2 : ( 'T1 →'T2 → bool) → 'T1 [] →'T2 [] → bool | 두 배열의 해당 요소 쌍이 제공된 조건을 충족하는지 여부를 테스트합니다. |
채우기 : 'T [] → int → int →'T → 단위 | 배열의 요소 범위를 제공된 값으로 채 웁니다. |
필터 : ( 'T → bool) →'T [] → 'T [] | 제공된 조건이 반환하는 제공된 배열의 요소 만 포함하는 컬렉션을 반환합니다. true. |
찾기 : ( 'T → bool) →'T [] → 'T | 제공된 함수가 반환하는 첫 번째 요소를 반환합니다. true. 그러한 요소가없는 경우 KeyNotFoundException을 발생시킵니다. |
findIndex : ( 'T → bool) →'T [] → int | 제공된 조건을 충족하는 배열에서 첫 번째 요소의 인덱스를 반환합니다. 조건을 만족하는 요소가 없으면 KeyNotFoundException을 발생시킵니다. |
fold : ( 'State →'T → 'State) →'State → 'T [] →'State | 계산을 통해 누산기 인수를 스레딩하여 배열의 각 요소에 함수를 적용합니다. 입력 함수가 f이고 배열 요소가 i0 ... iN이면이 함수는 f (... (fs i0) ...) iN을 계산합니다. |
fold2 : ( '상태 →'T1 → 'T2 →'상태) → '상태 →'T1 [] → 'T2 [] →'상태 | 계산을 통해 누산기 인수를 스레딩하는 왼쪽에서 오른쪽으로 제공된 두 배열의 요소 쌍에 함수를 적용합니다. 두 입력 배열의 길이는 같아야합니다. 그렇지 않으면 ArgumentException이 발생합니다. |
foldBack : ( 'T →'상태 → '상태) →'T [] → '상태 →'상태 | 계산을 통해 누산기 인수를 스레딩하여 배열의 각 요소에 함수를 적용합니다. 입력 함수가 f이고 배열 요소가 i0 ... iN이면이 함수는 f i0 (... (f iN s))를 계산합니다. |
foldBack2 : ( 'T1 →'T2 → '상태 →'상태) → 'T1 [] →'T2 [] → '상태 →'상태 | 계산을 통해 누산기 인수를 스레딩하는 오른쪽에서 왼쪽으로 제공된 두 배열의 요소 쌍에 함수를 적용합니다. 두 입력 배열의 길이는 같아야합니다. 그렇지 않으면 ArgumentException이 발생합니다. |
forall : ( 'T → bool) →'T [] → bool | 배열의 모든 요소가 제공된 조건을 충족하는지 테스트합니다. |
forall2 : ( 'T1 →'T2 → bool) → 'T1 [] →'T2 [] → bool | 제공된 두 배열의 모든 해당 요소가 제공된 조건을 충족하는지 테스트합니다. |
get : 'T [] → int →'T | 배열에서 요소를 가져옵니다. |
init : int → (int → 'T) →'T [] | 제공된 함수를 사용하여 제공된 차원의 배열을 만듭니다. |
isEmpty : 'T [] → bool | 배열에 요소가 있는지 여부를 테스트합니다. |
iter : ( 'T → 단위) →'T [] → 단위 | 제공된 함수를 배열의 각 요소에 적용합니다. |
iter2 : ( 'T1 →'T2 → 단위) → 'T1 [] →'T2 [] → 단위) | 제공된 함수를 두 배열의 일치하는 인덱스에서 요소 쌍에 적용합니다. 두 배열은 길이가 같아야합니다. 그렇지 않으면 ArgumentException이 발생합니다. |
iteri : (int → 'T → unit) →'T [] → unit | 제공된 함수를 배열의 각 요소에 적용합니다. 함수에 전달 된 정수는 요소의 인덱스를 나타냅니다. |
iteri2 : (int → 'T1 →'T2 → 단위) → 'T1 [] →'T2 [] → 단위 | 제공된 함수를 두 배열의 일치하는 인덱스에서 요소 쌍에 적용하고 요소의 인덱스도 전달합니다. 두 배열은 길이가 같아야합니다. 그렇지 않으면 ArgumentException이 발생합니다. |
길이 : 'T [] → int | 배열의 길이를 반환합니다. Length 속성은 동일한 작업을 수행합니다. |
지도 : ( 'T →'U) → 'T [] →'U [] | 제공된 함수를 제공된 배열의 각 요소에 적용한 결과 인 요소가있는 배열을 만듭니다. |
map2 : ( 'T1 →'T2 → 'U) →'T1 [] → 'T2 [] →'U [] | 제공된 함수를 제공된 두 배열의 해당 요소에 적용한 결과 인 요소가있는 배열을 만듭니다. 두 입력 배열의 길이는 같아야합니다. 그렇지 않으면 ArgumentException이 발생합니다. |
mapi : (int → 'T →'U) → 'T [] →'U [] | 제공된 함수를 제공된 배열의 각 요소에 적용한 결과 인 요소가있는 배열을 만듭니다. 함수에 전달 된 정수 인덱스는 변환되는 요소의 인덱스를 나타냅니다. |
mapi2 : (int → 'T1 →'T2 → 'U) →'T1 [] → 'T2 [] →'U [] | 제공된 함수를 쌍으로 두 컬렉션의 해당 요소에 적용한 결과 인 요소가 요소의 인덱스도 전달하는 배열을 만듭니다. 두 입력 배열의 길이는 같아야합니다. 그렇지 않으면 ArgumentException이 발생합니다. |
최대 : 'T [] →'T | 배열의 모든 요소 중 가장 큰 요소를 반환합니다. Operators.max는 요소를 비교하는 데 사용됩니다. |
maxBy : ( 'T →'U) → 'T [] →'T | 함수 결과에서 Operators.max를 통해 비교 한 배열의 모든 요소 중 가장 큰 요소를 반환합니다. |
min : ( 'T [] →'T | 배열의 모든 요소 중 가장 작은 요소를 반환합니다. Operators.min은 요소를 비교하는 데 사용됩니다. |
minBy : ( 'T →'U) → 'T [] →'T | 배열의 모든 요소 중 가장 작은 요소를 반환합니다. Operators.min은 요소를 비교하는 데 사용됩니다. |
ofList : 'T리스트 →'T [] | 제공된 목록에서 배열을 만듭니다. |
ofSeq : seq < 'T> →'T [] | 제공된 열거 가능한 개체에서 배열을 만듭니다. |
파티션 : ( 'T → bool) →'T [] → 'T [] *'T [] | 배열을 두 개의 배열로 분할합니다. 하나는 제공된 조건이 반환하는 요소를 포함합니다. true, 그리고 그것이 반환하는 것을 포함하는 다른 false. |
permute : (int → int) → 'T [] →'T [] | 지정된 순열에 따라 배열의 요소를 순열합니다. |
선택 : ( 'T →'U 옵션) → 'T [] →'U | 제공된 함수를 제공된 배열의 연속 요소에 적용하여 함수가 일부 x에 대해 Some (x)를 반환하는 첫 번째 결과를 반환합니다. 함수가 Some (x)를 반환하지 않으면 KeyNotFoundException이 발생합니다. |
감소 : ( 'T →'T → 'T) →'T [] → 'T | 계산을 통해 누산기 인수를 스레딩하여 배열의 각 요소에 함수를 적용합니다. 입력 함수가 f이고 배열 요소가 i0 ... iN이면이 함수는 f (... (f i0 i1) ...) iN을 계산합니다. 배열의 크기가 0이면 ArgumentException이 발생합니다. |
reduceBack : ( 'T →'T → 'T) →'T [] → 'T | 계산을 통해 누산기 인수를 스레딩하여 배열의 각 요소에 함수를 적용합니다. 입력 함수가 f이고 요소가 i0 ... iN이면이 함수는 f i0 (... (f iN-1 iN))을 계산합니다. 배열의 크기가 0이면 ArgumentException이 발생합니다. |
rev : 'T [] →'T [] | 제공된 배열에서 요소의 순서를 반대로합니다. |
스캔 : ( '상태 →'T → '상태) →'상태 → 'T [] →'상태 []) | 접기처럼 동작하지만 최종 결과와 함께 중간 결과를 반환합니다. |
scanBack : ( 'T →'상태 → '상태) →'T [] → '상태 →'상태 [] | foldBack처럼 동작하지만 최종 결과와 함께 중간 결과를 반환합니다. |
설정 : 'T [] → int →'T → 단위 | 배열의 요소를 설정합니다. |
정렬 : 'T [] →'T [] | 배열의 요소를 정렬하고 새 배열을 반환합니다. Operators.compare는 요소를 비교하는 데 사용됩니다. |
sortBy : ( 'T →'키) → 'T [] →'T [] | 제공된 함수를 사용하여 요소를 정렬 작업의 기반이되는 형식으로 변환하여 배열의 요소를 정렬하고 새 배열을 반환합니다. Operators.compare는 요소를 비교하는 데 사용됩니다. |
sortInPlace : 'T [] → 단위 | 제공된 비교 함수를 사용하여 제자리에서 배열을 변경하여 배열 요소를 정렬합니다. Operators.compare는 요소를 비교하는 데 사용됩니다. |
sortInPlaceBy : ( 'T →'키) → 'T [] → 단위 | 키에 제공된 프로젝션을 사용하여 제자리에서 배열을 변경하여 배열 요소를 정렬합니다. Operators.compare는 요소를 비교하는 데 사용됩니다. |
sortInPlaceWith : ( 'T →'T → int) → 'T [] → 단위 | 제공된 비교 함수를 사용하여 배열을 변경하여 배열의 요소를 정렬합니다. |
sortWith : ( 'T →'T → int) → 'T [] →'T [] | 제공된 비교 함수를 사용하여 배열의 요소를 정렬하고 새 배열을 반환합니다. |
sub : 'T [] → int → int →'T [] | 시작 인덱스와 길이로 지정되는 제공된 하위 범위를 포함하는 배열을 만듭니다. |
합계 : 'T [] → ^ T | 배열에있는 요소의 합계를 반환합니다. |
sumBy : ( 'T → ^ U) →'T [] → ^ U | 배열의 각 요소에 함수를 적용하여 생성 된 결과의 합계를 반환합니다. |
toList : 'T [] →'T리스트 | 제공된 배열을 목록으로 변환합니다. |
toSeq : 'T [] → seq <'T> | 제공된 배열을 시퀀스로 봅니다. |
tryFind : ( 'T → bool) →'T [] → 'T 옵션 | 제공된 함수가 반환하는 제공된 배열의 첫 번째 요소를 반환합니다. true. 보고None 그러한 요소가 존재하지 않는 경우. |
tryFindIndex : ( 'T → bool) →'T [] → int 옵션 | 제공된 조건을 충족하는 배열에서 첫 번째 요소의 인덱스를 반환합니다. |
tryPick : ( 'T →'U 옵션) → 'T [] →'U 옵션 | 제공된 함수를 제공된 배열의 연속 요소에 적용하고 함수가 일부 x에 대해 Some (x)를 반환하는 첫 번째 결과를 반환합니다. 함수가 Some (x)를 반환하지 않으면None 반환됩니다. |
압축 해제 : ( 'T1 *'T2) [] → 'T1 [] *'T2 [] | 튜플 쌍의 배열을 두 배열의 튜플로 분할합니다. |
unzip3 : ( 'T1 *'T2 * 'T3) [] →'T1 [] * 'T2 [] *'T3 [] | 세 요소의 튜플 배열을 세 배열의 튜플로 분할합니다. |
zeroCreate : int → 'T [] | 요소가 초기에 기본값 Unchecked.defaultof < 'T>로 설정된 배열을 만듭니다. |
zip : 'T1 [] →'T2 [] → ( 'T1 *'T2) [] | 두 배열을 요소가 두 개인 튜플 배열로 결합합니다. 두 배열의 길이는 같아야합니다. 그렇지 않으면 ArgumentException이 발생합니다. |
zip3 : 'T1 [] →'T2 [] → 'T3 [] → ('T1 * 'T2 * 113'T3) [] | 세 개의 배열을 세 개의 요소가있는 튜플의 배열로 결합합니다. 세 배열의 길이는 같아야합니다. 그렇지 않으면 ArgumentException이 발생합니다. |
다음 섹션에서는 이러한 기능 중 일부를 사용하는 방법을 살펴 봅니다.
함수를 사용하여 배열 만들기
어레이 모듈은 처음부터 어레이를 생성하는 여러 기능을 제공합니다.
그만큼 Array.empty 함수는 새로운 빈 배열을 만듭니다.
그만큼 Array.create 함수는 지정된 크기의 배열을 만들고 모든 요소를 주어진 값으로 설정합니다.
그만큼 Array.init 함수는 요소를 생성하는 차원과 함수가 주어지면 배열을 만듭니다.
그만큼 Array.zeroCreate 함수는 모든 요소가 0 값으로 초기화되는 배열을 만듭니다.
그만큼 Array.copy 함수는 기존 배열에서 복사 된 요소를 포함하는 새 배열을 만듭니다.
그만큼 Array.sub 함수는 배열의 하위 범위에서 새 배열을 생성합니다.
그만큼 Array.append 함수는 두 개의 기존 배열을 결합하여 새 배열을 만듭니다.
그만큼 Array.choose 함수는 새 배열에 포함 할 배열 요소를 선택합니다.
그만큼 Array.collect 함수는 기존 배열의 각 배열 요소에서 지정된 함수를 실행 한 다음 함수에서 생성 된 요소를 수집하여 새 배열로 결합합니다.
그만큼 Array.concat 함수는 배열의 시퀀스를 가져 와서 단일 배열로 결합합니다.
그만큼 Array.filter 함수는 부울 조건 함수를 취하고 조건이 참인 입력 배열의 요소 만 포함하는 새 배열을 생성합니다.
그만큼 Array.rev 함수는 기존 배열의 순서를 반대로하여 새 배열을 생성합니다.
다음 예제는 이러한 기능을 보여줍니다-
예 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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|]
예 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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|]
어레이 검색
그만큼 Array.find 함수는 부울 함수를 취하고 함수가 true를 반환하는 첫 번째 요소를 반환하고 그렇지 않으면 KeyNotFoundException을 발생시킵니다.
그만큼 Array.findIndex 함수는 요소 자체 대신 요소의 인덱스를 반환한다는 점을 제외하면 비슷하게 작동합니다.
다음 예제는이를 보여줍니다.
마이크로 소프트는이 흥미로운 프로그램 예제를 제공합니다. 주어진 숫자의 범위에서 완전한 제곱이면서 완전한 큐브 인 첫 번째 요소를 찾습니다.
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
The first element that is both a square and a cube is 64 and its index is 62.
그만큼 List<'T> class는 인덱스로 액세스 할 수있는 강력한 형식의 개체 목록을 나타냅니다.
List 클래스의 변경 가능한 대응 요소입니다. 인덱스로 액세스 할 수 있다는 점에서 배열과 유사하지만 배열과 달리 목록의 크기를 조정할 수 있습니다. 따라서 선언 중에 크기를 지정할 필요가 없습니다.
변경 가능한 목록 만들기
목록은 new키워드 및 목록의 생성자를 호출합니다. 다음 예제는 이것을 보여줍니다-
(* 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])
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
0: Gone with the Wind
1: Atlas Shrugged
2: Fountainhead
3: Thornbirds
4: Rebecca
5: Narnia
List (T) 클래스
List (T) 클래스는 인덱스로 액세스 할 수있는 강력한 형식의 개체 목록을 나타냅니다. 목록을 검색, 정렬 및 조작하는 방법을 제공합니다.
다음 표는 List (T) 클래스의 속성, 생성자 및 메서드를 제공합니다.
속성
특성 | 기술 |
---|---|
생산 능력 | 내부 데이터 구조가 크기를 조정하지 않고 보유 할 수있는 총 요소 수를 가져 오거나 설정합니다. |
카운트 | List (T)에 포함 된 요소의 수를 가져옵니다. |
안건 | 지정된 인덱스의 요소를 가져 오거나 설정합니다. |
생성자
건설자 | 기술 |
---|---|
리스트 (T) () | 비어 있고 기본 초기 용량이있는 List (T) 클래스의 새 인스턴스를 초기화합니다. |
목록 (T) (IEnumerable (T)) | 지정된 컬렉션에서 복사 된 요소를 포함하고 복사 된 요소 수를 수용 할 수있는 충분한 용량이있는 List (T) 클래스의 새 인스턴스를 초기화합니다. |
목록 (T) (Int32) | 비어 있고 지정된 초기 용량이있는 List (T) 클래스의 새 인스턴스를 초기화합니다. |
방법
행동 양식 | 기술 |
---|---|
더하다 | List (T) 끝에 개체를 추가합니다. |
AddRange | 지정된 컬렉션의 요소를 List (T) 끝에 추가합니다. |
AsReadOnly | 현재 컬렉션에 대한 읽기 전용 IList (T) 래퍼를 반환합니다. |
BinarySearch (T) | 기본 비교자를 사용하여 정렬 된 전체 List (T)에서 요소를 검색하고 요소의 0부터 시작하는 인덱스를 반환합니다. |
BinarySearch (T, IComparer (T)) | 지정된 비교자를 사용하여 정렬 된 전체 List (T)에서 요소를 검색하고 요소의 인덱스 (0부터 시작)를 반환합니다. |
바이너리 검색 (Int32, Int32, T, IComparer (T)) | 지정된 비교자를 사용하여 정렬 된 List (T)의 요소 범위에서 요소를 검색하고 요소의 0부터 시작하는 인덱스를 반환합니다. |
맑은 | List (T)에서 모든 요소를 제거합니다. |
포함 | 요소가 List (T)에 있는지 여부를 확인합니다. |
ConvertAll (T 출력) | 현재 List (T)의 요소를 다른 형식으로 변환하고 변환 된 요소가 포함 된 목록을 반환합니다. |
복사 대상 (T []) | 대상 배열의 시작 부분부터 전체 List (T)를 호환 가능한 1 차원 배열에 복사합니다. |
CopyTo (T [], Int32) | 대상 배열의 지정된 인덱스에서 시작하여 전체 List (T)를 호환되는 1 차원 배열에 복사합니다. |
CopyTo (Int32, T [], Int32, Int32) | 대상 배열의 지정된 인덱스에서 시작하여 List (T)의 요소 범위를 호환 가능한 1 차원 배열에 복사합니다. |
Equals (객체) | 지정된 개체가 현재 개체와 같은지 여부를 확인합니다. (Object에서 상 속됨) |
존재 | List (T)에 지정된 조건 자에 정의 된 조건과 일치하는 요소가 있는지 여부를 확인합니다. |
마무리 | 개체가 가비지 수집에 의해 회수되기 전에 리소스를 해제하고 다른 정리 작업을 수행 할 수 있도록합니다 (Object에서 상 속됨). |
찾기 | 지정된 조건 자에 정의 된 조건과 일치하는 요소를 검색하고 전체 List (T) 내에서 첫 번째 항목을 반환합니다. |
모두 찾기 | 지정된 술어로 정의 된 조건과 일치하는 모든 요소를 검색합니다. |
FindIndex (술어 (T)) | 지정된 조건 자에 정의 된 조건과 일치하는 요소를 검색하고 전체 List (T) 내에서 첫 번째 항목의 인덱스 (0부터 시작)를 반환합니다. |
FindIndex (Int32, 술어 (T)) | 지정된 조건 자에 정의 된 조건과 일치하는 요소를 검색하고 지정된 인덱스에서 마지막 요소까지 확장되는 List (T)의 요소 범위 내에서 첫 번째 항목의 0부터 시작하는 인덱스를 반환합니다. |
FindIndex (Int32, Int32, 술어 (T)) | 지정된 조건 자에 정의 된 조건과 일치하는 요소를 검색하고 지정된 인덱스에서 시작하고 지정된 수의 요소를 포함하는 List (T)의 요소 범위 내에서 첫 번째 항목의 0부터 시작하는 인덱스를 반환합니다. |
찾기 마지막 | 지정된 조건 자에 정의 된 조건과 일치하는 요소를 검색하고 전체 List (T) 내에서 마지막 항목을 반환합니다. |
FindLastIndex (술어 (T)) | 지정된 조건 자에 정의 된 조건과 일치하는 요소를 검색하고 전체 List (T) 내에서 마지막으로 발생한 인덱스 (0부터 시작)를 반환합니다. |
FindLastIndex (Int32, 조건 자 (T)) | 지정된 조건 자에 정의 된 조건과 일치하는 요소를 검색하고 첫 번째 요소에서 지정된 인덱스까지 확장되는 List (T)의 요소 범위 내에서 마지막으로 발생한 인덱스 (0부터 시작)를 반환합니다. |
FindLastIndex (Int32, Int32, 술어 (T)) | 지정된 조건 자에 의해 정의 된 조건과 일치하는 요소를 검색하고 지정된 수의 요소를 포함하고 지정된 인덱스에서 끝나는 List (T)의 요소 범위 내에서 마지막으로 발생한 인덱스 (0부터 시작)를 반환합니다. |
각각 | List (T)의 각 요소에 대해 지정된 작업을 수행합니다. |
GetEnumerator | List (T)를 반복하는 열거자를 반환합니다. |
GetHashCode | 기본 해시 함수 역할을합니다. (Object에서 상 속됨) |
GetRange | 소스 List (T)에있는 요소 범위의 단순 복사본을 만듭니다. |
GetType | 현재 인스턴스의 Type을 가져옵니다. (Object에서 상 속됨) |
IndexOf (T) | 지정된 개체를 검색하고 전체 List (T) 내에서 처음 나타나는 인덱스 (0부터 시작)를 반환합니다. |
IndexOf (T, Int32) | 지정된 개체를 검색하고 지정된 인덱스에서 마지막 요소까지 확장되는 List (T)의 요소 범위 내에서 첫 번째 항목의 0부터 시작하는 인덱스를 반환합니다. |
IndexOf (T, Int32, Int32) | 지정된 개체를 검색하고 지정된 인덱스에서 시작하고 지정된 수의 요소를 포함하는 List (T)의 요소 범위 내에서 첫 번째 항목의 0부터 시작하는 인덱스를 반환합니다. |
끼워 넣다 | 지정된 인덱스의 List (T)에 요소를 삽입합니다. |
InsertRange | 컬렉션의 요소를 지정된 인덱스의 List (T)에 삽입합니다. |
LastIndexOf (T) | 지정된 개체를 검색하고 전체 List (T) 내에서 마지막으로 발생한 인덱스 (0부터 시작)를 반환합니다. |
LastIndexOf (T, Int32) | 지정된 개체를 검색하고 첫 번째 요소에서 지정된 인덱스까지 확장되는 List (T)의 요소 범위 내에서 마지막으로 발생한 인덱스 (0부터 시작)를 반환합니다. |
LastIndexOf (T, Int32, Int32) | 지정된 개체를 검색하고 지정된 수의 요소를 포함하고 지정된 인덱스에서 끝나는 List (T)의 요소 범위 내에서 마지막으로 발생한 인덱스 (0부터 시작)를 반환합니다. |
MemberwiseClone | 현재 Object의 단순 복사본을 만듭니다. (Object에서 상 속됨) |
없애다 | List (T)에서 특정 개체의 첫 번째 항목을 제거합니다. |
모두 제거 | 지정된 술어로 정의 된 조건과 일치하는 모든 요소를 제거합니다. |
RemoveAt | List (T)의 지정된 인덱스에서 요소를 제거합니다. |
RemoveRange | List (T)에서 요소 범위를 제거합니다. |
역전() | 전체 List (T)에서 요소의 순서를 반대로합니다. |
역방향 (Int32, Int32) | 지정된 범위에있는 요소의 순서를 반대로합니다. |
종류() | 기본 비교자를 사용하여 전체 List (T)의 요소를 정렬합니다. |
정렬 (비교 (T)) | 지정된 System을 사용하여 전체 List (T)의 요소를 정렬합니다. 비교 (T). |
정렬 (IComparer (T)) | 지정된 비교자를 사용하여 전체 List (T)의 요소를 정렬합니다. |
정렬 (Int32, Int32, IComparer (T)) | 지정된 비교자를 사용하여 List (T)의 요소 범위에있는 요소를 정렬합니다. |
ToArray | List (T)의 요소를 새 배열에 복사합니다. |
ToString | 현재 개체를 나타내는 문자열을 반환합니다. (Object에서 상 속됨) |
TrimExcess | 목록 (T)에있는 요소의 수가 임계 값 미만인 경우 용량을 실제 요소 수로 설정합니다. |
TrueForAll | List (T)의 모든 요소가 지정된 조건 자에 정의 된 조건과 일치하는지 여부를 확인합니다. |
예
(* 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])
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
그만큼 Dictionary<'TKey, 'TValue> 클래스는 F # 맵 데이터 구조의 가변 아날로그이며 동일한 함수를 많이 포함합니다.
F #의 맵 장에서 요약하면 맵은 값을 키와 연결하는 특수한 종류의 집합입니다.
가변 사전 만들기
가변 사전은 new키워드 및 목록의 생성자를 호출합니다. 다음 예제는 이것을 보여줍니다-
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Dictionary - students: seq
[[1501, Zara Ali]; [1502, Rishita Gupta]; [1503, Robin Sahoo];
[1504, Gillian Megan]]
Dictionary (TKey, TValue) 클래스
Dictionary (TKey, TValue) 클래스는 키와 값의 모음을 나타냅니다.
다음 표는 List (T) 클래스의 속성, 생성자 및 메서드를 제공합니다.
속성
특성 | 기술 |
---|---|
비교 자 | 사전의 키가 같음을 확인하는 데 사용되는 IEqualityComparer (T)를 가져옵니다. |
카운트 | Dictionary (TKey, TValue)에 포함 된 키 / 값 쌍의 수를 가져옵니다. |
안건 | 지정된 키와 연결된 값을 가져 오거나 설정합니다. |
키 | Dictionary (TKey, TValue)의 키를 포함하는 컬렉션을 가져옵니다. |
가치 | Dictionary (TKey, TValue)의 값을 포함하는 컬렉션을 가져옵니다. |
생성자
생성자 | 기술 |
---|---|
사전 (TKey, TValue) () | 새 인스턴스를 초기화합니다. Dictionary(TKey, TValue) 비어 있고 기본 초기 용량을 가지며 키 유형에 대해 기본 같음 비교자를 사용하는 클래스입니다. |
사전 (TKey, TValue) (IDictionary (TKey, TValue)) | 새 인스턴스를 초기화합니다. Dictionary(TKey, TValue) 지정된에서 복사 된 요소를 포함하는 클래스 IDictionary(TKey, TValue) 키 유형에 대해 기본 같음 비교자를 사용합니다. |
사전 (TKey, TValue) (IEqualityComparer (TKey)) | 새 인스턴스를 초기화합니다. Dictionary(TKey, TValue) 비어 있고 기본 초기 용량을 가지며 지정된 IEqualityComparer(T). |
사전 (TKey, TValue) (Int32) | 새 인스턴스를 초기화합니다. Dictionary(TKey, TValue) 비어 있고 지정된 초기 용량을 가지며 키 유형에 대해 기본 같음 비교자를 사용하는 클래스입니다. |
사전 (TKey, TValue) (IDictionary (TKey, TValue), IEqualityComparer (TKey)) | 새 인스턴스를 초기화합니다. Dictionary(TKey, TValue) 지정된에서 복사 된 요소를 포함하는 클래스 IDictionary(TKey, TValue) 그리고 지정된 IEqualityComparer(T). |
사전 (TKey, TValue) (Int32, IEqualityComparer (TKey)) | 새 인스턴스를 초기화합니다. Dictionary(TKey, TValue) 비어 있고 지정된 초기 용량을 가지며 지정된 IEqualityComparer(T). |
Dictionary (TKey, TValue) (SerializationInfo, StreamingContext) | 새 인스턴스를 초기화합니다. ictionary(TKey, TValue) 직렬화 된 데이터가있는 클래스. |
행동 양식
방법 | 기술 |
---|---|
더하다 | 지정된 키와 값을 사전에 추가합니다. |
맑은 | Dictionary (TKey, TValue)에서 모든 키와 값을 제거합니다. |
ContainsKey | Dictionary (TKey, TValue)에 지정된 키가 포함되어 있는지 여부를 확인합니다. |
ContainsValue | Dictionary (TKey, TValue)에 특정 값이 포함되어 있는지 여부를 확인합니다. |
Equals (객체) | 지정된 개체가 현재 개체와 같은지 여부를 확인합니다. (Object에서 상 속됨) |
마무리 | 개체가 가비지 수집에 의해 회수되기 전에 리소스를 해제하고 다른 정리 작업을 수행 할 수 있도록합니다. (Object에서 상 속됨) |
GetEnumerator | Dictionary (TKey, TValue)를 반복하는 열거자를 반환합니다. |
GetHashCode | 기본 해시 함수 역할을합니다. (Object에서 상 속됨) |
GetObjectData | System.Runtime.Serialization.ISerializable 인터페이스를 구현하고 Dictionary (TKey, TValue) 인스턴스를 직렬화하는 데 필요한 데이터를 반환합니다. |
GetType | 현재 인스턴스의 Type을 가져옵니다. (Object에서 상 속됨) |
MemberwiseClone | 현재 Object의 단순 복사본을 만듭니다. (Object에서 상 속됨) |
OnDeserialization | System.Runtime.Serialization.ISerializable 인터페이스를 구현하고 deserialization이 완료되면 deserialization 이벤트를 발생시킵니다. |
없애다 | Dictionary (TKey, TValue)에서 지정된 키가있는 값을 제거합니다. |
ToString | 현재 개체를 나타내는 문자열을 반환합니다. (Object에서 상 속됨) |
TryGetValue | 지정된 키와 관련된 값을 가져옵니다. |
예
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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"]
기본 입력 출력에는 다음이 포함됩니다.
- 콘솔에서 읽고 쓰기.
- 파일 읽기 및 쓰기.
Core.Printf 모듈
우리는 사용하고 의 printf 와 printfn 콘솔에 쓰기위한 기능. 이 섹션에서는Printf F #의 모듈.
위의 기능 외에도 F # 의 Core.Printf 모듈에는 % 마커를 자리 표시 자로 사용하여 인쇄 및 서식을 지정하는 다양한 방법이 있습니다. 다음 표는 간단한 설명과 함께 방법을 보여줍니다-
값 | 기술 |
---|---|
bprintf : StringBuilder → BuilderFormat < 'T> →'T | StringBuilder로 인쇄합니다. |
eprintf : TextWriterFormat < 'T> →'T | 형식화 된 출력을 stderr로 인쇄합니다. |
eprintfn : TextWriterFormat < 'T> →'T | 형식화 된 출력을 stderr로 인쇄하고 개행 문자를 추가합니다. |
failwithf : StringFormat < 'T,'Result> → 'T | 문자열 버퍼에 인쇄하고 주어진 결과로 예외를 발생시킵니다. |
fprintf : TextWriter → TextWriterFormat < 'T> →'T | 텍스트 작성기로 인쇄합니다. |
fprintfn : TextWriter → TextWriterFormat < 'T> →'T | 줄 바꿈을 추가하여 텍스트 작성기로 인쇄합니다. |
kbprintf : (단위 → '결과) → StringBuilder → BuilderFormat <'T, 'Result> →'T | bprintf와 비슷하지만 지정된 함수를 호출하여 결과를 생성합니다. |
kfprintf : (단위 → '결과) → TextWriter → TextWriterFormat <'T, 'Result> →'T | fprintf와 비슷하지만 지정된 함수를 호출하여 결과를 생성합니다. |
kprintf : (문자열 → '결과) → StringFormat <'T, 'Result> →'T | printf와 비슷하지만 지정된 함수를 호출하여 결과를 생성합니다. 예를 들어, 모든 출력이 채널에 입력 된 후 인쇄가 강제로 플러시되도록합니다. |
ksprintf : (문자열 → '결과) → StringFormat <'T, 'Result> →'T | sprintf와 비슷하지만 지정된 함수를 호출하여 결과를 생성합니다. |
printf : TextWriterFormat < 'T> →'T | 형식화 된 출력을 stdout에 인쇄합니다. |
printfn : TextWriterFormat < 'T> →'T | 형식화 된 출력을 stdout에 인쇄하고 개행 문자를 추가합니다. |
sprintf : StringFormat < 'T> →'T | 내부 문자열 버퍼를 사용하여 문자열로 인쇄하고 결과를 문자열로 반환합니다. |
형식 사양
형식 사양은 프로그래머의 필요에 따라 입력 또는 출력을 형식화하는 데 사용됩니다.
형식 자리 표시자를 나타내는 % 마커가있는 문자열입니다.
형식 자리 표시 자의 구문은 다음과 같습니다.
%[flags][width][.precision][type]
그만큼 type 다음과 같이 해석됩니다-
유형 | 기술 |
---|---|
%비 | 형식 a bool, 형식 true 또는 false. |
%씨 | 문자를 형식화합니다. |
%에스 | 형식 a string, 이스케이프 문자를 해석하지 않고 내용으로 형식화됩니다. |
% d, % i | 기본 정수 유형이 부호있는 경우 부호가있는 10 진수 정수로 형식화 된 모든 기본 정수 유형을 형식화합니다. |
%유 | 부호없는 십진 정수로 형식화 된 기본 정수 유형을 형식화합니다. |
%엑스 | 소문자 a-f를 사용하여 부호없는 16 진 정수로 형식화 된 기본 정수 유형을 형식화합니다. |
%엑스 | A에서 F까지 대문자를 사용하여 부호없는 16 진 정수로 형식화 된 기본 정수 유형을 형식화합니다. |
%영형 | 부호없는 8 진 정수로 형식화 된 기본 정수 유형을 형식화합니다. |
% e, % E, % f, % F, % g, % G | 기본 부동 소수점 유형을 포맷합니다. (float, float32) C 스타일 부동 소수점 형식 사양을 사용하여 형식화됩니다. |
% e, % E | [-] d.dddde [sign] ddd 형식의 부호있는 값을 형식화합니다. 여기서 d는 단일 십진수, dddd는 하나 이상의 십진수, ddd는 정확히 십진수 세 자리, 부호는 + 또는-입니다. |
%에프 | [-] dddd.dddd 형식의 부호있는 값을 형식화합니다. 여기서 dddd는 하나 이상의 십진수입니다. 소수점 앞의 자릿수는 숫자의 크기에 따라 다르며 소수점 뒤의 자릿수는 요청 된 정밀도에 따라 다릅니다. |
% g, % G | f 또는 e 형식으로 인쇄 된 부호있는 값을 형식화합니다. 지정된 값과 정밀도에 대해 더 압축 된 형식입니다. |
%미디엄 | Decimal 값을 형식화합니다. |
%영형 | 개체를 boxing하고 해당 개체를 사용하여 인쇄 된 모든 값을 형식화합니다. ToString 방법. |
% A, % + A | 기본 레이아웃 설정으로 인쇄 된 모든 값의 형식을 지정합니다. % + A를 사용하여 내부 및 개인 표현이있는 구별 된 공용체의 구조를 인쇄하십시오. |
%ㅏ | 일반 형식 지정자에는 두 개의 인수가 필요합니다. 첫 번째 인수는 두 개의 인수를받는 함수입니다. 첫 번째는 주어진 서식 지정 함수 (예 : TextWriter)에 적합한 유형의 컨텍스트 매개 변수이고 두 번째는 인쇄 할 값이며 적절한 텍스트를 출력하거나 반환합니다. 두 번째 인수는 인쇄 할 특정 값입니다. |
%티 | 일반 형식 지정자에는 하나의 인수가 필요합니다. 주어진 형식화 함수 (aTextWriter)에 대해 적절한 유형의 컨텍스트 매개 변수를 받아들이고 적절한 텍스트를 출력하거나 반환하는 함수입니다. 기본 정수 유형은 다음과 같습니다.byte, sbyte, int16, uint16, int32, uint32, int64, uint64, nativeint, 과 unativeint. 기본 부동 소수점 유형은 다음과 같습니다. float 과 float32. |
그만큼 width선택적 매개 변수입니다. 결과의 최소 너비를 나타내는 정수입니다. 예를 들어 % 5d는 공백이 5 자 이상인 정수를 인쇄합니다.
유효한 flags 다음 표에 설명되어 있습니다.
값 | 기술 |
---|---|
0 | 필요한 너비를 구성하기 위해 공백 대신 0을 추가하도록 지정합니다. |
- | 지정된 너비 내에서 결과를 왼쪽 정렬하도록 지정합니다. |
+ | 숫자가 양수인 경우 + 문자를 추가하도록 지정합니다 (음수의-기호와 일치). |
' ' (우주) | 숫자가 양수인 경우 추가 공백을 추가하도록 지정합니다 (음수의-기호와 일치). |
# | 유효하지 않습니다. |
예
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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
콘솔 클래스
이 클래스는 .NET 프레임 워크의 일부입니다. 콘솔 애플리케이션의 표준 입력, 출력 및 오류 스트림을 나타냅니다.
콘솔에서 읽고 쓰는 다양한 방법을 제공합니다. 다음 표는 방법을 보여줍니다-
방법 | 기술 |
---|---|
삑 하는 소리() | 콘솔 스피커를 통해 경고음을 재생합니다. |
경고음 (Int32, Int32) | 콘솔 스피커를 통해 지정된 주파수 및 지속 시간의 비프 음을 재생합니다. |
맑은 | 콘솔 버퍼와 디스플레이 정보의 해당 콘솔 창을 지 웁니다. |
MoveBufferArea (Int32, Int32, Int32, Int32, Int32, Int32) | 화면 버퍼의 지정된 소스 영역을 지정된 대상 영역에 복사합니다. |
MoveBufferArea (Int32, Int32, Int32, Int32, Int32, Int32, Char, ConsoleColor, ConsoleColor) | 화면 버퍼의 지정된 소스 영역을 지정된 대상 영역에 복사합니다. |
OpenStandardError () | 표준 오류 스트림을 획득합니다. |
OpenStandardError (Int32) | 지정된 버퍼 크기로 설정된 표준 오류 스트림을 가져옵니다. |
OpenStandardInput () | 표준 입력 스트림을 획득합니다. |
OpenStandardInput (Int32) | 지정된 버퍼 크기로 설정된 표준 입력 스트림을 가져옵니다. |
OpenStandardOutput () | 표준 출력 스트림을 획득합니다. |
OpenStandardOutput (Int32) | 지정된 버퍼 크기로 설정된 표준 출력 스트림을 가져옵니다. |
읽다 | 표준 입력 스트림에서 다음 문자를 읽습니다. |
ReadKey () | 사용자가 누른 다음 문자 또는 기능 키를 얻습니다. 누른 키가 콘솔 창에 표시됩니다. |
ReadKey (부울) | 사용자가 누른 다음 문자 또는 기능 키를 얻습니다. 누른 키는 선택적으로 콘솔 창에 표시됩니다. |
ReadLine | 표준 입력 스트림에서 다음 문자 행을 읽습니다. |
ResetColor | 콘솔 전경색과 배경색을 기본값으로 설정합니다. |
SetBufferSize | 화면 버퍼 영역의 높이와 너비를 지정된 값으로 설정합니다. |
SetCursorPosition | 커서의 위치를 설정합니다. |
SetError | Error 속성을 지정된 TextWriter 개체 로 설정 합니다. |
SetIn | In 속성을 지정된 TextReader 개체 로 설정 합니다. |
SetOut | Out 속성을 지정된 TextWriter 개체 로 설정 합니다. |
SetWindowPosition | 화면 버퍼를 기준으로 콘솔 창의 위치를 설정합니다. |
SetWindowSize | 콘솔 창의 높이와 너비를 지정된 값으로 설정합니다. |
쓰기 (부울) | 지정된 부울 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (Char) | 지정된 유니 코드 문자 값을 표준 출력 스트림에 씁니다. |
쓰기 (Char []) | 지정된 유니 코드 문자 배열을 표준 출력 스트림에 씁니다. |
쓰기 (10 진수) | 지정된 Decimal 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (Double) | 지정된 배정 밀도 부동 소수점 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (Int32) | 지정된 32 비트 부호있는 정수 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (Int64) | 지정된 64 비트 부호있는 정수 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (객체) | 지정된 개체의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (단일) | 지정된 단 정밀도 부동 소수점 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (문자열) | 지정된 문자열 값을 표준 출력 스트림에 씁니다. |
쓰기 (UInt32) | 지정된 32 비트 부호없는 정수 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (UInt64) | 지정된 64 비트 부호없는 정수 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (문자열, 개체) | 지정된 형식 정보를 사용하여 지정된 개체의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (문자열, 개체 []) | 지정된 형식 정보를 사용하여 지정된 개체 배열의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (Char [], Int32, Int32) | 유니 코드 문자의 지정된 하위 배열을 표준 출력 스트림에 씁니다. |
쓰기 (문자열, 개체, 개체) | 지정된 형식 정보를 사용하여 지정된 개체의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (문자열, 개체, 개체, 개체) | 지정된 형식 정보를 사용하여 지정된 개체의 텍스트 표현을 표준 출력 스트림에 씁니다. |
쓰기 (문자열, 개체, 개체, 개체, 개체) | 지정된 형식 정보를 사용하여 지정된 개체 및 가변 길이 매개 변수 목록의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine () | 현재 줄 종결자를 표준 출력 스트림에 씁니다. |
WriteLine (부울) | 현재 줄 종결자가 뒤에 오는 지정된 부울 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (Char) | 표준 출력 스트림에 지정된 유니 코드 문자 뒤에 현재 줄 종결 자 값을 씁니다. |
WriteLine (Char []) | 현재 줄 종결자가 뒤에 오는 지정된 유니 코드 문자 배열을 표준 출력 스트림에 씁니다. |
WriteLine (10 진수) | 현재 줄 종결자가 뒤에 오는 지정된 Decimal 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (더블) | 현재 줄 종결자가 뒤에 오는 지정된 배정 밀도 부동 소수점 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (Int32) | 현재 줄 종결자가 뒤에 오는 지정된 32 비트 부호있는 정수 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (Int64) | 현재 줄 종결자가 뒤에 오는 지정된 64 비트 부호있는 정수 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (객체) | 현재 줄 종결자가 뒤에 오는 지정된 개체의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (단일) | 현재 줄 종결자가 뒤에 오는 지정된 단 정밀도 부동 소수점 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (문자열) | 현재 줄 종결자가 뒤에 오는 지정된 문자열 값을 표준 출력 스트림에 씁니다. |
WriteLine (UInt32) | 현재 줄 종결자가 뒤에 오는 지정된 32 비트 부호없는 정수 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (UInt64) | 현재 줄 종결자가 뒤에 오는 지정된 64 비트 부호없는 정수 값의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (문자열, 객체) | 지정된 형식 정보를 사용하여 현재 줄 종결자가 뒤에 오는 지정된 개체의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (문자열, 개체 []) | 지정된 형식 정보를 사용하여 현재 줄 종결자가 뒤에 오는 지정된 개체 배열의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (Char [], Int32, Int32) | 현재 줄 종결자가 뒤에 오는 유니 코드 문자의 지정된 하위 배열을 표준 출력 스트림에 씁니다. |
WriteLine (문자열, 개체, 개체) | 지정된 형식 정보를 사용하여 현재 줄 종결자가 뒤에 오는 지정된 개체의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (문자열, 개체, 개체, 개체) | 지정된 형식 정보를 사용하여 현재 줄 종결자가 뒤에 오는 지정된 개체의 텍스트 표현을 표준 출력 스트림에 씁니다. |
WriteLine (문자열, 개체, 개체, 개체, 개체) | 지정된 형식 정보를 사용하여 지정된 개체 및 가변 길이 매개 변수 목록과 그 뒤에 현재 줄 종결자가 오는 텍스트 표현을 표준 출력 스트림에 씁니다. |
다음 예제는 콘솔에서 읽고 쓰기를 보여줍니다.
예
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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
What's your name? Kabir
Hello, Kabir
Big Greetings from TutorialsPoint and Absoulte Classes
|2015-Jan-05|
System.IO 네임 스페이스
System.IO 네임 스페이스에는 기본 I / O를 수행하는 데 유용한 다양한 클래스가 포함되어 있습니다.
여기에는 파일 및 데이터 스트림을 읽고 쓸 수있는 유형 또는 클래스와 기본 파일 및 디렉토리 지원을 제공하는 유형이 포함되어 있습니다.
파일 시스템 작업에 유용한 클래스-
- System.IO.File 클래스는 파일 생성, 추가 및 삭제에 사용됩니다.
- System.IO.Directory 클래스는 디렉터리 생성, 이동 및 삭제에 사용됩니다.
- System.IO.Path 클래스는 파일 경로를 나타내는 문자열에 대한 작업을 수행합니다.
- System.IO.FileSystemWatcher 클래스를 사용하면 사용자가 디렉터리에서 변경 내용을 수신 할 수 있습니다.
스트림 작업에 유용한 클래스 (바이트 시퀀스)-
- System.IO.StreamReader 클래스는 스트림에서 문자를 읽는 데 사용됩니다.
- System.IO.StreamWriter 클래스는 스트림에 문자를 쓰는 데 사용됩니다.
- System.IO.MemoryStream 클래스는 메모리 내 바이트 스트림을 만듭니다.
다음 표는 간략한 설명과 함께 네임 스페이스에 제공된 모든 클래스를 보여줍니다.
수업 | 기술 |
---|---|
BinaryReader | 특정 인코딩에서 기본 데이터 유형을 이진 값으로 읽습니다. |
BinaryWriter | 이진 형식의 기본 형식을 스트림에 쓰고 특정 인코딩으로 문자열 쓰기를 지원합니다. |
BufferedStream | 다른 스트림에 대한 읽기 및 쓰기 작업을위한 버퍼링 계층을 추가합니다. |
예배 규칙서 | 디렉터리 및 하위 디렉터리를 통해 생성, 이동 및 열거하기위한 정적 메서드를 노출합니다. |
DirectoryInfo | 디렉터리 및 하위 디렉터리를 통해 생성, 이동 및 열거하기위한 인스턴스 메서드를 노출합니다. |
DirectoryNotFoundException | 파일 또는 디렉터리의 일부를 찾을 수 없을 때 throw되는 예외입니다. |
DriveInfo | 드라이브 정보에 대한 액세스를 제공합니다. |
DriveNotFoundException | 사용할 수없는 드라이브 또는 공유에 액세스하려고 할 때 throw되는 예외입니다. |
EndOfStreamException | 읽을 때 throw되는 예외는 스트림의 끝을 지나서 시도됩니다. |
ErrorEventArgs | FileSystemWatcher.Error 이벤트에 대한 데이터를 제공합니다. |
파일 | 단일 파일의 생성, 복사, 삭제, 이동 및 열기를위한 정적 메서드를 제공하고 FileStream 객체 생성을 지원합니다. |
FileFormatException | 특정 파일 형식 사양을 준수해야하는 입력 파일 또는 데이터 스트림이 잘못된 경우 throw되는 예외입니다. |
FileInfo | 파일 생성, 복사, 삭제, 이동 및 열기를위한 속성 및 인스턴스 메서드를 제공하고 FileStream 개체 생성을 지원합니다. |
FileLoadException | 관리되는 어셈블리를 찾았지만로드 할 수없는 경우 throw되는 예외입니다. |
FileNotFoundException | 디스크에없는 파일에 대한 액세스 시도가 실패 할 때 throw되는 예외입니다. |
FileStream | 파일 주위에 Stream을 노출하여 동기 및 비동기 읽기 및 쓰기 작업을 모두 지원합니다. |
FileSystemEventArgs | 디렉토리 이벤트에 대한 데이터를 제공합니다-변경, 생성, 삭제. |
FileSystemInfo | FileInfo 및 DirectoryInfo 개체 모두에 대한 기본 클래스를 제공합니다. |
FileSystemWatcher | 파일 시스템 변경 알림을 수신하고 디렉토리 또는 디렉토리의 파일이 변경 될 때 이벤트를 발생시킵니다. |
InternalBufferOverflowException | 내부 버퍼가 오버플로 될 때 throw되는 예외입니다. |
InvalidDataException | 데이터 스트림이 잘못된 형식 인 경우 throw되는 예외입니다. |
IODescriptionAttribute | 이벤트, 익스텐더 또는 속성을 참조 할 때 시각적 디자이너가 표시 할 수있는 설명을 설정합니다. |
IOException | I / O 오류가 발생할 때 throw되는 예외입니다. |
MemoryStream | 백업 저장소가 메모리 인 스트림을 만듭니다. |
통로 | 파일 또는 디렉토리 경로 정보를 포함하는 String 인스턴스에 대한 작업을 수행합니다. 이러한 작업은 크로스 플랫폼 방식으로 수행됩니다. |
PathTooLongException | 경로 또는 파일 이름이 시스템 정의 최대 길이보다 길 때 throw되는 예외입니다. |
PipeException | 명명 된 파이프 내에서 오류가 발생하면 throw됩니다. |
RenamedEventArgs | Renamed 이벤트에 대한 데이터를 제공합니다. |
흐름 | 일련의 바이트에 대한 일반보기를 제공합니다. 이것은 추상 클래스입니다. |
StreamReader | 특정 인코딩의 바이트 스트림에서 문자를 읽는 TextReader를 구현합니다. |
StreamWriter | 특정 인코딩으로 스트림에 문자를 쓰기위한 TextWriter를 구현합니다. 이 유형에 대한 .NET Framework 소스 코드를 찾아 보려면 참조 소스를 참조하십시오. |
StringReader | 문자열에서 읽는 TextReader를 구현합니다. |
StringWriter | 문자열에 정보를 쓰기위한 TextWriter를 구현합니다. 정보는 기본 StringBuilder에 저장됩니다. |
TextReader | 순차적 인 일련의 문자를 읽을 수있는 판독기를 나타냅니다. |
TextWriter | 연속적인 일련의 문자를 쓸 수있는 작성자를 나타냅니다. 이 클래스는 추상적입니다. |
UnmanagedMemoryAccessor | 관리 코드에서 관리되지 않는 메모리 블록에 대한 임의 액세스를 제공합니다. |
UnmanagedMemoryStream | 관리 코드에서 관리되지 않는 메모리 블록에 대한 액세스를 제공합니다. |
WindowsRuntimeStorageExtensions | Windows 스토어 앱을 개발할 때 Windows 런타임의 IStorageFile 및 IStorageFolder 인터페이스에 대한 확장 메서드를 포함합니다. |
WindowsRuntimeStreamExtensions | Windows 런타임의 스트림과 Windows 스토어 앱용 .NET의 관리되는 스트림간에 변환하기위한 확장 메서드가 포함되어 있습니다. |
예
다음 예제는 test.txt라는 파일을 만들고 거기에 메시지를 쓰고 파일에서 텍스트를 읽고 콘솔에 인쇄합니다.
Note −이를 수행하는 데 필요한 코드의 양이 놀랍도록 적습니다!
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Hello There
Welcome to:
Tutorials Point
Generics를 사용하면 프로그램에서 실제로 사용될 때까지 클래스 또는 메서드에서 프로그래밍 요소의 데이터 유형 지정을 지연 할 수 있습니다. 즉, 제네릭을 사용하면 모든 데이터 유형과 함께 작동 할 수있는 클래스 또는 메서드를 작성할 수 있습니다.
데이터 유형에 대한 대체 매개 변수를 사용하여 클래스 또는 메소드에 대한 스펙을 작성합니다. 컴파일러가 클래스에 대한 생성자 또는 메서드에 대한 함수 호출을 발견하면 특정 데이터 유형을 처리하는 코드를 생성합니다.
F #에서 함수 값, 메서드, 속성 및 집계 형식 (예 : 클래스, 레코드 및 구분 된 공용체)은 제네릭 일 수 있습니다.
일반 구문에는 하나 이상의 유형 매개 변수가 포함됩니다. 일반 함수 및 유형을 사용하면 각 유형에 대해 코드를 반복하지 않고도 다양한 유형에서 작동하는 코드를 작성할 수 있습니다.
통사론
일반 구문을 작성하는 구문은 다음과 같습니다.
// 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
예
(* Generic Function *)
let printFunc<'T> x y =
printfn "%A, %A" x y
printFunc<float> 10.0 20.0
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
10.0, 20.0
작은 따옴표 구문을 사용하여 일반 함수를 만들 수도 있습니다.
(* Generic Function *)
let printFunction (x: 'a) (y: 'a) =
printfn "%A %A" x y
printFunction 10.0 20.0
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
10.0 20.0
제네릭 함수 또는 메서드를 사용할 때 형식 인수를 지정하지 않아도 될 수 있습니다. 그러나 모호한 경우 첫 번째 예에서했던 것처럼 꺾쇠 괄호 안에 유형 인수를 제공 할 수 있습니다.
둘 이상의 유형이있는 경우 여러 유형 인수를 쉼표로 구분합니다.
일반 클래스
일반 함수와 마찬가지로 일반 클래스를 작성할 수도 있습니다. 다음 예제는 이것을 보여줍니다-
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) } )
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
"zara"
seq [(1, 1); (2, 4); (3, 9); (4, 16); ...]
대리자는 메서드에 대한 참조를 보유하는 참조 형식 변수입니다. 참조는 런타임에 변경할 수 있습니다. F # 대리자는 C 또는 C ++에서 함수에 대한 포인터와 유사합니다.
대리인 선언
대리자 선언은 대리자가 참조 할 수있는 메서드를 결정합니다. 델리게이트는 델리게이트와 동일한 서명을 가진 메서드를 참조 할 수 있습니다.
위임 선언 구문은 다음과 같습니다.
type delegate-typename = delegate of type1 -> type2
예를 들어, 대리인을 고려하십시오-
// Delegate1 works with tuple arguments.
type Delegate1 = delegate of (int * int) -> int
// Delegate2 works with curried arguments.
type Delegate2 = delegate of int * int -> int
두 대리자는 두 개의 int 매개 변수가 있고 int 형식 변수를 반환하는 모든 메서드를 참조하는 데 사용할 수 있습니다 .
구문에서-
type1 인수 유형을 나타냅니다.
type2 반환 유형을 나타냅니다.
참고-
인수 유형은 자동으로 커리됩니다.
대리자는 함수 값과 정적 또는 인스턴스 메서드에 연결할 수 있습니다.
F # 함수 값은 대리자 생성자에 인수로 직접 전달할 수 있습니다.
정적 메서드의 경우 클래스 이름과 메서드를 사용하여 대리자가 호출됩니다. 인스턴스 메서드의 경우 개체 인스턴스 및 메서드의 이름이 사용됩니다.
대리자 형식의 Invoke 메서드는 캡슐화 된 함수를 호출합니다.
Also, delegates can be passed as function values by referencing the Invoke method name without the parentheses.
The following example demonstrates the concept −
Example
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)
When you compile and execute the program, it yields the following 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
An enumeration is a set of named integer constants.
In F#, enumerations, also known as enums, are integral types where labels are assigned to a subset of the values. You can use them in place of literals to make code more readable and maintainable.
Declaring Enumerations
The general syntax for declaring an enumeration is −
type enum-name =
| value1 = integer-literal1
| value2 = integer-literal2
...
The following example demonstrates the use of enumerations −
Example
// 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
When you compile and execute the program, it yields the following output −
Monday: Mon
Saturday: Sat
Sunday: Sun
Pattern matching allows you to “compare data with a logical structure or structures, decompose data into constituent parts, or extract information from data in various ways”.
In other terms, it provides a more flexible and powerful way of testing data against a series of conditions and performing some computations based on the condition met.
Conceptually, it is like a series of if… then statements.
Syntax
In high level terms, pattern matching follows this syntax in F# −
match expr with
| pat1 - result1
| pat2 -> result2
| pat3 when expr2 -> result3
| _ -> defaultResult
Where,
- Each | symbol defines a condition.
- The -> symbol means "if the condition is true, return this value...".
- The _ symbol provides the default pattern, meaning that it matches all other things like a wildcard.
Example 1
The following example, calculates the Fibonacci numbers using pattern matching syntax −
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)
When you compile and execute the program, it yields the following 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
You can also chain together multiple conditions, which return the same value. For example −
Example 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"
When you compile and execute the program, it yields the following output −
Winter
Spring
Autumn
Rainy
Pattern Matching Functions
F# allows you to write pattern matching functions using the function keyword −
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")
When you compile and execute the program, it yields the following output −
10
20.5
21
8.75
15
Adding Filters or Guards to Patterns
You can add filters, or guards, to patterns using the when keyword.
Example 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)
When you compile and execute the program, it yields the following output −
-1
1
0
Example 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)
When you compile and execute the program, it yields the following output −
11 is less than 25
72 is greater than 10
0 equals 0
Pattern Matching with Tuples
The following example demonstrates the pattern matching with tuples −
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"))
When you compile and execute the program, it yields the following output −
Hello, Zara
Hello, Raman from the department of Computer Sc.
You are not registered into the system
Pattern Matching with Records
The following example demonstrates pattern matching with records −
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 }
When you compile and execute the program, it yields the following 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).
An exception is a problem that arises during the execution of a program. An F# exception is a response to an exceptional circumstance that arises while a program is running, such as an attempt to divide by zero.
Exceptions provide a way to transfer control from one part of a program to another. F# exception handling provides the following constructs −
Construct | Description |
---|---|
raise expr | Raises the given exception. |
failwith expr | Raises the System.Exception exception. |
try expr with rules | Catches expressions matching the pattern rules. |
try expr finally expr | Execution the finally expression both when the computation is successful and when an exception is raised. |
| :? ArgumentException | A rule matching the given .NET exception type. |
| :? ArgumentException as e | A rule matching the given .NET exception type, binding the name e to the exception object value. |
| Failure(msg) → expr | A rule matching the given data-carrying F# exception. |
| exn → expr | A rule matching any exception, binding the name exn to the exception object value. |
| exn when expr → expr | A rule matching the exception under the given condition, binding the name exn to the exception object value. |
Let us start with the basic syntax of Exception Handling.
Syntax
Basic syntax for F# exception handling block is −
exception exception-type of argument-type
Where,
exception-type is the name of a new F# exception type.
argument-type represents the type of an argument that can be supplied when you raise an exception of this type.
Multiple arguments can be specified by using a tuple type for argument-type.
그만큼 try...with 식은 F # 언어에서 예외 처리에 사용됩니다.
try… with expression 구문은 다음과 같습니다.
try
expression1
with
| pattern1 -> expression2
| pattern2 -> expression3
...
그만큼 try...finally expression을 사용하면 코드 블록에서 예외가 발생하더라도 정리 코드를 실행할 수 있습니다.
try… finally 표현식의 구문은 다음과 같습니다.
try
expression1
finally
expression2
그만큼 raise함수는 오류 또는 예외 조건이 발생했음을 나타내는 데 사용됩니다. 또한 예외 개체의 오류에 대한 정보를 캡처합니다.
raise 함수의 구문은 다음과 같습니다.
raise (expression)
그만큼 failwith 함수는 F # 예외를 생성합니다.
failwith 함수의 구문은 다음과 같습니다.
failwith error-message-string
그만큼 invalidArg 함수는 인수 예외를 생성합니다.
invalidArg parameter-name error-message-string
예외 처리의 예
예 1
다음 프로그램은 간단한 try… 블록을 사용한 기본적인 예외 처리를 보여줍니다.
let divisionprog x y =
try
Some (x / y)
with
| :? System.DivideByZeroException -> printfn "Division by zero!"; None
let result1 = divisionprog 100 0
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Division by zero!
예 2
F #은 exception예외 선언을위한 유형. 필터에서 직접 예외 유형을 사용할 수 있습니다.try...with 표현.
다음 예제는 이것을 보여줍니다-
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Error2 Error Not detected 100
Error1 Equal Number Error
예제 3
다음 예제는 중첩 된 예외 처리를 보여줍니다.
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
From the finally block.
Error: outer error
Error:inner error
From the finally block.
From the finally block.
Error: outer error
예 4
다음 기능은 failwith 기능-
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Divisor cannot be zero.
0
25
예 5
그만큼 invalidArg함수는 인수 예외를 생성합니다. 다음 프로그램은 이것을 보여줍니다-
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)
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Sunday
Thursday
Unhandled Exception:
System.ArgumentException: You have entered 9.
…
시스템에 따라 시스템에서 오류를 일으키는 파일 및 변수에 대한 기타 정보도 표시됩니다.
클래스는 속성, 메서드 및 이벤트를 가질 수있는 개체를 나타내는 형식입니다. '응용 프로그램에서 동작, 프로세스 및 모든 개념 엔터티를 모델링하는 데 사용됩니다.'
통사론
클래스 유형을 정의하는 구문은 다음과 같습니다.
// 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 ...
...
어디,
그만큼 type-name유효한 식별자입니다. 이에 대한 기본 액세스 수정자는 다음과 같습니다.public.
그만큼 type-params 선택적 일반 유형 매개 변수를 설명합니다.
그만큼 parameter-list생성자 매개 변수를 설명합니다. 기본 생성자의 기본 액세스 수정자는 다음과 같습니다.public.
그만큼 identifier 옵션과 함께 사용 as 키워드는 인스턴스 변수에 이름을 제공합니다. self-identifier, 유형의 인스턴스를 참조하기 위해 유형 정의에서 사용할 수 있습니다.
그만큼 inherit 키워드를 사용하면 클래스의 기본 클래스를 지정할 수 있습니다.
그만큼 let 바인딩을 사용하면 클래스에 로컬로 필드 또는 함수 값을 선언 할 수 있습니다.
그만큼 do-bindings 섹션에는 객체 생성시 실행되는 코드가 포함됩니다.
그만큼 member-list 추가 생성자, 인스턴스 및 정적 메서드 선언, 인터페이스 선언, 추상 바인딩, 속성 및 이벤트 선언으로 구성됩니다.
키워드 class 과 end 정의의 시작과 끝을 표시하는 것은 선택 사항입니다.
클래스 생성자
생성자는 클래스 유형의 인스턴스를 만드는 코드입니다.
F #에서 생성자는 다른 .Net 언어와 약간 다르게 작동합니다. 클래스 정의에서 기본 생성자의 인수는 매개 변수 목록으로 설명됩니다.
생성자의 본문은 let 과 do 바인딩.
새 키워드를 사용하여 추가 생성자를 추가하여 구성원을 추가 할 수 있습니다.
new (argument-list) = constructor-body
다음 예제는 개념을 설명합니다-
예
다음 프로그램은 클래스의 객체가 생성되는 동안 라인의 길이를 계산하는 생성자와 함께 라인 클래스를 생성합니다.
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)
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Creating Line: {(1, 1), (4, 5)}
Length: 5
바인딩하자
클래스 정의의 let 바인딩을 사용하면 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")
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Hello Zara
Greetings 클래스에 대해 자체 식별자 gr 사용에 유의하십시오 .
F #의 구조는 값 형식 데이터 형식입니다. 단일 변수를 만들고 다양한 데이터 유형의 관련 데이터를 보유하는 데 도움이됩니다. 그만큼struct 키워드는 구조를 만드는 데 사용됩니다.
통사론
구조를 정의하는 구문은 다음과 같습니다.
[ attributes ]
type [accessibility-modifier] type-name =
struct
type-definition-elements
end
// or
[ attributes ]
[<StructAttribute>]
type [accessibility-modifier] type-name =
type-definition-elements
두 가지 구문이 있습니다. 첫 번째 구문은 주로 사용됩니다.struct 과 end 키워드, 당신은 생략 할 수 있습니다 StructAttribute 속성.
구조 정의 요소는-
- 회원 선언 및 정의.
- 생성자 및 변경 가능 및 변경 불가능한 필드.
- 멤버 및 인터페이스 구현.
클래스와 달리 구조는 상속 될 수 없으며 let 또는 do 바인딩을 포함 할 수 없습니다. 이후 구조에는 let 바인딩이 없습니다. 다음을 사용하여 구조의 필드를 선언해야합니다.val 예어.
다음을 사용하여 필드 및 유형을 정의 할 때 val키워드를 사용하면 필드 값을 초기화 할 수 없습니다. 대신 0 또는 null로 초기화됩니다. 따라서 암시 적 생성자가있는 구조의 경우val 선언은 DefaultValue 속성.
예
다음 프로그램은 생성자와 함께 선 구조를 만듭니다. 이 프로그램은 구조를 사용하여 선의 길이를 계산합니다-
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Length of the Line: 5
F #에서 사용할 수있는 대부분의 기본 제공 연산자를 재정의하거나 오버로드 할 수 있습니다. 따라서 프로그래머는 사용자 정의 유형에도 연산자를 사용할 수 있습니다.
연산자는 특수 이름이 괄호로 묶인 함수입니다. 정적 클래스 멤버로 정의되어야합니다. 다른 함수와 마찬가지로 오버로드 된 연산자에는 반환 형식과 매개 변수 목록이 있습니다.
다음 예는 복소수에 대한 + 연산자를 보여줍니다-
//overloading + operator
static member (+) (a : Complex, b: Complex) =
Complex(a.x + b.x, a.y + b.y)
위의 함수는 사용자 정의 클래스 Complex에 대한 더하기 연산자 (+)를 구현합니다. 두 개체의 특성을 추가하고 결과 Complex 개체를 반환합니다.
연산자 오버로딩 구현
다음 프로그램은 완전한 구현을 보여줍니다-
//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())
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
7 5
4.2 3.1
11.2 8.1
2.8 1.9
객체 지향 프로그래밍에서 가장 중요한 개념 중 하나는 상속입니다. 상속을 통해 다른 클래스의 관점에서 클래스를 정의 할 수 있으므로 응용 프로그램을 쉽게 만들고 유지 관리 할 수 있습니다. 또한 코드 기능을 재사용 할 수있는 기회와 빠른 구현 시간을 제공합니다.
클래스를 만들 때 완전히 새로운 데이터 멤버와 멤버 함수를 작성하는 대신 프로그래머는 새 클래스가 기존 클래스의 멤버를 상속하도록 지정할 수 있습니다. 이 기존 클래스를 기본 클래스라고하고 새 클래스를 파생 클래스라고합니다.
상속 개념은 IS-A 관계를 구현합니다. 예를 들어, 포유류 IS A 동물, 개 IS-A 포유류 따라서 개 IS-A 동물도 마찬가지입니다.
기본 클래스 및 하위 클래스
하위 클래스는 이미 정의 된 기본 클래스에서 파생됩니다. 하위 클래스는 기본 클래스의 멤버를 상속 할뿐만 아니라 자체 멤버도 있습니다.
서브 클래스는 inherit 아래와 같이 키워드-
type MyDerived(...) =
inherit MyBase(...)
F #에서 클래스는 최대 하나의 직접 기본 클래스를 가질 수 있습니다. 다음을 사용하여 기본 클래스를 지정하지 않은 경우inherit 키워드에서 클래스는 Object에서 암시 적으로 상속합니다.
참고-
기본 클래스의 메서드와 멤버는 파생 클래스의 직접 멤버처럼 파생 클래스의 사용자가 사용할 수 있습니다.
바인딩 및 생성자 매개 변수는 클래스 전용이므로 파생 클래스에서 액세스 할 수 없습니다.
키워드 base기본 클래스 인스턴스를 나타냅니다. 자기 식별자처럼 사용됩니다.
예
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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam
메서드 재정의
기본 클래스 메서드의 기본 동작을 재정의하고 하위 클래스 또는 파생 클래스에서 다르게 구현할 수 있습니다.
F #의 메서드는 기본적으로 재정의 할 수 없습니다.
파생 클래스의 메서드를 재정의하려면 다음을 사용하여 메서드를 재정의 가능으로 선언해야합니다. abstract 과 default 다음과 같이 키워드-
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
이제 Person 클래스 의 Greet 메서드를 파생 클래스에서 재정의 할 수 있습니다. 다음 예제는 이것을 보여줍니다-
예
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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Hi, I'm Mohan
Student Zara
Teacher Mariam.
추상 클래스
때로는 현실적으로 구현해서는 안되는 불완전한 객체 구현을 제공해야합니다. 나중에 다른 프로그래머는 완전한 구현을 위해 추상 클래스의 하위 클래스를 만들어야합니다.
예를 들어, 학교 관리 시스템에서는 Person 클래스가 필요하지 않습니다. 그러나 학생 또는 교사 클래스가 필요합니다. 이러한 경우 Person 클래스를 추상 클래스로 선언 할 수 있습니다.
그만큼 AbstractClass 속성은 컴파일러에게 클래스에 추상 멤버가 있음을 알려줍니다.
클래스가 완전히 구현되지 않았기 때문에 추상 클래스의 인스턴스를 만들 수 없습니다.
다음 예제는 이것을 보여줍니다-
예
[<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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Student Zara
Teacher Mariam.
인터페이스는 클래스의 구현 세부 사항을 작성하는 추상적 인 방법을 제공합니다. 클래스가 구현하고 공개적으로 노출해야하는 메서드를 선언하는 템플릿입니다.
통사론
인터페이스는 다른 클래스가 구현하는 관련 멤버 집합을 지정합니다. 다음과 같은 구문이 있습니다.
// 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
참고-
인터페이스 선언에서 멤버는 구현되지 않습니다.
회원은 추상적이며 abstract예어. 그러나 다음을 사용하여 기본 구현을 제공 할 수 있습니다.default 예어.
객체 표현식을 사용하거나 클래스 유형을 사용하여 인터페이스를 구현할 수 있습니다.
클래스 또는 개체 구현에서 인터페이스의 추상 메서드에 대한 메서드 본문을 제공해야합니다.
키워드 interface 과 end, 정의의 시작과 끝을 표시하는 것은 선택 사항입니다.
예를 들면
type IPerson =
abstract Name : string
abstract Enter : unit -> unit
abstract Leave : unit -> unit
인터페이스 메서드 호출
인터페이스 메서드는 클래스의 인스턴스 나 인터페이스를 구현하는 형식이 아닌 인터페이스를 통해 호출됩니다. 인터페이스 메서드를 호출하려면 다음을 사용하여 인터페이스 유형으로 캐스팅합니다.:> 운영자 (업 캐스트 운영자).
예를 들면
(s :> IPerson).Enter()
(s :> IPerson).Leave()
다음 예제는 개념을 설명합니다-
예
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()
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Student entering premises!
Student leaving premises!
Stuff member entering premises!
Stuff member leaving premises!
인터페이스 상속
인터페이스는 하나 이상의 기본 인터페이스에서 상속 할 수 있습니다.
다음 예제는 개념을 보여줍니다-
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))
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
10
15
5
이벤트를 통해 클래스는 서로간에 메시지를 보내고받을 수 있습니다.
GUI에서 이벤트는 키 누르기, 클릭, 마우스 이동 등과 같은 사용자 작업 또는 시스템 생성 알림과 같은 일부 발생입니다. 응용 프로그램은 이벤트가 발생할 때 응답해야합니다. 예를 들어, 인터럽트. 이벤트는 프로세스 간 통신에 사용됩니다.
객체는 동기식 메시지 전달을 통해 서로 통신합니다.
이벤트는 다른 기능에 첨부됩니다. 개체 등록callback 함수를 이벤트에 추가하고 이러한 콜백은 이벤트가 일부 객체에 의해 트리거 될 때 실행됩니다.
이벤트 클래스 및 이벤트 모듈
Control.Event < 'T> 클래스는 관찰 가능한 개체 또는 이벤트를 만드는 데 도움이됩니다.
그것은 이벤트와 함께 작업하기 위해 다음과 같은 인스턴스 멤버가 있습니다-
회원 | 기술 |
---|---|
게시 | 관찰을 일급 값으로 게시합니다. |
방아쇠 | 주어진 매개 변수를 사용하여 관찰을 트리거합니다. |
Control.Event 모듈은 이벤트 스트림을 관리하는 기능을 제공합니다-
값 | 기술 |
---|---|
추가 : ( 'T → 유닛) → 이벤트 <'Del, 'T> → 유닛 | 주어진 이벤트가 트리거 될 때마다 주어진 함수를 실행합니다. |
선택 : ( 'T →'U 옵션) → IEvent < 'Del,'T> → IEvent < 'U> | 원래 이벤트에서 선택한 메시지에서 발생하는 새 이벤트를 반환합니다. 선택 기능은 원본 메시지를 선택적 새 메시지로 가져옵니다. |
필터 : ( 'T → bool) → IEvent <'Del, 'T> → IEvent <'T> | 원래 이벤트를 수신하고 이벤트에 대한 인수가 지정된 함수를 전달할 때만 결과 이벤트를 트리거하는 새 이벤트를 반환합니다. |
맵 : ( 'T →'U) → IEvent < 'Del,'T> → IEvent < 'U> | 주어진 함수에 의해 변환 된 값을 전달하는 새 이벤트를 반환합니다. |
merge : IEvent < 'Del1,'T> → IEvent < 'Del2,'T> → IEvent < 'T> | 입력 이벤트 중 하나가 발생하면 출력 이벤트를 발생시킵니다. |
쌍으로 : IEvent < 'Del,'T> → IEvent < 'T *'T> | 입력 이벤트의 두 번째 및 후속 트리거에서 트리거되는 새 이벤트를 반환합니다. 그만큼Nth 입력 이벤트를 트리거하면 N-1th 과 Nth쌍으로 트리거. 전달 된 인수N-1th 트리거링은 숨겨진 내부 상태로 유지됩니다. Nth 트리거링이 발생합니다. |
파티션 : ( 'T → bool) → IEvent <'Del, 'T> → IEvent <'T> * IEvent < 'T> | 원래 이벤트를 수신하는 새 이벤트를 반환하고 이벤트 인수에 대한 술어 적용이 true를 반환하면 첫 번째 결과 이벤트를 트리거하고 false를 반환하면 두 번째 이벤트를 트리거합니다. |
스캔 : ( 'U →'T → 'U) →'U → IEvent < 'Del,'T> → IEvent < 'U> | 입력 이벤트에서 트리거 된 연속 값에 주어진 누적 함수를 적용한 결과로 구성된 새 이벤트를 반환합니다. 내부 상태 항목은 상태 매개 변수의 현재 값을 기록합니다. 누적 함수를 실행하는 동안 내부 상태는 잠기지 않으므로 입력 IEvent가 동시에 여러 스레드에 의해 트리거되지 않도록주의해야합니다. |
split : ( 'T → 선택 <'U1, 'U2>) → IEvent <'Del, 'T> → IEvent <'U1> * IEvent < 'U2> | 원래 이벤트를 수신하는 새 이벤트를 반환하고 이벤트 인수에 대한 함수의 응용 프로그램이 Choice1Of2를 반환하면 첫 번째 결과 이벤트를 트리거하고 Choice2Of2를 반환하면 두 번째 이벤트를 트리거합니다. |
이벤트 생성
이벤트는 Event수업. 이벤트 생성자는 이벤트를 만드는 데 사용됩니다.
예
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
그런 다음 리스너가 이벤트에 연결할 수 있도록 nameChanged 필드를 공용 멤버로 노출해야합니다. Publish 이벤트의 속성-
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 *)
다음으로 이벤트 핸들러에 콜백을 추가합니다. 각 이벤트 핸들러는 여러 메소드를 제공하는 IEvent < 'T> 유형을 가지고 있습니다.
방법 | 기술 |
---|---|
val 추가 : 이벤트 :( 'T → 단위) → 단위 | 리스너 함수를 이벤트에 연결합니다. 이벤트가 시작되면 리스너가 호출됩니다. |
val AddHandler : 'del → 단위 | 처리기 대리자 개체를 이벤트에 연결합니다. 나중에 RemoveHandler를 사용하여 처리기를 제거 할 수 있습니다. 이벤트가 시작되면 리스너가 호출됩니다. |
val RemoveHandler : 'del → 단위 | 이벤트 리스너 저장소에서 리스너 대리자를 제거합니다. |
다음 섹션에서는 완전한 예를 제공합니다.
예
다음 예제는 위에서 논의한 개념과 기술을 보여줍니다.
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"
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
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!
MSDN 라이브러리에 따라 F # 모듈은 do 바인딩의 형식, 값, 함수 값 및 코드와 같은 F # 코드 구문의 그룹입니다. 정적 멤버 만있는 CLR (공용 언어 런타임) 클래스로 구현됩니다.
전체 파일이 모듈에 포함되는지 여부에 따라 두 가지 유형의 모듈 선언이 있습니다.
- 최상위 모듈 선언
- 로컬 모듈 선언
최상위 모듈 선언에서는 전체 파일이 모듈에 포함됩니다. 이 경우 파일의 첫 번째 선언은 모듈 선언입니다. 최상위 모듈에서 선언을 들여 쓸 필요가 없습니다.
로컬 모듈 선언에서는 해당 모듈 선언 아래에 들여 쓰기 된 선언 만 모듈의 일부입니다.
통사론
모듈 선언 구문은 다음과 같습니다.
// Top-level module declaration.
module [accessibility-modifier] [qualified-namespace.]module-name
declarations
// Local module declaration.
module [accessibility-modifier] module-name =
declarations
접근성 수정자는 공개, 비공개, 내부 중 하나 일 수 있습니다. 기본값은public.
다음 예제는 개념을 보여줍니다-
예 1
모듈 파일 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
프로그램 파일 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
34
16
225
2
110
90
1000
10
예 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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
125
325
ㅏ namespace하나의 이름 집합을 다른 이름과 구분하는 방법을 제공하도록 설계되었습니다. 한 네임 스페이스에서 선언 된 클래스 이름은 다른 네임 스페이스에서 선언 된 동일한 클래스 이름과 충돌하지 않습니다.
MSDN 라이브러리에 따라 namespace 프로그램 요소 그룹에 이름을 첨부 할 수 있도록하여 관련 기능 영역으로 코드를 구성 할 수 있습니다.
네임 스페이스 선언
네임 스페이스에서 코드를 구성하려면 네임 스페이스를 파일의 첫 번째 선언으로 선언해야합니다. 그러면 전체 파일의 내용이 네임 스페이스의 일부가됩니다.
namespace [parent-namespaces.]identifier
다음 예제는 개념을 설명합니다-
예
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
프로그램을 컴파일하고 실행하면 다음과 같은 출력이 생성됩니다.
Values from Module1: ("one", "two", "three") 150
Values from Module2: seq [1; 4; 9; 16; ...] 200