7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. Elixir

Dasar-dasar Elixir Metaprogramming

Read Time: 11 mins

Indonesian (Bahasa Indonesia) translation by Imam Firmansyah (you can also view the original English article)

Metaprogramming adalah sesuatu yang hebat, tetapi teknik yang sangat sulit, itu berarti sebuah program bisa menganalisis atau bahkan bisa berubah sendiri saat digunakan. Banyak Bahasa sekarang mendukung fitur ini, dan elixir tanpa pengecualian.

Dengan metaprogramming, Anda bisa membuat macro kompleks baru, terdefinisi secara dinamis dan menunda suatu eksekusi kode, yang berarti memperbolehkan Anda untuk menulis kode lebih singkat dan kuat. Ini sudah pasti topik yang berat, tetapi diharapkan setelah membaca artikel ini Anda akan mengerti dasar dari bagaimana cara memulai metaprogramming di Elixir.

Di artikel ini Anda akan mempelajari:

  • Apa itu syntax abstrak dan bagaimana kode Elixir bisa diwakili secara rahasia.
  • Apa itu quote dan unquote function.
  • Apa itu macros dan bagaimana bekerja dengan itu.
  • Bagaimana memasukan values dengan binding.
  • Kenapa harus macros higienis.

Sebelum mulai, sekiranya, biarkan saya memberikan sedikit pesan. Ingat kata-kata paman dari spider man's "Dengan kekuatan yang hebat datang dengan tanggung jawab yang besar"? Ini bisa dimasukan kedalam metaprogramming juga karena ini sangat kuat yang bisa membuat Anda memutar dan membelokan kode sesuai keinginan.

Tetap, Anda tidak boleh menyalah gunakan itu, dan Anda harus tetap pada solusi yang sederhana ketika itu bisa dan mungkin. Terlalu banyak metaprogramming membuat kode Anda akan lebih sulit dimengerti dan di tangani, jadi berhati-hatilah.

Abstract Syntax Tree dan Quote

Hal pertama yang harus dimengerti adalah bagaimana kode Elixir sebenarnya ada. Gambaran ini biasanya disebut Abstract Syntax Trees(AST), tetapi petunjuk Elixir yang resmi merekomendasikan mereka menyebut simply quoted expressions.

Sepertinya ekspresi datang dari bentuk tuple dengan tiga elemen, tetapi bagaimana kita membuktikan itu? Baik, ada sebuah fungsi yang disebut quote yang membalikkan gambaran dari beberapa kode yang diberikan. Pada dasarnya, itu membuat kode menjadi bentuk yang belum terevaluasi. . Sebagai contoh:

Jadi apa yang terjadi disana? Tuple dikembalikan dari suatu fungsi quote yang selalu memilki tiga elemen:

  1. Atom atau tuple lain dengan nilai yang sama. Pada kasus ini, itu adalah atom :+, yang berarti kita melakukan sesuatu yang lebih. Ngomong-ngomong, bentuk dari penulisan ini seharusnya familiar jika Anda datang dari dunia ruby.
  2. Daftar dari kata kunci dengan metadata. Sebagai contoh kita melihat modul Kernel yang sudah terimport secara otomatis.
  3. Daftar dari argumen atau beberapa atom. Pada kasus ini, ini adalah daftar dengan 1 dan 2.

Gambaran ini mungkin lebih sulit, tentu saja:

Dengan kata lain, beberapa literal mengembalikan nilainya sendiri ketika di quote, secara spesifik:

  • atom
  • integer
  • float
  • list
  • string
  • tuples (tapi hanya dengan dua elemen!)

Pada contoh berikutnya, kita bisa melihat meng-quote beberapa atom dan mengembalikan atom ini kembali:

Sekarang kita sudah tahu bagaimana kode di gambarkan secara mendalam, mari mulai menuju sesi selanjutnya dan melihat apa itu macros dan kenapa quoted epression itu penting.

Macro

Macro adalah bentuk istimewa seperti function, tetapi satu-satunya yang mengembalikan quoted code. Kode ini kemudian di letakan pada aplikasi, dan eksekusinya di tunda. Apa yang menarik adalah macros juga tidak mengevaluasi parameter yang dikirim ke mereka, mereka menggambarkan sebagai quoted expression juga. Macros bisa digunakan untuk membuat kustomisasi, fungsi yang kompleks digunakan untuk project Anda.

Ingat bahwa, akan tetapi, macros lebih sulit dari fungsi biasa, dan panduan resmi juga menulis bahwa ini harus digunakan pada kesempatan terakhir. Dengan kata lain, jika Anda bisa menggunakan sebuah function, jangan membuat sebuah macro karena akan membuat kode menjadi lebih kompleks dan, secara efektif, lebih sulit untuk ditangani. Tetap, macros ada porsi mereka sendiri, jadi mari kita lihat bagaimana cara membuatnya.

Ini bermula dengan memanggil defmacro (ini adalah macro itu sendiri):

Macro ini secara sederhana menerima beberapa argumen dan menampilkannya.

Juga, ini baik untuk berkata macro bisa di private, sama seperti function. Private macros bisa dipanggil dari modul yang mereka definisi. Untuk mendefinisikan sebuah macro, gunakan defmacrop.

Sekarang mari membuat modul terpisah yang akan digunakan:

Ketika menjalankan kode ini, {:{}, [line: 11], [1, 2, 3]} akan ditampilkan, yang dimana berarti argument itu memiliki bentuk quote (tidak terevaluasi). Sebelum melakukan proses, namun, biarkan saya membuat sedikit catatan.

Require

Kenapa kita membuat dua modul yang berbeda: satu untuk mendefinisikan sebuah macro dan satu untuk menjalankan suatu kode? Sepertinya kita harus melakukan seperti ini, karena macros di proses sebelum program di eksekusi. Kita juga harus memastikan macro yang terdefinisi ada modul yang tersedia, dan ini dapat dilakukan dengan require. Fungsi ini, pada dasarnya, memastikan modul yang diberikan ter compile sebelum yang sekarang berjalan.

Anda akan bertanya, kenapa kita tidak menghilangkan main module? Coba lakukan ini:

Sayangnya, kita mendapatkan pesan error yang berkata bahwa test tidak dapat ditemukan, walaupun ada macro yang memilki nama yang sama. Ini terjadi karena MyLib di definisikan pada scope yang sama (dan file yang sama) dimana kita berusaha menggunakan itu. Ini mungkin agak aneh, tetapi untuk sekarang harus diingat bahwa modul yang berbeda harus dibuat untuk menghindari masalah ini

Juga perlu dicatat macros tidak bisa digunakan secara global: pertama Anda harus import atau membutuhkan module tertentu.

Macro dan Ekspresi Quoted

Jadi sekarang kita tahu bagaimana Elixir expression di tampilkan dari dalam dan apa itu macros… Sekarang apa? Baik, sekarang kita dapat memanfaatkan pengetahuan ini dan melihat bagaimana quoted code bisa di evaluasi.

Mari kita kembali pada macros. Ini penting untuk diketahui bahwa akhir ekspresi dari semua macro adalah diharapkan sebagian quoted code yang akan di eksekusi dan di kembalikan secara otomatis ketika macro di panggil. Kita dapat menulis kembali contoh dari sesi sebelumnya dengan memindahkan IO.inspect ke Main modul:

Lihat apa yang terjadi? Tuple dikembalikan oleh macro yang tidak di memilki quote tetapi di evaluasi! Anda boleh mencoba menambahkan dua integer:

Sekali lagi, kode di eksekusi, dan 3 ditampilkan. Kita bisa mencoba menggunakan quote function secara langsung, dan akhir dari baris tetap bisa di evaluasi:

Arg wtelah di quote (catatan, ngomong-ngomong, kita masih bisa melihat nomor pada baris dimana macro dipanggil), tetapi quoted expression dengan tuple {1,2,3} telah di evaluasi untuk kita karena ini adalah baris terakhir dari macro.

Kita mungkin tergoda untuk menggunakan arg dalam ekspresi matematika:

Tetapi ini akan meningkatkan error yang mengatakan arg tidak ada. Kenapa begitu? Ini karena arg biasanya dimasukan ke string yang kita quote. Tapi apa yang harus kita lakukan selain mengevaluasiarg, memasukan hasil ke string, dan kemudian melakukan quote. Untuk melakukan ini, kita membutuhkan fungsi lain yang disebut unquote.

Unquoting Kode

unquote adalah sebuah fungsi yang memasukan hasil dari evaluasi kode ke dalam kode yang akan di berikan quote. Ini mungkin terdengar aneh, tetapi di kenyataan ini lumayan mudah dilakukan. Mari merubah contoh kode sebelumnya:

Sekarang program kita akan mengembalikan 4, yang dimana itu adalah yang kita inginkan! Yang terjadi adalah kode itu membiarkan unquote function berjalan hanya ketika quoted code telah di eksekusi, tidak ketika awal di urai.

Mari melihat contoh yang lebih sulit. Seharusmya kita akan membuat sebuah fungsi yang akan menjalakan beberapa ekspresi jika string yang diberikan adalah suatu palindrome. Kita bisa menulis sesuatu seperti ini:

Akhiran _f disini berarti fungsi ini akan membuat macro yang sama. Namun, jika kita mencoba untuk menjalankan fungsi ini sekarang, teks tetap akan ditampilkan walaupun string bukanlah sebuah palindrome:

Argumen itu melewati sebuah fungsi yang di evaluasi sebelum fungsi itu benar-benar dipanggil, jadi kita melihat sebuah string "yes" yang ditampilkan pada layar.ini sudah pasti bukan yang ingin kita capai, jadi mari kita mencoba menggunakan macro:

Disini kita meng-quote kode yang mengandung if condition dan menggunakan unquote untuk mengevaluasi nilai dari sebuah argumen ketika macro benar-benar dipanggil. Pada contoh ini, tidak akan ada yang ditampilkan pada layar, yang berarti benar!

Injecting Values Dengan Bindings

Menggunakan unquotetidak hanya satu-satunya cara untuk memasukan kode ke quoted block. Kita juga bisa menggunakan fitur bernama binding. Sebenarnya, ini secara sederhana sebuah pilihan untuk melanjutkan ke quote function yang menerima sebuah daftar keyword dengan semua variable yang memiliki unquote maksimal satu kali.

Untuk melakukan binding, gunakan bind_quoted ke quote function seperti ini:

Ini akan berguna ketika Anda menginginkan ekspresi yang menggunakan banyak tempat untuk di evaluasi hanya sekali. Seperti yang di demonstasikan pada contoh ini, kita dapat membuat sebuah macro sederhana yang memiliki output string dua kali dengan penundaan selama dua detik:

Sekarang, jika Anda memanggil itu untuk melewati waktu pada sistem, dua baris ini memiliki hasil yang sama:

Ini bukanlah kasus dengan unquote, karena argument ini akan di evaluasi dua kali dengan keterlambatan yang kecil, jadi hasilnya tidak akan sama:

Mengubah Quoted Code

Terkadang, Anda akan mengerti apa bentuk dari quoted code yang sebenarnya ketika kita melakukan debug pada itu, sebagai contoh. Ini bisa di selesaikan dengan menggunakan to_string function:

String yang di cetak akan seperti ini:

Kita bisa melihat str rgumen yang diberikan telah di evaluasi, dan hasilnya adalah telah dimasukan kedalam code. \n berarti "baris baru".

Juga, kita dapat menambahkan quoted code menggunakan expand_once dan expand:

Yang akan menghasilkan:

Tentu saja, representasi quote ini bisa kembali lagi menjadi sebuah string:

Kita akan mendapatkan hasil yang sama dari sebelumnya:

Expand function itu lebih sulit saat dicoba untuk mengekspansi setiap macro yang diberikan pada code:

Hasilnya akan seperti ini:

Kita melihat hasil ini karena if ini benar sebuah macro yang bergantung pada case statement, itu akan ikut terekspansi juga.

Sebagai contoh, __ENV__ bentuk spesial dari yang mengembalikan environment information seperti module, file, line, variable pada ruang lingkup saat ini dan imports.

Macros Higienis

Anda mungkin pernah mendengar macros sebenarnya higienis. Apa yang dimaksud adalah dia tidak mengubah setiap variable diluar dari cakupan kita. Untuk membuktikan ini, mari menambahkan contoh variable, coba mengubah nilai dari berbagai tempat, dan kemudian liat hasilnya:

Jadi other_var memberikan nilai didalam start! function, didalam sebuah macro, dan didalam quote. Anda akan melihat hasil seperti ini:

Ini berarti variable kita independent, dan kita tidak memperkenalkan konflik apapun yang menggunakan nama yang sama dimanapun (Meskipun, tentu saja, ini akan lebih baik untuk menjauhi dari pendekatan semacam itu).

Jika Anda benar menginginkan untuk merubah variabel yang ada diluar didalam sebuah macro, Anda mungkin akan menggunakan var!seperti ini:

Dengan menggunakan var!, kita secara efektif berkata bahwa variabel yang diberikan seharusnya tidak higienis. Sangat berhati-hatilah dengan melakukan pendekatan ini, Namun, Anda akan kehilangan jejak dengan apa yang sedang terjadi.

Kesimpulan

Pada artikel ini, kita telah mendiskusikan metaprogramming dasar dengan Bahasa Elixir. Kita telah mengetahui penggunaan dari quoteunquote, macros dan bindings ketika melihat beberapa contoh dan kasus. Pada saat ini, Anda sudah siap untuk menerapkan pengetahuan ini pada latihan dan membuat lebih ringkas dan program yang kuat. Ingat, walaupun, itu biasanya lebih baik untuk mempunyai pemahaman kode daripada meringkat kode, jadi jangan terlalu menggunakan metaprogramming pada project Anda.

Jika Anda suka untuk mempelajari lebih lanjut tentang fitur yang telah saya deskripsikan, silahkan untuk membaca pedoman untuk memulai macrosquote dan unquote. Saya sangat berharap artikel ini memberikan Anda sebuah informasi yang menarik tentang metaprogramming di elixir, yang sudah pasti cukup sulit pada awalnya. Bagaimanapun juga, jangan takut untuk bereksperimen dengan tools baru!

Saya berterima kasih untuk telah bersama saya, dan sampai bertemu berikutnya.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Scroll to top
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.