Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Fungsi adalah unit dasar eksekusi program dalam bahasa pemrograman apa pun. Seperti dalam bahasa lain, fungsi F# memiliki nama, dapat memiliki parameter dan mengambil argumen, dan memiliki isi. F# juga mendukung konstruksi pemrograman fungsional seperti memperlakukan fungsi sebagai nilai, menggunakan fungsi yang tidak disebutkan namanya dalam ekspresi, komposisi fungsi untuk membentuk fungsi baru, fungsi kurir, dan definisi implisit fungsi dengan cara aplikasi parsial argumen fungsi.
Anda menentukan fungsi dengan menggunakan let kata kunci, atau, jika fungsi rekursif, let rec kombinasi kata kunci.
Sintaksis
// 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
Komentar
Nama fungsi adalah pengidentifikasi yang mewakili fungsi. Daftar parameter terdiri dari parameter berturut-turut yang dipisahkan oleh spasi. Anda dapat menentukan jenis eksplisit untuk setiap parameter, seperti yang dijelaskan di bagian Parameter. Jika Anda tidak menentukan jenis argumen tertentu, pengkompilasi mencoba menyimpulkan jenis dari isi fungsi. Isi fungsi terdiri dari ekspresi. Ekspresi yang membentuk isi fungsi biasanya merupakan ekspresi majemuk yang terdiri dari sejumlah ekspresi yang berpuncak dalam ekspresi akhir yang merupakan nilai pengembalian. Jenis pengembalian adalah titik dua diikuti oleh jenis dan bersifat opsional. Jika Anda tidak menentukan jenis nilai yang dikembalikan secara eksplisit, pengkompilasi menentukan jenis pengembalian dari ekspresi akhir.
Definisi fungsi sederhana menyerupan berikut ini:
let f x = x + 1
Di contoh sebelumnya, nama fungsi adalah f, argumennya adalah x, yang memiliki jenis int, bagian isi fungsi adalah x + 1, dan nilai yang ditampilkan berjenis int.
Fungsi dapat ditandai inline. Untuk informasi tentang inline, lihat Fungsi Sebaris.
Ruang Lingkup
Pada tingkat cakupan apa pun selain cakupan modul, ini bukan kesalahan untuk menggunakan kembali nilai atau nama fungsi. Jika Anda menggunakan kembali nama, nama yang dinyatakan kemudian membayangi nama yang dideklarasikan sebelumnya. Namun, pada cakupan tingkat atas dalam modul, nama harus unik. Misalnya, kode berikut menghasilkan kesalahan ketika muncul di cakupan modul, tetapi tidak ketika muncul di dalam fungsi:
let list1 = [ 1; 2; 3 ]
// Error: duplicate definition.
let list1 = []
let function1 () =
let list1 = [ 1; 2; 3 ]
let list1 = []
list1
Tetapi kode berikut dapat diterima di tingkat cakupan apa pun:
let list1 = [ 1; 2; 3 ]
let sumPlus x =
// OK: inner list1 hides the outer list1.
let list1 = [ 1; 5; 10 ]
x + List.sum list1
Parameter-parameternya
Nama parameter tercantum setelah nama fungsi. Anda dapat menentukan jenis untuk parameter, seperti yang ditunjukkan dalam contoh berikut:
let f (x: int) = x + 1
Jika Anda menentukan jenis, itu mengikuti nama parameter dan dipisahkan dari nama dengan titik dua. Jika Anda menghilangkan jenis untuk parameter, jenis parameter disimpulkan oleh pengkompilasi. Misalnya, dalam definisi fungsi berikut, argumen x disimpulkan berjenis int karena 1 berjenis int.
let f x = x + 1
Namun, pengkompilasi akan mencoba membuat fungsi se generik mungkin. Misalnya, perhatikan kode berikut:
let f x = (x, x)
Fungsi ini membuat tuple dari satu argumen dari jenis apa pun. Karena jenis tidak ditentukan, fungsi dapat digunakan dengan jenis argumen apa pun. Untuk informasi selengkapnya, lihat Generalisasi Otomatis.
Badan Fungsi
Isi fungsi dapat berisi definisi variabel dan fungsi lokal. Variabel dan fungsi tersebut berada dalam cakupan dalam isi fungsi saat ini tetapi tidak di luarnya. Anda harus menggunakan indentasi untuk menunjukkan bahwa definisi berada dalam isi fungsi, seperti yang ditunjukkan dalam contoh berikut:
let cylinderVolume radius length =
// Define a local value pi.
let pi = 3.14159
length * pi * radius * radius
Untuk informasi selengkapnya, lihat Panduan Pemformatan Kode dan Sintaks Verbose.
Mengembalikan Nilai
Pengkompilasi menggunakan ekspresi akhir dalam isi fungsi untuk menentukan nilai dan jenis yang dikembalikan. Pengkompilasi mungkin menyimpulkan jenis ekspresi akhir dari ekspresi sebelumnya. Dalam fungsi cylinderVolume, ditunjukkan di bagian sebelumnya, jenis pi ditentukan dari jenis literal 3.14159 menjadi float. Pengkompilasi menggunakan jenis pi untuk menentukan jenis ekspresi length * pi * radius * radius menjadi float. Oleh karena itu, jenis pengembalian keseluruhan fungsi adalah float.
Untuk menentukan jenis pengembalian secara eksplisit, tulis kode sebagai berikut:
let cylinderVolume radius length : float =
// Define a local value pi.
let pi = 3.14159
length * pi * radius * radius
Seperti yang ditulis kode di atas, kompilator menerapkan float ke seluruh fungsi; jika Anda bermaksud menerapkannya ke jenis parameter juga, gunakan kode berikut:
let cylinderVolume (radius: float) (length: float) : float
Memanggil Fungsi
Anda memanggil fungsi dengan menentukan nama fungsi diikuti dengan spasi lalu argumen apa pun yang dipisahkan oleh spasi. Misalnya, untuk memanggil fungsi cylinderVolume dan menetapkan hasilnya ke nilai vol, Anda menulis kode berikut:
let vol = cylinderVolume 2.0 3.0
Aplikasi Parsial Argumen
Jika Anda menyediakan kurang dari jumlah argumen yang ditentukan, Anda membuat fungsi baru yang mengharapkan argumen yang tersisa. Metode penanganan argumen ini disebut sebagai currying dan merupakan karakteristik bahasa pemrograman fungsi seperti F#. Misalnya, Anda bekerja dengan dua ukuran pipa: satu memiliki radius 2,0 dan yang lainnya memiliki radius 3,0. Anda dapat membuat fungsi yang menentukan volume pipa sebagai berikut:
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
Anda kemudian akan menyediakan argumen akhir sesuai kebutuhan untuk berbagai panjang pipa dari dua ukuran yang berbeda:
let length1 = 30.0
let length2 = 40.0
let smallPipeVol1 = smallPipeVolume length1
let smallPipeVol2 = smallPipeVolume length2
let bigPipeVol1 = bigPipeVolume length1
let bigPipeVol2 = bigPipeVolume length2
Fungsi Rekursif
Fungsi rekursif adalah fungsi yang memanggil diri mereka sendiri. Mereka mengharuskan Anda menentukan kata kunci rekam mengikuti kata kunci let . Panggil fungsi rekursif dari dalam isi fungsi sama seperti Anda akan memanggil panggilan fungsi apa pun. Fungsi rekursif berikut menghitung angka Fibonacci ke-n. Urutan angka Fibonacci telah dikenal sejak zaman kuno dan merupakan urutan di mana setiap angka berturut-turut adalah jumlah dari dua angka sebelumnya dalam urutan.
let rec fib n =
if n < 2 then 1 else fib (n - 1) + fib (n - 2)
Beberapa fungsi rekursif mungkin meluapkan tumpukan program atau melakukan secara tidak efisien jika Anda tidak menulisnya dengan hati-hati dan dengan kesadaran akan teknik khusus, seperti penggunaan rekursi ekor, akumulator, dan kelanjutan.
Nilai Fungsi
Di F#, semua fungsi dianggap sebagai nilai; bahkan, mereka dikenal sebagai nilai fungsi. Karena fungsi adalah nilai, fungsi tersebut dapat digunakan sebagai argumen ke fungsi lain atau dalam konteks lain di mana nilai digunakan. Berikut ini adalah contoh fungsi yang mengambil nilai fungsi sebagai argumen:
let apply1 (transform: int -> int) y = transform y
Anda menentukan jenis nilai fungsi dengan menggunakan -> token. Di sisi kiri token ini adalah jenis argumen, dan di sisi kanan adalah nilai yang dikembalikan. Dalam contoh sebelumnya, apply1 adalah fungsi yang mengambil fungsi transform sebagai argumen, di mana transform adalah fungsi yang mengambil bilangan bulat dan mengembalikan bilangan bulat lain. Kode berikut menunjukkan cara menggunakan apply1:
let increment x = x + 1
let result1 = apply1 increment 100
Nilai result akan menjadi 101 setelah kode sebelumnya berjalan.
Beberapa argumen dipisahkan oleh token berturut-turut -> , seperti yang ditunjukkan dalam contoh berikut:
let apply2 (f: int -> int -> int) x y = f x y
let mul x y = x * y
let result2 = apply2 mul 10 20
Hasilnya adalah 200.
Ekspresi Lambda
Ekspresi lambda adalah fungsi yang tidak disebutkan namanya. Dalam contoh sebelumnya, alih-alih menentukan kenaikan fungsi bernama dan mul, Anda dapat menggunakan ekspresi lambda sebagai berikut:
let result3 = apply1 (fun x -> x + 1) 100
let result4 = apply2 (fun x y -> x * y) 10 20
Anda menentukan ekspresi lambda dengan menggunakan fun kata kunci. Ekspresi lambda menyerupai definisi fungsi, kecuali bahwa alih-alih = token, -> token digunakan untuk memisahkan daftar argumen dari isi fungsi. Seperti dalam definisi fungsi reguler, jenis argumen dapat disimpulkan atau ditentukan secara eksplisit, dan jenis pengembalian ekspresi lambda disimpulkan dari jenis ekspresi terakhir dalam isi. Untuk informasi selengkapnya, lihat Ekspresi Lambda: Kata fun Kunci.
Rantai Pengolahan
Operator pipa |> digunakan secara ekstensif saat memproses data di F#. Operator ini memungkinkan Anda untuk membuat "alur" fungsi dengan cara yang fleksibel. Pipelining memungkinkan panggilan fungsi dirangkai bersama-sama sebagai operasi berturut-turut:
let result = 100 |> function1 |> function2
Contoh berikut menjelaskan bagaimana Anda dapat menggunakan operator ini untuk membangun alur fungsi sederhana:
/// 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
Hasilnya adalah [2; 10; 26]. Sampel sebelumnya menggunakan fungsi pemrosesan daftar, menunjukkan bagaimana fungsi dapat digunakan untuk memproses data saat membangun alur. Operator alur itu sendiri didefinisikan dalam pustaka inti F# sebagai berikut:
let (|>) x f = f x
Komposisi fungsi
Fungsi dalam F# dapat terdiri dari fungsi lain. Komposisi dua fungsi function1 dan function2 adalah fungsi lain yang mewakili aplikasi function1 diikuti oleh aplikasi function2:
let function1 x = x + 1
let function2 x = x * 2
let h = function1 >> function2
let result5 = h 100
Hasilnya adalah 202.
Operator >> komposisi mengambil dua fungsi dan mengembalikan fungsi; sebaliknya, operator |> alur mengambil nilai dan fungsi dan mengembalikan nilai. Contoh kode berikut menunjukkan perbedaan antara operator alur dan komposisi dengan menunjukkan perbedaan dalam tanda tangan dan penggunaan fungsi.
// 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
Fungsi Kelebihan Beban
Anda dapat membebani metode berlebih dari jenis tetapi bukan fungsi. Untuk informasi selengkapnya, lihat Metode.