İşlevler

İşlevler, herhangi bir programlama dilinde program yürütmenin temel birimidir. Diğer dillerde olduğu gibi, F# işlevinin bir adı vardır, parametreleri olabilir, bağımsız değişkenler alır ve bir gövdesi vardır. F# ayrıca işlevleri değer olarak kabul etmek, ifadelerde adlandırlanmamış işlevleri kullanmak, yeni işlevler oluşturmak için işlev bileşimini, curried işlevleri ve işlev bağımsız değişkenlerinin kısmi uygulamasıyla işlevlerin örtülü tanımını kullanmak gibi işlevsel programlama yapılarını da destekler.

İşlevleri tanımlamak için anahtar sözcüğünü veya işlevin tekrarlayıcı let olduğunu anahtar sözcük let rec birleşimini kullanırsiniz.

Syntax

// Non-recursive function definition.
let [inline] function-name parameter-list [ : return-type ] = function-body
// Recursive function definition.
let rec function-name parameter-list = recursive-function-body

Açıklamalar

İşlev-adı, işlevi temsil eden bir tanımlayıcıdır. Parametre-listesi, boşluklarla ayrılmış olan ve takipte olan parametrelerden oluşur. Parametreler bölümünde açıklandığı gibi her parametre için açık bir tür belirtebilirsiniz. Belirli bir bağımsız değişken türü belirtmezseniz, derleyici türü işlev gövdesinden çıkarım yapmaya çalışır. İşlev gövdesi bir ifadeden oluşur. İşlev gövdeyi yapan ifade genellikle dönüş değeri olan son ifadede sonuç alan bir dizi ifadeden oluşan bileşik bir ifadedir. Dönüş türü, ardından bir tür gelen iki nokta üst üstedir ve isteğe bağlıdır. Dönüş değerinin türünü açıkça belirtmezseniz, derleyici son ifadeden dönüş türünü belirler.

Basit bir işlev tanımı aşağıdakine benzer:

let f x = x + 1

Önceki örnekte işlev adı , bağımsız değişkeni türünde, işlev gövdesi ise ve f x dönüş değeri int x + 1 int türündedir.

İşlevler olarak inline işaretlenir. hakkında bilgi için inline bkz. Satır Içi İşlevler.

Kapsam

Modül kapsamı dışında herhangi bir kapsam düzeyinde, bir değerin veya işlev adının yeniden kullanılması hata değildir. Bir adı yeniden kullanmanız, daha sonra bildirilen adın daha önce bildirilen adı gölgeletir. Ancak, bir modülde üst düzey kapsamda adların benzersiz olması gerekir. Örneğin, aşağıdaki kod modül kapsamında göründüğünde bir hata üretir, ancak bir işlevin içinde göründüğünde üretmez:

let list1 = [ 1; 2; 3]
// Error: duplicate definition.
let list1 = []
let function1 () =
   let list1 = [1; 2; 3]
   let list1 = []
   list1

Ancak aşağıdaki kod herhangi bir kapsam düzeyinde kabul edilebilir:

let list1 = [ 1; 2; 3]
let sumPlus x =
// OK: inner list1 hides the outer list1.
   let list1 = [1; 5; 10]
   x + List.sum list1

Parametreler

Parametre adları işlev adının ardından listelenir. Aşağıdaki örnekte gösterildiği gibi parametre için bir tür belirtsiniz:

let f (x : int) = x + 1

Bir tür belirtirsiniz, parametrenin adını izler ve addan iki nokta üst üste ile ayrılır. Parametrenin türünü atlarsanız, parametre türü derleyici tarafından alıtır. Örneğin, aşağıdaki işlev tanımında, 1 türünde olduğundan bağımsız x int değişkeninin türünde olduğu atılır. int

let f x = x + 1

Ancak, derleyici işlevi mümkün olduğunca genel hale yapmaya çalışmaz. Örneğin, aşağıdaki kodu not anın:

let f x = (x, x)

işlevi, herhangi bir türe sahip bir bağımsız değişkenden bir kayıt oluşturur. Tür belirtilmemiş olduğundan işlev herhangi bir bağımsız değişken türüyle kullanılabilir. Daha fazla bilgi için bkz. Otomatik Genelleştirme.

İşlev Gövdeleri

İşlev gövdesi yerel değişkenlerin ve işlevlerin tanımlarını içerebilir. Bu tür değişkenler ve işlevler, geçerli işlevin gövdesinde kapsamdadır ancak bunun dışında değildir. Basit söz dizimi seçeneğini etkinleştirdikten sonra, aşağıdaki örnekte gösterildiği gibi bir tanımın işlev gövdesinde olduğunu belirtmek için girintileme kullansanız gerekir:

