📜  F#面试问题

📅  最后修改于: 2021-01-01 14:54:34             🧑  作者: Mango

F#面试题

下面列出了最常见的F#面试问题和答案。

1)什么是F#?

F#是一种计算机编程语言。它是由Microsoft设计和开发的。它支持功能,面向对象和命令式编程方法。您可以使用此编程语言创建应用程序。

2)F#的功能是什么?

F#具有许多功能。以下是F#的主要功能:

  • 类型推断
  • 类型扩展
  • 更少的代码
  • 不变的数据
  • 模式匹配
  • 断言
  • Lambda表达式
  • 函数组成和流水线
  • 对象表达
  • 延迟计算等

3)F#中可用的数据类型是什么?

F#提供了一组丰富的数据类型。它有助于处理任何数据,无论是科学数据,业务分析数据还是其他数据。您都可以在此处查看数据类型表。

F#中的数据类型

Types Data Types
Primitive data types char, byte, bool, int, float
Derived data types class, array, list, records, sequence
Enumeration enum
Unit type It is used if other data types are not specified.

4)F#中的单位类型是什么?

单位类型是指示没有特定值的类型。单位类型只有一个值。如果没有其他值,则此值充当占位符。

例:

let function1 x y = x + y               

function1 10 20      // this line results a compiler warning
    
// changing the code to the following and eliminates the warning
let result = function1 10 20

// Use this if you are calling the function and don't want the return value
function1 10 20 |> ignore

5)什么是F#中的向上转换和向下转换?

转换是将一种类型转换为另一种类型的过程。 F#主要提供两个运算符来处理上播和下播。 :>运算符用于向上转换对象,而:?>运算符用于向下转换对象。

例:

type BaseClass() =
 class
  member this.ShowClassName()=
    printfn "BaseClass"
 end

type DerivedClass() = 
 class
  inherit BaseClass()
  member this.ShowClassName()=
   printfn "DerivedClass"
 end

let baseClass = new BaseClass()            
let derivedClass : DerivedClass = new DerivedClass()
baseClass.ShowClassName()    
derivedClass.ShowClassName()
let castIntoBaseClass = derivedClass :> BaseClass        // upcasting 
castIntoBaseClass.ShowClassName()
let castIntoDerivedClass = baseClass :?> DerivedClass   // downcasting
castIntoDerivedClass.ShowClassName()

6)F#中可用的运算符是什么?

运算符只是用于执行操作的符号。可以有多种类型的运算,例如算术运算,按位运算,逻辑运算等。

可以使用以下类型的运算符来执行F#语言的不同类型的运算。

  • 算术运算运算符:算术运算运算符将数值作为其操作数,并返回单个数值。
  • 布尔运算符:布尔运算符用于检查条件表达式。如果表达式满足条件,则返回true,否则返回false。
  • 按位运算符:在F#中,按位运算运算符处理单个位,并在求值后返回结果。
  • 可空运运算符:可空运运算符用于处理数据库查询。它处理存储在表中代替数据的空值。

7)F#中提供哪些令牌?

  • 关键字:它包含有关所有F#语言关键字的信息的链接。
  • 符号和运算符:它包含F#语言中使用的符号和运算符的表。

8)F#中的函数组成和流水线是什么?

在F#中,功能可以由其他功能组成。这是一个组合过程,其中一个函数代表两个组合函数的应用。 F#函数流水线允许我们在链中调用函数。流水线运算符将一个函数和一个参数作为操作数,并返回一个值。

F#函数组成示例

let function1 name= 
  name + " FSharp"
let function2 name = 
   name + " Programming"

let programmingName = function1 >> function2
let result = programmingName "Hello"
printf "%s" result

F#函数流水线示例

let function1 name= 
  name + " FSharp"
let function2 name = 
   name + " Programming"

let result = "Hello" |> function1 |> function2
printf "%s" result

9)F#中的lambda表达式是什么?

Lambda表达式是未命名或匿名函数。有时,可以定义一个lambda表达式来代替定义全名函数。它优化了代码。您必须使用fun关键字定义lambda表达式。

