Apa itu lexical scoping (static scoping)?

Lexical scoping atau disebut juga static scoping adalah sebuah aturan umum yang digunakan oleh banyak bahasa pemrograman modern. Konsep ini mengatur scope atau cakupan sebuah variabel agar bisa dipanggil (direferensikan) dari dalam blok kode tempat variabel tersebut didefinisikan. Cakupan atau scope ini ditentukan saat proses kompilasi berlangsung. Variabel yang dideklarasikan dengan cara ini kadang disebut sebagai private variable.

Dalam bahasa pemrograman, scope menunjukkan di area mana sebuah fungsi atau variabel bisa diakses oleh bagian kode lain. Beberapa istilah umum yang sering dikaitkan dengan scope, antara lain:

  • Global scope: ruang lingkup global atau publik.
  • Local scope: ruang lingkup lokal atau terbatas.
  • Scope chain: rantai scope yang unik dari scope tempat variabel dipanggil hingga ke global scope.

Memahami lexical scoping

Secara sederhana, lexical scope sebuah item di bahasa pemrograman adalah tempat di mana item itu dibuat. Cakupan dari variabel ditentukan berdasarkan struktur teks (lexical) dari sebuah program. Variabel bisa dideklarasikan dalam scope tertentu dan hanya bisa diakses di dalam area tersebut.

Dengan kata lain, lexical scope memungkinkan fungsi untuk mengakses variabel dari parent scope-nya. Ketika lexical scope digunakan, fungsi-fungsi di dalam (inner) dapat mengakses variabel dari luar (outer scope) sampai ke global scope. Tapi, sebaliknya, scope luar tidak bisa mengakses variabel dari fungsi yang ada di dalamnya. Artinya, fungsi anak secara lexical terikat dengan fungsi induknya.

Banyak bahasa pemrograman modern yang menggunakan lexical scoping, seperti:

Beberapa bahasa algoritmik lain yang juga menggunakan lexical scoping antara lain Ada, Pascal, dan Modula-2.

Contoh lexical scoping

Untuk memahami lexical scoping, berikut ini contoh kode di R. R adalah bahasa pemrograman open source yang banyak digunakan di Windows, Linux, dan macOS. Seperti bahasa lainnya, aturan scoping di R menentukan bagaimana nilai akan diasosiasikan dengan variabel bebas dalam fungsi.

Beginilah cara lexical scoping ditunjukkan dalam bahasa R:

#Assign a value to a
a <- 7
#Defining function b and c
b <- function() a
c <- function(){
a < - 8
b()
}
# Call to function c
c()

Di sini, variabel a diberi nilai. Kemudian fungsi b dibuat yang akan mengembalikan nilai dari a. Di baris ke-3, fungsi c didefinisikan, membuat pemetaan baru untuk a, lalu memanggil b(). Nilai keluaran akhirnya adalah hasil dari pemanggilan fungsi tersebut.

Lexical scoping di JavaScript

JavaScript menggunakan lexical scoping untuk menentukan nama variabel saat fungsi dibuat di dalam fungsi lain. Parent scope dari sebuah fungsi ditentukan berdasarkan di mana fungsi itu dibuat, bukan di mana fungsi itu dijalankan.

Karena JavaScript mengizinkan fungsi untuk dipassing ke scope lain, maka hubungan antara fungsi anak dan fungsi induk bisa terputus. Untuk menjaga koneksi ini, JavaScript menggunakan closure. Closure memungkinkan sebuah fungsi tetap memiliki referensi ke parent scope-nya.

JavaScript menggunakan scope chain atau rantai scope untuk menemukan variabel yang bisa diakses di scope tertentu. Ia akan mencari variabel yang dipanggil dari scope saat ini, lalu terus naik ke parent scope hingga mencapai global scope.

Berikut contoh lexical scoping dalam JavaScript:

var a = 10
var func = function (){
var b = 20;
    console.log("a dan b bisa diakses (luar):", a, b);
    var innerFunc= function (){
        var c = 30;
        console.log("a, b, dan c bisa diakses (dalam):", a, b, c);
    }
    innerFunc();
    return;
}
func();
console.log("hanya a yang bisa diakses (global):", a);

Pada kode ini, variabel a bisa diakses oleh semua fungsi karena berada di global scope. Variabel b hanya bisa diakses dalam fungsi func, sedangkan variabel c hanya bisa diakses di dalam innerFunc. Karena innerFunc berada dalam func, ia tetap bisa mengakses variabel dari scope luar.

Dynamic scoping

Dynamic scoping merupakan kebalikan dari lexical scoping. Dengan pendekatan ini, variabel bisa dipanggil dari luar blok kode tempat variabel itu didefinisikan. Variabel seperti ini kadang disebut juga sebagai public variable.

Dalam dynamic scoping, sebuah variabel akan mengambil nilai terakhir yang di-assign. Setiap kali fungsi baru dijalankan, scope baru akan ditambahkan ke stack. Identifier global akan merujuk pada identifier yang paling baru di lingkungan tersebut. Jadi, kompiler akan memeriksa blok saat ini terlebih dahulu, lalu naik ke fungsi-fungsi yang memanggilnya secara bertahap.

Berbeda dengan lexical scoping, dynamic scoping tidak banyak digunakan di bahasa modern. Tapi beberapa bahasa lama masih mendukung, seperti versi awal Lisp, bash, dan LaTeX. Perl dan Common Lisp juga mengizinkan penggunaan dynamic scoping meskipun default-nya tetap lexical.

Contoh dynamic scoping bisa kamu lihat dari kode R yang tadi:

#Assign a value to a
a <- 7
#Defining function b and c
b <- function() a
c <- function() {
a < - 8
b()
}
# Call to function c
c()

Lexical scoping dan dynamic scoping adalah dua pendekatan berbeda untuk menentukan parent scope dari sebuah fungsi. Keduanya memiliki implikasi yang penting dalam cara program dijalankan dan bagaimana variabel ditangani di memori.

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *