Julia: tampilkan kode sumber fungsi dari repl

Dibuat pada 20 Mar 2013  ·  22Komentar  ·  Sumber: JuliaLang/julia

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.

REPL help wanted

Komentar yang paling membantu

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.

Semua 22 komentar

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

  • mendapatkan kode AST yang diturunkan sebelumnya yaitu sumber dari repl atau saat runtime
  • mendefinisikan ulang / menghapus variabel / jenis / fungsi / jenis

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

Apakah halaman ini membantu?
0 / 5 - 0 peringkat