Apakah ada cara untuk secara eksplisit mensyaratkan dalam Julia (misalnya katakan dalam modul atau paket) bahwa jenis harus dinyatakan ? Apakah misalnya PackageCompiler
atau Lint.jl
memiliki dukungan untuk pemeriksaan semacam itu? Secara lebih luas, apakah distribusi standar Julia sendiri menyediakan penganalisa kode statis atau yang setara yang dapat membantu memeriksa persyaratan ini?
Sebagai contoh yang memotivasi, katakanlah kami ingin memastikan bahwa basis kode produksi kami yang berkembang hanya menerima kode yang selalu dinyatakan , berdasarkan hipotesis bahwa basis kode besar dengan deklarasi tipe cenderung lebih dapat dipertahankan.
Jika kita ingin menegakkan kondisi itu, apakah Julia dalam distribusi standarnya menyediakan mekanisme untuk meminta deklarasi jenis atau membantu memajukan tujuan itu? (mis. apa pun yang dapat diperiksa melalui linter, kait komit, atau yang setara?)
sumber
hasmethod(f, (Any,) )
akan kembalifalse
jika tidak ada generik yang telah didefinisikan. Anda masih harus mencocokkan jumlah argumen (yaituhasmethod(f, (Any,Any) )
untuk fungsi dua argumen).Jawaban:
Jawaban singkatnya adalah: tidak, saat ini tidak ada alat untuk mengetik kode Julia Anda. Namun pada prinsipnya mungkin, dan beberapa pekerjaan telah dilakukan ke arah ini di masa lalu, tetapi tidak ada cara yang baik untuk melakukannya sekarang.
Jawaban yang lebih panjang adalah "ketik anotasi" adalah herring merah di sini, yang benar-benar Anda inginkan adalah pengecekan tipe, jadi bagian yang lebih luas dari pertanyaan Anda sebenarnya adalah pertanyaan yang tepat. Saya dapat berbicara sedikit tentang mengapa anotasi jenis adalah herring merah, beberapa hal lain yang bukan solusi yang tepat, dan seperti apa bentuk solusi yang tepat.
Membutuhkan anotasi jenis mungkin tidak memenuhi apa yang Anda inginkan: orang bisa saja memasukkan
::Any
bidang, argumen, atau ekspresi apa pun dan itu akan memiliki anotasi jenis, tetapi tidak ada yang memberi tahu Anda atau kompilator apa pun yang berguna tentang jenis sebenarnya dari benda itu. Ini menambahkan banyak suara visual tanpa benar-benar menambahkan informasi apa pun.Bagaimana dengan membutuhkan anotasi jenis konkret? Itu mengesampingkan hanya meletakkan
::Any
segala sesuatu (yang memang dilakukan oleh Julia secara implisit). Namun, ada banyak kegunaan abstrak yang benar-benar valid yang membuat ini ilegal. Misalnya, definisiidentity
fungsi adalahAnotasi jenis konkret apa yang akan Anda pakai di
x
bawah persyaratan ini? Definisi ini berlaku untuk apa punx
, apa pun jenisnya — itulah jenis fungsinya. Satu-satunya jenis anotasi yang benar adalahx::Any
. Ini bukan anomali: ada banyak definisi fungsi yang memerlukan tipe abstrak agar benar, sehingga memaksa mereka untuk menggunakan tipe konkret akan sangat membatasi dalam hal apa jenis kode Julia yang dapat ditulis.Ada gagasan "stabilitas tipe" yang sering dibicarakan di Julia. Istilah ini tampaknya berasal dari komunitas Julia, tetapi telah diambil oleh komunitas bahasa dinamis lainnya, seperti R. Agak sulit untuk didefinisikan, tetapi secara kasar berarti bahwa jika Anda mengetahui jenis konkret dari argumen suatu metode, Anda tahu jenis nilai pengembaliannya juga. Bahkan jika suatu metode adalah tipe stabil, itu tidak cukup untuk menjamin bahwa ia akan mengetik cek karena stabilitas tipe tidak berbicara tentang aturan apa pun untuk memutuskan apakah tipe sesuatu memeriksa atau tidak. Tapi ini semakin ke arah yang benar: Anda ingin dapat memeriksa bahwa setiap definisi metode adalah tipe stabil.
Anda banyak yang tidak ingin memerlukan stabilitas tipe, bahkan jika Anda bisa. Sejak Julia 1.0, sudah biasa menggunakan serikat kecil. Ini dimulai dengan mendesain ulang protokol iterasi, yang sekarang digunakan
nothing
untuk menunjukkan bahwa iterasi dilakukan versus mengembalikan(value, state)
tuple ketika ada lebih banyak nilai untuk iterate.find*
Fungsi - fungsi di perpustakaan standar juga menggunakan nilai kembalinothing
untuk menunjukkan bahwa tidak ada nilai yang ditemukan. Ini adalah jenis ketidakstabilan secara teknis, tetapi mereka disengaja dan kompiler cukup pandai dalam berpikir tentang mereka mengoptimalkan sekitar ketidakstabilan. Jadi setidaknya serikat kecil mungkin harus diizinkan dalam kode. Selain itu, tidak ada tempat yang jelas untuk menggambar garis. Meskipun mungkin orang bisa mengatakan bahwa tipe pengembalianUnion{Nothing, T}
dapat diterima, tetapi tidak ada yang lebih tidak terduga dari itu.Apa yang Anda mungkin benar-benar inginkan, alih-alih memerlukan anotasi jenis atau stabilitas tipe, adalah memiliki alat yang akan memeriksa bahwa kode Anda tidak dapat melempar kesalahan metode, atau mungkin lebih luas sehingga tidak akan membuang segala jenis kesalahan yang tidak terduga. Kompiler seringkali dapat dengan tepat menentukan metode mana yang akan dipanggil di setiap situs panggilan, atau setidaknya mempersempitnya ke beberapa metode. Begitulah cara menghasilkan kode cepat — pengiriman dinamis penuh sangat lambat (jauh lebih lambat daripada vtables di C ++, misalnya). Jika Anda telah menulis kode yang salah, di sisi lain, kompiler dapat memancarkan kesalahan tanpa syarat: kompiler tahu Anda membuat kesalahan tetapi tidak memberi tahu Anda sampai runtime karena itu adalah semantik bahasa. Seseorang dapat meminta kompilator untuk dapat menentukan metode mana yang dapat dipanggil di setiap situs panggilan: itu akan menjamin bahwa kode akan cepat dan tidak ada kesalahan metode. Itulah yang harus dilakukan alat pengecekan tipe yang baik untuk Julia. Ada dasar yang bagus untuk hal semacam ini karena kompiler sudah melakukan banyak pekerjaan ini sebagai bagian dari proses menghasilkan kode.
sumber
Ini pertanyaan yang menarik. Pertanyaan kuncinya adalah apa yang kita definisikan sebagai tipe yang dideklarasikan . Jika Anda maksudkan ada
::SomeType
pernyataan dalam setiap definisi metode maka agak sulit dilakukan karena Anda memiliki berbagai kemungkinan pembuatan kode dinamis di Julia. Mungkin ada solusi lengkap dalam hal ini tetapi saya tidak mengetahuinya (saya ingin mempelajarinya).Hal yang terlintas dalam pikiran saya, yang tampaknya relatif lebih mudah untuk dilakukan adalah memeriksa apakah ada metode yang didefinisikan dalam modul menerima
Any
sebagai argumennya. Ini serupa tetapi tidak setara dengan pernyataan sebelumnya sebagai:terlihat sama untuk
methods
fungsi sebagai tanda tangan dari kedua fungsi menerimax
sebagaiAny
.Sekarang untuk memeriksa apakah ada metode dalam modul / paket menerima
Any
sebagai argumen untuk salah satu metode yang didefinisikan di dalamnya sesuatu seperti kode berikut dapat digunakan (saya belum mengujinya secara ekstensif karena saya baru saja menuliskannya, tetapi tampaknya sebagian besar menutup kemungkinan kasus):Sekarang ketika Anda menjalankannya pada
Base.Iterators
modul Anda mendapatkan:dan ketika Anda mis memeriksa paket DataStructures.jl Anda mendapatkan:
Apa yang saya usulkan bukanlah solusi lengkap untuk pertanyaan Anda, tetapi saya menemukan itu berguna untuk diri saya sendiri sehingga saya berpikir untuk membagikannya.
EDIT
Kode di atas menerima
f
untuk menjadiFunction
saja. Secara umum Anda dapat memiliki jenis yang dapat dipanggil. Kemudiancheck_declared(m::Module, f::Function)
tanda tangan dapat diubah menjadicheck_declared(m::Module, f)
(sebenarnya maka fungsi itu sendiri akan memungkinkanAny
sebagai argumen kedua :)) dan meneruskan semua nama yang dievaluasi ke fungsi ini. Maka Anda harus memeriksa apakahmethods(f)
ada positiflength
di dalam fungsi (sepertimethods
untuk pengembalian yang tidak dapat dipanggil, nilai yang memiliki panjang0
).sumber