let result = (fun a -> a+1) 100
printf "%d" result

10)什么是F#的内联函数?

F#内联函数是直接集成到调用代码中的函数。它有助于优化代码,有时还可以提高性能。

type InlineClass() =
  class
    member inline this.inlineFunction(a) = a*a
  end
 
let obj = new InlineClass()
let result = obj.inlineFunction 2
printf "%d" result

11)F#中的let绑定是什么?

绑定是将标识符或函数与值相关联的过程。 Let关键字用于将标识符绑定到值。在F#中,我们使用let关键字声明变量,函数和私有类成员。

F#让函数绑定

我们使用let关键字在F#中定义一个函数。

let ShowName() = 
 printf "Hello FSharp"
ShowName()

12)什么是F#中的“绑定”?

Do绑定用于执行代码而无需定义函数或任何类型。您可以通过在F#中使用do绑定来编写独立的代码。

type DoBindingClass() = 
 class
  do printf "Hello FSharp"   
 end
new DoBindingClass()

13)什么是F#中的类型注释?

F#允许类型的注释,这样就可以明确提到标识符或参数或函数的返回类型的类型。您必须使用:(冒号)在F#中应用注释。

let a:int = 10
printf "%d" a

14)什么是F#中的类型推断?

类型推断意味着在编写代码时,您无需指定值或变量的类型。 F#编译器的功能足以推断出值的类型。

let add a b =      //Here, all parameters are inferred to int because of passing values during calling
 a+b               // Return type of this function is int because the type of this expression is int.
printf "%d" (add 10 20)

15)什么是F#中的自动概括?

如果代码未明确指定任何类型,则编译器将考虑泛型。这称为自动概括。它有助于编写通用代码而不会增加复杂性。

16)F#中的元组是什么?

在F#中,元组是匿名值的集合。值可以相同或不同。它也使我们也可以将表达式作为值。

let (id,name) = (1, "Fsharp")
printfn "%d" id
printfn "%s" name  

17)函数可以在F#中返回多个值吗?

是的,通过使用元组,您可以在函数返回多个值。

let TupleExample a b = 
 let c = a+b
 let d = a-b
 (c, d)
 
let tupleValues = TupleExample 50 10 
printf "%A" tupleValues

18)F#中的列表是什么?

它是相同类型元素的不可变集合。它保持元素的顺序。

F#清单范例

let list = [1;2;3;4;5;6;7;8;9]
for i  in list do
 printfn "%d" i

19)F#中的数组是什么?

数组是相同类型数据的可变集合。它从索引0开始到n-1,其中n是数组的长度。

let arr = [| 1; 2; 3; 4; 5; |]               // Creating and initializing array
for i = 0 to arr.Length-1 do                   // Traversing of array
  printfn "%d" arr.[i]

20)F#中的序列是什么?

序列是一系列相同类型的元素。它提供了比列表更好的性能。

您可以创建如下的序列表达式。在这里,我们使用了Seq.iter()函数来迭代序列。我们还可以使用循环或数组格式说明符来迭代序列元素。

let seq1 =
 seq { 0 .. 10 }
Seq.iter(fun a->printf " %d" a)seq1

21)F#中有哪些选项?

当函数或变量不存在任何值时,将使用选项类型。它提供表达式Some和值None用于处理空值或变量。

let sub a b =
 if(a>b) then
  Some(a-b)
  else None
printf "%A" (sub 20 10)

22)F#中的泛型是什么?

F#允许您编写通用函数,方法,类型,变量等。它有助于避免每种类型的代码重复。通过编写通用代码,您可以将其应用于任何类型或值。

let genericFunctionExample<'T> x y =
    printfn "%A %A" x y

genericFunctionExample 1 2

23)F#中的记录是什么?

记录用于存储标签和值形式的元素。它可以存储任何数据。您不必将相同的类型值存储为列表。记录默认是不可变的,因此您不能修改原始记录。

