Powershell: Saran: terapkan kondisional ternary

Dibuat pada 2 Mar 2017  ·  52Komentar  ·  Sumber: PowerShell/PowerShell

Persyaratan ternary gaya-C akan menjadi tambahan yang berguna untuk bahasa ini.

Misalnya, alih-alih menulis:

if ((get-date).tostring("ss") % 2) { 'odd'  } else  { 'even' }

seseorang dapat menulis:

(get-date).tostring("ss") % 2   ?   'odd'   :    'even'

Itu juga akan meredakan kekecewaan yang sudah lama terjadi:

Di Microsoft, "mengirim berarti memilih". Salah satu hal yang sangat kami kecewakan karena tidak dapat mengirim di V1.0 adalah operator ternary.

Dari posting blog Tim PowerShell tertanggal 29 Desember 2006.


Terkait: terapkan tugas null-coalescence dan null-soaking dan null-conditional

Committee-Reviewed Issue-Enhancement WG-Language

Komentar yang paling membantu

@RichardSiddaway : Jika kita melihat Stack Overflow di pertanyaan yang diberi tag PowerShell _asked sejak 2014_, kita mendapatkan (pada tulisan ini):

  • kira-kira 106.000 posting ditandai powershell (ini termasuk jawaban juga; jika Anda membatasi kueri untuk pertanyaan, Anda mendapatkan sekitar 46.000)
  • dari jumlah tersebut, 71 berisi kata PSItem (13 di antaranya adalah pertanyaan), yaitu kurang dari 1%

$PSItem diperkenalkan di v3 pada September 2012, jadi untuk amannya saya memilih 2014 sebagai tanggal mulai kueri.

Meskipun ini bukan metrik yang tepat, - situs tidak mengizinkan Anda untuk mencari $_ atau _ , sayangnya, dan saya yakin ada pertanyaan yang mengandung _neither_ $_ atau $PSItem , dan pertanyaan pra-v3 masih diajukan - saya masih berpikir aman untuk menyimpulkan bahwa $_ digunakan jauh lebih sering daripada $PSItem .

Namun, poin yang lebih besar adalah tidak perlu _memilih_:

Sama seperti $PSItem dan $_ hidup berdampingan dengan bahagia, begitu juga ForEach-Object dan % , Where-Object dan ? , .. .:

$a ? $b : $c dapat hidup berdampingan dengan if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c })

Adapun rekap _positive_ alasan untuk memperkenalkan $a ? $b : $c

  • lebih ringkas, kurang berantakan secara visual, menggunakan sintaks yang akrab bagi sebagian besar programmer.

  • lebih efisien, karena tidak perlu $(...) , yang if pernyataan perlu untuk memungkinkan penggunaannya sebagai bagian dari ekspresi yang lebih besar (yang lebih berisik, kurang efisien, dan dapat memiliki sisi yang tidak diinginkan efek)

Adapun masalah ketidakjelasan:

Seseorang yang menulis _ekspresi_ (berlawanan dengan hanya _memanggil perintah_ dengan argumen (sederhana)) dapat dianggap memiliki beberapa pengalaman pengembang, dan perasaan (anekdot) saya adalah bahwa sebagian besar pengembang setidaknya _recognize_ $a ? $b : $c sebagai if kental

Sekalipun tidak, bagaimanapun, itu mudah dijelaskan, dan selain dari penggunaan _symbols_ yang tidak jelas, kompleksitas konseptualnya sama dengan if ($a) { $b } else { $c } , dan bahkan kurang dari
$(if ($a) { $b } else { $c })

Dengan asumsi bahwa itu menarik setelah diperkenalkan - tentu saja, diskusi ini menunjukkan bahwa ada permintaan untuk itu - sering menghadapinya akan membuatnya menjadi idiom yang akrab dan mudah dikenali (yang lebih ringkas, lebih mudah diketik dan, setidaknya bagi saya dan beberapa orang lain di sini, lebih mudah dibaca) - seperti kebanyakan orang tampaknya lebih suka $_ daripada $PSItem .

Semua 52 komentar

Perhatikan bahwa dengan perubahan untuk mengizinkan penugasan dari pernyataan, kebutuhan akan operator ternary berkurang. Anda cukup melakukannya
$var = if ($x) { $x } else { $y }
Ini tidak sesingkat operator ternary tetapi bisa dibilang lebih mudah dibaca.

Ya, meskipun Anda masih harus menggunakan $(...) _di tambahan_ jika kondisional adalah bagian dari ekspresi yang lebih besar:

'The current sec. is ' + $(if ((get-date).tostring("ss") % 2) { 'odd'  } else  { 'even' })

vs.

powershell 'The current sec. is ' + ((get-date).tostring("ss") % 2 ? 'odd' : 'even')

Saya tahu bahwa keterbacaan ada di mata ... eh ... pembaca, tetapi saya pribadi menemukan yang terakhir secara visual lebih mudah diuraikan, dan harus mengetik lebih sedikit selalu merupakan bonus.

