Julia: mini julep: jika x maka y

Dibuat pada 16 Mei 2016  ·  53Komentar  ·  Sumber: JuliaLang/julia

Dalam berbagai diskusi, disarankan untuk mengizinkan sintaks seperti:

if x then y

Sebagai pernyataan "jika" bentuk pendek dan sebagai alternatif dari yang umum:

x && y

sintaks yang memanfaatkan operator hubung singkat && untuk mengeksekusi y secara kondisional (dengan y sering mengandung efek samping lain dan tidak selalu mengembalikan Bool ).

Keuntungan utama dari konstruksi if-then ini adalah: kode yang lebih mudah dibaca, tidak terlalu bergantung pada penyalahgunaan && , dan secara formal menyertakan formulir pernyataan "jika" yang tidak memerlukan end kata kunci.

Terpikir oleh saya tempo hari, bahwa sintaks ini juga akan menyediakan sarana yang nyaman untuk mengimplementasikan #550, yang akan terlihat seperti:

A = [if x % 2 == 0 then f(x) for x in 1:10]

Mengandalkan fakta bahwa if-then tidak memerlukan kata kunci end , yang mungkin tetap kita perlukan dalam beberapa bentuk bahkan jika kita menggunakan penjaga gaya python:

A = [f(x) for x in range(10) if x % 2 == 0]

Untuk lebih jelasnya, sintaks Julia guard pada dasarnya akan melakukan penulisan ulang dari:

A = [if x % 2 == 0 then f(x) for x in 1:10]

ke

A = [Filter(x->x % 2 == 0, f(x) for x in 1:10)]

Juga sebagai catatan klarifikasi, ini akan memungkinkan sintaks penjaga di level _generator_ bukan hanya level _comprehension_ (yang juga cocok dengan apa yang diizinkan python).

julep

Komentar yang paling membantu

Mungkin saya minoritas karena bahasa lain telah mengambil pendekatan ini, tetapi saya selalu menemukan tindakan yang datang sebelum kondisi menjadi sangat aneh, misalnya println("positive") if x > 0 . Saya kira ini lebih ringkas daripada if x > 0 println("positive") end tetapi setidaknya bagi saya itu harus mengorbankan keterbacaan.

Saya menganggapnya seperti percakapan:

Julia: "Saya akan mencetak string..."
Harold: "Luar biasa!"
Julia: "...tapi hanya jika beberapa syarat terpenuhi."
Harold: "Oh. :("

melawan

Julia: "Jika beberapa syarat terpenuhi, saya akan mencetak string."
Harold: "Oke, keren."

Semua 53 komentar

Sintaks pengubah if/for gaya Perl/Ruby sepertinya akan lebih cocok dengan ini. Dengan kata lain:

println("positive") if x > 0         # conditional execution
x^2 for x=1:100                      # generator
[ x^2 for x=1:100 ]                  # comprehension
x^2 if x % 3 == 0 for x = 1:100      # filtered generator
[ x^2 if x % 3 == 0 for x = 1:100 ]  # filtered comprehension

Ini juga memiliki manfaat memiliki preseden dalam bahasa lain, yang if - then tanpa end sintaks tampaknya tidak.

Sekedar catatan tambahan tentang manajemen masalah: #6823 membahas masalah ini dengan tepat. Di beberapa titik ditutup tanpa komentar, saya menindaklanjuti bertanya mengapa ditutup karena jelas belum ada konsensus untuk menutupnya, tetapi tidak pernah mendapat balasan. Tampaknya akan lebih efisien untuk tidak menutup masalah seperti #6823, jika tidak, diskusi ini hanya akan berputar-putar dan semua poin dalam masalah asli akan diulang lagi. Mungkin masuk akal untuk mengubah judul #6823 di beberapa titik, dan kemudian menambahkan ini di sini.

Ya, poin yang bagus. Memang #6823 tampaknya menjadi diskusi tengah dan mungkin seharusnya tidak ditutup.

Mungkin saya minoritas karena bahasa lain telah mengambil pendekatan ini, tetapi saya selalu menemukan tindakan yang datang sebelum kondisi menjadi sangat aneh, misalnya println("positive") if x > 0 . Saya kira ini lebih ringkas daripada if x > 0 println("positive") end tetapi setidaknya bagi saya itu harus mengorbankan keterbacaan.

Saya menganggapnya seperti percakapan:

Julia: "Saya akan mencetak string..."
Harold: "Luar biasa!"
Julia: "...tapi hanya jika beberapa syarat terpenuhi."
Harold: "Oh. :("

melawan

Julia: "Jika beberapa syarat terpenuhi, saya akan mencetak string."
Harold: "Oke, keren."

@ararslan : Saya tidak setuju, yang merupakan salah satu alasan mengapa fitur ini tidak ada di Julia meskipun sebelumnya ada seni di Ruby dan Perl. Namun, itu bercampur jauh lebih baik dengan sintaks pengubah for untuk generator dan pemahaman, itulah sebabnya saya membawanya ke sini.

@StefanKarpinski Ya setuju, itu lebih cocok dengan itu. Saya masih putus asa terikat pada kondisi sebelum tindakan sekalipun. :smile: (Tapi seperti yang sering saya katakan baru-baru ini, pendapat saya tidak terlalu penting; saya hanya seorang pria.)

Saya kira jika Anda memiliki sesuatu seperti

if x % 3 == 0 then x^2 for x = 1:100

maka tidak segera jelas bahwa Anda memulai pemahaman/generator/thingamajig, karena itu juga dibaca seolah-olah dapat dikelompokkan seperti

if x % 3 == 0 then (x^2 for x = 1:100)

yaitu, jika beberapa kondisi maka generator. Saya tidak keberatan

if x % 3 == 0 x^2 end for x = 1:100            # More obvious what's happening, IMO
filter(x -> x % 3 == 0, [x^2 for x = 1:100])   # Verbose, but... ¯\_(ツ)_/¯

Saya kira jika kondisinya mengikuti tindakan di generator, saya pikir saya lebih suka kata kunci yang berbeda dari if , misalnya where . Kemudian dibaca hampir seperti kueri SQL, mis

x^2 for x = 1:100 where x % 3 == 0

Saya pikir where membuatnya sedikit lebih jelas bahwa Anda memfilter nilai x yang dihasilkan oleh for daripada yang dilakukan if .

Tampaknya lebih baik bagi saya untuk memiliki aliran data dalam satu arah, meskipun dalam hal ini kanan ke kiri daripada kiri ke kanan.

Bisakah Anda menguraikan apa yang Anda maksud dengan itu?

Nilai for 1:n "menghasilkan", if x % 3 == 0 memfilternya dan x^2 mengubahnya – generator sudah mengalir dari kanan ke kiri dan untuk menjaga aliran itu, filter harus masuk Tengah. Jika klausa if berada di sebelah kanan klausa for maka data "mengalir" dari tengah ke paling kanan lalu ke paling kiri, yang aneh. Jika klausa if ada di sebelah kiri maka data "mengalir" dari paling kanan ke paling kiri ke tengah. Saya tahu SQL menempatkan klausa where di sebelah kanan nama tabel dan ekspresi di sebelah kiri - karena itu lebih mirip bahasa Inggris - tapi saya selalu merasa ini menjengkelkan untuk dibaca dan saya pikir membaca seperti bahasa Inggris bukan heuristik yang harus diambil terlalu jauh dalam desain bahasa pemrograman.

Hal-hal yang saya tidak suka tentang if x then y :

  1. Ini memperkenalkan kata kunci then baru.
  2. Menulis if x y end lebih pendek dari if x then y ; x && y bahkan lebih pendek.
  3. Kata kunci then banyak digunakan dalam bahasa untuk jenis sintaks yang berlawanan: sintaks multibaris if yang memerlukan kata kunci end (atau fi dalam bash , hiks).

Oh ya, saya mengerti apa yang Anda maksud sekarang tentang aliran. Itu masuk akal. Terima kasih atas penjelasannya!

Apakah akan aneh untuk bisa melakukannya

x^2 if x % 3 == 0 for x = 1:100

dan _tidak_ bisa melakukannya

println("positive") if x > 0

?

Semua poin bagus.

Saya sebenarnya sangat menyukai sintaks @StefanKarpinski yang pertama kali diusulkan dalam komentar pertamanya. Saya terutama tertarik untuk memiliki generator bersyarat, dengan _if_-form bentuk pendek yang lebih umum sebagai bonus.

Mengenai generator, saya membaca if (atau where - Saya tidak punya pendapat tentang itu) untuk menjadi bagian dari jangkauan... itu membuat iterator x = 1:10 if/where x % 2 == 0 , yang kemudian digabungkan dengan ekspresi di sebelah kiri untuk membuat Array (atau generator).

Dalam arti tertentu, x = 1:10 where x % 2 == 0 itu sendiri merupakan generator untuk beberapa jenis iterable. Ini bisa menjadi sintaks yang berdiri sendiri, bukan?

Saya merasa bahwa pemfilteran entah bagaimana merupakan operasi yang berbeda dengan pernyataan if a then b bersyarat. Pemfilteran bekerja pada rentang iterasi. Ketika if a then b digabungkan dengan ekspresi di sebelah kiri generator, saya mengharapkannya untuk memancarkan nothing dalam kasus a adalah false . Bandingkan apa yang terjadi secara logis jika saya menambahkan tanda kurung:

[(x^2 if i % 2 == 1) for i = 1:10] # [nothing, 4, nothing, 16, nothing, 36, nothing, 64, nothing, 100]
[x^2 (for i = 1:10 where i % 2 == 0)] # [4, 16, 36, 64, 100]

Mengambil contoh @ararslan , jika kami mengizinkan

println("positive") if x > 0

maka IMHO berikut ini

x^2 if x % 3 == 0 for x = 1:100

mungkin harus memancarkan nothing, nothing, 9, nothing, nothing, 36, ...

Akhirnya, jika kita menggunakan steno if conditional, suara saya adalah untuk kondisi sebelum pernyataan, untuk alasan yang digariskan oleh posting pertama @ararslan - menjadi prinsip yang paling tidak mengejutkan dalam membaca kode. (ingat, jika mereka mengatakan kode lebih banyak dibaca daripada ditulis, maka if a then b adalah sintaks yang lebih baik daripada a && b bahkan jika yang terakhir lebih pendek). Ini juga berarti dua kemungkinan jenis if di dalam generator akan berbeda - di paling kiri - dengan ekspresi - atau di paling kanan - dengan rentang.

Mengenai tradisi di Ruby/Perl, saya merasa lebih baik mencoba dan menemukan solusi terbaik daripada terjebak oleh tradisi. Jika berhasil dan terasa natural orang akan menyukainya.

Juga, jika kita memiliki if/where dalam rentang, apakah kita perlu berhati-hati untuk memastikan rentang tetap Cartesian untuk generator multidimensi?

# Make a circular array (filled with distance to center)
r = 5
[sqrt(x^2 + y^2) for x = -5:5, y = -5:5 where x^2 + y^2 <= r^2]

Ini agak-keren dan agak-mengerikan!

Saya merasa bahwa pemfilteran entah bagaimana merupakan operasi yang berbeda dengan pernyataan bersyarat if a then b.

Ya! Saya akan memposting komentar yang sama ini. Pemfilteran beroperasi pada iterator secara keseluruhan, dan bukan bagian dari ekspresi yang dihitung di dalamnya.

Saya juga merasakan hal yang sama dengan @andyferris bahwa if antara ekspresi dan iterasi tampaknya "mengubah" nilai ekspresi daripada bentuk iterasi, dan harus menghasilkan nogthing ketika kondisi tidak terpenuhi (tetapi saya mungkin dimanjakan oleh pemahaman python/haskell).

Jelas x if false akan mengevaluasi ke nothing bila tidak dalam konteks ekspresi generator. Sangat masuk akal untuk mendukung [x^2 if x % 3 == 0 for x=1:100] tetapi tidak x if y dengan sendirinya.

Secara pribadi, saya lebih suka menghilangkan end jika hanya ada satu pernyataan.

if length(A) != length(B) throw(ArgumentError("..."))

Jika tidak ada end , maka dapat diasumsikan bahwa hanya ada satu ekspresi. Saya kira itu sudah dibahas panjang lebar sebelumnya?
Saya perhatikan bahwa saya lebih suka untuk tidak memiliki titik koma setelah kondisi - setelah ekspresi... _maybe_... Saya tidak akan menyukainya.

Saya lebih suka itu, daripada memiliki dua sintaks yang berbeda untuk bentuk pernyataan if yang serupa;if x; ...; end , dan if x then; ... . _(Edit: if condition then action telah tumbuh pada saya.)_

Akan sangat masuk akal untuk mendukung [x^2 jika x % 3 == 0 untuk x=1:100] tetapi tidak x jika y dengan sendirinya.

@StefanKarpinski Saya benar-benar setuju dengan ini. Namun...

Jika klausa if berada di sebelah kiri maka data “mengalir” dari paling kanan ke paling kiri ke tengah.

Saya membaca x^2 if x % 2 == 0 for x in 1:10 sebagai, x^2 where x % 2 == 0 for each x in 1:10 , yang, karena pemahamannya, masuk akal bagi saya; Anda paling tertarik dengan transformasi.
Dalam kueri SQL, poin yang sama benar, bukan?

Karena itu saya tidak berpikir bahwa menjadikan "generator" sebagai titik awal untuk membacanya, cukup tepat, _untuk pemahaman_. Sebuah for loop di sisi lain... Itu lebih masuk akal.

Secara pribadi, saya lebih suka bisa menghilangkan akhir jika hanya ada satu pernyataan.

Saya mengusulkan ini sejak lama tetapi tidak mendapatkan daya tarik: https://github.com/JuliaLang/julia/issues/1657 . Ini sebenarnya akan menjadi perubahan yang relatif tidak mengganggu karena akan aneh dan jarang melihat beberapa kode tulis seperti ini:

if cond body
end

Apa pendapat Anda tentang menggunakan blok do alih-alih then ? yaitu: if x do y end

Hanya sedikit komentar sampingan: Saya tidak melihat cara if x y dengan sendirinya (yaitu di luar generator) dapat ditangani dengan benar di dalam editor tanpa julia parser yang lengkap, karena Anda perlu dapat menentukan berapa banyak token yang mengikuti if . Saya sedang memikirkan vim, tetapi saya kira editor lain mungkin berada dalam situasi yang sama. Hal yang sama dapat berlaku tentang y if x , tetapi saya tidak yakin (pengungkapan penuh: Saya juga sangat tidak menyukai y if x dengan sendirinya; saya tidak menentang if x y pada prinsipnya tetapi pikir itu mungkin sedikit sulit untuk diuraikan untuk manusia juga, tidak hanya editor).

@diegozea Masalah yang sama, saya pikir. Saya masih lebih suka if x y .

