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 #에는 두 가지 기본 제공 함수가 있습니다. fstsnd, 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 목록 주어진 술어가 리턴하는 요소를 포함하는 두 개의 콜렉션으로 콜렉션을 분할합니다. truefalse 각기.
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 모듈

우리는 사용하고 의 printfprintfn 콘솔에 쓰기위한 기능. 이 섹션에서는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. 기본 부동 소수점 유형은 다음과 같습니다. floatfloat32.

그만큼 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 추가 생성자, 인스턴스 및 정적 메서드 선언, 인터페이스 선언, 추상 바인딩, 속성 및 이벤트 선언으로 구성됩니다.

  • 키워드 classend 정의의 시작과 끝을 표시하는 것은 선택 사항입니다.

클래스 생성자

생성자는 클래스 유형의 인스턴스를 만드는 코드입니다.

F #에서 생성자는 다른 .Net 언어와 약간 다르게 작동합니다. 클래스 정의에서 기본 생성자의 인수는 매개 변수 목록으로 설명됩니다.

생성자의 본문은 letdo 바인딩.

새 키워드를 사용하여 추가 생성자를 추가하여 구성원을 추가 할 수 있습니다.

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

두 가지 구문이 있습니다. 첫 번째 구문은 주로 사용됩니다.structend 키워드, 당신은 생략 할 수 있습니다 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 #의 메서드는 기본적으로 재정의 할 수 없습니다.

파생 클래스의 메서드를 재정의하려면 다음을 사용하여 메서드를 재정의 가능으로 선언해야합니다. abstractdefault 다음과 같이 키워드-

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 예어.

  • 객체 표현식을 사용하거나 클래스 유형을 사용하여 인터페이스를 구현할 수 있습니다.

  • 클래스 또는 개체 구현에서 인터페이스의 추상 메서드에 대한 메서드 본문을 제공해야합니다.

  • 키워드 interfaceend, 정의의 시작과 끝을 표시하는 것은 선택 사항입니다.

예를 들면

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-1thNth쌍으로 트리거. 전달 된 인수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