type RecordExample = { x : float; y: float; z: float; }
let getRecordValues = { x = 2.0; y = 1.0; z = 0.0; }
printf "%A\n" getRecordValues             // Access all values of record
printf "%f" getRecordValues.x    // Access individual values of record

24)F#中的枚举是什么?

枚举通常被称为枚举。它是标签和值对的组合。标签被分配给值的子集。您可以使用它们代替字面量,以使代码更具可读性和可维护性。

type Year =
   | January = 0
   | Fabruary = 1
   | March = 2
   | April = 3

// Use of an enumeration.
let monthName = enum(3)
printf "%A" monthName
let monthLiteral : Year = Year.January
let n = int monthLiteral
printf "\n%d" n

25)F#中的参考单元是什么?

参考单元引用存储位置。它允许您创建可变值。 F#默认使用不可变数据结构。

let refVariable = ref 50
printf "%d" refVariable.Value

26)F#中的结构是什么?

F#结构是用于组织数据的数据结构,它是值类型,比类有效。它不允许let绑定,因此必须使用val关键字声明字段。

type Book = struct
   val title : string
   val author: string
   val price : float
   new (title, author, price) =           // Constructor
      {title = title; author = author; price = price;}
end
let book = new Book("FSharp Programming", "Chris Smith", 100.0)   // Calling Constructor
printfn "Title  : %s " book.title
printfn "Author : %s"  book.author
printfn "Price  : $%0.2f"  book.price   

27)什么是F#中的歧视联盟?

这是一个有用的数据结构。它有助于存储异构数据。联合用于表示树数据结构。它提供了案例,每个案例都包含异构数据。

type Calcualte =  
    | Add of val1 : int * val2 : int  
    | Multiply of val1 : int * val2 : int  
  
let compute vall =  
   match vall with  
     | Add (val1, val2) -> val1+val2  
     | Multiply (val1, val2)->val1*val2  
  
let addition = compute (Add(10,10))  
let multiplication = compute (Multiply(2,5))  
  
printf "Addition = %d\nMultiplication = %d" addition multiplication  

28)F#中的对象是什么?

该对象是真实世界的实体。它可以是任何东西-手机,汽车,足球等。

对象是类的实例,我们可以使用此类的对象来访问该类的所有成员。

让我们看一下如何在F#中创建对象的示例。

let objectName = new ClassName()

29)F#中的类是什么?

类是对象的模板或蓝图。它用于封装数据成员和成员方法。它可以包含字段,方法,构造函数,静态方法等。

type Student (id,name)= 
 class
  member x.show = 
  printf "%d \n%s" id name 

 end
let a = new Student (12,"FSharp")
a.show

30)F#中的构造函数是什么?

在F#中,构造函数与其他.Net语言有所不同。总是有可能带有或不带有参数的主要构造函数。这些参数的范围遍及整个类。

type Employee(name) = 
 class
  do printf "%s" name
 end
let e = new Employee("FSharp")

31)F#中的自我是什么?

在F#中,一个self用于引用当前类类型的对象。 Self与C#和Java中的此关键字相同。您可以根据需要命名自己的标识符。您不限于.Net语言这样的名称或self。

type Employee(id,name) as this =
    let id = id
    let name = name
    do this.Display()           // This is how we can use self(this) object
    member this.Display() =
        printf "%d %s" id name
let e =new Employee(100, "Rajkumar")

32)F#中的静态是什么?

在F#中,static是关键字。它用于制作静态字段或静态方法。静态不是对象的一部分。它具有其存储空间来存储静态数据。它用于在对象之间共享通用属性。

type Account(accno,name) = class
 static let rateOfInterest = 8.8
 member this.display()=
  printfn "%d %s %0.2f" accno name rateOfInterest 
end
let a1 = new Account(101,"Rajkumar")
let a2 = new Account(102, "john")
a1.display()
a2.display()

33)F#中的继承是什么?

在F#中,继承是子类自动获取其父类的所有属性和行为的过程。它用于重用代码。

type Employee(name:string) =
 class
  member this.ShowName() = printf"Name = %s\n" name
 end
