Rust: Argumen default dan argumen kata kunci

Dibuat pada 6 Jun 2013  ·  70Komentar  ·  Sumber: rust-lang/rust

Saya tidak melihat masalah untuk argumen kata kunci, ada rencana untuk ini di masa mendatang?


CATATAN: Pelacak bug bukanlah tempat untuk berdiskusi tentang desain. Silakan arahkan semua diskusi desain ke etherpad ( https://pad.riseup.net/p/hvbg6dQQnEe7 ) atau buat halaman bikeshedding di wiki.

Etherpad:

Komentar yang paling membantu

Triage 2013-08-05: tidak ada kemajuan (yang saya tahu), meskipun masih rapi; mungkin sintaks deklarasi bisa terlihat seperti

fn foo(bar: int, qux: int = 4, ham: Option<int> = None) { ... }

di mana RHS adalah expr konstan (yaitu hal-hal yang valid dalam deklarasi static ).

Semua 70 komentar

Belum ada rencana untuk itu, meski belum ada yang menyuarakan penentangannya. Saya telah memikirkan masalah ini untuk waktu yang lama, dan pada dasarnya bermuara pada permintaan untuk argumen default. Saya kira itu akan terlihat seperti:

fn foo(bar: int, qux=2: int, ham=0: uint) { ... }

Yang kemudian dapat disebut sebagai foo(1) , foo(1, 3) , foo(1, ham=4) , foo(6, 7, 8) , dll.

EDIT: Silakan lihat sintaks yang diusulkan huonw di bawah ini, yang terlihat jauh lebih baik dan lebih seragam dengan sintaks deklarasi saat ini.

Triage 2013-08-05: tidak ada kemajuan (yang saya tahu), meskipun masih rapi; mungkin sintaks deklarasi bisa terlihat seperti

fn foo(bar: int, qux: int = 4, ham: Option<int> = None) { ... }

di mana RHS adalah expr konstan (yaitu hal-hal yang valid dalam deklarasi static ).

IMO ini sangat berguna, bahkan sistem C++ dari _argumen default_ di mana Anda hanya dapat kembali ke default untuk mengikuti argumen yang tidak ditentukan akan sangat bagus ... mengurangi jumlah varian fungsi bernama alternatif sementara tidak serumit kelebihan beban .. bisa mendeklarasikan yang ada di struct dan varian enum juga akan bagus.
Mungkin subset sederhana dari perilaku yang diperlukan ini dapat diimplementasikan sebelum ada konsensus tentang bagaimana/jika memanggil parameter kata kunci bernama ... itu akan menyiapkan internal?

apakah layak/berguna untuk diimplementasikan sebagai ekspresi ... dalam hal argumen yang ditentukan sebelumnya & parameter tipe generik (mis.. kemampuan untuk mencari nol::, atau tulis hal-hal seperti slice(&self, start:uint , end:uint=self.len ()) /* "foobarbaz".slice(6) == "baz" .. atau create_window(parent,x,y, width :uint=parent.width ()/4, height:uint= (width_161)/100) /_ default adalah jendela berbentuk rasio emas, dan 1/4 lebar layar jika Anda tidak menentukan ukuran sama sekali.. */ .. .. atau apakah itu terdengar seperti resep untuk mengasapi kode..

Default gaya c++ akan menghalangi aplikasi functoin parsial seperti haskell, tetapi saya dengar itu tidak mungkin masuk?

Inilah ide lain untuk argumen default. Daripada membiarkan argumen dihilangkan sepenuhnya, kami mengizinkan argumen yang memiliki default untuk dipanggil dengan _ .

Jadi, berikan contoh indah @huonw tentang:

fn foo(bar: int, qux: int = 4, ham: Option<int> = None) { ... }

...kita bisa memanggil ini sebagai foo(1, 2, None) , foo(1, _, Some(1)) , foo(1, _, _) , dll.

Namun, ide ini tidak akan benar-benar memberikan manfaat apa pun untuk mengadopsi argumen kata kunci, mengingat itu masih bersifat posisional.

Mengubah judul menjadi "Argumen default dan argumen kata kunci".

tidak diimplementasikan, tetapi saya mencoba menambahkan ast & parser; https://github.com/dobkeratops/rust/compare/default_args , apakah ini cara yang tepat untuk melakukannya? (Opsi @expr .. itu akan membutuhkan batasan pada apa yang bisa menjadi expr? )
mencelupkan jari kaki saya ke dalam air untuk bereksperimen dengan fitur ini.
saya akan tertarik pada ini untuk meningkatkan subset api C++ yang dapat diterjemahkan, dan itu pasti sesuatu yang saya lewatkan dari C++, dan fitur kata kunci bernama akan luar biasa melampaui apa yang dilakukan c++.
Tampaknya sederhana dan logis untuk menggunakan sintaks deklarasi kedua yang disarankan

@dobkeratops yang terlihat bagus (walaupun type Default = Option<@expr> mungkin tidak diperlukan).

Batasan pada expr masuk rustc::middle::check_const ; anda harus menambahkan fungsi seperti check_fn yang memeriksa setiap argumen. (Juga, mungkin harus ada pemeriksaan bahwa argumen default hanya muncul di akhir; dan saya kira harus ada sesuatu di pemeriksa tipe rustc::middle::typeck , dan di trans juga. )

Ok bidang ini diberi nama jadi itu anotasi yang tidak perlu.
Terima kasih atas petunjuk di mana mencarinya, saya mencari di rustc::middle::typeck::.. mod.rs (check_fn something ).

atas nama 'integrasi berkelanjutan', apakah layak saya menyerahkan dasar sepele sebagai pr, jika saya gagal dalam hal ini mungkin seseorang yang mengetahui basis kode lebih baik dapat melakukan bagian lain jauh lebih cepat di lain waktu.
Saya selalu paranoid tentang perubahan yang menyimpang

Itu hanya merusak jika Anda benar-benar memutuskan _melawan_ mereka?

Seseorang menyarankan hal semacam ini dapat masuk dengan opsi -Z (..Session::debug_opts...tetapi saya tidak menemukan swere ini saat ini disebarkan di mana-mana (misalnya di parser).

Saya dapat melihat Anda mungkin keberatan dengan penguraian kompiler sesuatu yang belum digunakan, saya dapat mengubahnya dari peringatan menjadi kesalahan mungkin ...

@dobkeratops Perhatikan bahwa belum ada pengembang resmi yang mengomentari ini, jadi sangat tidak mungkin PR apa pun akan diterima. Ada banyak diskusi yang bisa dilakukan di sini mengenai 1) apakah kita menginginkan argumen default, 2) jika demikian, seperti apa sintaks yang seharusnya, dan 3) apakah kita menginginkan argumen kata kunci (karena semantik yang kita pilih untuk argumen default dapat menghalangi hal ini). ).

Oke, saya kira mereka akan menjadi prioritas yang sangat rendah untuk waktu yang lama, karena mereka tidak memblokir apa pun (mereka tentu saja bukan yang teratas dalam daftar keinginan saya).
Hanya berpikir itu mungkin buah yang menggantung rendah, dan keakraban lain untuk orang C++ ..
Saya kira makro terkadang dapat melakukan pekerjaan serupa (dan lebih banyak lagi) .. dan saya bisa mendapatkan kebiasaan penamaan yang lebih baik untuk variasi umum/tidak umum

Saya dapat melihat bahwa argumen bernama tidak kritis, tetapi argumen opsional IMO semacam itu. Karena di beberapa tempat saya pikir saya melihat beberapa metode dengan tanda tangan yang sama dan nama yang mirip hanya untuk menawarkan antarmuka yang lebih mudah ketika argumen yang diberikan tidak diperlukan. Akan menyebalkan jika kita berakhir dengan fungsi warisan seperti itu hanya karena sebuah fitur hilang.

Ada banyak bagian halus di sini. Argumen default apa pun adalah bentuk implisit dari kelebihan beban, jadi (saya kira) kemungkinan terintegrasi dengan algoritme resolusi sifat dan/atau inferensi tipe. Ini mungkin tidak terlalu sulit, tetapi perlu desain yang cermat, dan pada titik ini saya tidak yakin kita memiliki anggaran waktu untuk itu. Sebagai fitur _language_ saya membayangkan itu kompatibel; sebagai fitur api mungkin akan menginformasikan beberapa desain api, jadi mewakili risiko bc.

@Seldaek Saya setuju bahwa jika kita menginginkan argumen default, maka penting untuk mengimplementasikannya sebelum kita berkomitmen pada kompatibilitas mundur stdlib. Namun, saya tahu setidaknya satu bahasa (Go) yang secara filosofis menolak argumen default yang mendukung pendekatan fungsi-dengan-nama-dan-tanda tangan yang sedikit berbeda.

Namun, tidak seperti Rust, Go memiliki beberapa fitur yang membuat tidak adanya argumen default tidak terlalu menyakitkan. Pertama, mereka memiliki fungsi variadik.[1] Kedua, Anda diizinkan untuk menghilangkan bidang saat membuat struct, yang berarti mudah untuk meneruskan struct konfigurasi ke suatu fungsi (bidang yang dihilangkan tampaknya disetel ke nilai default yang ditentukan oleh kompiler(?), daripada menjadi sesuatu yang dapat dilakukan pengguna menyesuaikan). [2]

Untuk yang pertama, kami mungkin bisa lolos dengan peretasan makro untuk mencapai hasil yang sama (meskipun dengan biaya implementasi yang melelahkan). Memang, pengganti yang akan datang untuk fmt!() melakukan ini:

ifmt!("{foo} {1} {bar} {0}", 0, 1, foo=2, bar=3)

Ini adalah kode yang berfungsi hari ini.

Adapun yang terakhir, analog terbaik yang kami miliki adalah menggunakan pembaruan struct fungsional sebagai berikut:

struct Foo { x: int, y: int, z: int }

impl Foo {
    fn default() -> Foo {
        Foo{x: 0, y: 0, z: 0}
    }
}

fn bar(f: Foo) {
    printf!(f);
}

fn main() {
    bar(Foo{y: 5, ..Foo::default()});
}

Saya pernah melihat metode ini disarankan begitu saja di masa lalu sebagai solusi untuk kurangnya argumen default, tetapi dalam praktiknya cukup canggung (bandingkan bar(Foo{y: 5, ..Foo::default()}) dengan bar(y=5) , atau proposal bar(_, 5, _) ), dan tentu saja memaksa semua pemanggil untuk membuat struct bahkan jika mereka _do_ ingin meneruskan semua argumen.

Untuk mengulangi, sebagai orang yang berasal dari Python dan Javascript, saya jelas akan menyambut argumen default. Namun, saya agak berempati dengan filosofi Go untuk membuat API eksplisit (sebagai imbalan untuk (sangat berpotensi) menggelembungkan jumlah fungsi dalam API itu sendiri).

[1] https://groups.google.com/d/msg/golang-nuts/NWMReL1HueQ/X9mdYduCOB8J

[2] http://stackoverflow.com/questions/2032149/optional-parameters

Saya juga harus menunjukkan bahwa itu berinteraksi dengan penutupan dan mengambil referensi kelas satu ke fungsi.