Dengan fitur yang sering digunakan, saya pikir mengingat sintaks ternary yang lebih abstrak tidak akan menjadi masalah (dan, tentu saja, orang dapat terus menggunakan if , jika mereka mau).

@ mklement0 saya harus setuju nanti memiliki beban kognitif yang lebih sedikit.

Ini pasti ada di daftar teratas saya.
@BrucePay , apakah ada alasan mengapa ini menjadi ide yang buruk? Atau hanya tentang 'mengirim adalah memilih'?

Di masa lalu, permintaan fitur ini ditolak karena lebih sulit dipahami oleh skrip yang kurang berpengalaman, dan bahwa bentuk ekspresi dari pernyataan if adalah alternatif yang lebih jelas, meskipun lebih bertele-tele.

Perspektif pribadi saya: jika bahasa itu hanya untuk saya, saya mungkin telah menambahkannya sejak lama. Tapi ... Saya menemukan banyak pengembang tidak menggunakannya, yang sebenarnya menunjukkan ada beberapa kebenaran pada hipotesis bahwa orang yang kurang berpengalaman akan mengalami masalah dengan operator ternary.

@lzybkr :

Ada baiknya membedakan antara _penggunaan aktif_ fitur vs. kemampuan untuk _mengenali_ dan memahaminya.

Jelas, setiap orang dapat memilih apakah akan menggunakan fitur seperti itu, tetapi apakah Anda mengatakan bahwa "bermasalah dengan" berarti bahwa orang yang kurang berpengalaman tidak akan _memahaminya ketika mereka melihatnya dalam kode orang lain?

@mklement0 - kami memperkenalkan $psitem sebagai alias untuk $_ karena umpan balik yang cukup bahwa $_ samar dan membingungkan, jadi saya yakin operator ternary akan sulit untuk beberapa yang kurang orang yang berpengalaman untuk mengerti.

Di sisi lain, ada banyak elemen di PowerShell yang membingungkan bagi pemula, atau bahkan pengembang yang cukup berpengalaman.

Seperti halnya bahasa lain, dibutuhkan beberapa upaya untuk mempelajari sintaks dan makna konstruksi bahasa.
Saya tidak tahu apakah menurut saya operator ternary sangat sulit untuk dipahami.

Apakah Anda memiliki data yang menunjukkan demikian?

Saya percaya satu-satunya data adalah anekdot, tetapi kritik berlaku untuk bahasa samar apa pun - bash, perl, dll.

Dan untuk lebih jelasnya, saya memberikan konteks historisnya. Mungkin PowerShell cukup umum sekarang sehingga sintaks yang lebih samar tidak akan memengaruhi adopsi.

Juga perlu diingat - beberapa bahasa singkat masih menggunakan if/then sebagai operator ternary, misalnya F#.

Yang mengatakan, mungkin itu mungkin untuk menggunakan lebih sedikit karakter dan tidak terlalu samar:

if ($x) { $y } else { $z }
$x -then $y -else $z
$x ? $y : $z

-then/-else cocok dengan sintaks PowerShell - tetapi, operator (atau operator jika terlalu membingungkan untuk dianggap sebagai operator tunggal), Anda mendapatkan keuntungan karena tidak memerlukan tanda kurung dan kurung kurawal.

Kemudian lagi, ini meminta masalah yang mirip dengan foreach vs. foreach-object . tapi mungkin tidak seburuk itu, saya tidak tahu.

@lzybkr :

Cryptic dalam dosis homeopati sehat:

PowerShell secara keseluruhan tidak samar, tetapi dalam beberapa kasus menawarkan sintaks samar sebagai _alternatif_ ringkas (Anda masih dapat bertele-tele jika diinginkan) untuk konstruksi _sering digunakan_, terutama ? untuk Where-Object dan % untuk ForEach-Object .

Memberikan $x ? $y : $z sebagai alternatif singkat untuk if ($x) then { $y } else { $z } kepada saya adalah dalam semangat yang sama.

Aspek samar diperbaiki oleh ? yang mengingatkan pada _question_ dan oleh karena itu menyarankan suatu kondisi (walaupun satu _mendahului_ ? dalam kasus ini), dan - yang lebih penting - menjadi _a konstruksi yang berpotensi akrab dari beberapa bahasa lain_, dengan semantik dasar yang sama.

Anda tidak mendapatkan manfaat yang sama dengan $x -then $y -else $z : tidak familiar.

Juga, sementara banyak operator PS memiliki nama simbolis, banyak yang tidak: * / + % ...
Ini secara inheren juga samar, kami hanya tidak menganggapnya seperti itu lagi, karena mereka begitu akrab dan ada di mana-mana.

Perasaan saya adalah bahwa $x ? $y : $z juga sudah akrab bagi banyak orang, dan akan menjadi lebih lagi setelah diperkenalkan ke dalam bahasa, mengingat kebutuhan yang sering akan conditional yang ringkas.

Perhatikan bahwa Anda akan sangat terbatas pada apa yang dapat Anda tentukan dengan operator ini. Secara khusus Anda tidak akan dapat menggunakan perintah kecuali Anda membungkusnya dalam tanda kurung:

