Function Composition
Function Composition atau komposisi fungsi adalah teknik dalam Functional Programming untuk menggabungkan dua atau lebih fungsi sehingga output dari satu fungsi menjadi input bagi fungsi berikutnya.
Konsep ini memungkinkan beberapa proses kecil digabungkan menjadi satu alur pemrosesan data.
Daripada membuat satu fungsi yang menangani banyak proses sekaligus, kita dapat membuat beberapa fungsi sederhana, kemudian menggabungkannya.
Contoh sederhana:
def multiply_by_two(number):
return number * 2
def add_five(number):
return number + 5
Kedua fungsi tersebut dapat dikomposisikan:
result = add_five(multiply_by_two(10))
print(result)
Output:
25
Alurnya:
10
↓
multiply_by_two()
↓
20
↓
add_five()
↓
25
Dengan demikian:
add_five(multiply_by_two(10))
dapat dibaca sebagai:
10 → dikali 2 → ditambah 5 → 25
Mengapa Function Composition?
Function composition membantu kita membangun program dari fungsi-fungsi kecil yang memiliki tanggung jawab jelas.
Misalnya terdapat tiga proses:
Data
↓
Validasi
↓
Transformasi
↓
Perhitungan
↓
Hasil
Masing-masing proses dapat dibuat menjadi fungsi terpisah.
Keuntungan pendekatan ini:
- Fungsi lebih kecil dan fokus.
- Fungsi lebih mudah diuji.
- Fungsi dapat digunakan kembali.
- Logika program lebih mudah dipahami.
- Proses pemrosesan data dapat disusun secara bertahap.
Contoh Function Composition Sederhana
Misalnya kita ingin melakukan dua operasi terhadap sebuah angka.
Pertama, mengalikan angka dengan 2.
def multiply_by_two(number):
return number * 2
Kemudian menambahkan 10.
def add_ten(number):
return number + 10
Kita dapat menggabungkannya:
result = add_ten(multiply_by_two(5))
print(result)
Output:
20
Urutan proses:
5
↓
multiply_by_two(5)
↓
10
↓
add_ten(10)
↓
20
Function Composition dengan Beberapa Fungsi
Komposisi tidak terbatas pada dua fungsi. Kita dapat menggabungkan beberapa fungsi sekaligus.
Contoh:
def multiply_by_two(number):
return number * 2
def add_ten(number):
return number + 10
def square(number):
return number ** 2
Ketiga fungsi tersebut dapat dikomposisikan:
result = square(add_ten(multiply_by_two(5)))
print(result)
Output:
400
Alurnya:
5
↓
multiply_by_two()
↓
10
↓
add_ten()
↓
20
↓
square()
↓
400
Perhatikan bahwa fungsi paling dalam dijalankan terlebih dahulu:
multiply_by_two(5)
Kemudian hasilnya diberikan kepada:
add_ten(...)
Kemudian hasil akhirnya diberikan kepada:
square(...)
Function Composition dan Pure Function
Function composition sangat erat kaitannya dengan pure function.
Pure function memiliki karakteristik:
- Input yang sama menghasilkan output yang sama.
- Tidak memiliki side effect.
Contoh:
def double(number):
return number * 2
def increment(number):
return number + 1
Keduanya merupakan fungsi sederhana yang tidak mengubah data di luar fungsi.
Kita dapat menggabungkannya:
result = increment(double(5))
print(result)
Output:
11
Prosesnya:
5
↓
double()
↓
10
↓
increment()
↓
11
Pendekatan seperti ini membuat alur transformasi data menjadi lebih mudah diprediksi.
Function Composition dengan map()
Function composition juga dapat digunakan bersama fungsi functional programming seperti map().
Contoh:
def double(number):
return number * 2
def square(number):
return number ** 2
numbers = [1, 2, 3, 4]
result = map(
square,
map(double, numbers)
)
print(list(result))
Output:
[4, 16, 36, 64]
Prosesnya:
[1, 2, 3, 4]
↓
double
↓
[2, 4, 6, 8]
↓
square
↓
[4, 16, 36, 64]
Kita juga dapat menuliskannya menggunakan list comprehension:
numbers = [1, 2, 3, 4]
result = [
square(double(number))
for number in numbers
]
print(result)
Output:
[4, 16, 36, 64]
Kedua pendekatan tersebut menghasilkan hasil yang sama.
Function Composition dengan Lambda
Function composition juga dapat dikombinasikan dengan lambda.
Contoh:
double = lambda number: number * 2
add_ten = lambda number: number + 10
result = add_ten(double(5))
print(result)
Output:
20
Namun, penggunaan lambda sebaiknya tetap mempertimbangkan keterbacaan kode.
Untuk fungsi yang memiliki logika lebih kompleks, penggunaan def biasanya lebih mudah dipahami.
Membuat Fungsi Composition
Python tidak menyediakan fungsi compose() bawaan seperti beberapa bahasa atau library functional programming.
Namun, kita dapat membuat fungsi composition sendiri.
Contoh:
def compose(function1, function2):
def composed(value):
return function2(function1(value))
return composed
Sekarang kita dapat membuat fungsi baru berdasarkan dua fungsi.
def double(number):
return number * 2
def add_ten(number):
return number + 10
double_then_add_ten = compose(double, add_ten)
result = double_then_add_ten(5)
print(result)
Output:
20
Alurnya:
5
↓
double()
↓
10
↓
add_ten()
↓
20
Fungsi:
double_then_add_ten
sekarang menjadi fungsi baru yang melakukan dua operasi secara berurutan.
Komposisi Fungsi dari Kiri ke Kanan
Ketika membuat fungsi composition sendiri, penting memahami urutan eksekusi.
Misalnya:
compose(double, add_ten)
berarti:
input
↓
double
↓
add_ten
↓
output
Sehingga:
compose(double, add_ten)(5)
menghasilkan:
double(5)
↓
10
↓
add_ten(10)
↓
20
Secara konsep:
add_ten(double(5))
Composition sebagai Pipeline
Function composition dapat dipahami seperti pipeline.
Setiap fungsi menjadi satu tahap pemrosesan.
Input
↓
Function A
↓
Function B
↓
Function C
↓
Output
Contoh:
def remove_spaces(text):
return text.replace(" ", "")
def uppercase(text):
return text.upper()
def add_prefix(text):
return "DATA-" + text
Fungsi tersebut dapat digunakan secara berurutan:
result = add_prefix(
uppercase(
remove_spaces("hello python")
)
)
print(result)
Output:
DATA-HELLOPYTHON
Alurnya:
"hello python"
↓
remove_spaces()
↓
"hellopython"
↓
uppercase()
↓
"HELLOPYTHON"
↓
add_prefix()
↓
"DATA-HELLOPYTHON"
Function Composition vs Function Chaining
Function composition sering terlihat seperti function chaining, tetapi konsepnya perlu dibedakan.
Pada composition, output dari satu fungsi menjadi input fungsi lainnya.
Contoh:
result = function_c(
function_b(
function_a(value)
)
)
Sedangkan method chaining biasanya menggunakan objek yang sama secara berurutan.
Contoh:
text = " hello python "
result = text.strip().upper().replace(" ", "-")
print(result)
Keduanya sama-sama menyusun beberapa operasi, tetapi mekanismenya berbeda.
Function Composition dan Reusability
Salah satu manfaat utama composition adalah kita dapat menggunakan kembali fungsi-fungsi kecil dalam berbagai kombinasi.
Misalnya:
def double(number):
return number * 2
def add_five(number):
return number + 5
def square(number):
return number ** 2
Kita dapat membuat beberapa alur berbeda.
result1 = add_five(double(10))
result2 = square(double(10))
result3 = square(add_five(10))
Setiap fungsi tetap sederhana, tetapi dapat dikombinasikan sesuai kebutuhan.
Kapan Menggunakan Function Composition?
Function composition cocok digunakan ketika:
- Sebuah proses terdiri dari beberapa tahap.
- Setiap tahap dapat dibuat sebagai fungsi terpisah.
- Fungsi memiliki tanggung jawab yang jelas.
- Fungsi dapat digunakan kembali.
- Data perlu melewati beberapa transformasi.
- Ingin membuat pipeline pemrosesan data.
Contoh konsep:
Input
↓
Validasi
↓
Transformasi
↓
Filter
↓
Perhitungan
↓
Output
Setiap tahap dapat direpresentasikan sebagai fungsi.
Readability
Function composition dapat membuat kode lebih terstruktur, tetapi composition yang terlalu dalam dapat membuat kode sulit dibaca.
Contoh:
result = function_d(
function_c(
function_b(
function_a(value)
)
)
)
Jika terlalu banyak fungsi bersarang, lebih baik memecah proses menjadi beberapa tahap.
Contoh:
step1 = function_a(value)
step2 = function_b(step1)
step3 = function_c(step2)
result = function_d(step3)
Pendekatan ini mungkin lebih panjang, tetapi alurnya lebih mudah dibaca dan di-debug.
Kesimpulan
Function Composition adalah teknik menggabungkan beberapa fungsi sehingga output dari suatu fungsi menjadi input bagi fungsi berikutnya.
Konsep dasarnya:
Input
↓
Function A
↓
Function B
↓
Function C
↓
Output
Contoh:
result = function_c(
function_b(
function_a(value)
)
)
Function composition merupakan konsep penting dalam Functional Programming karena mendorong kita untuk membuat fungsi-fungsi kecil, terisolasi, dapat digunakan kembali, dan kemudian menggabungkannya menjadi proses yang lebih kompleks.
Konsep ini juga berhubungan erat dengan:
- Pure Functions
- First-Class Functions
- Higher-Order Functions
map()filter()lambda- Immutability
- Function Pipeline
Hal terpenting bukan membuat kode sesingkat mungkin, tetapi membangun alur transformasi data yang jelas, terprediksi, dan mudah dipelihara.