Julia memiliki banyak REPL yang berguna seperti methods
dan help
.
Namun, saya tetap hanya perlu melihat kode untuk melihat apa yang dilakukannya.
Akan sangat menyenangkan bisa melakukan:
julia> methods(base)
# methods for generic function base
base(base::Integer,n::Integer,pad::Integer) at intfuncs.jl:290
base(symbols::Array{Uint8,N},n::Integer,p::Integer) at intfuncs.jl:291
base(base_or_symbols::Union(Integer,Array{Uint8,N}),n::Integer) at intfuncs.jl:292
julia> implementation(base,1)
base(base::Integer, n::Integer, pad::Integer) = _base(dig_syms,int(base),unsigned(abs(n)),pad,n<0)
julia> implementation(base,3)
base(base_or_symbols::Union(Integer,Array{Uint8}), n::Integer) = base(base_or_symbols, n, 1)
Ini seperti lompatan kode di beberapa IDE, tetapi di REPL, dan hanya menampilkan satu fungsi.
Ini jelas memiliki batasan, karena Anda tidak bisa hanya menggulir ke atas dan melihat implementasi _base
atau mencari definisi dig_syms
dalam file itu, tetapi itu memungkinkan Anda melihat apa nilai default adalah.
Anda sudah dapat melihat tanda tangan untuk _base
, yang membuat implementasi base
lebih bermakna. (tanpa perlu beralih dari REPL ke editor teks)
julia> methods(Base._base)
# methods for generic function _base
_base(symbols::Array{Uint8,N},b::Int32,x::Unsigned,pad::Int32,neg::Bool) at intfuncs.jl:278
Mengingat bahwa nomor baris / file sudah termasuk dalam output methods
, sepertinya mudah untuk mengambil baris kode yang sesuai dari file.
Jika kita menyimpan sumber (terkompresi) dari setiap definisi metode saat berjalan secara interaktif, ini dapat dilakukan dengan lebih mudah dan bekerja dengan benar bahkan ketika file sumber berubah dan bahkan ketika anotasi baris sumber tidak cukup sempurna. Itu juga akan membantu # 265 (lihat juga diskusi ini ) karena Anda dapat menggunakan sumber untuk mengkompilasi ulang sesuatu. Kami juga dapat menyimpan AST dalam bentuk terkompresi - enam vs. setengah lusin.
Tidak, itu tidak akan membantu dengan # 265. Kami sudah memiliki semua informasi, hanya saja tidak terlihat seperti kode sumber lagi. Jika Anda ingin melihat kode aslinya, cara terbaik adalah dengan membacanya dari file.
Setuju dengan @JeffBezanson dan ini akan menjadi penyimpangan dari R di mana mengetikkan fungsi tanpa tanda kurung akan menghilangkan kode sumber. Jika panjang sumber lebih dari beberapa baris, itu menjadi tidak dapat digunakan (tidak ada cara untuk menggulir keluaran afaik).
+1 dengan membaca dari file.
Perbaikan yang lebih baik https://github.com/JuliaLang/julia/issues/2594 , ini benar-benar membunuh pengguna windows ketika start
adalah perintah asli cmd
dan notepad
tidak dapat menyorot sintaks atau tampilkan / lompat ke nomor baris.
edit
benar-benar fungsi yang berguna, jika kita bisa memperbaikinya / membuatnya lebih baik.
Sekadar memahami, apakah perasaan di sini bahwa seharusnya tidak ada fungsi untuk menggemakan kode sumber metode, melainkan mengandalkan 'edit' untuk tujuan itu? Itu mungkin tidak berfungsi dengan baik dengan notebook web IPython yang berinteraksi dengan kernel Julia jarak jauh, karena saya pikir file tersebut akan terbuka di mesin kernel dan bukan di klien.
Untuk apa nilainya, dalam mode interaktif, saya ingin menyimpan kode sumber, daripada bergantung pada apa yang ada di file. Saya ingin dapat melihat kode sumber dari hal-hal yang dimasukkan melalui repl juga. Lihat juga # 3988.
dukungan pager # 6921 dapat meniadakan beberapa kekhawatiran tentang kegunaan ini.
Saya menemukan ini sangat nyaman di ipython (melalui func??
), meskipun - tidak seperti kasus julia - beberapa fungsi disembunyikan (misalnya fungsi built-in / cython).
Selain itu, <strong i="5">@less</strong> func(x)
melakukan hampir persis seperti yang diminta @astrieanna (dengan paging), tetapi bergantung pada $PAGER
eksternal.
<strong i="5">@less</strong> func(x)
tidak berfungsi untuk fungsi interaktif, tetapi itu tampaknya menjadi masalah yang harus diutarakan di edisi lain.
Jika dua fitur berikut tersedia
maka dimungkinkan untuk melakukan daftar kode waktu proses / traversal / manipulasi / generasi.
julia> q=:( function a(i::Int) ; return i+4 ; end ; b=4 ; println(a(b)) )
quote
function a(i::Int) # none, line 1:
return i + 4
end
begin
b = 4
println(a(b))
end
end
julia> function exprdescend(ex) ; if (isa(ex,Expr)) ; println("Descending Expr:",ex) ; println("head:",ex.head); println("args:",ex.args) ; println("type:",ex.typ) ; for i in ex.args ; exprdescend(i) ; end ; else ; println("*:",typeof(ex),":",ex) ; end ; end
// # ''try it ... long output''
sebagai tanggapan atas komentar: JeffBezanson mengomentari pada 20 Maret 2013
"Tidak, ini tidak akan membantu dengan # 265. Kami sudah memiliki semua informasi, hanya saja tidak terlihat seperti kode sumber lagi. Jika Anda ingin melihat kode aslinya, cara terbaik adalah dengan membacanya dari file . "
Jadi menurut Anda ini mungkin? Apa yang terjadi jika ada pernyataan include / require dan hal-hal lain?
// # str = read_whole_file_into_a_string(filename)
julia> str="for i in [1,2,3,4] ; println(i) ; end "
julia> s=parse(str)
:(for i = [1,2,3,4] # line 1:
println(i)
end)
julia> exprdescend(s)
Descending Expr:for i = [1,2,3,4] # line 1:
println(i)
end
head:for
args:{:(i = [1,2,3,4]),quote # line 1:
println(i)
end}
type:Any
Descending Expr:i = [1,2,3,4]
head:=
args:{:i,:([1,2,3,4])}
type:Any
*:Symbol:i
Descending Expr:[1,2,3,4]
head:vcat
args:{1,2,3,4}
type:Any
*:Int64:1
*:Int64:2
*:Int64:3
*:Int64:4
Descending Expr:begin # line 1:
println(i)
end
head:block
args:{:( # line 1:),:(println(i))}
type:Any
*:LineNumberNode: # line 1:
Descending Expr:println(i)
head:call
args:{:println,:i}
type:Any
*:Symbol:println
*:Symbol:i
@hgkamath Saya khawatir saya tidak mengerti pertanyaannya, tapi sepertinya lebih cocok untuk milis pengguna. Silakan baca bagian metaprogramming dan refleksi dari manual.
Kasus penggunaan lainnya adalah @generated
functions (dari https://groups.google.com/d/topic/julia-users/4pkWhcap1Zg/discussion).
Oh, apakah saya menyelesaikan ini di # 22007?
Semacam - Saya masih berpikir bahwa dalam mode REPL kita harus menyimpan sumber asli untuk fungsi tampilan.
Ada juga pertanyaan tentang menampilkan fungsi anonim, di mana alangkah baiknya dapat menampilkan AST asli.
julia> x -> x+1
(::#5) (generic function with 1 method)
tidak terlalu berguna. (Lihat juga ceramah .)
dalam mode REPL
pada dasarnya kami sudah melakukannya, itu hanya mengganggu untuk mengakses:
let h = Base.active_repl.interface.modes[1].hist,
replno = match(r"REPL\[(\d+)\]", $filename)
replno === nothing || h.history[h.start_idx + parse(Int, replno[1])]
end
"menjengkelkan untuk mengakses" == "tidak cukup berguna untuk dianggap diselesaikan"
Saya akui itu akan berguna. Saya sering men-debug dengan memodifikasi fungsi dalam dan menjalankan variasi berbeda dalam REPL berbeda untuk membandingkannya. Kadang-kadang saya kehilangan jejak REPL mana yang sesuai dengan variasi mana. Mencetak fungsi yang saat ini didefinisikan akan menyenangkan untuk dimiliki.
Kasus penggunaan di Yao disediakan oleh https://github.com/MasonProtter/LegibleLambdas.jl
Setiap blok memiliki argumen jumlah qubit, dan kami tidak ingin menulisnya berulang kali, sehingga dapat di-curried secara otomatis ketika Anda tidak memberi makan nomor ini, mis.
julia> using Yao
julia> control(2, 1=>X)
(n -> control(n, 2, 1 => X gate))
Jadi pengguna akan menyadari ini bukan blok, itu membutuhkan jumlah qubit ini untuk evaluasi lebih lanjut. Sebelum kita memiliki LegibleLambdas, cukup membingungkan hanya dengan angka seperti #42
. Ini juga terjadi pada Flux saat Pengoptimal mengembalikan lambda sebelumnya.
Tetapi ada banyak kasus sudut yang tidak dapat kami dukung di LegibleLambdas, alangkah baiknya, bahwa kami bisa langsung mendapatkan informasi ini di REPL dengan dukungan dari kompilator, bukan paket eksternal.
Bagi saya masih tampak menyimpang bahwa kami mendukung ini
julia> <strong i="6">@code_native</strong> 1 + 2
.section __TEXT,__text,regular,pure_instructions
; ┌ @ int.jl:53 within `+'
leaq (%rdi,%rsi), %rax
retq
; └
; ┌ @ int.jl:53 within `<invalid>'
nopw %cs:(%rax,%rax)
; └
dan ini
julia> <strong i="10">@code_llvm</strong> 1 + 2
; @ int.jl:53 within `+'
define i64 @"julia_+_13402"(i64, i64) {
top:
%2 = add i64 %1, %0
ret i64 %2
}
dan ini
julia> <strong i="14">@code_typed</strong> 1 + 2
CodeInfo(
1 ─ %1 = Base.add_int(x, y)::Int64
└── return %1
) => Int64
dan ini
julia> <strong i="18">@code_lowered</strong> 1 + 2
CodeInfo(
1 ─ %1 = Base.add_int(x, y)
└── return %1
)
tapi bukan ini
julia> <strong i="23">@code_source</strong> 1 + 2
ERROR: LoadError: UndefVarError: <strong i="24">@code_source</strong> not defined
in expression starting at REPL[23]:1
Kita dapat melakukan introspeksi pada semua versi yang mungkin berbeda dari sebuah metode kecuali yang setiap orang yang menggunakan Julia tahu cara membaca dan menulis. Saya akan menandai ini sebagai "bantuan ingin" untuk menunjukkan bahwa itu akan menjadi tambahan yang disambut baik untuk bahasa memiliki mode opsional di mana kita mengingat representasi sumber suatu fungsi. Ini bisa dihidupkan secara default dalam mode interaktif tetapi dimatikan secara default dalam mode non-interaktif.
Fungsionalitas serupa sekarang diterapkan oleh https://github.com/timholy/CodeTracking.jl , yang merupakan bagian dari Revise.jl. Saya memainkannya sedikit, dan meskipun tidak sempurna, ia bekerja lebih sering daripada tidak. Dokumentasi mengatakan jauh lebih baik bila juga menggunakan Revise.
Ini disarankan dalam diskusi ini .
Ini mungkin sangat bagus dalam kombinasi dengan diferensiasi otomatis (seperti https://github.com/FluxML/Zygote.jl), karena Anda kemudian dapat menampilkan turunan sebagai kode julia
Komentar yang paling membantu
Bagi saya masih tampak menyimpang bahwa kami mendukung ini
dan ini
dan ini
dan ini
tapi bukan ini
Kita dapat melakukan introspeksi pada semua versi yang mungkin berbeda dari sebuah metode kecuali yang setiap orang yang menggunakan Julia tahu cara membaca dan menulis. Saya akan menandai ini sebagai "bantuan ingin" untuk menunjukkan bahwa itu akan menjadi tambahan yang disambut baik untuk bahasa memiliki mode opsional di mana kita mengingat representasi sumber suatu fungsi. Ini bisa dihidupkan secara default dalam mode interaktif tetapi dimatikan secara default dalam mode non-interaktif.