(test-path foo.txt) ? (get-content foo.txt) : (get-content bar.txt)

dibandingkan dengan

if (test-path foo.txt) {get-content foo.txt} else {get-content bar.txt}

atau

get-content ((test-path foo.txt) ? "foo.txt" : "bar.txt")

vs

get-content $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"})

Menurut saya, ada sedikit keuntungan dalam hal singkatnya dan kerugian yang jelas dalam keterbacaan. Operator ternary jauh kurang menarik bila Anda memiliki bahasa berorientasi ekspresi. Ketika saya mulai menggunakan bahasa 16 tahun yang lalu, menambahkan operator ternary tampak jelas berasal dari latar belakang C. Sekarang saya senang kami tidak pernah menambahkannya. Ini hanya terasa seperti kekacauan.

Secara khusus Anda tidak akan dapat menggunakan perintah kecuali Anda membungkusnya dalam tanda kurung:

Itu berlaku untuk _any_ operator PowerShell.

Tidak semua pernyataan PowerShell melibatkan perintah, dan ketika mereka melakukannya, pengguna sudah tahu bahwa (...) adalah harga masuk untuk perintah (dalam banyak kasus).

Dalam contoh Anda sendiri, bagi saya ((test-path foo.txt) ? "foo.txt" : "bar.txt") mengalahkan $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"}) , baik untuk ketidakjelasan membutuhkan $(...) dan kebisingan yang diperkenalkan oleh kurung kurawal.

Mungkin hanya saya, tetapi saya menemukan ini:

get-content ((test-path foo.txt) ? "foo.txt" : "bar.txt")

cara yang lebih mudah untuk memindai/mengurai secara visual daripada ini:

get-content $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"})

Satu-satunya keluhan saya tentang masalah ini adalah jika Anda akan melakukan ternary ?: maka Anda juga harus melakukan null-coalescing ?? :

$logDir = $env:LogDir ?? "$PSScriptRoot\Log"

Saya telah melihat sejumlah implementasi Invoke-Ternary dan Invoke-NullCoalescing di alam liar (mis. https://github.com/dahlbyk/posh-git/blob/master/src/Utils.ps1#L12). Hal semacam itu menunjukkan ada keinginan umum untuk fitur seperti itu dimasukkan ke dalam bahasa.

@rkeithhill : saya setuju; re null-coalescing: sudah ada masalah, yang juga mencakup perendaman nol: #3240

Jadi argumen pembuat kode yang kurang berpengalaman tidak akan dapat dengan mudah menggunakan pernyataan kode gabungan nol atau terner yang menurut saya agak picik. Tidak ada persyaratan untuk menggunakan fitur "canggih" ini dan jika seorang programmer tidak dapat membaca kodenya karena mereka kurang pengalaman, maka secara pribadi itu adalah isyarat saya bahwa saya perlu mempelajari sesuatu yang baru dengan sangat cepat.
Ketika saya pertama kali melihat ternary di C# saya seperti WTF yang baru saja diperkenalkan oleh MS, sampai saya mengambil beberapa menit untuk membaca ini, yang kemudian saya ketagihan.

Contoh praktis di POSH, saya memiliki baris ini:
$mc_object = ($Message.fields | where Name -Match appname).Content
yang bagus dan keren kecuali ketika objek $Message tidak memiliki properti yang diajukan yang memiliki nama "nama aplikasi", dan karena saya tidak mengontrol data berformat JSON asalnya, saya harus menentukan apa yang harus dilakukan.

Jadi dengan operasi penggabungan nol yang harus saya lakukan adalah menambahkan ?? "" di akhir untuk memastikan bahwa $mc_object selalu merupakan string yang valid, bahkan jika setter asli adalah nol. Jika tidak, saya harus melakukan beberapa teknik berbeda untuk mencapai apa yang dapat dilakukan oleh 4 penekanan tombol, seperti
$mc_object = if(-not ($Message.fields | where Name -Match appname).Content)){""}else{($Message.fields | where Name -Match appname).Content}
Itu bagi saya sangat tidak terbaca, tetapi kemudian saya dapat membersihkannya sedikit dengan melakukan sesuatu seperti ini, yang sedang saya lakukan.
$mc_object = ($Message.fields | where Name -Match appname).Content if(-not $mc_object){$mc_object = ""}

Meskipun tidak buruk, lebih dari 4 tombol ditekan ke null-coelasce.

Bagaimanapun, saya pasti memilih ternary dan null-coelasce di Powershell, itu menambahkan beberapa fitur yang sangat canggih dan hanya membuat Powershell lebih menarik untuk digunakan dalam bentuk "inti" pada sistem apa pun.

@lzybkr Saya belum melihat ada orang yang benar-benar mengadopsi $PSItem . Saya bekerja di tim besar yang terdiri dari orang-orang yang menulis skrip dan mereka semua masih menggunakan $_ , bahkan pengguna PowerShell yang kurang berpengalaman.

@tibmeister atau....

if (-not ($mc_object = $Message.fields.where{$_.Name -match 'appname'}.Content)) {
    $mc_object = ''
}

Tugas sebagai ekspresi akan melewati, tetapi sangat tidak terbaca.

Saya secara teratur menggunakan $psitem

Selama beberapa tahun menilai Game Skrip $psitem banyak digunakan dalam jawaban

@RichardSiddaway : Jika kita melihat Stack Overflow di pertanyaan yang diberi tag PowerShell _asked sejak 2014_, kita mendapatkan (pada tulisan ini):

  • kira-kira 106.000 posting ditandai powershell (ini termasuk jawaban juga; jika Anda membatasi kueri untuk pertanyaan, Anda mendapatkan sekitar 46.000)
  • dari jumlah tersebut, 71 berisi kata PSItem (13 di antaranya adalah pertanyaan), yaitu kurang dari 1%

$PSItem diperkenalkan di v3 pada September 2012, jadi untuk amannya saya memilih 2014 sebagai tanggal mulai kueri.

Meskipun ini bukan metrik yang tepat, - situs tidak mengizinkan Anda untuk mencari $_ atau _ , sayangnya, dan saya yakin ada pertanyaan yang mengandung _neither_ $_ atau $PSItem , dan pertanyaan pra-v3 masih diajukan - saya masih berpikir aman untuk menyimpulkan bahwa $_ digunakan jauh lebih sering daripada $PSItem .

Namun, poin yang lebih besar adalah tidak perlu _memilih_:

Sama seperti $PSItem dan $_ hidup berdampingan dengan bahagia, begitu juga ForEach-Object dan % , Where-Object dan ? , .. .:

$a ? $b : $c dapat hidup berdampingan dengan if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c })

Adapun rekap _positive_ alasan untuk memperkenalkan $a ? $b : $c

  • lebih ringkas, kurang berantakan secara visual, menggunakan sintaks yang akrab bagi sebagian besar programmer.

  • lebih efisien, karena tidak perlu $(...) , yang if pernyataan perlu untuk memungkinkan penggunaannya sebagai bagian dari ekspresi yang lebih besar (yang lebih berisik, kurang efisien, dan dapat memiliki sisi yang tidak diinginkan efek)

Adapun masalah ketidakjelasan:

Seseorang yang menulis _ekspresi_ (berlawanan dengan hanya _memanggil perintah_ dengan argumen (sederhana)) dapat dianggap memiliki beberapa pengalaman pengembang, dan perasaan (anekdot) saya adalah bahwa sebagian besar pengembang setidaknya _recognize_ $a ? $b : $c sebagai if kental

Sekalipun tidak, bagaimanapun, itu mudah dijelaskan, dan selain dari penggunaan _symbols_ yang tidak jelas, kompleksitas konseptualnya sama dengan if ($a) { $b } else { $c } , dan bahkan kurang dari
$(if ($a) { $b } else { $c })

Dengan asumsi bahwa itu menarik setelah diperkenalkan - tentu saja, diskusi ini menunjukkan bahwa ada permintaan untuk itu - sering menghadapinya akan membuatnya menjadi idiom yang akrab dan mudah dikenali (yang lebih ringkas, lebih mudah diketik dan, setidaknya bagi saya dan beberapa orang lain di sini, lebih mudah dibaca) - seperti kebanyakan orang tampaknya lebih suka $_ daripada $PSItem .

mklement0, Anda memiliki contoh yang sangat luar biasa dan saya pikir menunjukkan intinya dengan jelas, terima kasih.

Membaca ulang dan meninjau kembali ini dan melihat beberapa pertanyaan, saya mendapati diri saya lebih condong ke arah sintaksis yang sedikit lebih bertele-tele yang disarankan:

$value = $a -eq $b -then $trueVal -else $falseval

atau, untuk sintaks yang lebih mudah dibaca secara semantik:

$value = $trueVal -if $a -eq $b -else $falseVal

@ vexx32 Sementara saya tidak keberatan dengan contoh pertama Anda, saya menemukan kondisi di tengah ekspresi sangat berat.

Ya, saya pikir saya cenderung setuju, tapi itu tidak membaca sedikit lebih ... lancar. Tapi aku masih cenderung pergi ke yang pertama.

Mengingat bahwa PowerShell dimaksudkan untuk menjadi bahasa "di jalan" untuk C#, saya pikir menggunakan ? : adalah cara yang tepat. Bahkan JavaScript menggunakan sintaks ini dan ini adalah salah satu bahasa paling populer saat ini. :-)

Setuju, @rkeithhill , baik untuk keakraban konstruksi dari beberapa bahasa lain _dan_ keinginan untuk juga memiliki tugas null-coalescing, null-soaking, dan null-conditional , yang dalam C# didasarkan pada ? juga.

Dua yang terakhir - misalnya $foo?.bar dan $var ?= 'default val' - tidak benar-benar mungkin tanpa representasi berbasis simbol, dan bahkan untuk penggabungan nol $a ?? 'value-if-null' tampaknya lebih disukai daripada sesuatu seperti $a -elseifnull 'value-if-null' .

Ingat bahwa ? , sebagai alias yang sering digunakan untuk Where-Object , sudah tertanam kuat sebagai representasi _conditional_, jadi mentransfer pengetahuan itu ke variasi penggunaannya tampaknya logis.

Apakah PowerShell benar-benar on-ramp ke C# ? saya tahu itu adalah niat yang dinyatakan 10-12 tahun yang lalu tetapi apakah itu benar-benar terjadi? Kecurigaan saya adalah bahwa untuk sebagian besar pengguna PowerShell, C# bukanlah tempat yang ingin mereka tuju.

jika persyaratan ternary akan terjadi, saya lebih suka melihat sesuatu seperti
$nilai = $trueVal -jika $a -eq $b -else $falseVal

seperti yang disebutkan oleh @vexx32

Lebih masuk akal bagi rata-rata pengguna PowerShell.

@mklement0 Komentar saya tentang $psitem didasarkan pada pengalaman pribadi saya. Jika Anda memiliki pengalaman yang berbeda, itu tidak membatalkan pengalaman saya

saya tahu itu adalah niat yang dinyatakan 10-12 tahun yang lalu

Yup, di awal-awal KTT MVP antara lain dilakukan oleh Jeffrey. Saya belum pernah mendengar yang berbeda sejak saat itu.

Juga, hampir semua konstruksi bersyarat/loop mengambil dari C# (dan garis keturunan C), if {} , while {} , do {} while , switch {} , untuk {} , {} , coba {} tangkap {} akhirnya {}`. Masuk akal bagi saya bahwa konstruksi bersyarat ini juga demikian.

Itu adalah kata kunci bahasa, @rkeithhill. Operator sama sekali berbeda.

Saya pikir Anda akan menemukan bahwa sebagian besar operator yang digunakan di PowerShell sangat berbeda dari padanan C# mereka. Tim PS sangat jelas memilih sintaks yang lebih deskriptif untuk sebagian besar operator.

Saya akan mempertimbangkan bahwa perilaku ternary juga harus mengikuti lebih banyak opsi sintaksis verbose yang tersedia. PowerShell mungkin telah dipahami sebagai 'on-ramp' untuk C#, tetapi itu tidak berarti ia harus mewarisi lebih banyak sintaksis simbolisnya. Memang, ada banyak tempat yang dengan susah payah dihindari .

Pertimbangkan, jika Anda mau, bahwa argumen Anda untuk sintaks simbolis berakar pada bagaimana bahasa pemrograman umum lainnya mewakili konsep ini. PowerShell bukanlah orang yang menempuh rute itu di pos, alih-alih lebih memilih untuk bekerja dengan sintaksis deskriptif yang dapat dibuat masuk akal. Hanya karena mereka yang menggunakan yang sudah memiliki pengalaman dalam C# yang akrab dengan sintaks tersebut pasti bukan alasan untuk menggunakannya.

Jika PowerShell adalah bahasa 'on-ramp' untuk C# atau bahasa lain (yang, menurut saya, sejauh ini cukup baik) maka kita perlu mempertimbangkan common denominator terendah di sini dan memikirkan apa yang akan ditemukan oleh orang yang paling tidak berpengalaman masuk akal dan intuitif .

Saya tidak mengatakan solusi saya disodorkan adalah itu, tapi saya pikir mereka mungkin menuju ke arah yang lebih masuk akal dari perspektif ini.

@vexx32
Bagaimana dengan operator ini?

.
=
[]
,
+ - * / %
++ --
+=  -=  *=  /= %=

Secara umum, saya setuju bahwa mengikuti petunjuk C# tidak selalu tepat, dan bahwa menjaga semangat PowerShell harus diutamakan.

Sebaliknya, saya menyarankan agar tidak menyimpang dari C# dalam kasus di mana sintaks yang sama tampaknya cocok, dan bagi saya proposal yang ada - bersama dengan #3240 - adalah contohnya.

Jika kita mengesampingkan bahasa lain:

  • Semantik ? masuk akal meluas ke operator yang diusulkan.

  • Jika Anda melihat nilai dalam operator _related_ yang diusulkan - perendaman nol ( ?. ), penggabungan nol ( ?? ) dan penetapan bersyarat nol ( ?= ) - lalu memilih untuk bentuk ternary verbose seperti -then / -else bukanlah pilihan, jika Anda ingin semua operator terkait ini mencerminkan kesamaan (yang jelas-jelas mereka miliki secara konseptual).

Semakin eksotis suatu fitur, semakin penting verbositasnya.

Semakin sering sebuah fitur digunakan, semakin penting koncisionnya. Dan keabstrakan dari representasi berbasis simbol tidak lagi menjadi masalah melalui paparan sintaksis yang berulang-ulang - seperti halnya * , misalnya.

Semua operator yang dibahas kepada saya termasuk dalam kategori yang terakhir.


@RichardSiddaway :

Komentar saya tentang $psitem didasarkan pada pengalaman pribadi saya. Jika Anda memiliki pengalaman yang berbeda, itu tidak membatalkan pengalaman saya

