Konsep Pemrograman Fungsional

Pengantar pemrograman fungsional

Earth Engine menggunakan sistem pemrosesan paralel untuk melakukan komputasi di sejumlah besar mesin. Untuk mengaktifkan pemrosesan tersebut, Earth Engine memanfaatkan teknik standar yang umumnya digunakan oleh bahasa fungsional, seperti transparansi referensial dan evaluasi lambat, untuk mendapatkan pengoptimalan dan efisiensi yang signifikan.

Konsep utama yang membedakan pemrograman fungsional dari pemrograman prosedural adalah tidak adanya efek samping. Artinya, fungsi yang Anda tulis tidak bergantung pada atau memperbarui data yang berada di luar fungsi. Seperti yang akan Anda lihat dalam contoh di bawah, Anda dapat menyusun ulang masalah sehingga dapat diselesaikan menggunakan fungsi tanpa efek samping, yang lebih cocok untuk dieksekusi secara paralel.

Loop For

Penggunaan loop for tidak disarankan di Earth Engine. Hasil yang sama dapat dicapai menggunakan operasi map() dengan menentukan fungsi yang dapat diterapkan secara independen ke setiap elemen. Hal ini memungkinkan sistem mendistribusikan pemrosesan ke mesin yang berbeda.

Contoh di bawah mengilustrasikan cara mengambil daftar angka dan membuat daftar lain dengan kuadrat setiap angka menggunakan map():

Code Editor (JavaScript)

// This generates a list of numbers from 1 to 10.
var myList = ee.List.sequence(1, 10);

// The map() operation takes a function that works on each element independently
// and returns a value. You define a function that can be applied to the input.
var computeSquares = function(number) {
  // We define the operation using the EE API.
  return ee.Number(number).pow(2);
};

// Apply your function to each item in the list by using the map() function.
var squares = myList.map(computeSquares);
print(squares);  // [1, 4, 9, 16, 25, 36, 49, 64, 81]

Kondisi If/Else

Masalah umum lain yang dihadapi oleh pengguna baru yang terbiasa dengan paradigma pemrograman prosedural adalah penggunaan operator kondisional if/else yang tepat di Earth Engine. Meskipun API menyediakan algoritma ee.Algorithms.If(), penggunaannya sangat tidak disarankan dan lebih baik menggunakan pendekatan yang lebih fungsional menggunakan map() dan filter. Earth Engine menggunakan eksekusi tertunda, yang berarti evaluasi ekspresi ditunda hingga nilai yang direalisasikan benar-benar diperlukan. Dalam beberapa kasus, jenis model eksekusi ini akan mengevaluasi alternatif benar dan salah dari pernyataan ee.Algorithms.If(). Hal ini dapat menyebabkan penggunaan komputasi dan memori tambahan, bergantung pada ekspresi dan resource yang diperlukan untuk mengeksekusinya.

Misalnya, Anda ingin menyelesaikan varian contoh di atas, dengan tugas menghitung kuadrat hanya bilangan ganjil. Pendekatan fungsional untuk menyelesaikan masalah ini tanpa kondisi if/else, ditunjukkan di bawah:

Code Editor (JavaScript)

// The following function determines if a number is even or odd.  The mod(2)
// function returns 0 if the number is even and 1 if it is odd (the remainder
// after dividing by 2).  The input is multiplied by this remainder so even
// numbers get set to 0 and odd numbers are left unchanged.
var getOddNumbers = function(number) {
  number = ee.Number(number);   // Cast the input to a Number so we can use mod.
  var remainder = number.mod(2);
  return number.multiply(remainder);
};

var newList = myList.map(getOddNumbers);

// Remove the 0 values.
var oddNumbers = newList.removeAll([0]);

var squares = oddNumbers.map(computeSquares);
print(squares);  // [1, 9, 25, 49, 81]

Paradigma ini sangat berlaku saat bekerja dengan koleksi. Jika Anda ingin menerapkan algoritma yang berbeda ke koleksi berdasarkan beberapa kondisi, cara yang lebih disukai adalah dengan memfilter koleksi berdasarkan kondisi terlebih dahulu, lalu map() fungsi yang berbeda ke setiap subset. Hal ini memungkinkan sistem memparalelkan operasi. Contoh:

Code Editor (JavaScript)

// Import Landsat 8 TOA collection and filter to 2018 images.
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
  .filterDate('2018-01-01', '2019-01-01');

// Divide the collection into 2 subsets and apply a different algorithm on them.
var subset1 = collection.filter(ee.Filter.lt('SUN_ELEVATION', 40));
var subset2 = collection.filter(ee.Filter.gte('SUN_ELEVATION', 40));

// Multiply all images in subset1 collection by 2;
// do nothing to subset2 collection.
var processed1 = subset1.map(function(image) {
  return image.multiply(2);
});
var processed2 = subset2;

// Merge the collections to get a single collection.
var final = processed1.merge(processed2);
print('Original collection size', collection.size());
print('Processed collection size', final.size());

Iterasi Kumulatif

Anda mungkin perlu melakukan operasi berurutan, di mana hasil setiap iterasi digunakan oleh iterasi berikutnya. Earth Engine menyediakan metode iterate() untuk tugas tersebut. Ingatlah bahwa iterate() dieksekusi secara berurutan dan oleh karena itu akan lambat untuk operasi besar. Gunakan hanya jika Anda tidak dapat menggunakan map() dan filter untuk mendapatkan output yang diinginkan.

Contoh yang baik dari iterate() adalah pembuatan deret bilangan Fibonacci. Di sini, setiap angka dalam deret adalah jumlah dari 2 angka sebelumnya. Fungsi iterate() menggunakan 2 argumen, fungsi (algoritma) dan nilai awal. Fungsi itu sendiri meneruskan 2 nilai, nilai saat ini dalam iterasi, dan hasil iterasi sebelumnya. Contoh berikut menunjukkan cara menerapkan deret fibonacci di Earth Engine.

Code Editor (JavaScript)

var algorithm = function(current, previous) {
  previous = ee.List(previous);
  var n1 = ee.Number(previous.get(-1));
  var n2 = ee.Number(previous.get(-2));
  return previous.add(n1.add(n2));
};

// Compute 10 iterations.
var numIteration = ee.List.repeat(1, 10);
var start = [0, 1];
var sequence = numIteration.iterate(algorithm, start);
print(sequence);  // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

Setelah memahami konsep javascript dengan baik, Anda dapat melihat Tutorial API untuk pengantar fungsionalitas geospasial Earth Engine API.