@bstrie terima kasih atas ikhtisar Go. Saya setuju dengan poin bahwa overloading mungkin ide yang buruk karena menciptakan API yang membingungkan. Demikian pula metode jQuery "kelebihan beban" yang dapat menerima panggilan balik di hampir semua argumen yang Anda inginkan sangat aneh dan sulit untuk diterapkan.

Dan saya agak setuju bahwa fungsi pembungkus untuk mengisi argumen default tidak terlalu buruk dalam beberapa kasus. Tapi masalahnya adalah sementara itu menyelamatkan Anda dari beberapa kasus yang membingungkan, itu memang memperkenalkan banyak boilerplate pada yang lain. Salah satu contohnya adalah *::to_str_radix(num, radix) . Jika kami memiliki argumen opsional, ini dapat dilipat menjadi *::to_str(num, radix = 10) . Saya merasa bahwa dalam beberapa kasus ledakan varian fungsi benar-benar membuat hal-hal menjadi kurang intuitif dan lebih sulit untuk diingat. Hanya dua sen saya meskipun jelas.

Saya bisa melihat ini adalah waktu yang tepat untuk menunda mereka;
tetapi apakah _benar-benar_ menghilangkan default secara filosofis, atau apakah itu hanya membenarkan implementasi trade-off penganggaran waktu yang mereka buat? Saya akan terkejut jika ada yang berpikir mengarungi long_function_names_with_lots_of_trailing_qualifiers adalah langkah maju :) , tetapi jika mereka mengatakan "itu memungkinkan kami memanfaatkan alat sederhana, kami belum mengembangkan memiliki IDE yang kuat .." itu masalah lain.

Saya benar-benar merindukan overloading dan default dari C++ .. tapi saya senang menukarnya dengan kenyamanan Rusts lainnya dan janji alternatif C++ (setelah terjebak dengan 1 bahasa utama begitu lama ..)

Untuk percobaan, saya berpikir untuk mencoba melakukannya sebagai 'peretasan parser' ... bekerja di level makro? inlining expr default di situs panggilan di mana argumen tidak ada?
Saya menyadari bahwa itu tidak mungkin menjadi desain yang dapat diterima - tetapi itu membuat saya percaya bahwa tidak _tidak mungkin_ untuk memiliki argumen default yang berfungsi dengan fitur rusts.

Satu hal yang saya masih benar-benar terbiasa adalah bahwa metode secara teori jauh lebih bisa digunakan dalam karat.
Kembali di C++ saya takut pada mereka karena masalah header/dependensi, (ini adalah alasan utama saya di sini), jadi saya sering secara naluriah memilih fungsi terlebih dahulu.
Mungkin saya akan kehilangan default lebih sedikit ketika saya menggunakan karat lebih baik ..

Supaya idenya tidak hilang: aspek cerewet dari bar(Foo{y: 5, ..Foo::default()}) menurut saya adalah bagian ..Foo::default() .

Jika kita membuatnya lebih mudah untuk meninggalkan bidang dalam konstruksi struct, membiarkannya jatuh ke default, maka mungkin pendekatan ini akan lebih cocok.

Misalnya formulir baru, mungkin hanya ditentukan untuk struktur yang menerapkan beberapa sifat yang sesuai ( Zero atau Default atau apa pun), yang terlihat seperti ini:

Foo{y: 5, *) mana * menggantikan ..Foo::default() .

Maka contohnya adalah "hanya" bar(Foo{y: 5, *}) . Mungkin orang lain lebih suka Foo tidak ada di sana juga, tetapi ini tampaknya cukup bersih bagi saya.

Saya kira enums juga memberi Anda beberapa cara lain untuk dengan mudah meneruskan grup params opsional secara berbeda dengan apa yang digunakan oleh programmer C++ ... dan cara menyelingi anotasi & nilai dengan panggilan.
Itu sepertinya cocok untuk kasus seperti membuat sesuatu dengan banyak parameter pengaturan dengan baik

@pnkfelix Ingat bahwa Foo struct dalam contoh itu mungkin akan memiliki nama yang jauh lebih deskriptif, dan bahkan dengan gula yang Anda usulkan akan terlihat seperti ini dalam praktiknya:

html::start_server(html::ServerOpts{port: 10088, *});

Itu memang terlihat sedikit lebih bagus. Masih belum yakin apakah itu cukup membantu untuk menjamin sintaks baru, atau apakah itu cukup untuk memenuhi semua kasus penggunaan argumen default.

Sebenarnya, untuk menggunakan contoh saya sendiri, ketika menginisialisasi sesuatu dengan banyak opsi seperti server HTML, saya mungkin akan dengan senang hati menyiapkan server_opts struct sebelumnya dan kemudian hanya memanggil start_server(server_opts) . Dan saya benar-benar tidak keberatan menambahkan baris dengan ..html::ServerOpts::default jika inisialisasi struct saya sudah mencakup beberapa baris.

Saya pikir mungkin kita perlu memikirkan kembali di mana argumen default akan paling berguna. Bagi saya, itu bukan tempat di mana ada banyak argumen potensial; ini seharusnya cukup jarang, dan beberapa baris untuk memulai struct konfigurasi baik-baik saja. Sebaliknya, saya paling merindukan argumen default ketika 1) operasi cukup umum, dan 2) operasi memiliki, paling banyak, satu atau dua argumen yang hampir selalu berlebihan tetapi diperlukan untuk kelengkapan. Sebagai contoh:

let foo = Some('a');
foo.unwrap();  // same as today
foo.unwrap('z');  // imagine that this replaced unwrap_or_default

int::from_str("4");  // same as today
int::from_str("4", 16);  // imagine that this replaced from_str_radix

Namun, sekarang setelah saya mengetik ini, saya sebenarnya lebih suka eksplisit metode terpisah. :) Mungkin saya tidak benar-benar tahu apa yang saya inginkan!

@dobkeratops , dari pengalaman Anda dengan C++, dapatkah Anda memberi kami beberapa contoh API C++ yang bagus yang diaktifkan oleh argumen default?

Komentar di https://github.com/mozilla/rust/wiki/Meeting-weekly-2013-08-13 tampaknya menunjukkan bahwa para pengembang melihat ini sebagai fitur masa depan yang jauh. Pencalonan.

OCaml melakukan argumen opsional/default tanpa kelebihan beban, saya percaya. Argumen opsional tipe T tanpa nilai default secara implisit dikonversi ke opsi T dan fungsi harus memeriksa apakah ada nilai yang diberikan. Ada juga batasan pada deklarasi dan penggunaan argumen opsional untuk membuat kompilator mengetahui kapan sebuah argumen telah dihilangkan. Semua argumen opsional harus memiliki label (harus berupa argumen kata kunci agar opsional). Ini memperumit sistem tipe OCaml (label menjadi bagian dari tipe fungsi) tetapi saya pikir ini adalah artefak karena harus bekerja sama dengan sistem tipe Hindley-Milner lainnya.

Berasal dari C++, saya akan sangat merindukan nilai argumen default. Saya sering menggunakan fungsi dengan sejumlah besar parameter, di mana sebagian besar hampir selalu memiliki nilai default, kecuali beberapa kasus penggunaan atau pengujian yang jarang. Menambahkan turunan nama fungsi kombinatorial murni sebagai pengganti nilai default, akan membuat kekacauan besar pada nama yang sangat panjang.

Saya setuju bahwa argumen default dan/atau argumen kata kunci akan sangat berguna. Saya pikir kita harus bekerja menuju proposal pra-1.0 yang menguraikan apa yang perlu dilakukan dalam hal kelebihan beban dan mungkin berdiskusi tentang sintaks.

Senang melihat lebih banyak orang berkomentar mendukung :) Alasan lain saya menginginkannya adalah untuk meningkatkan jumlah C++ API yang dapat diterjemahkan dengan mulus. Menggunakan pustaka C++ adalah salah satu alasan utama mengapa kita terjebak dengan C++.

Saya menduga satu-satunya cara kami mendapatkan ini jika komunitas dapat _menerapkannya_ tanpa biaya apa pun kepada pengembang inti.
Saya setuju mereka memiliki hal-hal yang jauh lebih penting untuk dilakukan, & enum memulihkan polimorfisme yang hilang dengan kemungkinan yang tidak segera terlihat oleh otak yang dikondisikan C++.

Inilah sebabnya mengapa saya ingin mengirimkan dasar untuk menguraikannya ke dalam struktur data AST. Itu akan siap untuk orang lain untuk mengambilnya dan mencoba untuk mendapatkan solusi. umpan balik awal membuat saya putus asa untuk membuat PR.

dari c++ saya melihat apa yang dimiliki scala dan python dalam hal ini dengan iri. Bahasa non-GC asli dengan keanggunan itu akan sangat bagus.
..fungsinya lebih banyak di satu tempat, lebih sedikit navigasi untuk mencari tahu apa yang terjadi, lebih sedikit kedalaman sarang, lebih sedikit noise di kode sumber. Bukan hanya sepele kurang mengetik.
mungkin Anda bahkan bisa mengklaim lebih mendokumentasikan diri sendiri, tanda tangan fungsi memberi tahu Anda lebih banyak tentang cara penggunaannya.

bit yang sulit adalah pemeriksa tipe, mencegah kemungkinan bug yang halus dan kesalahan yang membingungkan jika itu hanya dilakukan sebagai peretasan parser, pikirnya.

bayangkan jika Anda hanya bisa menulis hal-hal seperti ini ..

fn substr(a:&str, start:int, end:int=a.len())->~str

hanya meretas hal semacam itu ke dalam AST tanpa pemeriksaan kesalahan, saya yakin banyak yang bisa salah .. tapi bayangkan jika kita bisa memperbaikinya untuk melakukan apa yang diharapkan :)

Hanya bug. Kami dapat memperdebatkan manfaatnya, tetapi tidak akan memblokir rilisnya.

Saya suka perilaku yang dijelaskan @tautologico dalam komentarnya.

Diterapkan ke Rust, saya yakin ini akan diterjemahkan sebagai berikut:

fn ga(bu: int, zo: Option<int>, meu: Option<int>) {
  let zo = zo.get_or_default(42);
  let meu = meu.get_or_default(99);
  ...
}

Dan ini semua akan menjadi panggilan yang valid:

ga(10, 20, 30); // 20 and 30 are automagically
                // converted to Some(20) and Some(30)
ga(10, 20);         // ga(10, 20, 99) 
ga(10);             // ga(10, 42, 99)
ga(10, None, None); // ga(10, 42, 99)
ga(10, 20, None);   // ga(10, 20, 99)
ga(10, None, 30);   // ga(10, 42, 30)

Aturannya adalah parameter tambahan Option<T> dapat dihilangkan. Di sini, Option jenis digunakan kembali, tetapi jika ini menyebabkan beberapa masalah lain yang lebih spesifik OptParam jenis dapat dibuat.

Proposal ini memungkinkan penelepon untuk memilih dengan tepat parameter yang ingin dia berikan dan parameter yang dia ingin tetap default, terlepas dari posisinya. Juga, saya pikir itu hal yang baik bahwa nilai default tidak muncul dalam daftar parameter. Dengan cara ini, nilai default tidak terbatas pada ekspresi konstan, dapat bergantung pada status objek, atau dapat bergantung pada parameter lain.

Contoh kehidupan nyata dari fungsi yang menampilkan kotak dialog GUI:

fn showDialog(message: ~str,
              parent: Option<Widget>,
              title: Option<~str>,
              type: Option<DialogType>,
              icon: Option<Icon>) { ... }

// Display an info box in the middle of the screen.
// Set the title to "information", translated in the current locale
// Set the icon to an "info" icon
showDialog(~"hello, world!");

// Display a warning box in the middle of the screen.
// Set the title to "warning", translated in the current locale
// Set the icon to a "warning" icon
showDialog(~"sick, sad world!", None, None, WarningDialog);

// Display a warning box in the middle of the screen.
// Set the title to "warning", translated in the current locale
// Set the icon to a custom icon
showDialog(~"sick, sad world!", None, None, WarningDialog, bugIcon);

Dalam contoh ini:

  • nilai default parent adalah None (tanpa induk)
  • nilai default type adalah InfoDialog
  • nilai default icon tergantung pada nilai type
  • nilai default title tergantung pada nilai type dan pada lokal saat ini

Anda sekarang juga mengusulkan penambahan Option sebagai tipe primitif baru. Ini sepenuhnya merupakan fitur perpustakaan sekarang, karena ini adalah enum tua yang polos.

Saya ingin menambahkan bahwa argumen default IMO satu miliar kali lebih baik dengan argumen kata kunci. Saya tidak suka ide args default tetapi tidak ada args kata kunci.

satu adalah batu loncatan ke yang lain dan default masih berguna sendiri, Anda memiliki beberapa bendera tambahan .. dan dapat meninggalkannya jika Anda hanya menginginkan default ..
setuju mereka menggabungkan dengan baik jika Anda memiliki keduanya.
Titik lengket sebenarnya mengimplementasikannya :)
bagaimana memasangnya kembali ke dalam typechecker/type inferer.. atau bagaimana cara memasukkannya.

Nilai default untuk argumen posisi menghasilkan kode samar. Mengapa tidak hanya memiliki default untuk argumen kata kunci? (Jika ini diterapkan).

IMO ... ini bukan "salah-atau".
Mereka berdua berguna. Yang satu lebih sederhana untuk diimplementasikan , dengan lebih sedikit pilihan dalam sintaks;
jadi masuk akal bagi kita untuk seperti itu, atau mencoba menerapkannya terlebih dahulu, sebagai batu loncatan...

Bagaimana menghilangkan nilai yang default lebih samar daripada panggilan fungsi normal? Pemrogram C++ sudah terbiasa mengurutkan parameter untuk ini. Biasanya semacam kata kontrol-bendera dengan default yang masuk akal di akhir.. hilangkan saja nilainya alih-alih menulis (..,BLAH_DEFAULT) apa pun.. menjelaskan dengan hanya mencantumkan informasi penting. Orang yang membutuhkan Rust kemungkinan besar sudah berurusan dengan C++ dan karenanya terbiasa.

Saya menyadari sebelumnya hari ini bahwa proposal saya di atas (yang mencoba memanfaatkan sintaks ekstensi struct yang ada untuk memberikan sesuatu yang mendekati argumen default, karena saya melihat struct telah menyediakan bahan untuk argumen kata kunci), mengabaikan satu masalah penting: sintaks yang saya usulkan diasumsikan bahwa seseorang akan dapat memberikan default untuk _setiap_ argumen (dan kemudian semuanya akan diangkat ke dalam parameter struct tunggal).

Ini tentu saja tidak benar secara umum: Seseorang cukup sering memiliki beberapa argumen yang diperlukan dan yang lainnya opsional.

Saya masih ingin mencari cara untuk memanfaatkan fitur yang sudah kita miliki, daripada membuang lebih jauh dengan sintaks deklarasi fungsi, terutama karena deklarasi fungsi _sudah berbulu_ berkat berbagai cara seseorang dapat menuliskan fungsi/penutupan/metode.


Brainstorming saya saat ini berfokus pada apakah kita dapat memanfaatkan sintaks struct yang ada, mungkin dengan menambahkan ekspresi default untuk bidang dalam definisi item struct. Itu kemudian akan memungkinkan seseorang untuk memiliki beberapa bidang yang dapat dijatuhkan dan bidang lain yang diperlukan. Sesuatu seperti:

struct Foo { x: int = 0, y:int = 0, z:int = 0 }

fn bar(f: Foo) {
    printf!(f);
}

struct Baz { x: int, y: int, z:int = 0 }

fn quux(g: Baz} {
    printf!(g);
}

fn main() {
    bar(Foo{y: 5});
    quux(Baz{y: 5}); // ~ERROR: required field, `x`
}

@pnkfelix Saya suka saran itu, mungkin tidak akan terlalu sulit untuk memanfaatkan internal yang sama tetapi menghasilkan struct anonim. Jadi ambil contoh Anda, ini akan menjadi kode yang sama secara efektif dengan sedikit sihir kompiler untuk menyimpulkan struct:

fn bar({ x: int = 0, y:int = 0, z:int = 0 }) {
    printf!(f);
}

fn quux({ x: int, y: int, z:int = 0 }) {
    printf!(g);
}

fn main() {
    bar({ y: 5 });
    quux({ y: 5 }); // ~ERROR: required field, `x`
}

@visionmedia @bstrie Apakah kita benar-benar perlu khawatir tentang menghilangkan nama struct? Bukankah deklarasi penggunaan rebinding menyelesaikan masalah nama panjang, dengan menurunkan jumlah minimum karakter tambahan di situs panggilan menjadi 3 (untuk nama + tanda kurung kiri dan kanan)?

Yaitu, dengan contoh ServerOpts yang diajukan bstrie kepada saya:

fn main() {
  use O = html::StartServerOptions;
  ...
  html::start_server(O{port: 10088});
}

@pnkfelix saya suka

struct Foo {
   x: int = 10,
   y: float = 1.0
}

sintaks, tapi saya rasa kita tidak membutuhkannya untuk mendapatkan argumen wajib yang masuk akal (sayangnya tidak disebutkan namanya), cukup berikan yang wajib secara terpisah:

struct FooOptions { ... }
static default: FooOptions = FooOptions { ... };
fn foo(compulsory: int, required: uint, necessary: float, optionals: FooOptions) { ... }

FWIW, saya juga suka struct dengan ide nilai default. Saya kira itu akan menjadi jalan pintas untuk:

struct Test {
    m: int,
    y: int
}

static DEFAULT: Test = Test{m: 10, y: 15};

Test{y: 5, ..DEFAULT}

Saya suka struct default di dalam definisi juga

Saya sudah mendapatkan parsing dengan sintaks itu juga tetapi tidak benar-benar digunakan .. Saya masih tidak tahu jalan di sekitar sumber typechecker dll ...

Mungkin fakta bahwa sudah ada mekanisme default di sana mungkin membuatnya sedikit lebih mudah untuk diterapkan.

ulang. struct anonim saya pikir mereka awalnya memilikinya tetapi harus menghapusnya 'karena interaksi aneh'?
saya lebih suka memiliki kedua mekanisme yang tersedia. mungkin parameter struct akan mengurangi kebutuhan akan argumen _keyword_, tetapi mengikuti default seperti di c++ masih berguna

sebagai referensi -
http://www.parashift.com/c++-faq-lite/named-parameter-idiom.html
lol - argumen kata kunci yang menarik tetapi benar akan menghindari perlunya peretasan berat boilerplate seperti ini

ulang. struct anonim saya pikir mereka awalnya memilikinya tetapi harus menghapusnya 'karena interaksi aneh'?

Awalnya semua tipe struktur adalah struktural. Mereka dihapus (diganti dengan tipe struct nominal) karena interaksi canggung dengan sifat, saya percaya.

Saya suka nilai default dalam ide definisi struct. Ini tampaknya mudah dipahami dan setidaknya menghindari keharusan untuk menghitung setiap bidang saat membuat struct - ini adalah masalah untuk struct tipe "opsi" karena itu berarti bahwa ketika bidang "opsional" baru ditambahkan maka setiap situs panggilan harus dimodifikasi menjadi inisialisasi ke 0/None/etc.

Berasal dari Perl (di mana default adalah pola ad-hoc), Python 2 (di mana Anda bisa mendapatkan foo() takes at least 2 arguments (2 given) ), dan Python 3 (di mana Anda dapat memiliki argumen bernama-saja _without_ default), saya dengan rendah hati mengusulkan: tambahkan sedikit _teeny_ gula untuk memungkinkan mendeklarasikan struct sebagai argumen terakhir untuk suatu fungsi, tetapi biarkan pemanggil _inline_ bidang struct.

misalnya

impl int {
    struct FromStrOptions {
        radix: uint = 10
    }
    fn from_str(s: str, opts: FromStrOptions) -> int {
        // ...
    }
}

int::from_str("4", radix: 10);

Keuntungan:

  • Tidak ada sintaks baru untuk definisi fungsi, yang sebenarnya tidak peduli sama sekali bagaimana pemanggil memanggilnya. Ini mirip dengan cara melewati blok dengan do bekerja: ini murni urusan penelepon. (Apakah perlu ada cara untuk memilih masuk/keluar, untuk kasus memiliki argumen terakhir yang merupakan struct tetapi tidak bermaksud menggunakannya untuk kwargs? Apakah ada yang peduli? Saya rasa tidak ada yang peduli dengan do .)
  • Tata letak biner dan semantik panggilan C dan lain-lain masih cukup terdefinisi dengan baik.
  • Overloading berdasarkan tipe atau arity tidak lebih sulit untuk diterapkan suatu hari nanti, kecuali tipe argumen terakhir tidak dapat berkontribusi pada tipe overloading. Seharusnya tidak mengganggu argumen variadic, jika itu pernah terjadi.
  • Set default yang sama dapat digunakan kembali dalam beberapa fungsi.
  • Sesuatu seperti **kwargs gratis: cukup buat struct dan berikan sebagai argumen posisi.
  • Argumen kata kunci yang diperlukan secara alami keluar dari ini: jangan berikan default di struct, dan Anda dipaksa untuk memberikan _something_ dengan nama.
  • Tidak ada kebingungan yang aneh ketika menyampaikan argumen posisi dengan nama; Anda tidak bisa melakukan itu.

Kekurangan:

  • Sedikit ajaib. Tapi tidak lebih dari melewati 5 dan memiliki tipe yang disimpulkan dari argspec fungsi, saya pikir.
  • Tidak jelas bagaimana interaksinya dengan idiom do yang ada. Mungkin cukup mudah untuk mengatakan bahwa itu harus menjadi argumen terakhir _written_, yaitu ini berfungsi sebagai argumen kedua dari terakhir hanya jika digunakan dengan do .

FWIW int::from_str("4", radix: 10) akan bertentangan dengan, yang diusulkan sebelumnya, penggunaan : sebagai operator ascription tipe.

Kutukan, digagalkan oleh ASCII.

int::from_str("4", radix☃ 10)

saya akan memilih untuk menggunakan = untuk argumen kata kunci, hanya melarang ide C tentang penugasan dalam subekspresi.. (yang mungkin tidak terlalu cocok dengan ide-ide karat yang sebagian besar tidak dapat diubah) .. saya pikir Scala memiliki ini, untuk a kemungkinan contoh bagaimana itu cocok dengan sintaks seperti c?

Apakah ada tempat untuk melakukan brainstorming bagaimana menerapkan semua ini. Saya bertanya-tanya apakah gaya argumentasi variabel dapat diimplementasikan secara internal seperti fungsi yang berlebihan berdasarkan jumlah argumen (hampir seolah-olah jumlah argumen di-postfix ke nama fungsi ..)

Kami membicarakan hal ini dalam pertemuan mingguan

Saya pikir semua orang setuju bahwa komplikasi lebih lanjut pada deklarasi fungsi/formulir doa tidak baik, dan bahwa memperluas deklarasi struct untuk memungkinkan default-bidang (terkait dengan ekspresi const), seperti yang disarankan dalam komentar saya sebelumnya , akan menjadi cara yang masuk akal untuk mendapatkan sebagian besar dari apa yang diinginkan di sini.

Tim juga memutuskan bahwa menyelesaikan ini dengan cara apa pun bukanlah prioritas untuk rilis 1.0. Pimpinan proyek @brson menyarankan agar kami membiarkan

Jadi itu adalah petunjuk yang kuat untuk semua kontributor: retas semua yang Anda suka, tapi tolong jangan kirimkan permintaan tarik atau r+ apa pun untuk bug ini sampai rilis rilis 1.0.

Hands down, Rust adalah bahasa yang luar biasa. Itu melakukan banyak hal dengan benar, itu bahkan tidak lucu. Tapi saya pikir menunda fitur ini untuk posting 1.0 adalah sebuah kesalahan.

Biarkan saya menguraikan.

Argumen fungsi default adalah _critical_ untuk desain API yang baik; kurangnya mereka memperumit apa yang seharusnya menjadi API yang lebih sederhana. Contoh dari perpustakaan std:

Dan lain-lain.

Memiliki semua nama fungsi tambahan yang dapat dihapus dengan argumen default tidak perlu meningkatkan beban kognitif. Pengguna sekarang harus tahu dua (atau lebih) nama, bukan satu.

Jika argumen default ditunda setelah 1.0, maka fungsi ini di perpustakaan std tidak dapat dihapus karena kompatibilitas mundur. Ini berarti bahwa meskipun argumen default ditambahkan di masa mendatang dan versi fungsi "vanilla" sekarang dapat melakukan pekerjaan varian lain, varian lama akan tetap ada dan pengembang harus mengetahuinya karena seseorang pasti akan menggunakannya mereka, meskipun hanya karena kesalahan.

Sehingga beban kognitif ekstra akan tetap _selamanya_.

[NB Argumen yang sama dapat dibuat untuk kelebihan fungsi berbasis tipe parameter (solusi berbasis sifat saat ini terlalu rumit dan fungsi perpustakaan std tidak menggunakannya), tetapi masalah ini bukan tempat untuk diskusi itu.]

Rust devs, terima kasih telah mengerjakan Rust dan membuatnya luar biasa!

Saya menambahkan tonggak "masa depan yang jauh" untuk menekankan keputusasaan ekstrem yang ingin kami komunikasikan di tim inti kepada siapa pun yang menghabiskan waktu sedetik pun untuk masalah ini. Jika Anda ingin berkontribusi pada Rust sekarang, harap atasi salah satu dari 41 bug terbuka pada pencapaian 1 (terdefinisi dengan baik):

https://github.com/mozilla/rust/issues?milestone=12&state=open

atau salah satu dari 104 bug terbuka pada pencapaian 2 (kompatibilitas mundur):

https://github.com/mozilla/rust/issues?milestone=13&state=open

atau salah satu dari 68 bug terbuka pada tonggak 3 (fitur yang kami sepakati pada satu titik sangat penting untuk merilis Rust 1.0):

https://github.com/mozilla/rust/issues?milestone=14&state=open

atau bahkan hanya mengomentari salah satu bug tersebut untuk meminta klarifikasi atau menyarankan cara untuk membuat kemajuan. Itu 213 bug untuk dipilih; membuat kemajuan pada salah satu dari mereka pada saat ini akan jauh lebih berharga bagi Rust daripada masalah ini. Dan siapa pun yang dapat menutup salah satu bug ini akan sangat berterima kasih.