Ya, komentar Anda didasarkan pada pengalaman _personal_.
Milik saya didasarkan pada _menganalisis data_ dari situs Q & A populer Stack Overflow, untuk menyimpulkan _general_ pola penggunaan (dalam batasan yang dinyatakan) - yang tidak terkait dengan pengalaman pribadi saya.

Satu-satunya alasan Anda dapat menganggap komentar saya tidak valid jika Anda yakin pengamatan pribadi Anda mencerminkan kebenaran "transpersonal" - klaim yang tidak Anda buat dalam komentar Anda. Apakah Anda bermaksud membuatnya? Jika demikian, kita perlu mendiskusikan _that_.

Hampir semua operator tersebut adalah operator matematika dengan arti yang relatif dapat dipahami dengan jelas, @ mklement0

Operator ternary adalah operator kondisional , dan _semua_ operator Boolean/kondisional PS berbentuk lebih verbose: -and , -or , -eq , -ne , -contains , dll.

Saya setuju bahwa singkatan ini mungkin masuk akal karena kebutuhan akan fitur di sekitarnya dan operator terkait. Tapi saya pikir sintaks ternary "standar" tidak terlalu intuitif bagi kita yang belum berulang kali terpapar padanya.

operator adalah operator matematika

Di antara yang terdaftar, hanya + - * / % memiliki arti matematis (murni), tetapi aspek yang dipahami dengan jelas juga berlaku untuk yang lain (dengan pengecualian = , karena sering dikacaukan dengan pengujian kesetaraan ).

Konstruksi yang lebih baik untuk membandingkan <condition> ? <if-true> : <else> adalah if _statement_, bukan operator lain. Sementara if jelas lebih bertele-tele, justru aspek itulah yang dimaksudkan untuk ditangani oleh operasi ternary (selain menjadi ekspresi yang benar dan dapat dikomposisi, tidak seperti if ).

Ada spektrum ringkas, pasti, tetapi, seperti yang Anda katakan, untuk mengakomodasi semua operator terkait yang diusulkan secara konsisten, sintaks berbasis simbol masuk akal.

bagi kita yang belum berulang kali terpapar.

Yah, itu mudah-mudahan akan segera berubah. 😁
Poin diambil, tetapi (a) sintaksnya mudah dijelaskan dan memiliki kompleksitas konseptual yang sama dengan pernyataan if , dan (b) paparan berulang akan membantu retensi memori.

@mklement0 Bagaimana Anda menyarankan menangani ? menjadi karakter nama yang valid? Menghancurkan perubahan? Saya menganggap orang-orang di inti PowerShell berpengalaman dalam PowerShell apa adanya dan bahwa sintaks tambahan (yang telah ada dalam bahasa lain selama hampir 50 tahun) tidak akan menjadi penghalang. Mereka selalu dapat menggunakan if/else jika mereka menginginkan lebih banyak verbositas.

? hanya alias yang valid dalam mode perintah ; di semua varian mode ekspresi itu hanya karakter yang tidak valid saat ini. Tidak ada tabrakan.

Jika Anda mencoba memasukkan kode ini, itu hanya akan keluar:

$Value = $true
$Value ? "Hello!" : "Goodbye!"

Hasil:

At line:1 char:8
+ $Value ? "Hello!" : "Goodbye!"
+        ~
Unexpected token '?' in expression or statement.
+ CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken

@vexx32

$what? # <- example of a valid variable name

Dalam contoh perendaman nolnya: $var?.maybenull() tidak peduli bahwa ada tanda tanya di sana dan jika seseorang mencoba terlalu menyingkat, ternary mereka akan pecah.

Maaf, itu sebagian besar sedang dibahas dalam masalah lain tentang itu jadi saya tidak berpikir Anda mengacu pada itu.

Apakah kita dapat mencegahnya dari menjadi karakter nama variabel yang valid terserah pada tim PS, tetapi saya cenderung berpendapat bahwa mencegahnya dianggap sebagai karakter nama variabel secara default tidak akan banyak berpengaruh. Saya rasa saya belum pernah melihat orang yang benar-benar menggunakan ? sebagai bagian dari nama variabel.

@ vexx32 Ya, saya harus

$var = $test?$thing1:$thing2

tapi saya mungkin terlalu banyak membagi rambut pada kasus-kasus tepi bagi kita yang tinggal di cangkang.

Dikoreksi:

$var = ${test}?${thing1}:$thing2

@mklement0 - Saya tidak selalu setuju dengan:

Konstruksi yang lebih baik untuk dibandingkan?:to adalah pernyataan if, bukan operator lain. Sementara if pasti lebih bertele-tele, justru aspek itulah yang dimaksudkan untuk ditangani oleh operasi ternary (selain menjadi ekspresi yang benar dan dapat dikomposisi, tidak seperti jika).

Secara khusus, operator ternary ada karena C/C# adalah bahasa berorientasi pernyataan tetapi memerlukan ekspresi kondisional.

Dalam bahasa berorientasi ekspresi (misalnya F# atau Rust), tidak ada sintaksis yang singkat karena dianggap tidak perlu. Saya pikir diskusi lama tentang Rust menghapus operator ternary ini menarik.

Satu hal yang sangat saya sukai di Rust adalah penggunaan operator ? untuk penanganan kesalahan. Saya tidak memiliki proposal konkret untuk menggunakan ? di PowerShell, tetapi rasanya ? lebih baik digunakan untuk penanganan kesalahan daripada untuk ekspresi bersyarat.

@TheIncorrigible1 , @vexx32 : Ya, perendaman nol secara teknis akan menjadi perubahan besar, tapi mudah-mudahan tipe ember 3 (memang, mari kita lanjutkan diskusi di sana); untuk operasi ternary, penggunaan {...} / whitespace yang disarankan sebelum ? untuk disambiguasi tampaknya menyelesaikan masalah itu.

@lzybkr :

Secara khusus, operator ternary ada karena C/C# adalah bahasa berorientasi pernyataan tetapi memerlukan ekspresi kondisional.

Nah, dalam pernyataan kontrol aliran PowerShell seperti if terdapat _half_-expressions; dalam ekspresi _simple_, operasi ternary yang diusulkan akan setara; di _nested_, itu tidak akan:

$foo = $True  ?     1   :      0    # proposed ternary
$foo = if ($True) { 1 } else { 0 }  # equivalent `if` statement
$foo = 1 + ($True  ?     1   :      0)   # nesting OK; note that + would have higher precedence
$foo = 1 + if ($True) { 1 } else { 0 }  # !! doesn't work
$foo = 1 + (if ($True) { 1 } else { 0 })  # !! doesn't work, even with parentheses
$foo = 1 + $(if ($True) { 1 } else { 0 })  # only $(...) (and situationally @(...)) work

Kebutuhan akan $() / @() lebih dari sekadar ketidaknyamanan sintaks: ia memiliki implikasi perilaku dan kinerja.

Yang mengatakan, saya _wish_ bahwa pernyataan seperti if dan foreach adalah ekspresi yang dapat dipercaya (dua contoh lagi dari hal-hal yang saat ini gagal: foreach ($i in 1..5) { $i } | Write-Output atau foreach ($i in 1..5) { $i } > out.txt ).
Saya tidak cukup tahu untuk menilai apakah mereka _tidak bisa_, namun dan/atau jika ada masalah kompatibilitas ke belakang.
Lihat juga: #6817


Jika if menjadi ekspresi penuh di PowerShell, maka Anda dapat membuat argumen yang mengarah pada penghapusan kondisi ternary dari Rust: maka tidak lagi _necessary_.

Namun, motivasi saya untuk proposal ini tidak pernah _necessity_ - ini tentang ringkas, kenyamanan, dan keterbacaan (kekacauan visual).


Saya tidak punya proposal konkret untuk digunakan? di PowerShell, tapi rasanya seperti ? bisa lebih baik digunakan untuk penanganan kesalahan daripada untuk ekspresi bersyarat.

Saya pikir memperkenalkan ? dengan semantik yang berbeda secara fundamental daripada di C# akan menjadi sumber kebingungan yang abadi.

Secara terpisah, peningkatan dalam penanganan kesalahan PowerShell layak untuk didiskusikan.

Jika kita mencari alternatif yang ringkas namun tidak intuitif untuk If/then/Else, kita sudah memilikinya.

( 'False', 'True' )[( Test-Condition )]

Dan itu bekerja dalam ekspresi.

"This statement is " + ( 'False', 'True' )[( Test-Condition )]

@TimCurwick : Itu ringkas (dan lebih tidak jelas), tetapi tidak setara: persyaratan ternary yang diusulkan adalah _short-circuiting_ (seperti pernyataan if ), sedangkan sintaks Anda selalu mengevaluasi _both_ alternatif.

Yang mengatakan, sintaks Anda tentu saja merupakan hal terbaik berikutnya yang tersedia saat ini, dengan asumsi seseorang mengetahui batasan yang disebutkan.

Mengenai diskusi tentang cara menampilkan pilihan ternary di PowerShell, adakah yang mempertimbangkan opsi dalam format yang sama seperti yang digunakan oleh -replace / .replace() ?

$a -eq $b -ternary $a,$c
$true -ternary 1,0

atau

($a -eq $b).ternary($a,$c)
($true).ternary(1,0)

Ini akan memperjelas bahwa operator sedang melakukan tindakan ternary dengan menyebutnya ternary . Ini bertele-tele, tetapi masih pendek untuk ditulis, dan ini menggunakan perilaku umum yang ada -operator $first,$second , jadi seharusnya terasa akrab bagi pengguna PowerShell di semua rentang pengalaman

mungkin berhasil, tetapi akan lebih canggung daripada alternatif yang diusulkan. -replace bekerja seperti itu karena hanya menerima array argumen yang sebenarnya. .Replace() tidak dikelola oleh tim PS -- ini adalah metode pada kelas .NET System.String .

Jika kita mencoba menggunakan salah satu dari sintaks tersebut, itu berarti metode ETS (tidak apa-apa, tetapi cenderung menambahkan sedikit overhead kinerja untuk pembuatan objek yang perlu dilampirkan) atau, dengan versi operator Anda usulkan, kami tidak akan dapat dengan mudah memiliki array sebagai argumen.

Tanpa selubung khusus operator seperti itu di dalam parser, kami tidak akan dapat melakukan hubungan pendek. Sintaks ternary dalam bahasa lain umumnya ada karena Anda _tidak ingin_ benar-benar mengevaluasi kedua opsi; waktu komputasi lebih cepat jika hanya cabang yang benar yang perlu dievaluasi, daripada harus sepenuhnya mengevaluasi kedua opsi (yang mungkin datang dengan beberapa efek samping yang signifikan).

Dan karena itu sudah memerlukan casing khusus, akan lebih efektif untuk memperkenalkan sintaks baru untuknya, untuk meminimalkan kebingungan (akan sedikit menyesatkan untuk memiliki sesuatu yang terlihat seperti array tetapi tidak dapat digunakan seperti itu; itu tidak akan mendukung pembuatan "array" sebelumnya dan meneruskannya sebagai variabel, misalnya). Fakta bahwa argumen metode sudah sedikit bertentangan dengan sintaksis array seringkali sudah menyesatkan. Saya rasa saya tidak ingin menambahkan perilaku varian _ketiga_ untuk koma ke dalam campuran.

@PowerShell/powershell-committee membahas ini secara panjang lebar, kami tidak semua setuju, tetapi mayoritas setuju bahwa ada nilai dalam memiliki operator ini dan untuk menyelaraskan dengan sintaks C# menjaga ?: seperti yang diharapkan adalah bahwa sebagian besar penggunaan akan berasal dari pengembang C#. Fitur ini akan menjadi Eksperimental menunggu umpan balik penggunaan nyata.

@SteveL-MSFT Jadi itu berarti fitur ini bergerak maju untuk 7.0? Apakah itu akan merusak kompatibilitas pada variabel yang dapat menggunakan ? dalam simbolnya?

@TheIncorrigible1 ya, fitur ini bergerak maju di PS7. Seharusnya tidak merusak kompatibilitas dengan penggunaan ? alias. Ada kekhawatiran tentang ketajaman visual ? ketika melirik skrip yang mencoba membedakan Where-Object dan ternary , tetapi kita akan melihat apa tanggapan pengguna tentang ini. Secara umum, kami tidak mengharapkan sebagian besar pengguna untuk menggunakan operator ini, tetapi itu tidak akan mencegahnya untuk bergerak maju.

@SteveL-MSFT maksud saya variabel dengan nama $isValid? atau serupa. Ini adalah token yang valid dalam iterasi PS saat ini.

@TheIncorrigible1 :

Memerlukan spasi putih antara operan pertama dan ? menyelesaikan masalah itu, seperti yang disarankan sebelumnya, dan bagi saya itu adalah solusi yang sangat masuk akal:

  • : _also_ memerlukan spasi di sekitarnya, karena sesuatu seperti $true ? $number:42 tidak akan berfungsi, mengingat $number:42 akan _secara keseluruhan_ ditafsirkan sebagai referensi variabel tunggal.

  • Sementara C# _does_ allow true?number:42 , saya rasa kita tidak perlu - atau, memang, bisa - mengkhawatirkan kompatibilitas pada tingkat itu. Saya pribadi menghargai keringkasan, tetapi tidak dengan mengorbankan keterbacaan; bahkan jika saya _could_ menulis $true?$number:42 , saya tidak akan melakukannya.

(Kompatibilitas mundur memang akan menjadi masalah ketika (petunjuk, petunjuk) kami menerapkan akses bersyarat nol . Permisif PowerShell sehubungan dengan nama pengenal umumnya bermasalah, seperti yang dikatakan @KirkMunro baru-baru ini, tetapi kapal itu telah berlayar )

Ya, saya pikir meninggalkan persyaratan spasi masuk akal. Bagaimanapun, ini cukup singkat. 😁

Prototipe mencoba cukup keras untuk mengurai angka dengan ? dan : di dalamnya secara berbeda dalam konteks operator ternary (di mana kita tahu kita mengharapkan ekspresi). Jadi Anda dapat menulis hal-hal seperti ${isWindows}?12:47 .
Angka-angka seperti 123? atau 1:23 diberi token sebagai token umum hari ini, yang sama sekali tidak berguna jika kita tahu bahwa kita mengharapkan ekspresi.

Untuk variabel, tidak ada perubahan sama sekali tentang bagaimana ? atau : dapat digunakan untuk nama variabel, karena variabel adalah ekspresi.

Poin bagus, @daxian-dbw; Saya lupa bahwa {...} dapat digunakan untuk menyelesaikan ambiguitas batas nama variabel apa pun, jadi saya kira pegolf kode dapat menggunakan sesuatu seperti ${isWindows}?${number}:47

Bisakah kita menutup ini sekarang?

Tutup melalui #10367

Apakah halaman ini membantu?
0 / 5 - 0 peringkat