Konsep Pemrograman Fungsional

Pengantar pemrograman fungsional

Earth Engine menggunakan sistem pemrosesan paralel untuk melakukan komputasi di sejumlah besar mesin. Untuk memungkinkan pemrosesan tersebut, Earth Engine memanfaatkan teknik standar yang biasa digunakan oleh bahasa fungsional, seperti transparansi referensial dan evaluasi lambat, untuk pengoptimalan dan peningkatan 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 jauh lebih cocok untuk dieksekusi secara paralel.

Loop For

Penggunaan loop for tidak direkomendasikan di Earth Engine. Hasil yang sama dapat dicapai menggunakan operasi map(), tempat Anda 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 dari setiap angka menggunakan map():

Editor Kode (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 dianjurkan dan sebaiknya menggunakan pendekatan yang lebih fungsional menggunakan map() dan filter. Earth Engine menggunakan eksekusi yang ditangguhkan, yang berarti bahwa 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 komputasi dan penggunaan memori tambahan, bergantung pada ekspresi dan resource yang diperlukan untuk menjalankannya.

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

Editor Kode (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 menggunakan koleksi. Jika Anda ingin menerapkan algoritma yang berbeda ke koleksi berdasarkan beberapa kondisi, cara yang lebih disukai adalah dengan memfilter koleksi terlebih dahulu berdasarkan kondisi, lalu map() fungsi yang berbeda ke setiap subset. Hal ini memungkinkan sistem untuk memparalelkan operasi. Contoh:

Editor Kode (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, dengan hasil setiap iterasi digunakan oleh iterasi berikutnya. Earth Engine menyediakan metode iterate() untuk tugas tersebut. Ingat bahwa iterate() dijalankan secara berurutan, sehingga akan lambat untuk operasi besar. Gunakan hanya jika Anda tidak dapat menggunakan map() dan filter untuk mencapai output yang diinginkan.

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

Editor Kode (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 fungsi geospasial Earth Engine API.