Bagikan melalui


Fungsi Sebaris

Fungsi sebaris adalah fungsi yang terintegrasi secara langsung ke dalam kode panggilan.

Menggunakan Fungsi Sebaris

Ketika Anda menggunakan parameter jenis statis, fungsi apa pun yang diparameterkan menurut parameter jenis harus sebaris. Ini menjamin bahwa kompilator bisa menyelesaikan parameter jenis ini. Ketika Anda menggunakan parameter jenis generik biasa, tidak ada batasan tersebut.

Selain mengaktifkan penggunaan batasan-batasan anggota, fungsi sebaris dapat membantu dalam mengoptimalkan kode. Namun, penggunaan fungsi sebaris yang berlebihan bisa menyebabkan kode Anda kurang tahan terhadap perubahan pengoptimalan kompilator serta implementasi fungsi pustaka. Untuk alasan ini, Anda harus menghindari penggunaan fungsi sebaris untuk pengoptimalan kecuali Anda telah mencoba semua teknik pengoptimalan lainnya. Membuat sebuah fungsi atau metode sebaris terkadang bisa meningkatkan performa, tetapi itu tidak selalu terjadi. Oleh karena itu, Anda juga harus menggunakan pengukuran performa untuk memverifikasi bahwa pembuatan fungsi sebaris tertentu benar-benar memberi efek positif.

Pengubah inline bisa diterapkan ke fungsi di tingkat atas, pada tingkat modul, atau pada tingkat metode di sebuah kelas.

Contoh kode berikut mengilustrasikan fungsi sebaris di tingkat atas, metode instans sebaris, serta metode statis sebaris.

let inline increment x = x + 1
type WrapInt32() =
    member inline this.incrementByOne(x) = x + 1
    static member inline Increment(x) = x + 1

Fungsi Sebaris dan Inferensi Jenis

Kehadiran inline memengaruhi inferensi jenis. Ini karena fungsi sebaris bisa mempunyai parameter jenis yang diselesaikan secara statis, sedangkan fungsi non-sebaris tidak bisa. Contoh kode berikut menunjukkan kasus di mana inline berguna karena Anda menggunakan fungsi yang mempunyai parameter jenis yang diselesaikan secara statis, float operator konversi.

let inline printAsFloatingPoint number =
    printfn "%f" (float number)

Tanpa pengubah inline, inferensi jenis memaksa fungsi untuk mengambil jenis tertentu, dalam hal ini int. Tetapi dengan pengubah inline, fungsi juga disimpulkan mempunyai parameter jenis yang diselesaikan secara statis. Dengan pengubah inline, jenisnya disimpulkan sebagai berikut ini:

^a -> unit when ^a : (static member op_Explicit : ^a -> float)

Ini berarti bahwa fungsi menerima jenis apa pun yang mendukung konversi ke float.

InlineIfLambda

Kompilator F# menyertakan pengoptimal yang melakukan inlining kode. Atribut InlineIfLambda memungkinkan kode untuk secara opsional menunjukkan bahwa, jika argumen ditentukan sebagai fungsi lambda, argumen itu sendiri harus selalu disisipkan di situs panggilan. Untuk informasi selengkapnya, lihat F# RFC FS-1098.

Misalnya, pertimbangkan fungsi iterateTwice berikut untuk melintasi array:

let inline iterateTwice ([<InlineIfLambda>] action) (array: 'T[]) =
    for i = 0 to array.Length-1 do
        action array[i]
    for i = 0 to array.Length-1 do
        action array[i]

Jika situs panggilan adalah:

let arr = [| 1.. 100 |]
let mutable sum = 0
arr  |> iterateTwice (fun x ->
    sum <- sum + x)

Kemudian setelah inlining dan optimasi lainnya, kodenya menjadi:

let arr = [| 1..100 |]
let mutable sum = 0
for i = 0 to arr.Length - 1 do
    sum <- sum + arr[i] 
for i = 0 to arr.Length - 1 do
    sum <- sum + arr[i] 

Pengoptimalan ini diterapkan terlepas dari ukuran ekspresi lambda yang terlibat. Fitur ini juga dapat digunakan untuk menerapkan loop unrolling dan transformasi serupa dengan lebih andal.

Peringatan keikutsertaan (/warnon:3517 atau properti <WarnOn>3517</WarnOn>) bisa diaktifkan untuk menunjukkan tempat dalam kode Anda di mana argumen InlineIfLambda tidak terikat dengan ekspresi lambda di situs panggilan. Dalam situasi normal, peringatan ini tidak boleh diaktifkan. Namun, dalam beberapa jenis pemrograman performa tinggi, akan berguna untuk memastikan semua kode sejajar dan diratakan.

Lihat juga