@carlobaldassi Ada beberapa hal yang dapat Anda lakukan untuk memudahkan manusia menguraikan.

Anda bisa memaksa pernyataan tunggal itu jika tidak akan memiliki baris baru antara kondisi dan ekspresi.
Saya tidak yakin saya ingin dipaksa melakukan itu untuk ekspresi yang panjang.

Atau, Anda bisa memaksa ada baris baru setelah ekspresi jika ada baris baru setelah kondisi; jadi, berikut ini tidak akan dikompilasi, tetapi tentu saja memberikan pesan kesalahan yang jelas:

if length(A) != length(B)
    throw(ArgumentError("lengths must match")
if some_condition(A, B)
   N *= 2

Tapi, ini akan:

if length(A) != length(B) throw(ArgumentError("lengths must match")
if some_condition(A, B) N *= 2

dan ini akan:

if length(A) != length(B)
    throw(ArgumentError("lengths must match")

if some_condition(A, B)
   N *= 2

Ini juga akan mencegah Anda membuat kesalahan seperti ini:

if is_present(x)
    y = 2 * x[]

    return y * 2

Saya pikir argumen terbesar untuk if x then y yang masih menang atas sintaks lainnya adalah readability . Itu if x y end , if x y atau x && y lebih pendek tidak relevan dalam buku saya (di luar fakta bahwa kita sedang berbicara tentang perbedaan 1-5 karakter yang sepele) karena tidak satu pun dari itu hampir sejelas if x then y . Ini juga menghindari masalah penguraian editor atau kemungkinan pemecahan kode sebelumnya. Ini hanya sintaks yang bagus, bersih, pendek untuk pernyataan if pendek.

Namun, saya mengenali potensi kebingungan penggunaan if-then dalam kasus generator; mengingat itu, saya setuju itu

x^2 if x % 3 == 0 for x = 1:100      # filtered generator
[ x^2 if x % 3 == 0 for x = 1:100 ]  # filtered comprehension

paling jelas, mengakui bahwa struktur ekspresinya adalah

generated_value_expr  value_generator_expr  =>  generator_expression

[generator_filter_expr]  for_generator_expr  => value_generator_expr

yaitu generator_filter_expr diterapkan langsung ke nilai yang dihasilkan dari for_generator_expr sebelum meneruskan nilai yang tidak difilter ke generated_value_expr .

Saya pikir perbedaan itu penting di sini, karena bukan logika yang sama yang memungkinkan

println("positive") if x > 0 

TL;DR: Kita harus memiliki x^2 if x % 3 == 0 for x = 1:100 untuk generator yang difilter, tetapi logika sintaks yang sama tidak berlaku untuk println("hey") if x > 0 , oleh karena itu, kita masih harus mempertimbangkan if x then y untuk bentuk pendek jika-sintaks. Meskipun jelas dua ide di sini sekarang sama sekali tidak berhubungan.

@H-225 Itu tampak aneh dan pada akhirnya tidak Julian bagi saya, terutama dengan tindakan pada baris baru tanpa end .

Masih akan menjadi mimpi buruk bagi editor untuk menguraikan karena editor (seperti Vim) tidak peduli apa itu dan bukan kondisi atau tindakan--memang, mereka tidak memiliki cara untuk mengetahui tanpa pengurai Julia--tetapi mereka peduli tentang penempatan hal-hal seperti if dan end . Saya pikir akan sangat sulit untuk membuat Vim mengenali bahwa end tidak diperlukan dalam skenario itu. Saya menyadari bahwa memudahkan editor bukanlah argumen yang baik untuk keputusan desain, saya hanya mengatakannya.

Pasti :-1: untuk if x y dari saya. Saya lebih suka if x then y daripada itu, karena lebih mudah bagi otak kecil saya untuk menguraikan. :menjulurkan lidah mengedip mata:

Apakah ada alasan untuk tidak menggunakan operator tanda tanya ternary untuk pernyataan if juga? Anda sudah dapat meniru pernyataan if dengan melakukan

condition ? if_condition_true_eval_expr : nothing

mengapa tidak membuatnya saja sehingga jika Anda tidak menyertakan titik dua maka itu adalah pernyataan if, maka Anda hanya perlu

condition ? if_condition_true_eval_expr

dengan cara ini Anda tidak perlu memasukkan kata kunci baru, apakah ini akan berhasil?

@esproff Lucunya, saya akan menyarankan yang sebaliknya: memperluas ide if-then dalam julep ini menjadi satu baris ekspresi if-then-else

if cond then a else b

di mana klausa else adalah opsional. Bahkan mungkin lebih rendah secara identik ke cond ? b : c . Bagi saya, ini semua tentang menjauh dari ternary gaya-C dan menuju kode yang lebih dapat dibaca manusia. (Saya pasti pernah menggunakan condition ? a : nothing sebelumnya - sepertinya peretasan (karena memang demikian, nothing penting untuk beberapa alasan yang tidak jelas) dan membingungkan orang lain untuk membacanya).

Tapi tentu saja, mengapa kita tidak bisa memiliki semua ide ini secara bersamaan?

@andyferris Ya itu cara lain, Pythonic, untuk pergi. Saya kira itu tergantung pada seberapa singkat Anda ingin menjadi, matematikawan umumnya tampaknya menghargai ketegasan, tapi sejujurnya saya akan senang dengan baik, selama saya tidak harus menggunakan kikuk

if condition; eval_expr; end

tapi sejujurnya saya akan senang dengan keduanya, selama saya tidak harus menggunakan kikuk

if condition; eval_expr; end

Memang!

Untuk apa nilainya, saya suka notasi x && y dan tidak melihatnya sebagai penyalahgunaan.

Saya pribadi lebih suka solusi berbasis operator yang tidak mengembalikan false jika pernyataan pertama salah. Saya akan baik-baik saja dengan hampir semua hal, meskipun saya suka a ?: b sebagai versi dua argumen dari operator ternary.

Ide ? dibahas cukup luas di #6823, mungkin perlu dibaca ulang diskusi itu.

Saya sampai di sini dari diskusi itu, tetapi saya pikir ini adalah tempat yang lebih baik untuk berkomentar. Saya pikir if a then b dan hanya menggunakan ? tanpa : masing-masing akan agak membingungkan, tetapi tidak akan mengeluh selama mereka menyediakan fungsionalitas yang sama.

Saya setuju dengan @EricForgy. Mungkin saat ini saya hanya terbiasa dengan mereka, tetapi bagi saya, menggunakan && dan || dengan cara ini terasa idiomatis bagi Julia, terutama untuk pemeriksaan kesalahan (mis x || throw(y) ). Mereka tampaknya tidak ambigu atau tidak terbaca sama sekali. Juga, saya tidak begitu mengerti mengapa x && y mengembalikan false jika x salah karena mungkin tidak boleh digunakan di akhir fungsi , di mana itu akan memengaruhi nilai pengembalian fungsi.

Terner gaya-C cukup ada di mana-mana; Saya berpendapat bahwa bukan hanya ahli matematika yang menghargai sintaks ini. Satu-satunya bahasa yang dapat saya pikirkan begitu saja yang memiliki ternaries tetapi tidak mendukung gaya-C adalah Python, dan FWIW saya membenci ternaries Python. condition ? action1 : action2 kompak dan dapat dibaca selama Anda menggunakan spasi putih dan menghormati panjang garis. Untuk kondisi dan tindakan yang lebih lama, seseorang harus menggunakan

if condition
    somelongaction1
else
    somelongaction2
end

bagaimanapun untuk keterbacaan.

Mengenai then , inti dari diskusi ini, FWIW saya mungkin tidak akan menggunakannya bahkan jika itu diterapkan karena, sekali lagi, && dan || terasa idiomatis bagi saya. Meskipun saya akan mengambil then dalam sekejap lebih dari if x y , x ? y , atau x ? y : nothing .

Secara pribadi, saya lebih suka y if x . Ini mungkin tampak seperti cara yang salah untuk melakukannya, tetapi ada prioritas di luar Ruby dan Perl: sintaks kasus matematika memilikinya seperti ini

image

Saya tidak _suka_ menggunakan && atau || untuk ini, karena saya tidak pernah ingat bahwa x && y = z tidak diurai seperti yang saya harapkan. Saya pikir ini memiliki beban kognitif yang lebih tinggi daripada y if x ; itu berlaku untuk if x y juga.

IMO, x ? y _smells_ seperti kesalahan sintaks, terlepas dari apakah itu benar-benar valid.

x ?? y mungkin? x ?: y adalah ekstensi GNU C yang berarti x ? x : y , jadi ?? dan ?: bisa menjadi versi prioritas rendah dari && dan || , mungkin.

Urutan pilihan saya: y if x == x ?? y < if x then y < x && y < x ? y < if x y .

FWIW. Saya lebih suka pemisahan kode yang singkat dan jelas dengan ? , && , dan || , meskipun sintaks cond ? expr mungkin lebih jelas daripada && .

Saya suka sering melakukan jenis aliran goodcondition || return , yang tidak mudah dengan pernyataan if. Saya tidak ingin kehilangan itu (atau diintimidasi agar tidak menggunakannya)

Untuk ternary tanpa : , mungkin lebih baik mengizinkan blok if / elseif singkat tanpa kondisi else :

x==5 ? f1() :
x==6 ? f2()

dan orang dapat membayangkan memperluas ini ke pernyataan tipe-switch:

match x:
    5 ? f1() :
    6 ? f2()

Dalam hal keterbacaan, itu tergantung. Untuk banyak kondisi/tindakan pendek, jauh lebih mudah dibaca (dengan spasi bersih!!) untuk dapat menyejajarkan kondisi/tindakan pada baris yang berurutan dengan pemisah yang jelas.

Untuk generator, saya lebih suka where atau when daripada menggunakan kembali if , karena ini adalah filter, bukan kondisional:

x = [i^2 for i in 1:10 when i%2 == 0]

Saya pikir lebih jelas bahwa ini berarti x = [i^2 for i in filter(..., 1:10)] .

Saya akan perhatikan bahwa sejak membahas ini, saya tidak akan lagi keberatan dengan if condition then action - itu sudah tumbuh pada saya.
Julia cenderung bersandar pada sisi yang lebih "bertele-tele", dengan function dan end , dll, jadi saya pikir itu akan cocok. Ini juga sedikit menjengkelkan karena harus menambahkan tanda kurung. ekspresi jika Anda bolak-balik antara sintaks condition && action .

Mengenai sintaks Perl/Ruby "action if condition": Saya sangat menyukai sintaks ini, dan meskipun saya setuju bahwa sintaks ini dapat mengurangi keterbacaan ketika digunakan secara tidak benar, saya juga percaya bahwa terkadang _meningkatkan_ keterbacaan.

Sebagai contoh:

throw(DomainError()) if some_condition || some_other_condition && so_on

Setelah membaca "lemparkan kesalahan domain jika" Anda sudah tahu bahwa yang berikut akan menjadi pemeriksaan kewarasan pada input. Anda kemudian dapat melompat ke baris berikutnya jika detail kondisional tidak penting bagi Anda.

Kalimat sebelumnya adalah contoh bagaimana konstruksi ini sering terjadi dalam bahasa alami. Tindakan "lompat ke baris berikutnya" muncul lebih dulu, dan tindakan "jika Anda tidak tertarik" yang kurang penting muncul di klausa bawahan. Sekali lagi, pembaca mungkin dapat menebak kira-kira apa yang akan mengikuti kata "jika" tanpa benar-benar membaca sampai akhir kalimat.

(Saya juga akan memberikan contoh kalimat referensi diri, jika saya bisa memikirkannya.)

Sebagai tangan Perl tua, saya bersimpati dengan sintaks ini tapi saya pikir itu akan sulit dijual kepada orang lain yang tidak berasal dari latar belakang Perl. Satu argumen yang mendukung adalah bahwa itu cocok dengan sintaks filter dalam pemahaman. Argumen yang menentang adalah aneh memiliki konstruksi di mana urutan evaluasi tidak dari kiri ke kanan. Tentu saja, pemahaman memiliki hal itu, jadi ️

Bagi saya pertanyaan terkait adalah: apakah kita menggeneralisasi percabangan atau penyaringan? Ini adalah generalisasi dari percabangan if semantik (dan sintaks), jadi mungkin akan disayangkan untuk meminjam sintaks dari pemahaman / generator untuk tujuan ini di mana sintaks tersebut sudah menunjukkan pemfilteran.

(Omong-omong, saya ingin beberapa sintaks yang bagus untuk memfilter, seperti sintaks . kami yang bagus. Untuk mengilustrasikan poin saya di atas, mungkin map - filter dapat terlihat seperti f.(a) if g.(a)

f(x) for x in a # lazy map
f(x) for x in a if g(x) # lazy map - filter
x for x in a if g(x) # lazy filter where `f` is `identity`

f.(a) # map / broadcast
f.(a) if g.(a) # like a map/broadcast - filter operation
a if g.(a) # like the above where `f` is implicitly `identity`
[1,2,3] if [true, false, true] == [1, 3] # or something... here we simply make `if` an infix operator for filtering

Maaf karena keluar dari topik dan saya sama sekali tidak yakin hal di atas adalah ide yang bagus, tetapi hanya menunjukkan bahwa mungkin ada potensi penggunaan lain dari sintaksis penyaringan pemahaman if yang memiliki semantik pemfilteran)

Akhirnya - saya agak setuju dengan pengamatan @tbreloff di atas... binary ? adalah sintaks yang paling ringkas (dan inti dari utas ini adalah membuat sintaks yang ringkas), dan saya selalu menemukan if pilihan yang agak mengejutkan untuk pemfilteran generator.

@StefanKarpinski menulis:

Sintaks pengubah if/for gaya Perl/Ruby sepertinya akan lebih cocok dengan ini. Dengan kata lain:
julia println("positive") if x > 0 # conditional execution x^2 for x=1:100 # generator [ x^2 for x=1:100 ] # comprehension x^2 if x % 3 == 0 for x = 1:100 # filtered generator [ x^2 if x % 3 == 0 for x = 1:100 ] # filtered comprehension
Ini juga memiliki manfaat memiliki preseden dalam bahasa lain, yang tampaknya tidak dimiliki oleh sintaks if-then tanpa akhir.

Dan akan lebih baik untuk tata bahasanya juga.

Saya pikir [x^2 if x % 3 == 0 for x = 1:100] seharusnya:

[(x^2 if x % 3 == 0) for x = 1:100]
 ```
Then `for` stay's in infix position which is currently an error. Of course we can change its meaning because of leading `[` but it would not work as generator:
```julia
x^2 if x % 3 == 0 for x = 1:100

Saya pikir [x^2 if x % 3 == 0 for x = 1:100] seharusnya:

Itu tidak akan menjadi generator yang difilter. 2 if x mengembalikan 2 ketika x benar, tetapi juga harus mengembalikan sesuatu ketika x salah; biasanya itu adalah nothing . Jadi itu akan memberikan serangkaian angka dan tidak ada apa-apa. Itu sebagian mengapa if harus muncul setelah for dalam sintaks generator yang difilter.

Ya kamu benar. Mungkin harus ditulis seperti itu:

[for x = 1:100 x^2 if x % 3 == 0]

Afaics, ini akan valid parseable tanpa menggunakan tanda kurung, keren!

Hanya berfikir...

[ for x = 1:100 if x % 3 == 0 push x^2]
for x = 1:100 if x % 3 == 0 push x^2  # other keyword could be used, e.g. yield

Ini lebih mirip dengan konstruksi alami

for x=1:100 
    if x%3==0 
          push!(somearray, x^2)
    end
end

Saya baru saja melihat julep ini lagi sambil melihat sesuatu yang lain.

Saya masih menginginkan sesuatu seperti bentuk baris tunggal if a then b ; Saya menemukan pengganti julian a && b cukup tidak terbaca bahkan setelah menggunakannya selama beberapa tahun: tidak ada cara untuk membacanya secara langsung sebagai kalimat bahasa Inggris.

Saya juga merasa bahwa kebutuhan untuk menjelaskan idiom a && b kepada pendatang baru agak memalukan ketika kita dapat memiliki sintaks alternatif yang terbukti sendiri dan hanya sedikit lebih lama.

tidak ada cara untuk membacanya secara langsung sebagai kalimat bahasa Inggris

a && b dibaca sebagai "a dan b" seperti pada "jika a maka lakukan juga b"
a || b dibaca sebagai "a atau b" seperti pada "a harus benar, jika tidak lakukan b"

Saya tahu apa fungsinya dan saya menggunakannya sesekali untuk singkatnya. Tapi coba semampu saya (seperti yang disebutkan, selama beberapa tahun sekarang) saya tidak bisa melihat "a dan b" sebagai kalimat. Itu hanya disonansi kognitif ringan setiap saat.

Sebaliknya saya selalu menemukan "a atau b" cukup mudah dibaca.

Lucunya, aspek yang berbeda dari ini muncul dua kali hari ini di tempat kerja.

Di pagi hari, kami memiliki Julia PR yang menggunakan && alih-alih if ... end dan saya menunjukkan bahwa, sebagai pembaca kode (peninjau PR), butuh usaha ekstra (dan mudah dilewatkan ) cabang yang mungkin atau mungkin tidak dieksekusi. Contohnya dalam bentuk a() && b!() di mana b! sangat bermutasi-y. (Dalam hal ini, b!() memindahkan atau menghapus file dalam sistem file, yang tampaknya berbahaya, tetapi otak saya tidak dapat memahami semuanya bahwa ini hanya bermasalah ketika !a() dan bahwa kasus ini sebenarnya dijaga dengan benar).

Sore harinya, software engineer lain (yang tidak mengenal Julia) menunjukkan bahwa, ketika berbicara bahasa Inggris dengan teman-teman, kadang-kadang dia akan menjawab pertanyaan dalam bentuk "Apakah a atau b " dengan jawaban "ya". Hanya teman-teman insinyur perangkat lunaknya yang akan mengerti - semua orang tidak akan mengerti sama sekali . Orang normal tidak berpikir seperti itu. Ini agak berhubungan dengan poin saya berikutnya (EDIT: dan saya seharusnya mengatakan, berhubungan dengan tanggapan Stefan di atas, yang bagi banyak orang saya tidak berpikir itu akan terjadi pada mereka).

Sikap saya tentang masalah ini selama ini adalah bahwa menggunakan && (atau || ) adalah sintaks pendek untuk percabangan yang hanya dapat dibaca oleh orang-orang dengan latar belakang PL yang kuat, dan bahkan kemudian menambahkan sedikit beban kognitif/visual (hanya untuk membedakan & vs && ). Saya merasa bahwa ketika bekerja dalam tim multidisiplin (campuran ilmuwan dan insinyur perangkat lunak) secara aktif membingungkan setengah tim. Bahkan sebagai insinyur perangkat lunak, saya merasa kami memiliki keterputusan yang aneh antara &(::Bool, ::Bool) --> Bool logis dan $#$13 &&(::Bool, ::Any) --> Any &(::Bool, ::Bool) --> Bool yang bercabang (ya, yang terakhir sebenarnya bukan fungsi, tetapi semoga Anda mengerti maksud saya) . Terlepas dari tipe itu sendiri, di Julia saya biasanya mengharapkan yang pertama menjadi "fungsional" sedangkan bentuk yang terakhir sering melibatkan potensi efek samping - terutama dalam ekspresi kedua.

EDIT: memikirkan ini lebih lanjut, masalahnya di sini sepenuhnya tentang efek samping dan aliran program. Sangat mudah bagi semua orang untuk memahami bahwa penggunaan "fungsional" dari && adalah pengoptimalan dari & . Relatif sulit untuk mendamaikan bahwa mereka sama sekali berbeda untuk ekspresi non-murni.

Dalam beberapa kasus, saya pikir "diutamakan" lebih jelas dengan if a then b :

guard && c += 1    # probably an error because it's parsed as (guard && c) += 1
guard && (c += 1)  # parentheses required 

if guard then c += 1  # no ambiguity here

Juga penyorotan sintaks di editor akan membantu menandai if di awal ekspresi.

Ini juga memiliki manfaat memiliki preseden dalam bahasa lain, yang if - then tanpa end sintaks tampaknya tidak.

Perlu dicatat bahwa _ada banyak_ preseden untuk sintaks if-then-else :

Dan sintaks itu dapat digunakan untuk satu baris dalam semua bahasa di atas.

Saya telah mengetahui diskusi ini selama satu jam, jadi maafkan saya jika ini telah disarankan.

Sepertinya saya menyukai opsi hubung singkat '&&' dan '||' digunakan karena kita ingin pernyataan if sederhana dalam satu baris, tanpa titik koma. Tapi hubungan arus pendek sepertinya merupakan perbaikan yang menciptakan masalah lain: Sebagai humam, sulit untuk memahami dan menguraikan sintaks itu tanpa terlihat sebelumnya, atau mengetahui bahwa ekspresi kedua hanya dievaluasi saat diperlukan. Pembacaan yang tidak intuitif (sebagai manusia) tampaknya disebabkan oleh ketidaksempurnaan visual dan logis dengan hubungan arus pendek. Bahkan tampaknya setelah mengetahui apa artinya, membaca mungkin lebih sulit dari yang seharusnya.

Jika saya tidak salah, kedua masalah dapat diperbaiki dengan makro:

@jika kondisi hasil

Negasi dapat ditangani dengan ! sebelum kondisi, atau sebagai alternatif makro @ifnot . Hanya saya, atau apakah itu bebas dari ambiguitas untuk komputer, mudah dibaca oleh manusia, dan semuanya dalam satu baris?

Bahkan tampaknya setelah mengetahui apa artinya, membaca mungkin lebih sulit dari yang seharusnya.

^ Saya sangat setuju dengan ini.

@jika kondisi hasil

Anda sudah dapat melakukan hal berikut, yang terlihat hampir sama:

if condition result end

Di bawah ini adalah makro untuk sintaks if-then-else lengkap. Namun, karena if dan else adalah kata kunci yang dicadangkan, makro menggunakan If , Then , dan Else sebagai gantinya.

syntax_error() = error("Valid syntax is either `<strong i="20">@If</strong> cond Then ex` or `<strong i="21">@If</strong> cond Then ex1 Else ex2`")

function If(exprs...)
    n_args = length(exprs)

    if n_args == 3
        if exprs[2] != :Then
            syntax_error()
        end

        ex = quote
            if $(exprs[1])
                $(exprs[3])
            end
        end
    elseif n_args == 5
        if ( exprs[2] != :Then ) || ( exprs[4] != :Else )
            syntax_error()
        end

        ex = quote
            if $(exprs[1])
                $(exprs[3])
            else
                $(exprs[5])
            end
        end
    else
        syntax_error()
    end

    return esc(ex)
end

macro If(exprs...)
    If(exprs...)
end

foo(x) = <strong i="22">@If</strong> x > 0 Then println("greater than zero") Else println("less than zero")

Dan di sini kita dapat melihat foo beraksi:

julia> foo(3)
greater than zero

julia> foo(-3)
less than zero

Saya lebih suka sesuatu seperti

x0 = 1
x1 = 2
x3 = 3 when y>0  # y>0 is evaluated first
x4 = 4

ketika akan memiliki prioritas kurang dari = dan dioperasikan dari kanan ke kiri.

Anda sudah dapat melakukan hal berikut, yang terlihat hampir sama:

if condition result end

Saya tidak tahu hal itu! Saya selalu berpikir bahwa yang membutuhkan titik koma di mana biasanya ada baris baru. Jadi dalam kasus saya, sintaksnya

if condition result end

sepenuhnya membuat penggunaan && menjadi mubazir, jadi tidak ada masalah! Saya melihat bahwa seseorang bahkan dapat melakukan hal berikut:

if condition result_1 else result_2 end

Dalam hal ini, menambahkan kata kunci end mungkin lebih mudah daripada membuat makro. Tapi terima kasih telah meluangkan waktu untuk membuatnya ^_^ Apakah ide yang baik untuk menambahkan kemungkinan pernyataan if satu baris dalam dokumentasi? Saya melihat bahwa jika seseorang melakukan ?If<enter> hasilnya sudah cukup beberapa baris ... Tapi saya merasa fitur ini harus diiklankan lebih banyak.

Sehubungan dengan diskusi asli, saya lebih suka menambahkan "Jika x maka y", meskipun saya merasa agak berlebihan dengan versi satu baris "jika". Tapi hei, tulis kode apa pun yang masuk akal bagi Anda, bukan?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat