Aracılığıyla paylaş


İşlevler

İşlevler, herhangi bir programlama dilinde program yürütmenin temel birimidir. Diğer dillerde olduğu gibi, bir F# işlevinin bir adı vardır, parametreleri olabilir, bağımsız değişkenleri alabilir ve bir gövdesi vardır. F# ayrıca işlevleri değer olarak işleme, ifadelerde adsız işlevleri kullanma, yeni işlevler oluşturmak için işlevlerin bileşimini, curried işlevleri ve işlev bağımsız değişkenlerinin kısmi uygulanması yoluyla işlevlerin örtük tanımını destekler.

İşlevleri anahtar sözcüğünü let kullanarak veya işlev özyinelemeliyse anahtar sözcük bileşimini let rec kullanarak tanımlarsınız.

Sözdizimi

// 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ış ardışık 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 çıkarsamaya çalışır. İşlev gövdesi bir ifadeden oluşur. İşlev gövdesini oluşturan ifade genellikle dönüş değeri olan son ifadede doruk noktası olan bir dizi ifadeden oluşan bileşik bir ifadedir. Dönüş türü bir iki nokta üst üste ve ardından bir türdür ve isteğe bağlıdır. Dönüş değerinin türünü açıkça belirtmezseniz, derleyici dönüş türünü son ifadeden belirler.

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

let f x = x + 1

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

İşlevler olarak işaretlenebilir inline. hakkında inlinebilgi için bkz. Satır içi İşlevler.

Scope

Modül kapsamı dışındaki herhangi bir kapsam düzeyinde, bir değerin veya işlev adının yeniden kullanılması bir hata değildir. Bir adı yeniden kullandığınızda, daha sonra bildirilen ad daha önce bildirilen adı gölgeler. Ancak, bir modüldeki en ü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 oluşturur, ancak bir işlevin içinde göründüğünde bu hataya neden olmaz:

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

Parametrelerin adları işlev adından sonra listelenir. Aşağıdaki örnekte gösterildiği gibi parametre için bir tür belirtebilirsiniz:

let f (x: int) = x + 1

Bir tür belirtirseniz, parametrenin adını izler ve adından iki nokta üst üste ile ayrılır. parametresinin türünü atlarsanız, parametre türü derleyici tarafından çıkarılır. Örneğin, aşağıdaki işlev tanımında, 1 türünde olduğundan bağımsız değişken x türünde intintolarak çıkarılır.

let f x = x + 1

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

let f x = (x, x)

İşlev, herhangi bir türdeki bağımsız değişkenden bir tanımlama grubu oluşturur. Tür belirtilmediğinden 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 kapsam içindedir, ancak bunun dışında değildir. Aşağıdaki örnekte gösterildiği gibi bir tanımın işlev gövdesinde olduğunu belirtmek için girinti kullanmalısınız:

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övdesindeki son ifadeyi kullanır. Derleyici, önceki ifadelerden son ifadenin türünü çıkarsayabilir. önceki bölümde gösterilen işlevinde cylinderVolumetürüpi, olacak floatdeğişmez 3.14159 değerin türünden belirlenir. Derleyici, olacak floatifadenin length * pi * radius * radius türünü belirlemek için türünü kullanırpi. Bu nedenle işlevin genel dönüş türü şeklindedir float.

Dönüş türünü 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ıklarından, derleyici float işlevinin tamamına uygular; bunu parametre türlerine de uygulamak istiyorsanız aşağıdaki kodu kullanın:

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

İşlev Çağırma

İşlev adını ve ardından boşluk ve boşluklarla ayrılmış bağımsız değişkenleri belirterek işlevleri çağırırsınız. Örneğin, function cylinderVolume işlevini çağırmak ve sonucu vol değerine atamak için aşağıdaki kodu yazarsınız:

let vol = cylinderVolume 2.0 3.0

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

Belirtilen sayıdan daha az bağımsız değişken sağlarsanız, kalan bağımsız değişkenleri bekleyen yeni bir işlev oluşturursunuz. 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 boru boyutuyla çalıştığınızı varsayalım: birinin yarıçapı 2,0 , diğerinin yarıçapı 3,0'dır. Boru hacmini aşağıdaki gibi belirleyen işlevler 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

Ardından, iki farklı boyuttaki borunun çeşitli uzunlukları için gereken son bağımsız değişkeni sağlamanız gerekir:

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 Fonksiyonlar

Özyinelemeli işlevler kendilerini çağıran işlevlerdir. Bunlar, let anahtar sözcüğünden sonra rec anahtar sözcüğünü belirtmenizi gerektirir. Herhangi bir işlev çağrısını çağıracağınız gibi, özyinelemeli işlevi işlevin gövdesinden çağırın. Aşağıdaki özyinelemeli işlev n. Fibonacci sayısını hesaplar. Fibonacci sayı dizisi antik çağdan beri bilinmektedir ve ardışık sayıların dizideki önceki iki sayının toplamı olduğu bir dizidir.

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

Bazı özyinelemeli işlevler program yığınını taşabilir veya bunları dikkatle ve kuyruk özyineleme kullanımı, biriktiriciler ve devamlılıklar gibi özel teknikler farkındalığıyla yazmazsanız verimsiz bir şekilde gerçekleştirebilir.

İşlev Değerleri

F# dilinde tüm işlevler değer olarak kabul edilir; aslında, bunlar işlev değerleri olarak bilinir. İşlevler değerler olduğundan, bunlar diğer işlevlere bağımsız değişken olarak veya değerlerin kullanıldığı diğer bağlamlarda kullanılabilir. Aşağıda, işlev değerini bağımsız değişken olarak alan bir işlev örneği verilmiştir:

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

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

let increment x = x + 1

let result1 = apply1 increment 100

Değeri result , önceki kod çalıştırıldıktan sonra 101 olur.

Aşağıdaki örnekte gösterildiği gibi birden çok bağımsız değişken ardışık -> 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 adsız bir işlevdir. Önceki örneklerde, adlandırılmış işlevleri increment ve mul olarak tanımlamak yerine lambda ifadelerini aşağıdaki gibi kullanabilirsiniz:

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

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

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

Boru Hatları

F# dilinde veri işlenirken boru işleci |> yoğun olarak kullanılır. Bu işleç, işlevlerin "işlem hatlarını" esnek bir şekilde oluşturmanıza olanak tanır. Kanal oluşturma, işlev çağrılarının ardışık işlemler olarak zincirlenmesine olanak tanır:

let result = 100 |> function1 |> function2

Aşağıdaki örnek, basit bir işlevsel işlem hattı oluşturmak için bu işleçleri nasıl kullanabileceğinizi açıklar:

/// 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ç [2; 10; 26]'dır. Önceki örnekte, işlevlerin işlem hatları oluştururken verileri işlemek için nasıl kullanılabileceğini gösteren liste işleme işlevleri kullanılmaktadır. İşlem hattı işlecinin kendisi F# çekirdek kitaplığında aşağıdaki gibi tanımlanır:

let (|>) x f = f x

İşlev bileşimi

F# içindeki işlevler diğer işlevlerden oluşturulabilir. İşlev1 ve işlev2 işlevlerinin bileşimi, işlev1 uygulamasını ve ardından işlev2 uygulamasını temsil eden 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.

Oluşturma işleci >> iki işlev alır ve bir işlev döndürür; buna karşılık işlem hattı işleci |> bir değer ve bir işlev alır ve bir değer döndürür. Aşağıdaki kod örneği, işlev imzalarındaki ve kullanımdaki farkları göstererek işlem hattı ve oluşturma 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

İşlevleri Aşırı Yükleme

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

Ayrıca bakınız