Saya memulai ini sebagai tempat untuk meninggalkan catatan tentang hal-hal yang perlu dipertimbangkan saat memeriksa konsistensi API di Julia 1.0.
[x] Prioritas konvensi. Membuat daftar dan memprioritaskan konvensi what-come-first kami dalam hal argumen fungsi untuk blok-do, argumen IO untuk fungsi yang dicetak, keluaran untuk fungsi di tempat, dll (https://github.com/JuliaLang/julia/issues/ 19150).
[] Argumen posisi vs kata kunci. Dulu kami tidak memiliki argumen kata kunci. Mereka terkadang masih dihindari karena pertimbangan kinerja. Kami harus membuat pilihan ini berdasarkan pada apa yang membuat API terbaik, bukan pada jenis bagasi historis tersebut (masalah kinerja kata kunci juga harus ditangani sehingga ini tidak lagi menjadi pertimbangan).
[] Alat metaprogramming. Kami memiliki banyak alat seperti @code_xxx
yang dipasangkan dengan fungsi dasar seperti code_xxx
. Ini harus berperilaku secara konsisten: tanda tangan serupa, jika ada fungsi dengan tanda tangan serupa, pastikan fungsi tersebut memiliki versi makro yang serupa. Idealnya, mereka semua harus mengembalikan nilai, daripada beberapa nilai kembali dan hasil pencetakan lainnya, meskipun itu mungkin sulit untuk hal-hal seperti kode LLVM dan kode perakitan.
[] IO <=> nama file yang setara. Kami biasanya mengizinkan nama file sebagai string untuk diteruskan sebagai pengganti objek IO dan perilaku standarnya adalah membuka file dalam mode yang sesuai, meneruskan objek IO yang dihasilkan ke fungsi yang sama dengan argumen yang sama, dan kemudian memastikan bahwa objek IO ditutup setelah itu. Pastikan semua fungsi penerima IO yang sesuai mengikuti pola ini.
[] Reducers API. Pastikan reduksi memiliki perilaku yang konsisten - semua menggunakan fungsi peta sebelum reduksi; argumen dimensi yang kongruen, dll.
[] Argumen dimensi. Perlakuan yang konsisten terhadap argumen input "hitung di seluruh dimensi [ini] ini", jenis apa yang diizinkan, dll., Pertimbangkan apakah melakukan hal ini sebagai argumen kata kunci yang mungkin diinginkan.
[] Pasangan yang bermutasi / tidak bermutasi. Periksa apakah fungsi non-mutasi dipasangkan dengan fungsi mutasi yang masuk akal dan sebaliknya.
[] Tuple vs. vararg. Periksa apakah ada konsistensi umum antara apakah fungsi menggunakan tupel sebagai argumen terakhir atau vararg.
[] Serikat vs. nullables vs. kesalahan. Aturan yang konsisten tentang kapan fungsi harus menampilkan kesalahan, dan kapan harus mengembalikan Nullable atau Unions (mis. Parse / tryparse, cocok, dll.).
[] Dukung generator seluas mungkin. Pastikan semua fungsi yang dapat bekerja dengan generator melakukannya. Kami sudah cukup mahir dalam hal ini, tetapi saya rasa kami melewatkan beberapa.
[] Pemilihan jenis keluaran. Bersikaplah konsisten tentang apakah API "tipe keluaran" harus dalam hal jenis elemen atau jenis penampung keseluruhan (ref # 11557 dan # 16740).
[x] Pilih nama. Ada beberapa fungsi / operator dengan alias. Saya pikir ini baik-baik saja dalam kasus di mana salah satu nama adalah non-ASCII dan versi ASCII disediakan sehingga orang masih dapat menulis kode ASCII murni, tetapi ada juga kasus seperti <:
yang merupakan alias untuk issubtype
kedua nama tersebut adalah ASCII. Kita harus memilih satu dan menghentikan yang lain. Kami menghentikan is
mendukung ===
dan harus melakukan hal yang sama di sini.
[] Konsistensi dengan DataStructures . Ini agak di luar cakupan Base Julia, tetapi kita harus memastikan bahwa semua koleksi di DataStructures memiliki API yang konsisten dengan yang disediakan oleh Base. Hubungan ke arah lain adalah bahwa beberapa dari tipe tersebut dapat menginformasikan bagaimana kami akhirnya mendesain API di Base karena kami ingin mereka meluas dengan lancar dan konsisten.
[] NaN vs. Kesalahan Domain. Lihat https://github.com/JuliaLang/julia/issues/5234 - memiliki kebijakan kapan harus melakukannya dan pastikan dipatuhi secara konsisten.
[] Generator <=> koleksi. Terkadang Anda menginginkan koleksi, terkadang Anda menginginkan generator. Kita harus memeriksa semua API kita dan memastikan ada opsi untuk keduanya yang masuk akal. Dahulu kala, ada aturan untuk menggunakan nama huruf besar untuk versi generator dan nama huruf kecil untuk versi yang diinginkan dan mengembalikan koleksi baru. Tapi tidak ada yang memperhatikan itu, jadi mungkin kita perlu konvensi baru.
[] Fungsi urutan yang lebih tinggi pada asosiatif. Saat ini beberapa fungsi urutan yang lebih tinggi mengulangi koleksi asosiatif dengan tanda tangan (k,v)
- misalnya map
, filter
. Yang lain mengulangi pasangan, yaitu dengan tanda tangan kv
, mengharuskan tubuh untuk secara eksplisit merusak pasangan menjadi k
dan v
- misalnya all
, any
. Ini harus ditinjau dan dibuat konsisten.
[x] Konversi vs. membangun. Izinkan konversi jika sesuai. Misalnya, ada beberapa masalah / pertanyaan tentang convert(String, 'x')
. Secara umum, konversi sesuai jika ada satu transformasi kanonik. Konversi string menjadi angka secara umum tidak tepat karena ada banyak cara tekstual untuk merepresentasikan angka, jadi kita perlu mengurai, dengan opsi. Namun, ada satu cara kanonik untuk merepresentasikan nomor versi sebagai string, jadi kami dapat mengonversinya. Kita harus menerapkan logika ini dengan hati-hati dan universal.
[] Tinjau kelengkapan API koleksi. Kita harus melihat fungsi perpustakaan standar untuk koleksi yang disediakan oleh bahasa lain dan memastikan kita memiliki cara untuk mengekspresikan operasi umum yang mereka miliki. Misalnya, kita tidak memiliki fungsi flatten
atau fungsi concat
. Kami mungkin harus.
[] Menggarisbawahi audit.
Mohon maaf jika ini bukan tempat yang tepat untuk menyebutkan ini, tetapi alangkah baiknya jika kedepannya lebih konsisten dengan garis bawah dalam nama fungsi.
Tidak, ini tempat yang bagus untuk itu. Dan ya, kita harus berusaha untuk menghilangkan semua nama yang membutuhkan garis bawah :)
Untuk poin kedua @tkelman , lihat https://github.com/JuliaLang/julia/issues/19150
Ada juga Julep baru-baru ini mengenai API untuk find
dan fungsi terkait: https://github.com/JuliaLang/Juleps/blob/master/Find.md
Haruskah kita menghentikan put!
dan take!
pada saluran (dan mungkin melakukan hal yang sama untuk masa depan) karena kita memiliki push!
dan shift!
? Hanya menyarankan untuk menghapus 2 kata yang berlebihan di API.
Saya curiga shift!
ramah pengguna. Kandidat fetch!
kita sudah memiliki fetch
yang merupakan versi tidak bermutasi dari take!
ref # 13538 # 12469
@amitmurthy @malmaud
Edit: Bahkan masuk akal untuk menggunakan kembali send
dan recv
pada saluran. (Saya terkejut bahwa ini hanya digunakan untuk UDPSockets saat ini)
+1 untuk mengganti put!
/ take!
dengan push!
/ fetch!
Saya akan menambahkan penggantian nama @inferred
menjadi @test_inferred
.
Periksa kembali apakah spesialisasi konsisten dengan fungsi yang lebih umum, yaitu bukan sesuatu seperti # 20233.
Tinjau semua fungsi yang diekspor untuk memeriksa apakah ada yang dapat dihilangkan dengan menggantinya dengan beberapa pengiriman, misalnya print_with_color
Pasangan tipikal adalah push!
dan shift!
saat bekerja dengan struktur data seperti antrian.
Jika kita tidak akan menggunakan penyandingan nama tipikal untuk jenis struktur data ini karena kita khawatir bahwa operasi tersebut memerlukan overhead komunikasi yang tidak cukup disampaikan oleh nama-nama itu, maka menurut saya push!
masuk akal. send
dan recv
mungkin benar-benar lebih baik.
Mungkin periksa ulang apakah ada konsistensi umum antara apakah fungsi menggunakan tupel sebagai argumen terakhir atau vararg.
Mungkin terlalu besar untuk masalah ini, tetapi akan lebih baik untuk memiliki aturan yang konsisten tentang kapan fungsi harus menampilkan kesalahan, dan kapan mereka harus mengembalikan Nullable
s atau Union
s (mis. parse
/ tryparse
, match
, dll.)
Tidak masalah yang terlalu besar, @simonbyrne - ini adalah daftar cucian.
Btw: ini tidak benar-benar untuk perubahan tertentu (mis. Mengganti nama fungsi tertentu) - ini lebih tentang jenis hal yang dapat kita ulas. Untuk perubahan khusus yang diusulkan, cukup buka masalah yang mengusulkan perubahan itu.
Kami memiliki banyak alat seperti @code_xxx yang dipasangkan dengan fungsi dasar seperti code_xxx
Tidak yakin apakah ini yang Anda bicarakan, tetapi lihat CreateMacrosFrom.jl
Mendokumentasikan semua fungsi yang diekspor (termasuk doctests)
jika ini adalah bagian dari ini, maka mungkin juga: ingatlah untuk memberi label pengujian Anda dengan nomor terbitan / pr. Ini membuatnya lebih mudah untuk memahami mengapa tes itu ada. Saya tahu bagaimana git menyalahkan bekerja, tetapi ketika menambahkan testets (hanya untuk memberikan contoh) terkadang ada sedikit misteri apa yang sedang diuji, dan akan sangat bagus jika nomor masalah / pr selalu ada.
@dpsanders : dan makro yang diekspor! misal @fastmath
tidak memiliki dokumen.
Ini sangat kecil, tetapi fungsi string
dan Symbol
melakukan hal yang hampir sama dan memiliki kapitalisasi yang berbeda. Saya pikir symbol
akan lebih masuk akal.
@amellnik Perbedaannya adalah bahwa Symbol
adalah konstruktor tipe dan string
adalah fungsi biasa. IIRC kami dulu memiliki symbol
tetapi tidak digunakan lagi untuk mendukung tipe konstruktor. Saya tidak yakin perubahan diperlukan untuk ini, tetapi jika ada yang menurut saya kita harus menggunakan konstruktor String
sebagai pengganti string
.
jika ada yang saya pikir kita harus menggunakan konstruktor String sebagai pengganti string.
Tidak, keduanya adalah fungsi yang berbeda dan tidak boleh digabungkan
julia> String(UInt8[])
""
julia> string(UInt8[])
"UInt8[]"
Tidak, keduanya adalah fungsi yang berbeda dan tidak boleh digabungkan
Ini terlihat seperti situasi di mana string(args...)
seharusnya sudah tidak digunakan lagi demi sprint(print, args...)
, lalu - memiliki string
dan String
membingungkan. Kami dapat mengkhususkan diri pada sprint(::typeof(print), args...)
untuk memulihkan kinerja yang hilang. Sejalan dengan itu, mungkin juga masuk akal untuk menghentikan repr(x)
untuk sprint(showall, args...)
.
Kedengarannya oke meskipun memanggil string
untuk mengubah sesuatu menjadi string tampaknya cukup standar ....
memanggil string untuk mengubah sesuatu menjadi string tampaknya cukup standar
Ya, tapi di situlah pemutusan hubungan antara String
dan string
masuk.
sprint(print, ...)
terasa berlebihan. Jika kita menghilangkan string
, kita dapat mengganti nama sprint
menjadi string
jadi kita mendapatkan string(print, foo)
dan string(showall, foo)
yang menurut saya bagus .
Ini mungkin kasus di mana konsistensi dinilai terlalu tinggi. Saya pikir tidak apa-apa memiliki string(x)
untuk "beri saya representasi string x". Jika akan lebih rumit dari itu, misalnya meminta Anda menentukan fungsi pencetakan mana yang akan digunakan, maka menggunakan nama lain seperti sprint
masuk akal.
Saya juga boleh mengganti nama String(UInt8[])
menjadi yang lain, dan menggunakan String
bukan string
. string
memberi kita sedikit lebih banyak fleksibilitas di masa depan untuk mengubah jenis string yang kita kembalikan, tetapi sepertinya itu tidak akan terjadi.
Apakah reinterpret(String, ::Vector{UInt8}
masuk akal sama sekali, atau ini pelesetan dari reinterpret
?
Itu sepertinya masuk akal.
Masalahnya adalah fungsi ini terkadang menyalin, jadi nama itu agak menyesatkan.
Benar, tetapi string seharusnya tidak berubah, jadi kita mungkin bisa lolos begitu saja.
Ada juga metode String(::IOBuffer)
, tetapi sepertinya metode itu sudah tidak digunakan lagi menjadi readstring
.
Saya telah memikirkan tentang perubahan API yang Anda usulkan juga, tetapi antarmuka string(a, b...)
adalah ia merangkai dan menggabungkan argumennya, dan ini akan membuat pengecualian gotcha yang mengganggu untuk argumen pertama yang dapat dipanggil. Jika kita menghapus rangkaian dari string
maka itu bisa dibuat untuk bekerja.
Ya, setuju; konsistensi dan menghindari gotcha adalah yang paling penting.
Mencatat masalah # 18326 dan # 3893 dalam kategori "argumen dimensi".
Jika saya dapat menangani item lain: memastikan perilaku kontainer yang bisa berubah-ubah didokumentasikan dan konsisten.
@ JaredCrean2 :
Saya tentu berharap itu tidak melibatkan pembuatan banyak "salinan defensif".
Misalnya, jika saya memiliki array tipe yang bisa berubah dan saya memanggil sort
di atasnya, apakah titik array yang dikembalikan ke objek yang sama dengan array input, atau apakah itu menyalin objek dan membuat titik array yang dikembalikan ke mereka?
Objek yang sama. Saya cukup yakin semua metode penyortiran, getindex, pemfilteran, pencarian, dll koleksi kami mengikuti aturan ini, bukan?
Saya tidak berpikir ada kekurangan kejelasan atau konsistensi pada poin itu - selalu objek yang sama.
Sebenarnya, saya pikir satu - deepcopy
mana intinya adalah Anda mendapatkan semua objek baru.
Apakah itu didokumentasikan di suatu tempat?
Tidak - kami bisa, tetapi saya tidak yakin di mana sebaiknya mendokumentasikannya. Mengapa fungsi membuat salinan tidak perlu? Dari mana Anda mendapat kesan bahwa mereka mungkin?
Halo. Saya belum melihat saya percaya ada komentar tentang serialisasi data.
Cepat atau lambat program julia akan ditulis dan dijalankan secara publik, data terkadang mulai bertingkat, selama bertahun-tahun. Serialisasi data misalnya. rantai: objek ke byte yang didorong oleh jenis (mungkin melalui json atau ...) harus dibangun agar tahan waktu. Berpikir tentang pembuatan versi semantik dan api web mungkin juga dihitung.
Bisakah kami mengharapkan serialisasi untuk data pengguna tetap dekat dengan https://github.com/JuliaLang/julia/blob/v0.5.1/base/serialize.jl ?
Mengapa fungsi membuat salinan tidak perlu? Dari mana Anda mendapat kesan bahwa mereka mungkin?
Saya tidak tahu apakah mereka melakukannya atau tidak. Sejauh yang saya tahu, perilaku itu tidak ditentukan. Dari komentar @JeffBezanson , ada orang yang menganjurkan membuat salinan defensif, yang dia lawan. Jadi dokumentasi harus menjawab pertanyaan tentang salinan defensif di suatu tempat.
Anda tampaknya menyiratkan semacam prinsip tindakan terkecil, tetapi bergantung pada detail algoritme, apa yang dimaksud dengan "tindakan terkecil" menjadi ambigu. Untuk mendapatkan konsistensi di seluruh API, saya rasa diperlukan panduan yang lebih spesifik.
@ o314 : ini adalah masalah tinjauan konsistensi API, saya tidak yakin bagaimana hubungan serialisasi.
@ JaredCrean2 : apakah objek tingkat atas disalin atau tidak tentu perlu didokumentasikan. Apa yang saya katakan adalah bahwa objek yang lebih dalam tidak pernah disalin, kecuali dengan deepcopy (jelas).
Apa yang saya katakan adalah bahwa objek yang lebih dalam tidak pernah disalin, kecuali dengan deepcopy (jelas).
Baru-baru ini ada diskusi tentang ini dalam konteks copy
untuk beberapa pembungkus array, misalnya SubArray
dan SparseMatrixCSC
tetapi juga Symmetric
, LowerTriangular
. Menurut saya, di bawah kebijakan yang disebutkan di atas, copy
akan menjadi noop untuk jenis pembungkus seperti itu. Apakah kebijakan yang Anda sebutkan merupakan tingkat abstraksi yang tepat di sini? Misalnya, saya pikir ini menyiratkan bahwa jika Array
s diimplementasikan di Julia (membungkus buffer), perilaku copy
pada Array
s kemudian harus berubah menjadi noop.
Jika konvensi adalah bahwa objek yang lebih dalam tidak pernah disalin, maka yang tersisa hanyalah mendokumentasikannya. Dokumentasi adalah bagian yang sangat penting dari API. Perilaku ini mungkin tampak jelas bagi Anda (mungkin karena Anda menulis bagian-bagian kode), tetapi dari sudut pandang luar, perilaku ini tidak begitu jelas.
Edit: tidak melihat kiriman Andreas. Itu pertimbangan yang menarik.
@StefanKarpinski Saya setuju dengan maksud Anda.
Dan semua topik utama yang dibahas di sini sangat bagus dan cerdas.
Tetapi terkadang saya sedikit takut tentang keseimbangan antara proses dan data di Julia:
Kita bisa memanggil fortran atau c dengan mudah pasti,
Tetapi kode akan disebarkan dengan mudah di pusat data modern, misalnya. aws lambda dengan fungsinya sebagai pola layanan. akankah kode dapat dengan mudah dipanggil melalui internet, api terbuka?
Kadang-kadang seseorang harus menurunkan beban fungsional ke skala (tidak ada generik, tidak ada vaarg pada tanda tangan fungsi, tidak ada perintah tinggi pada api publik) dan mengikat lebih sistematis data di belakang (skema json / openapi).
Saya telah melihat beberapa perpustakaan python yang sangat bagus tenggelam dengan cara ini dan itu sangat disayangkan.
Saya pikir itu adalah poin penting bagi bahasa 1.0 untuk menjaga data dan fungsi tetap seimbang dan modular agar dapat dengan mudah diterapkan di web. Dan untuk fungsi antarmuka ini harus lebih sedikit hewan peliharaan dan lebih berorientasi pada ternak saat dibutuhkan.
Mungkin bukan itu intinya dalam topik ini.
@StefanKarpinski Saya mungkin telah salah paham tentang kiriman Anda. Saat kamu berkata
apakah objek tingkat atas disalin atau tidak tentu perlu didokumentasikan
apa artinya "objek tingkat atas"? Jika saya memiliki x::Vector{MyMutableType}
, apakah objek tingkat atas x
atau elemen x
?
Objek tingkat atas mengacu pada x
itu sendiri, bukan elemen x
.
@andreasnoack Gagasan tentang objek tingkat atas harus mengacu pada struktur abstrak yang diimplementasikan, bukan detail implementasi.
mungkin menambahkan float
dan fungsi serupa lainnya yang berfungsi pada tipe vs nilai?
Melihat catatan rilis 0.6, tampaknya aneh bahwa iszero(A::Array{T})
diperkenalkan, sementara banyak fungsi lainnya (misalnya sumabs
, isinteger
, isnumber
) melalui array tidak lagi digunakan untuk mendukung all(f,A)
.
Ada nol array, dan mereka adalah elemen nol dalam ruang vektornya. iszero
secara umum menguji apakah sesuatu adalah invers aditif, yang mana nol array.
Kembali. konsistensi garis bawah dalam nama fungsi, berikut adalah catatan singkat untuk count_ones
dan count_zeros
.
Menurut saya, jika Anda ingin menjaga API Julia tetap konsisten, Anda perlu memiliki beberapa perangkat lunak yang memungkinkan Anda (a) menentukan aturan / konvensi API, (b) melakukan analisis statis kode Julia untuk mendeteksi penyimpangan dari aturan / konvensi tersebut, dan (c) menawarkan saran. Alat seperti itu akan menguntungkan Julia Base dan semua Paket Julia. Paket Julia baru dapat membantu. (Lidah di pipi: hal pertama yang harus dilakukan paket ini adalah menyarankan namanya sendiri; APICheck.jl, ApiCheck.jl, API_Check.jl, APIChecker.jl, JuliaAPIChecker.jl, dll.) Saya agak baru mengenal Julia, jadi tidak ingin memimpin dalam hal seperti itu. Namun, saya tidak keberatan berkontribusi. Ada saran tentang cara menjalankannya?
Kami akan senang memilikinya di Lint.jl!
num2hex
dan hex2num
(# 22031 dan # 22088)
Saya juga percaya bahwa Lint.jl adalah paket yang tepat untuk pemeriksaan konsistensi API Julia. Tetapi jika kita menempuh jalan itu, daftar asli Stefan harus dibuat lebih tepat. Misalnya ketika dia menulis "kita harus memastikan bahwa semua koleksi di DataStructures memiliki API yang konsisten", pertanyaan yang muncul di benaknya adalah:
Untuk mengelola inventaris dan analisis seperti itu, kita mungkin ingin menambahkan proyek ke repositori Julia (proyek # 8), atau ke repositori JuliaPraxis (disarankan offline oleh TotalVerb) atau ke repositori Lint. Dalam hal ini kita perlu memilah siapa yang akan memiliki proyek semacam itu, orang mana yang harus dilibatkan sejak awal, dan siapa yang harus membuat keputusan akhir tentang apa sebenarnya konvensi Julia (untuk tujuan linting).
Tetapi sebelum melangkah lebih jauh ke arah ini, saya ingin bertanya kepada
Saya setuju bahwa menjelaskan hal ini secara spesifik adalah ide yang bagus. Mencari tahu daftar apa yang seharusnya menjadi bagian dari pekerjaan di sini - jika Anda ingin menerobosnya, itu akan bagus.
Apakah kita benar-benar membutuhkan Base.datatype_module dan Base.function_module?
Sebuah fungsi "modul" terpadu (mungkin getmodule) yang dikirimkan pada tipe data dan fungsi tampaknya lebih konsisten bagi saya.
Bagaimana dengan garis bawah di @code_typed
dan teman-teman?
Itu kesempatan bagus untuk refactoring (alasan yang dinyatakan untuk larangan garis bawah). Anda dapat memiliki makro @code
dengan argumen pertama adalah jenis kode yang Anda inginkan.
( @bramtayl , harap ingat untuk meletakkan backtick di sekitar makro karena ini mem-ping "kode" pengguna github jika tidak; @code
)
FWIW, penyelesaian tab hanya berfungsi dengan nama fungsi. Mampu melakukan @code_<TAB>
itu bagus ....
Jika refactoring dianggap tetapi ditolak, maka ada atau tidaknya garis bawah masih diperdebatkan, karena satu-satunya poin dari larangan garis bawah adalah untuk mendorong refactoring. Faktanya, dalam hal ini, sepertinya garis bawah harus didorong untuk membuat bahasanya lebih jelas
Audit garis bawah.
kontra-proposal: kami masih mengaudit nama-nama ini, tetapi kami malah menambahkan lebih banyak garis bawah yang akan membuat kode lebih mudah dibaca (codetyped vs code_typed, isos2 vs is_os2).
Saya tidak absolut tentang ini. Saya pikir code_typed
baik-baik saja, tab-complete yang berguna seperti yang ditunjukkan @KristofferC , dan sebenarnya tidak ada sesuatu yang jelas untuk dilewatkan sebagai argumen untuk memilih output mana yang Anda inginkan.
Bagi saya sepertinya kapal telah berlayar dengan menambahkan lebih banyak garis bawah, karena pada dasarnya kami harus menghilangkan setengah dari Base. Sebagai contoh, ada 74 fungsi predikat yang dimulai dengan is
dan hanya 6 yang dimulai dengan is_
. Mana yang lebih masuk akal, mencela 6 atau 74?
Oke, ada beberapa tujuan yang saling bertentangan di sini:
1) Membuat nama lebih mudah dibaca
2) Mengurangi churn kode
3) Mendorong refactoring
Menghilangkan garis bawah dengan bertabrakan kata gagal di semua 3 front.
Metode show
yang menerima aliran tidak !
-terminated tampaknya tidak sesuai dengan ketentuan biasa? Ref. https://github.com/JuliaLang/julia/pull/22604/commits/db9d70a279763ded5088016d9c3d4439a49e3fca#r125115063. Terbaik! (Edit: Saya kira ini cocok dengan metode write
yang menerima aliran.)
Ada ketidakkonsistenan dengan API sifat. Beberapa sifat dihitung dengan menyebut sifat seperti
TypeArithmetic(Float64)
sementara yang lain fungsi ini harus dieja dengan huruf kecil:
iteratorsize(Vector{Float64})
Pertimbangkan untuk mengganti nama size
-> shape
(xref # 22665)
Array{T,1}()
mungkin juga harus dihentikan:
julia> Array{Int,1}()
0-element Array{Int64,1}
julia> Array{Int,2}()
WARNING: Matrix{T}() is deprecated, use Matrix{T}(0, 0) instead.
Telah memikirkan tentang koleksi. Kami pada dasarnya memiliki tiga jenis:
k=>v
pairs.Saya menjadi skeptis dengan perilaku seperti dikt. Burung kenari di tambang batu bara adalah map
, yang beroperasi pada pasangan nilai-kunci tidaklah alami, karena Anda biasanya tidak ingin mengubah kumpulan kunci. Ini juga memungkinkan untuk array dan dicts untuk mengimplementasikan antarmuka yang sama:
keys
sesuai dengan eachindex
mapindexed
dan filterindexed
akan berguna untuk dicts dan array. Ini seperti peta dan filter kecuali juga meneruskan fungsi Anda indeks item yang dimaksud.pairs
, yang pada dasarnya merupakan jalan pintas untuk zip(keys(c), values(c))
.Pertimbangkan untuk mengganti nama ind2sub
dan sub2ind
, yang tampaknya matlabisme, dan yang memiliki nama non-julian dan aneh untuk pengguna non-matlab. Nama yang memungkinkan adalah indice
dan linearindice
. Saya tidak berani membuat PR karena saya tidak yakin apa yang orang pikirkan tentang itu, tapi akan lakukan jika ada dukungan.
Hal yang sama dengan rad2deg
dan deg2rad
.
Ref. # 22791 ( select
-> partialsort
). Terbaik!
Satu hal yang belum saya lihat di sini: apakah argumen posisi opsional masuk pertama atau terakhir? Terkadang argumen posisi opsional ditempatkan lebih dulu, seperti dalam sum(f, itr)
dan rand([rng,] ..)
. Tapi di tempat lain mereka pergi terakhir, misalnya median(v[, region])
atau split(s::AbstractString[, chars])
. Terkadang mereka bisa pergi dulu atau terakhir, tapi tidak keduanya! (Misalnya, mean
dapat mengambil fungsi terlebih dahulu atau dimensi terakhir, tetapi tidak keduanya.)
Semantik bahasa saat ini memaksa argumen opsional untuk menjadi yang terakhir: Anda dapat menulis f(a, b=1)
tetapi tidak f(b=1, a)
. Tetapi jika semua argumen opsional bertahan, apa yang terjadi pada blok do yang nyaman?
Jika tidak ada yang lain, itu adalah kutukan kecil bahwa bahasa harus mendefinisikan metode seperti itu, dari rand.jl
: shuffle!(a::AbstractVector) = shuffle!(GLOBAL_RNG, a)
. Sintaks argumen posisi opsional harus menangani kasus penggunaan ini dengan tepat.
Mungkin harus masuk ke masalah terpisah, tetapi tampaknya mungkin untuk memindahkan argumen opsional di mana pun Anda mau. Jadi misalnya, f(a = 1, b, c = 2)
akan menentukan f(x) = f(1, x, 2)
dan f(x, y) = f(x, y, 2)
xref # 22460 untuk upaya (tidak populer) dalam mengaktifkan argumen default di posisi mana pun.
Mungkin mengganti nama warn
menjadi warning
(matlab juga menggunakan ini), bukan masalah besar, tapi saya pikir saya akan menyebutkan?
Saya suka warn
karena ini kata kerja, seperti throw
.
Saya sangat bingung dengan ini:
julia> f(;a=1,b=1) = a+b
f (generic function with 1 method)
julia> f(a=4,5) # I intended to write f(a=4,b=5)
ERROR: MethodError: no method matching f(::Int64; a=4)
Closest candidates are:
f(; a, b) at REPL[13]:1
Saya sarankan hanya mengizinkan kata kunci terakhir saat memanggil fungsi, mirip dengan saat menentukan fungsi kata kunci.
Saya sarankan hanya mengizinkan kata kunci terakhir saat memanggil fungsi, mirip dengan saat menentukan fungsi kata kunci.
Ada banyak API yang memasukkan kata kunci di posisi lain berguna dan ergonomis.
Karena penasaran, apakah ada urutan evaluasi yang ditentukan untuk argumen posisi dan kata kunci? Saya melihat beberapa masalah lama dan https://docs.julialang.org/en/latest/manual/functions/#Evaluation -Scope-of-Default-Values-1 berbicara tentang cakupan, tetapi tidak ada yang saya temukan yang menyatakan apakah misalnya argumen dievaluasi dari kiri ke kanan, atau semua argumen posisi dievaluasi sebelum semua argumen kata kunci, atau jika tidak ada urutan evaluasi yang ditentukan (atau yang lainnya).
Tampaknya tidak sepadan dengan masalahnya sendiri, tetapi selalu tampak aneh bagi saya bahwa bits(1)
mengembalikan String
, sepertinya seharusnya BitVector
atau Vector{Bool}
.
Saya ingin menyarankan tinjauan tabel metode yang mengirimkan Function
atau Callable
. Mari kita coba memastikan API ini sesuai dengan yang kita inginkan… dan bahwa kita tidak melewatkan kesempatan untuk memungkinkan restrukturisasi tabel sedemikian rupa sehingga kita dapat mengizinkan objek apa pun.
Adapun all
dan any
, yang tampaknya langsung tidak berlaku lagi menjadi all(f(x) for x in xs)
, yang sudah dikurangi eta menjadi all(Generator(f, xs))
dan seharusnya tidak ada overhead.
Tidak yakin apakah itu yang Anda maksud, tapi saya pikir itu layak menyatakan hanya dalam kasus: Saya hardcore terhadap mencela setiap fungsional-gaya API untuk generator. Kami memiliki any(f, x)
dan all(f, x)
dan banyak digunakan; -10000000 untuk menghapusnya (atau metode lainnya, sungguh).
Saya generator pro. Tampak seperti blok bangunan fundamental dari program lazy dan harus diekspor. all(Generator(f, xs))
terkadang lebih nyaman untuk fungsi yang ditentukan daripada all(f(x) for x in xs)
. Juga +10000000 untuk mengembalikan saldo
Saya lebih suka memiliki lebih sedikit sintaks di sini jika memungkinkan. Jika mudah dan terbaca dan berhasil untuk mengekspresikan gagasan "ambil xs, terapkan f untuk semuanya, dan kembalikan benar jika semua itu benar", lalu mengapa kita harus memasukkannya ke dalam satu kata kerja?
Jika yang menjadi perhatian adalah kata benda yang tidak perlu x
di f(x) for x in xs
, maka saran @bramtayl untuk mengekspor Generator
(mungkin menggunakan nama yang lebih baik seperti Map
?) masuk akal.
Hal-hal seperti all(isnull, x)
cukup sederhana daripada all(isnull(v) for v in x)
. Kami telah menghentikan fungsi allnull
dari NullableArrays dan menggantikan all(isnull, x)
; jika sintaks itu hilang, kami mungkin harus memperkenalkannya kembali.
Bagaimana dengan mengganti nama strwidth
menjadi stringwidth
(Saya pikir ini adalah satu-satunya fungsi manipulasi string yang diekspor yang telah menyingkat string menjadi str)
Sebenarnya sudah diganti namanya menjadi textwidth
(https://github.com/JuliaLang/julia/pull/23667).
IMO, masalah ini terlalu luas untuk memiliki pencapaian 1.0, mengingat kami ingin segera mendapatkan fitur yang dibekukan. Kami mungkin memerlukan banyak pemilik dan menetapkan serangkaian fungsi untuk ditinjau jika kami ingin melakukan ini.
Selain itu, ini adalah tempat lain di mana FemtoCleaner dapat memperbarui banyak hal secara otomatis dari postingan 1.0, meskipun akan menyenangkan jika semuanya baik-baik saja.
hanya komentar tentang lebar teks:
INFO: Testing Cairo
Test Summary: | Pass Total
Image Surface | 7 7
Test Summary: | Pass Total
Conversions | 4 4
Test Summary: | Pass Total
TexLexer | 1 1
WARNING: both Compat and Cairo export "textwidth"; uses of it in module Main must be qualified
Samples : Error During Test
Got an exception of type LoadError outside of a <strong i="6">@test</strong>
LoadError: UndefVarError: textwidth not defined
Stacktrace:
[1] include_from_node1(::String) at .\loading.jl:576
[2] include(::String) at .\sysimg.jl:14
[3] macro expansion at C:\Users\appveyor\.julia\v0.6\Cairo\test\runtests.jl:86 [inlined]
[4] macro expansion at .\test.jl:860 [inlined]
[5] anonymous at .\<missing>:?
[6] include_from_node1(::String) at .\loading.jl:576
[7] include(::String) at .\sysimg.jl:14
[8] process_options(::Base.JLOptions) at .\client.jl:305
[9] _start() at .\client.jl:371
while loading C:\Users\appveyor\.julia\v0.6\Cairo\samples\sample_pango_text.jl, in expression starting on line 28
Pesan kesalahan tampaknya cukup jelas tentang apa masalahnya? Cairo
perlu memperluas metode dasar.
help?> Base.textwidth
No documentation found.
Binding Base.textwidth does not exist.
julia> versioninfo()
Julia Version 0.6.0
julia> Compat.textwidth
textwidth (generic function with 2 methods)
saya tidak ragu bahwa pesan (yang saya dapatkan melalui travis) tidak apa-apa, tetapi mengapa Compat mengekspor textwidth jika tidak dalam 0,6?
Karena itulah inti dari Compat? Diskusi ini terlalu banyak di luar ruang lingkup jadi saya sarankan kita bisa melanjutkannya pada wacana atau kendur.
Saya sarankan untuk mengubah copy
menjadi shallowcopy
dan deepcopy
menjadi copy
karena baru-baru ini saya perlu waktu cukup lama untuk menyadari bahwa salinan adalah salinan yang "dangkal" dan Fungsi yang saya tulis adalah memutasikan array array. Saya pikir akan jauh lebih intuitif jika copy
akan melakukan salinan "dalam" dan sesuatu seperti shallowcopy
digunakan untuk salinan dangkal? Saya tahu sekarang kapan harus menggunakan deepcopy
, tetapi saya pikir banyak pengguna lain akan mengalami masalah yang sama.
Mari kita coba pertahankan masalah ini demi konsistensi API, bukan tas "khusus yang tidak saya sukai".
Associative
nama tampaknya cukup konsisten dengan semua nama jenis lain di Julia.
Pertama, tipe biasanya bukan kata sifat. Kata benda adalah Association
, dan digunakan setidaknya oleh beberapa dokumen Mathematica yang saya temukan.
Saya pikir AbstractDict
akan jauh lebih konsisten dengan jenis lain seperti AbstractArray
, AbstractRange
, AbstractSet
dan AbstractString
, yang masing-masing memiliki jenis beton prototipe Dict
, Array
, Range
, Set
dan String
.
Jenis pengecualian kami ada di semua tempat: beberapa diberi nama FooError
, yang lain diberi nama BarException
; beberapa diekspor, sebagian besar tidak. Ini bisa menggunakan umpan untuk konsistensi.
Jadi apa yang lebih disukai, FooError
atau BarException
? Diekspor atau tidak?
Bagi saya, BarException
melibatkan suatu pola peningkatan / penangkapan.
Saya lebih suka banyak, dan beberapa lainnya di dunia fungsional juga, gunakan pola Some
/ None
(*) di mana aliran kontrol lebih langsung dan dapat diprediksi.
Jadi +1 untuk FooError
(*) Some
/ Void
ex Optional
di Julia # 23642.
Apakah hal-hal ini masih di atas meja mengingat fitur pembekuan? Saya terutama ingin menangani argumen opsional vs. kata kunci, tetapi daftar fungsi dengan beberapa argumen opsional (kasus paling jelas untuk menggunakan argumen kata kunci sebagai gantinya) cukup panjang.
Silakan lihat! Saya belum mendapat kesempatan untuk membahas masalah ini secara sistematis.
BTW, saya telah mencatat ketidakkonsistenan dalam penamaan ciri: kita memiliki iteratorsize
, iteratoreltype
, tetapi IndexStyle
, TypeRangeStep
, TypeArithmetic
dan TypeOrder
. Sepertinya varian CamelCase lebih banyak dan lebih baru, jadi mungkin kita harus mengadopsi konvensi itu di mana-mana?
Itu pasti harus dibuat konsisten. Apakah Anda ingin membuat PR?
Saya pikir ini harus diperbaiki sebagai bagian dari https://github.com/JuliaLang/julia/pull/25356.
EDIT: lihat juga https://github.com/JuliaLang/julia/issues/25440
Ini sebagian besar dilakukan atau dapat dilakukan dalam rilis 1.x. Saya dapat memperbarui kotak centang, tetapi kami baru saja memeriksanya pada panggilan triase dan semuanya kecuali # 25395 dan audit garis bawah selesai.
Berikut ini adalah analisis dari semua simbol yang diekspor dari Base yang berisi garis bawah, tidak digunakan lagi, dan bukan makro string. Hal utama yang perlu diperhatikan di sini adalah bahwa ini hanya nama yang diekspor; ini tidak termasuk nama yang tidak diekspor yang kami beri tahu orang-orang untuk menyebutnya memenuhi syarat.
Saya telah memisahkan hal-hal berdasarkan kategori. Semoga lebih bermanfaat daripada mengganggu.
Kami memiliki makro berikut dengan fungsi yang sesuai:
@code_llvm
, code_llvm
@code_lowered
, code_lowered
@code_native
, code_native
@code_typed
, code_typed
@code_warntype
, code_warntype
Perubahan apa pun yang diterapkan ke makro, jika ada, harus diterapkan dengan cara yang sama ke fungsi.
module_name
-> nameof
(# 25622)module_parent
-> parentmodule
(# 25629, lihat # 25436 untuk upaya sebelumnya dalam mengganti nama)method_exists
-> hasmethod
(# 25615)object_id
-> objectid
(# 25615)pointer_from_objref
pointer_from_objref
mungkin bisa dilakukan dengan nama yang lebih deskriptif, mungkin sesuatu seperti address
?
Jenis alias yang mengandung garis bawah adalah C_NULL
, Cintmax_t
, Cptrdiff_t
, Csize_t
, Cssize_t
, Cuintmax_t
, dan Cwchar_t
. Yang diakhiri dengan _t
harus tetap, karena mereka dinamai sesuai dengan tipe C yang sesuai.
C_NULL
adalah yang aneh di sini, menjadi satu-satunya alias C yang berisi garis bawah yang tidak dicerminkan di C (karena di C ini hanya NULL
). Kami dapat mempertimbangkan untuk menyebut ini CNULL
.
C_NULL
count_ones
count_zeros
trailing_ones
trailing_zeros
leading_ones
leading_zeros
Untuk diskusi tentang mengganti nama ini, lihat # 23531. Saya sangat menyukai menghapus garis bawah untuk ini, serta beberapa penggantian yang diusulkan dalam PR itu. Saya pikir itu harus dipertimbangkan kembali.
unsafe_copyto!
unsafe_load
unsafe_pointer_to_objref
unsafe_read
unsafe_store!
unsafe_string
unsafe_trunc
unsafe_wrap
unsafe_write
Mungkin tidak masalah untuk menyimpan ini sebagaimana adanya; keburukan garis bawah semakin menggarisbawahi ketidakamanan mereka.
broadcast_getindex
broadcast_setindex!
to_indices
Ternyata ada broadcast_getindex
dan broadcast_setindex!
. Saya tidak mengerti apa yang mereka lakukan. Mungkin mereka bisa menggunakan nama yang lebih deskriptif?
Menariknya, versi indeks tunggal to_indices
, Base.to_index
, tidak diekspor.
catch_backtrace
catch_stacktrace
-> stacktrace(catch_backtrace())
(# 25615)Agaknya ini adalah catch
blok ekivalen backtrace
dan stacktrace
, masing-masing.
current_task
task_local_storage
disable_sigint
reenable_sigint
process_exited
process_running
redirect_stderr
redirect_stdin
redirect_stdout
nb_available
-> bytesavailable
(# 25634)Alangkah baiknya memiliki fungsi redirection IO
-> IO
lebih umum di mana semua ini dapat digabungkan, misalnya redirect(STDOUT, io)
, sehingga menghapus garis bawah dan ekspor.
promote_rule
promote_shape
promote_type
Lihat # 23999 untuk diskusi yang relevan tentang promote_rule
.
print_with_color
-> printstyled
(lihat # 25522)print_shortest
(lihat # 25745)escape_string
(lihat # 25620)unescape_string
escape_string
dan unescape_string
agak aneh karena mereka dapat mencetak ke aliran atau mengembalikan string. Lihat # 25620 untuk proposal untuk memindahkan / mengganti namanya.
include_dependency
include_string
include_dependency
. Apakah ini bahkan digunakan di luar Base? Saya tidak dapat memikirkan situasi di mana Anda menginginkan ini daripada include
dalam skenario tipikal.
include_string
. Bukankah ini hanya versi resmi dari eval(parse())
?
gc_enable
-> GC.enable
(# 25616)get_zero_subnormals
set_zero_subnormals
time_ns
get_zero_subnormals
dan set_zero_subnormals
dapat dilakukan dengan nama yang lebih deskriptif. Apakah perlu diekspor?
+1 untuk method_exists => methodexists
dan object_id => objectid
. Ini juga agak konyol bahwa catch_stacktrace
bahkan ada. Ini bisa tidak berlaku lagi pada definisinya, stacktrace(catch_backtrace())
.
Bagaimana perasaan kami tentang menghilangkan garis bawah C_NULL
? Saya sudah cukup terbiasa dengannya, tetapi saya juga membeli argumen bahwa tidak ada nama C*
lainnya yang memiliki garis bawah.
Nama C lainnya adalah tipe, sedangkan C_NULL
adalah konstanta. Saya pikir itu bagus bagaimana itu dan mengikuti pedoman penamaan.
dan mengikuti pedoman penamaan.
Bagaimana?
Konstanta sering kali berupa huruf besar semua dengan garis bawah - C_NULL
mengikuti itu. Seperti yang dikatakan @ iamed2 , ini adalah nilai, bukan tipe, jadi konvensi penamaan Cfoo
tidak selalu berlaku.
Saya keliru mengira https://github.com/JuliaLang/julia/blob/master/doc/src/manual/variables.md#stylistic -conventions mereferensikan konstanta tetapi ternyata tidak. Mungkin seharusnya begitu.
Saya menyarankan antarmuka yang konsisten, suara matematis, untuk ruang Hilbert umum di mana vektor bukan Julia Array. Nama fungsi seperti vecdot
, vecnorm
, dll. Bisa juga diganti dengan konsep umum inner
dan norm
seperti yang dibahas di https: // github. com / JuliaLang / julia / issues / 25565.
Seperti yang telah saya katakan beberapa kali, ini bukanlah masalah umum untuk hal-hal yang ingin diubah.
Saya yakin item yang tersisa di bawah payung ini untuk 1.0 adalah # 25501 dan # 25717.
Saya ingin melakukan sesuatu dengan (get|set)_zero_subnormals
tetapi mungkin solusi jangka pendek terbaik adalah dengan melepasnya saja.
Sesuatu yang mungkin harus ditinjau adalah bagaimana angka diperlakukan dalam konteks operasi pengumpulan seperti map
dan collect
. Telah ditunjukkan bahwa yang pertama mengembalikan skalar tetapi yang terakhir mengembalikan larik 0D.
Komentar yang paling membantu
Audit garis bawah
Berikut ini adalah analisis dari semua simbol yang diekspor dari Base yang berisi garis bawah, tidak digunakan lagi, dan bukan makro string. Hal utama yang perlu diperhatikan di sini adalah bahwa ini hanya nama yang diekspor; ini tidak termasuk nama yang tidak diekspor yang kami beri tahu orang-orang untuk menyebutnya memenuhi syarat.
Saya telah memisahkan hal-hal berdasarkan kategori. Semoga lebih bermanfaat daripada mengganggu.
Refleksi
Kami memiliki makro berikut dengan fungsi yang sesuai:
@code_llvm
,code_llvm
@code_lowered
,code_lowered
@code_native
,code_native
@code_typed
,code_typed
@code_warntype
,code_warntype
Perubahan apa pun yang diterapkan ke makro, jika ada, harus diterapkan dengan cara yang sama ke fungsi.
module_name
->nameof
(# 25622)module_parent
->parentmodule
(# 25629, lihat # 25436 untuk upaya sebelumnya dalam mengganti nama)method_exists
->hasmethod
(# 25615)object_id
->objectid
(# 25615)pointer_from_objref
pointer_from_objref
mungkin bisa dilakukan dengan nama yang lebih deskriptif, mungkin sesuatu sepertiaddress
?Alias untuk interop C.
Jenis alias yang mengandung garis bawah adalah
C_NULL
,Cintmax_t
,Cptrdiff_t
,Csize_t
,Cssize_t
,Cuintmax_t
, danCwchar_t
. Yang diakhiri dengan_t
harus tetap, karena mereka dinamai sesuai dengan tipe C yang sesuai.C_NULL
adalah yang aneh di sini, menjadi satu-satunya alias C yang berisi garis bawah yang tidak dicerminkan di C (karena di C ini hanyaNULL
). Kami dapat mempertimbangkan untuk menyebut iniCNULL
.C_NULL
Sedikit menghitung
count_ones
count_zeros
trailing_ones
trailing_zeros
leading_ones
leading_zeros
Untuk diskusi tentang mengganti nama ini, lihat # 23531. Saya sangat menyukai menghapus garis bawah untuk ini, serta beberapa penggantian yang diusulkan dalam PR itu. Saya pikir itu harus dipertimbangkan kembali.
Operasi yang tidak aman
unsafe_copyto!
unsafe_load
unsafe_pointer_to_objref
unsafe_read
unsafe_store!
unsafe_string
unsafe_trunc
unsafe_wrap
unsafe_write
Mungkin tidak masalah untuk menyimpan ini sebagaimana adanya; keburukan garis bawah semakin menggarisbawahi ketidakamanan mereka.
Pengindeksan
broadcast_getindex
broadcast_setindex!
to_indices
Ternyata ada
broadcast_getindex
danbroadcast_setindex!
. Saya tidak mengerti apa yang mereka lakukan. Mungkin mereka bisa menggunakan nama yang lebih deskriptif?Menariknya, versi indeks tunggal
to_indices
,Base.to_index
, tidak diekspor.Jejak
catch_backtrace
catch_stacktrace
->stacktrace(catch_backtrace())
(# 25615)Agaknya ini adalah
catch
blok ekivalenbacktrace
danstacktrace
, masing-masing.Tugas, proses, dan sinyal
current_task
task_local_storage
disable_sigint
reenable_sigint
process_exited
process_running
Aliran
redirect_stderr
redirect_stdin
redirect_stdout
nb_available
->bytesavailable
(# 25634)Alangkah baiknya memiliki fungsi redirection
IO
->IO
lebih umum di mana semua ini dapat digabungkan, misalnyaredirect(STDOUT, io)
, sehingga menghapus garis bawah dan ekspor.Promosi
promote_rule
promote_shape
promote_type
Lihat # 23999 untuk diskusi yang relevan tentang
promote_rule
.Pencetakan
print_with_color
->printstyled
(lihat # 25522)print_shortest
(lihat # 25745)escape_string
(lihat # 25620)unescape_string
escape_string
danunescape_string
agak aneh karena mereka dapat mencetak ke aliran atau mengembalikan string. Lihat # 25620 untuk proposal untuk memindahkan / mengganti namanya.Pemuatan kode
include_dependency
include_string
include_dependency
. Apakah ini bahkan digunakan di luar Base? Saya tidak dapat memikirkan situasi di mana Anda menginginkan ini daripadainclude
dalam skenario tipikal.include_string
. Bukankah ini hanya versi resmi darieval(parse())
?Hal-hal yang tidak perlu saya kategorikan
gc_enable
->GC.enable
(# 25616)get_zero_subnormals
set_zero_subnormals
time_ns
get_zero_subnormals
danset_zero_subnormals
dapat dilakukan dengan nama yang lebih deskriptif. Apakah perlu diekspor?