Saya dapat melihat tim inti memiliki hal-hal yang jauh lebih penting untuk dilakukan tetapi tampaknya memalukan untuk 'mengkomunikasikan keputusasaan yang ekstrem' :(
+1 untuk komentar vallorics. penamaan itu sulit, menggali dokumentasi dan mempelajari lebih banyak nama tidak menyenangkan..; args/overloading default membuatnya lebih mudah; dengan kata kunci args Anda akan memiliki kesempatan untuk melampaui C++ dalam hal ini. (Saya berharap github memiliki pemungutan suara, saya bisa menekan +1 daripada mengoceh lebih banyak di sini lol)

@Valloric Saya sepenuhnya setuju (seperti yang saya katakan sebelumnya), dan sangat berharap tim inti karat mempertimbangkan kembali atau setidaknya membahas kembali argumen opsional karena itu memengaruhi desain API. Bernama args pasti bisa menunggu karena sebagian besar berdampak pada situs panggilan (tentu saja nama args menjadi bagian dari desain API setelah kami menamai args, jadi itu memang memiliki sedikit dampak tetapi tidak merusak BC jika nama args dibersihkan ketika args bernama diperkenalkan).

Tidak ada konsensus bahwa ini akan menjadi fitur bahasa yang baik. Juga tidak ada proposal konkret dengan semua detail yang dikerjakan untuk parameter bernama/default. Itu tidak akan terjadi untuk 1.0, karena ada seperangkat fitur bahasa inti yang ada untuk diperbaiki atau dihapus sebelum memimpikan gula sintaksis yang sangat tidak penting.

'bermimpi' membuatnya terdengar seperti sesuatu yang fantastis, tetapi fitur ini telah terbukti dalam bahasa lain. Ini bukan hanya gula sintaksis - ini mengurangi jumlah kode yang harus Anda navigasikan, mengurangi jumlah simbol yang harus Anda pelajari

Itu tidak akan terjadi untuk 1.0, karena ada seperangkat fitur bahasa inti yang ada untuk diperbaiki atau dihapus sebelum memimpikan gula sintaksis yang sangat tidak penting.

Saya tidak mengatakan bahwa fitur bahasa lain yang perlu diperbaiki/diimplementasikan tidak lebih penting; mereka mungkin. Tapi itu tidak baik/atau. Yang saya katakan adalah bahwa fitur ini harus dipertimbangkan dengan kuat untuk 1.0 (selain fitur lainnya) karena tidak memengaruhi kualitas API di perpustakaan std _forever_.

Ini mungkin pendapat yang kontroversial, tetapi bahasa pemrograman IMO hidup dan mati lebih banyak oleh API yang mereka sediakan daripada fitur inti di dalamnya. Pustaka std "termasuk baterai" Python menjual seluruh bahasa. CPAN membuat Perl tetap hidup. .Net membuat penulisan kode C# mengagumkan, dan LINQ adalah yang terbaik sejak mengiris roti. Salah satu kegagalan terbesar C++ adalah kurangnya API standar yang baik. Dll.

API sangat penting untuk keberhasilan suatu bahasa sehingga fitur yang memungkinkan pembuatan _good_ API tidak boleh dibuang sebagai "gula sintaksis yang tidak penting".

@dobkeratops : dengan mengatakan _dreaming up_, saya mencoba untuk menekankan bahwa tidak ada proposal lengkap yang dibuat sehingga tidak pada langkah pengambilan keputusan

Diskusi ini tidak produktif. Untuk mencegahnya menghabiskan lebih banyak waktu siapa pun, saya akan menutup masalah ini. Jika seseorang ingin membukanya kembali (atau memulai edisi baru) setahun dari sekarang, atau lebih lambat dari itu, tidak apa-apa.

Jika seseorang datang dengan proposal dengan hampir semua detailnya (tata bahasa, semantik), saya sarankan mempostingnya ke milis. Jika konsensus dicapai tentang cara tertentu untuk melakukan ini sebagai _cara yang benar_, maka masuk akal untuk membuka masalah dan mengimplementasikannya sebagai fitur eksperimental di balik tanda seperti fungsi once .

Saya kedua @thestinger -- jika seseorang (atau sekelompok kecil orang) memiliki proposal yang lengkap, atau proposal dengan beberapa titik kosong yang dieja dengan jelas yang siap untuk didiskusikan, akan tepat bagi orang itu untuk menjalankannya oleh milis. Itu tidak menjanjikan bahwa kami akan menerapkan proposal itu, tetapi melakukan pekerjaan memformalkan ide dan menjelaskan bagaimana itu berinteraksi dengan fitur bahasa lain akan sangat meningkatkan nilai saran.

@thestinger @catamorphism Terima kasih untuk tetap berpikiran terbuka! Ketika saya menemukan waktu, saya akan menyiapkan proposal dan mengirimkannya ke rust-dev.

Saya membuat pad untuk berdebat tentang fitur ini dan untuk menulis spesifikasi yang jelas tentangnya: https://pad.riseup.net/p/hvbg6dQQnEe7

Saya membuka kembali ini. Ini bukan prioritas - sudah terlalu banyak yang harus dilakukan - tetapi ini adalah fitur yang diinginkan orang, dan itu tidak sepenuhnya salah. Saya tidak ingin menutup percakapan apa pun tentang masalah ini.

@brson Terima kasih!

Saya telah mengedit masalah asli dengan tautan ke etherpad.

Hai.
Sejak pembuatan pad, telah dilengkapi dengan banyak proposisi desain, pertanyaan, masalah, dll...
Jadi saya telah membuat pad kedua untuk "meringkas" pad diskusi, pad ini akan digunakan untuk menggambarkan permintaan fitur dengan tepat.
Pad URL di sini: https://pad.riseup.net/p/Ca5PBeDjUGxW

@KokaKiwi semua pembalutnya kosong sekarang. Kemana perginya isinya?

@cmr , saya kira:

PERINGATAN: Pad ini akan DIHAPUS jika 30 hari berlalu tanpa suntingan. TIDAK ADA CARA untuk memulihkan pad setelah ini terjadi, jadi berhati-hatilah!

:mengernyit:

Saya sebenarnya mencari pad yang saya buat pada instance Mozilla Etherpad (untuk mencegah kasus ini), tetapi saya tidak dapat menemukannya di riwayat saya, dan saya lupa menerbitkan tautan di sini :(

@cmr @huonw @KokaKiwi , berikut adalah dua tautan di riwayat browser saya:

https://etherpad.mozilla.org/CQEDa85jLX
https://etherpad.mozilla.org/78FA1bozLd

@dram Itulah yang saya cari! terima kasih :smiley:
Mungkin masalahnya harus diedit dengan tautan baru, saya pikir.

(Diedit.)

Saya tidak memiliki sesuatu yang berarti untuk ditambahkan selain ini adalah salah satu hal yang saya perhatikan dengan cermat sebelum saya menginvestasikan lebih banyak waktu dengan bahasa tersebut. Berasal dari bahasa (Objective-C dan Python) yang memiliki fitur ini, saya percaya bahwa parameter bernama adalah dorongan besar tidak langsung untuk produktivitas karena cara mereka memaksa kode orang lain agar lebih mudah dibaca.

Proposal konkret harus dilakukan melalui proses RFC baru: https://github.com/rust-lang/rfcs

Ada terlalu banyak gagasan yang saling bertentangan dan utas percakapan yang berbeda di sini untuk menjadi area diskusi yang berguna.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat