Petualangan operator pipa di babel @ 7


Rilis babel@7.0.0-beta52 memiliki flag konfigurasi baru yang diperlukan untuk @babel/plugin-proposal-pipeline-operator , yang memecah kompatibilitas mundur untuk versi plugin sebelumnya. Pada artikel ini, Anda akan mempelajari apa itu operator pipeline dan mengapa perlu konfigurasi.


UPD: saluran pipa pintar muncul di babel@7.2.0: https://babeljs.io/blog/2018/12/03/7.2.0#smart-pipeline-operator-parsing-8289-https-githubcom-babel-babel- tarik-8289


Status saat ini


Gilbert Garza , yang awalnya mengusulkan operator pipeline , berangkat untuk mendapatkan sintaksis sederhana untuk "rantai panggilan fungsi yang dipesan dalam gaya fungsional yang dapat dibaca." Operator pipa berasal dari bahasa seperti F #, Hack, Elm, Elixir dan lainnya, dan ketika Anda menambahkannya ke JavaScript, dua masalah yang kontroversial muncul:


  • Di mana dan bagaimana menggunakan placeholder?
  • Bagaimana seharusnya async / await dalam satu pipeline?

Placeholder


Pertanyaan pertama diajukan oleh Kevin Smith di tiket ini , di mana ia menyarankan menggunakan gaya pipa dari bahasa Hack . Di Hack, placeholder diperlukan untuk sisi kanan pipeline, misalnya:


 namespace Hack\UserDocumentation\Operators\Pipe\Examples\MapFilterCountPiped; function piped_example(array<int> $arr): int { return $arr |> \array_map($x ==> $x * $x, $$) |> \array_filter($$, $x ==> $x % 2 == 0) |> \count($$); } var_dump(piped_example(range(1, 10))); 

Kami mengambil sebagai dasar bahwa placeholder dapat digunakan dalam ekspresi apa pun dan berisi nilai dari langkah pipa terakhir. Pendekatan ini memberi kita fleksibilitas dan banyak kesempatan untuk menulis ekspresi.


Sisi lain dari koin adalah kompleksitas bahasa karena penambahan token baru. Sejauh ini, kami telah memilih hash ( # ), dan meskipun diskusi masih terbuka, token apa pun berpotensi berpotongan dengan penggunaan lainnya. Sebagai contoh, hash juga digunakan oleh bidang privat kelas , sama seperti varian token lainnya yang digunakan .


Async / tunggu


Versi pertama dari pernyataan pipeline berisi sintaks ini untuk await :


 x |> await f 

apa yang bisa digunakan untuk:


 await f(x) 

Sayangnya, pengguna mungkin mengharapkan penyebaran seperti itu:


 (await f)(x) 

Sementara gagasan untuk menambahkan async ke pipeline tergelincir, anggota komite berbicara menentang operator pipeline yang tidak mendukung async / await . Ya, ada opsi untuk cara bekerja dengan fungsi yang mengembalikan Janji tanpa sintaks eksplisit, tetapi semua opsi ini terlalu rumit atau memerlukan fungsi tambahan.


Solusi yang Disarankan


Sebagai hasil dari diskusi, dua proposal dibentuk (selain pilihan minimal): gunakan F # -piplines dan Smart-pipeline. Mari kita simak saran-saran ini.


Opsi operator minimum


Penawaran ini hanya berlaku untuk fungsionalitas dasar. Dalam versi minimal, dukungan untuk sinkronisasi tidak dihapus dan tidak ada placeholder. Opsi ini sesuai dengan perilaku plugin babel dari versi sebelumnya, sebelum konfigurasi muncul, dan sesuai dengan spesifikasi saat ini untuk operator pipeline dalam repositori. Ini lebih banyak digunakan sebagai rancangan penyelidikan untuk mengidentifikasi kelebihan dan kekurangan dari proposal lain, dan tidak mungkin diterima tanpa perubahan mendasar yang ada dalam proposal alternatif.


F # Pipa


Placeholder untuk jalur pipa F # tidak diperlukan sama sekali. Dalam versi dasar, fungsi panah mencakup kebutuhan placeholder, yang membutuhkan lebih sedikit coretan, dan didasarkan pada sintaksis ES2015 yang umum bagi semua orang.


Saat ini (sesuai dengan spesifikasi garis F #) fungsi panah harus dibungkus dengan tanda kurung:


 let person = { score: 25 }; let newScore = person.score |> double |> (_ => add(7, _)) |> (_ => boundScore(0, 100, _)); 

Survei sedang dilakukan untuk menentukan apakah layak menggunakan fungsi panah tanpa tanda kurung, yang terlihat berlebihan secara sintaksis di sini.


Sedangkan untuk asinkron, await berfungsi sebagai fungsi unary di jalur pipa F #:


 promise |> await 

Apa yang terungkap di:


 await promise 

dan karenanya await dapat digunakan di tengah rantai panggilan asinkron yang panjang:


 promise |> await |> (x => doubleSay(x, ', ')) |> capitalize |> (x => x + '!') |> (x => new User.Message(x)) |> (x => stream.write(x)) |> await |> console.log; 

Pemrosesan await khusus semacam itu berpotensi membuka kemungkinan untuk menggunakan operator unary lainnya (misalnya, typeof ), tetapi spesifikasi asli pipa F # tidak mengandungnya.


Pipa Cerdas


Pipa smar membawa ide placeholder ke kesimpulan logis mereka, memungkinkan penggunaan parsial dan ekspresi sewenang-wenang dalam pipa. Rantai panjang sebelumnya dapat ditulis seperti ini:


 promise |> await # |> doubleSay(#, ', ') |> # || throw new TypeError() |> capitalize |> # + '!' |> new User.Message(#) |> await stream.write(#) |> console.log; 

Aturan untuk menggunakan placeholder di jalur pipa cerdas cukup sederhana. Jika pengidentifikasi tunggal dilewatkan ke langkah pipa, maka tidak ada token tambahan (pengganti) yang diperlukan, ini disebut "gaya telanjang" :


 x |> a; x |> fb; 

Tidak seperti Hack, fungsi unary tidak memerlukan token pengganti.


Untuk ekspresi lain, placeholder (disebut "token topik leksikal") diperlukan, dan saluran pipa dianggap berfungsi dalam "gaya tema" - "gaya topik" . Tidak adanya token pengganti dalam kasus ini menyebabkan kesalahan SyntaxError awal:


 10 |> # + 1; promise |> await #; 

Jika ada operator, tanda kurung (termasuk untuk memanggil metode), tanda kutip, atau apa pun selain pengidentifikasi dan titik, maka token pengganti diperlukan. Ini akan membantu untuk menghindari tembakan di kaki dan menghilangkan ketidakpastian.


Perpipaan pintar memecahkan masalah mendukung asinkron dengan cara yang lebih umum, yang memungkinkan kita untuk menggunakan semua kemungkinan ekspresi dalam perpipaan, tidak hanya await , tetapi juga typeof , yield dan operator lainnya.


Babel memasuki TKP


Segera setelah ketiga proposal dikonkretkan, kami sampai pada kesimpulan bahwa diskusi seperti itu tidak akan mengarah pada resolusi kontradiksi yang mendalam antara proposal. Kami memutuskan bahwa cara terbaik adalah mengumpulkan umpan balik dari pengembang menggunakan kalimat dalam kode nyata. Mengingat peran Babel dalam komunitas pengembang, kami memutuskan untuk menambahkan ketiga opsi ke plugin operator pipeline .


Karena parsing untuk ketiga kalimat sedikit, tetapi berbeda, dukungan mereka pertama-tama harus ditambahkan ke @babel/parser (yang merupakan babylon ), dan parser harus tahu proposal mana yang harus didukung sekarang. Dengan demikian, plugin operator pipeline memerlukan opsi "proposal" , baik untuk mengkonfigurasi babylon untuk penguraian maupun untuk transformasi selanjutnya.


Kami mengerjakan ini secara online karena kami harus membuat semua perubahan yang melanggar kompatibilitas sebelum babel @ 7 tidak lagi beta. Pada akhirnya, kami ingin menjadikan salah satu opsi pipeline default untuk plugin untuk menghilangkan kebutuhan akan opsi konfigurasi.


Karena keterbatasan ini, kami memutuskan untuk menambahkan opsi ke konfigurasi plugin dan membuatnya wajib, memaksa pengguna untuk memutuskan penawaran mana yang ingin mereka gunakan dalam proyek mereka. Segera setelah proposal spesifik dipilih sebagai perilaku kanonik operator, kami menandai opsi "proposal" sebagai usang, dan opsi kanonik akan bekerja secara default. Dukungan untuk penawaran yang dibatalkan akan berfungsi hingga versi utama berikutnya.


Ambil bagian


Jika Anda ingin berpartisipasi dalam pembahasan proposal, maka semua diskusi bersifat publik dan Anda dapat menemukannya dalam repositori proposal operator pipa . Presentasi dari pertemuan TC39 juga siap melayani Anda. Pada akhirnya, Anda dapat mengikuti James DiGioia , JS Choi, atau Daniel Ehrenberg di Twitter.


Tetapi yang lebih penting, segera setelah pekerjaan pada pipeline selesai, cobalah di proyek Anda! Kami juga berupaya menambahkan fitur baru untuk diganti , sehingga Anda dapat memeriksa kode Anda secara interaktif. Kami membutuhkan umpan balik, dan menggunakannya dalam kode nyata akan sangat membantu untuk merakitnya. Posting tweet ke @babeljs .

Source: https://habr.com/ru/post/id418125/


All Articles