let cylinderVolume radius length =
    // Define a local value pi.
    let pi = 3.14159
    length * pi * radius * radius

Daha fazla bilgi için bkz. Kod Biçimlendirme Yönergeleri ve Ayrıntılı Söz Dizimi.

Dönüş Değerleri

Derleyici, dönüş değerini ve türünü belirlemek için işlev gövdesinde son ifadeyi kullanır. Derleyici, son ifadenin türünü önceki ifadelerden çıkarıyor olabilir. önceki bölümde cylinderVolume gösterilen işlevinde, türü pi sabitin türünden olarak 3.14159 float belirlenir. Derleyici, olacak pi ifadenin türünü belirlemek için türünü h * pi * r * r float kullanır. Bu nedenle, işlevin genel dönüş türü float olur.

Dönüş değerini açıkça belirtmek için kodu aşağıdaki gibi yazın:

let cylinderVolume radius length : float =
   // Define a local value pi.
   let pi = 3.14159
   length * pi * radius * radius

Kod yukarıda yazıldığı için derleyici işlevin tamamına float uygular; Bunu parametre türlerine de uygulamak için aşağıdaki kodu kullanın:

let cylinderVolume (radius : float) (length : float) : float

İşlev Çağırma

İşlev adını ve ardından boşlukla ayrılmış bağımsız değişkenleri belirterek işlevleri çağırabilirsiniz. Örneğin, işlevi silindiriVolume'u çağıracak ve sonucu değer hacmine atamak için aşağıdaki kodu yazın:

let vol = cylinderVolume 2.0 3.0

Bağımsız Değişkenlerin Kısmi Uygulanması

Belirtilen sayıdan daha az bağımsız değişken sağlarsanız, kalan bağımsız değişkenleri beklediğiniz yeni bir işlev oluşturun. Bu bağımsız değişkenleri işleme yöntemi currying olarak adlandırılır ve F# gibi işlevsel programlama dillerinin bir özelliğidir. Örneğin, iki kanal boyutuyla çalıştığı düşünün: biri 2,0 yarıçapa, diğeri ise 3.0 yarıçapa sahiptir. Kanal hacmini belirleyen işlevleri aşağıdaki gibi oluşturabilirsiniz:

let smallPipeRadius = 2.0
let bigPipeRadius = 3.0

// These define functions that take the length as a remaining
// argument:

let smallPipeVolume = cylinderVolume smallPipeRadius
let bigPipeVolume = cylinderVolume bigPipeRadius

Daha sonra, iki farklı boyuttaki çeşitli kanal uzunlukları için gerektiğinde ek bağımsız değişkeni sağlarsanız:

let length1 = 30.0
let length2 = 40.0
let smallPipeVol1 = smallPipeVolume length1
let smallPipeVol2 = smallPipeVolume length2
let bigPipeVol1 = bigPipeVolume length1
let bigPipeVol2 = bigPipeVolume length2

Özyinelemeli İşlevler

Recursive işlevleri kendilerini çağıran işlevlerdir. Let anahtar sözcüğünün ardından rec anahtar sözcüğünü belirtmenizi gerektirir. Herhangi bir işlev çağrısında olduğu gibi, işlevin gövdesinin içinden, recursive işlevini çağırma. Aşağıdaki özyinelemeli işlev, n. Fibonacci sayısını hesaplar. Fibonacci sayı dizisi, eski zamandan beri bilinir ve her artıcı sayıcının dizide yer alan önceki iki sayına karşılık olduğu bir dizidir.

let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)

Bazı tekrarlayıcı işlevler, program yığınını taşabilir veya bunları özenli bir şekilde ve biriktiricilerin ve devamlılıkların kullanımı gibi özel teknikler farkındalığıyla yazmazsanız verimsiz bir şekilde gerçekleştirebilirsiniz.

İşlev Değerleri

F# içinde tüm işlevler değer olarak kabul edilir; aslında, bunlar işlev değerleri olarak bilinir. İşlevler değerler olduğundan, diğer işlevlere veya değerlerin bulunduğu diğer bağlamlarda bağımsız değişken olarak kullanılabilir. Aşağıda, bağımsız değişken olarak işlev değeri alan bir işlev örneği ve ardından ve bir örnek ve ardından ve bir işlev yer alır:

let apply1 (transform : int -> int ) y = transform y

Bir işlev değerinin türünü belirteci kullanarak -> belirtirsiniz. Bu belirteci sol tarafında bağımsız değişkenin türü, sağ tarafta ise dönüş değeri yer alır. Önceki örnekte, bir işlevi bağımsız değişken olarak alan bir işlevdir; burada bir tamsayı alan ve başka bir apply1 transform tamsayı transform döndüren bir işlevdir. Aşağıdaki kod, kullanımını apply1 gösterir:

let increment x = x + 1

let result1 = apply1 increment 100

Değeri, result önceki kod çalıştırılana kadar 101 olur.

Aşağıdaki örnekte gösterildiği gibi birden çok bağımsız -> değişken, sonraki belirteçlerle ayrılır:

let apply2 ( f: int -> int -> int) x y = f x y

let mul x y = x * y

let result2 = apply2 mul 10 20

Sonuç 200'dır.

Lambda İfadeleri

Lambda ifadesi, adlandırlanmamış bir işlevdir. Önceki örneklerde adlandırılmış işlevleri artırma ve tanımlama yerine aşağıdaki lambda ifadelerini kullanabilirsiniz:

let result3 = apply1 (fun x -> x + 1) 100

let result4 = apply2 (fun x y -> x * y ) 10 20

lambda ifadelerini tanımlamak için anahtar sözcüğünü fun kullanın. Lambda ifadesi işlev tanımına benzer ancak belirteci yerine bağımsız değişken listesini işlev gövdesinden ayırmak için belirteç = -> kullanılır. Normal bir işlev tanımında olduğu gibi, bağımsız değişken türleri açıkça belirtilebilir ve lambda ifadesinin dönüş türü gövdede son ifadenin türünden ortaya çıktı. Daha fazla bilgi için bkz. Lambda İfadeleri: Anahtar fun Sözcüğü.

Pipelines

Kanal |> işleci, F# içinde veri işleme sırasında kapsamlı olarak kullanılır. Bu işleç, işlevlerin "işlem hatlarını" esnek bir şekilde kurmasına olanak sağlar. Pipelining, işlev çağrılarının bir araya gelen işlemler olarak zincirlenerek çalışmasını sağlar:

let result = 100 |> function1 |> function2

Sonuç yine 202 olur. Aşağıdaki örnek, basit bir işlevsel işlem hattı oluşturmak için bu işleçleri nasıl kullanabileceğiniz hakkında bilgi sağlar:


/// Square the odd values of the input and add one, using F# pipe operators.
let squareAndAddOdd values =
    values
    |> List.filter (fun x -> x % 2 <> 0)
    |> List.map (fun x -> x * x + 1)

let numbers = [ 1; 2; 3; 4; 5 ]

let result = squareAndAddOdd numbers

Sonuç şu [2; 10; 26] şekildedir: . Önceki örnekte liste işleme işlevleri kullanılmıştır ve bu işlevler, işlem hatları inşa sırasında verileri işlemeye nasıl ekleyebilirsiniz? İşlem hattı işleci, F# çekirdek kitaplığında aşağıdaki gibi tanımlanır:

let (|>) x f = f x

İşlev bileşimi

F# içinde işlevler diğer işlevlerden birikebilirsiniz. function1 ve function2 işlevlerinin bileşimi, function1 işlevinin uygulamasını temsil eden ve işlev2 uygulamasını izleyen başka bir işlevdir:

let function1 x = x + 1
let function2 x = x * 2
let h = function1 >> function2
let result5 = h 100

Sonuç 202'dir.

Bileşim işleçleri iki işlev alır ve bir işlev verir; Buna karşılık, işlem hattı işleçleri bir işlev ve bağımsız değişken alır ve bir değer verir. Aşağıdaki kod örneği, işlev imzaları ve kullanımındaki farkları göstererek işlem hattı ile bileşim işleçleri arasındaki farkı gösterir.

// Function composition and pipeline operators compared.

let addOne x = x + 1
let timesTwo x = 2 * x

// Composition operator
// ( >> ) : ('T1 -> 'T2) -> ('T2 -> 'T3) -> 'T1 -> 'T3
let Compose2 = addOne >> timesTwo

// Backward composition operator
// ( << ) : ('T2 -> 'T3) -> ('T1 -> 'T2) -> 'T1 -> 'T3
let Compose1 = addOne << timesTwo

// Result is 5
let result1 = Compose1 2

// Result is 6
let result2 = Compose2 2

// Pipelining
// Pipeline operator
// ( |> ) : 'T1 -> ('T1 -> 'U) -> 'U
let Pipeline2 x = addOne x |> timesTwo

// Backward pipeline operator
// ( <| ) : ('T -> 'U) -> 'T -> 'U
let Pipeline1 x = addOne <| timesTwo x

// Result is 5
let result3 = Pipeline1 2

// Result is 6
let result4 = Pipeline2 2

Aşırı Yükleme İşlevleri

Bir türün yöntemlerini aşırı yükleyebilirsiniz, ancak işlevlere yük devredebilirsiniz. Daha fazla bilgi için bkz. Yöntemler.

Ayrıca bkz.