type Manager(name,salary:int) =
 class
  inherit Employee(name)
  member this.ShowSalary() = printf"Salary = $%d" salary
 end
let manager = new Manager("Rajkumar",10000)
manager.ShowName()
manager.ShowSalary()

34)F#中的方法重写是什么?

方法覆盖是面向对象编程方法的功能。它有助于实现多态性。我们可以使用继承来实现方法重写。

type Employee() =
 class
  abstract ShowName : unit -> unit
  default this.ShowName() = printfn"This is base class method"
 end 
type Manager() =
 class
  inherit Employee()
  override this.ShowName() = printf "This is derived class method"
 end

let employee = new Employee()
let manager = new Manager()
employee.ShowName()
manager.ShowName()

35)什么是抽象类?

抽象类用于提供类成员的完整实现。它可能包含非抽象方法。继承抽象类的类必须提供该抽象类的所有抽象方法的实现。

[]
type AbstractClass() = 
 class
  abstract member ShowClassName : unit -> unit
 end
type DerivedClass()  = 
 class
  inherit AbstractClass()
  override this.ShowClassName() = printf "This is derived class."
 end

let a = new DerivedClass()
a.ShowClassName()

36)F#中的接口是什么?

F#提供接口类型。它提供了纯抽象。它是抽象方法的集合。

type IEmployee =
   abstract member ShowName : unit -> unit
type Manager(id:int, name:string) =
   interface IEmployee with
      member this.ShowName() = printfn "Id = %d \nName = %s" id name

let manager = new Manager(100,"RajKumar")
//manager.ShowName()    // error: you can't directly access interface abstract method by using class object.
// so, we need to upcast class type object to interface type by using :> operator.
(manager :> IEmployee).ShowName()

37)F#中的类型扩展是什么?

类型扩展允许您将新成员添加到先前定义的对象类型。

type ClassExtension() =
 member this.ShowBefore() = printfn"Class before extension"

// Define type extension.
type ClassExtension with
 member this.ShowAfter() = printfn"Class after extension"

let classExtension = new ClassExtension()
classExtension.ShowBefore()
classExtension.ShowAfter()

38)F#中的代表是什么?

在F#中,委托是引用类型。它允许我们将函数作为对象调用。这是该语言的功能。与其他功能编程语言相比,它具有优势。

type Deligate() =
  static member mul(a : int, b : int) = a * b
  member x.Mul(a : int, b : int) = a * b
type Multiply = delegate of (int * int) -> int

let getIt (d : Multiply) (a : int) (b: int) =
   d.Invoke(a, b)
let d : Multiply = new Multiply( Deligate.mul )
for (a, b) in [(5, 8) ] do
  printfn "%d * %d = %d" a b (getIt d a b)

39)F#中的对象表达式是什么?

F#对象表达式是一个特殊的表达式。它基于现有的基本类型,接口或接口集创建一个匿名对象类型的新实例。

let ex =
 {
      new System.Exception() with member x.ToString() = "Hello FSharp" 
 }
printfn "%A" ex

40)什么是异常处理?

异常处理是处理程序异常终止的标准机制。异常是程序执行期间发生的情况。它可能导致异常终止程序,例如被零除或空指针。

let ExExample a b =
 let mutable c = 0
 c <- (a/b)
 printfn "Rest of the code"

ExExample 10 0

41)什么是F#中的try-with块?

在F#中,可以创建用户定义的异常。它提供了根据需求定义自定义异常的灵活性。

let ExExample a b =
  let mutable c = 0
  try
    c <- (a/b)
  with
    | :? System.DivideByZeroException as e -> printfn "%s" e.Message
  printfn "Rest of the code"

ExExample 10 0

42)F#中的FailWith和InvalidArg是什么?

在F#中,可以显式引发异常。您可以引发自定义异常。您也可以通过使用预定义的Exception方法(例如Failwith和InvalidArgs)来引发异常。

FailWith关键字的示例

let TestAgeValidation age  =
  try
     if (age<18) then failwith "Sorry, Age must be greater than 18"
  with
     | Failure(e) -> printfn "%s" e; 
  printf "Rest of the code"
TestAgeValidation 10

InvalidArg关键字示例

let TestInvalidArgument age =
 if(age<18) then
  invalidArg "TestInvalidArgument" ("Sorry, Age must be greater than 18")

TestInvalidArgument 10

43)F#中的断言是什么?

断言表达式是F#的调试功能。您可以使用它来测试表达式。在调试模式下失败时,它将生成一个系统错误对话框。

let divide (x:int, y:int):int =
 assert (x>0)
 let z = (x/y)
 z

let result = divide(10,2)
printf "%d" result

44)F#中的模块是什么?

该模块是类,函数和类型的集合。它有助于组织相关代码,因此我们可以轻松维护代码。

open Arithmetic
printf "%d" (sub 20 10)

45)F#中的访问控制是什么?

访问控制指定代码的可访问性。通过使用这些,您可以指定数据,方法,类等的范围。

F#中有3种访问控制。

  • Public:公共访问控制,也称为默认。所有人都可以使用。如果您未在代码中明确指定任何访问控制,则默认情况下,它将遵循公共访问控制。
  • 私有: F#提供了private关键字来声明类或类型中的私有成员。私有的范围仅限于在其中声明它的本地块。
  • 内部:内部访问控制只能从同一程序集中访问。程序集是在编译F#代码后由编译器自动生成的文件。

46)什么是F#中的资源管理?

F#在使用使用关键字的帮助下管理资源。资源可以是数据,文件或网络等。它从操作系统或其他服务提供者那里获取资源,以便可以将其提供给其他应用程序。

open System.IO
let ReleaseFile fileName content =
    using (System.IO.File.CreateText(fileName)) ( fun textFile ->
        textFile.WriteLine("{0}", content.ToString() )
    )

ReleaseFile "file/textFile.txt" "This is a text file. \nIt contains data."

47)F#中的属性是什么?

在F#中,该属性用于为程序代码构造启用元数据。该属性可以应用于任何构造,例如函数,模块,方法和类型。

open System
[]
let updateSystem() = 
 printf "updating..."

updateSystem

48)F#中的签名是什么?

在F#中,签名文件包含有关公共签名的信息。签名可以是一组程序元素,例如类型,名称空间和模块。

签名文件命名为signature.fsi

namespace FSharpPrograms
  module Arithmetic =
    val add : int * int -> int
    val sub : int * int -> int

49)F#中的开放关键字是什么?

导入声明指定模块或名称空间。您可以引用其元素,而无需使用完全限定的名称。

open System
Console.WriteLine("Hello, this is F# here.")

50)“基本”关键字的目的是什么?

“ base”关键字用作基类对象的名称。

51)“开始”关键字的目的是什么?

它用于表示代码块的开始。

52)'elif'关键字的目的是什么?

与分支相同。

53)'yield'关键字的目的是什么?

Yield关键字可用于序列表达式中以产生序列值。

54)'rec'关键字的目的是什么?

它用于指示递归函数。

55)“ extern”关键字的目的是什么?

它用于指示声明的程序元素是在某些其他程序集或二进制文件中定义的。

56)编写用于声明已区别联合的语法。

type name = 
| case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ] 
type2 ...]
| case-identifier2 [of [fieldname3 : ]type3 [ * [ fieldname4 : ]type4 ...]

57)“ F#中的变量是不可变的”解释。

这意味着,一旦将值分配给变量,就无法更改。

58)“筹款”函数的用途是什么?

用于指示错误发生。

59)什么是F#中的惰性计算?

惰性计算是F#的功能。延迟计算不会立即进行评估。需要结果时执行。

let add x y  = x+y
let result = lazy (add 10 10)
printfn "%d" (result.Force())

60)什么是F#中的XML文档?

在F#中,您可以使用三斜杠(///)代码注释生成文档。 XML注释可以在代码文件(.fs)或签名(.fsi)文件中的声明之前。

let add x y  = x+y
let result = lazy (add 10 10)
printfn "%d" (result.Force())