Julia: replからの関数ソースコードを表示

作成日 2013年03月20日  ·  22コメント  ·  ソース: JuliaLang/julia

Juliaには、 methodshelpような便利なREPLがたくさんあります。
ただし、コードが何をしているのかを確認するために、コードを確認する必要があります。
次のことができるのは素晴らしいことです。

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)

これは、一部のIDEのコードへのジャンプのようなものですが、REPLであり、1つの関数のみを表示します。
上にスクロールして_baseの実装を確認したり、そのファイルでdig_symsの定義を検索したりすることはできないため、これには明らかに制限がありますが、デフォルト値を確認することはできます。です。

_baseの署名はすでに確認できます。これにより、 baseの実装がより意味のあるものになります。 (REPLからテキストエディタに切り替える必要はありません)

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

行番号/ファイルがすでにmethodsの出力に含まれていることを考えると、ファイルから適切なコード行を取得するのは簡単なようです。

REPL help wanted

最も参考になるコメント

私たちがこれを支持していることはまだ私にはひねくれているようです

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)
; └

この

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
}

この

julia> <strong i="14">@code_typed</strong> 1 + 2
CodeInfo(
1 ─ %1 = Base.add_int(x, y)::Int64
└──      return %1
) => Int64

この

julia> <strong i="18">@code_lowered</strong> 1 + 2
CodeInfo(
1 ─ %1 = Base.add_int(x, y)
└──      return %1
)

しかしこれで

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

Juliaを使用するすべての人が読み取りと書き込みの方法を知っているものを除いて、メソッドのすべての異なる可能なバージョンを内省することができます。 これを「ヘルプ募集」としてマークして、関数のソース表現を記憶するオプションのモードを言語に追加することを歓迎することを示します。 インタラクティブモードではデフォルトでオンにできますが、非インタラクティブモードではデフォルトでオフになります。

全てのコメント22件

インタラクティブに実行するときに各メソッド定義のソース(圧縮)を保存すると、ソースファイルが変更された場合や、ソース行の注釈が完全ではない場合でも、これはかなり簡単に実行でき、正しく機能します。 ソースを使用して再コンパイルできるので、これは#265(

いいえ、#265では役に立ちません。 私たちはすでにすべての情報を持っています、それはもはやソースコードのようには見えません。 元のコードを見たい場合は、ファイルから読み取るのが最善の方法です。

@JeffBezansonに同意しなしで関数を入力するとソースコードが表示されるRからの逸脱になります。 ソースの長さが数行を超えると、使用できなくなります(出力afaikをスクロールする方法はありません)。

ファイルからの読み取りで+1。
より良い修正https://github.com/JuliaLang/julia/issues/2594、$#$ startがネイティブのcmdコマンドであり、 notepadが構文を強調表示できない場合、Windowsユーザーを本当に殺しますまた、行番号を表示/ジャンプしません。
editは、修正/改善できれば、本当に便利な関数です。

ただ理解するために、メソッドのソースコードをエコーする関数はなく、その目的のために「編集」に依存するべきであるという感覚はここにありますか? これは、リモートのJuliaカーネルと対話しているIPython Webノートブックではうまく機能しない可能性があります。これは、ファイルがクライアントではなくカーネルのマシンで開かれると思うためです。

インタラクティブモードでは、ファイルの内容に依存するのではなく、ソースコードを保持したいと思います。 repl経由で入力されたもののソースコードも見たいです。 #3988も参照してください。

ポケットベルのサポート#6921は、これの有用性に関するいくつかの懸念を否定する可能性があります。

これはipythonでは( func??を介して)非常に便利ですが、juliaの場合とは異なり、一部の関数は非表示になっています(組み込み/ Cython関数など)。

また、 <strong i="5">@less</strong> func(x)は、 @ astrieannaが(ページングを使用して)要求することをほぼ正確に$PAGER依存します。

<strong i="5">@less</strong> func(x)はインタラクティブ機能では機能しませんが、それは別の問題で言い換える必要がある問題のようです。

次の2つの機能が利用可能だった場合

  • 事前に下げられたASTコード、つまりreplからのソースまたは実行時のソースの取得
  • 変数/タイプ/関数/タイプの再定義/クリア

その後、実行時のコードリスト/トラバーサル/操作/生成を実行できる可能性があります。

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''

コメントへの返信:JeffBezansonが2013年3月20日にコメントしました
「いいえ、#265では役に立ちません。すでにすべての情報があります。ソースコードのようには見えません。元のコードを見たい場合は、ファイルから読み取るのが最善の方法です。 。」

だからあなたはこれが可能だと思いますか? include / requireステートメントなどがある場合はどうなりますか?

// # 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質問がわからないのではないかと思いますが、ユーザーのメーリングリストに適しているようです。 マニュアルのメタプログラミングリフレクションのセクションを読んでください。

別のユースケースは、 @generated関数です(https://groups.google.com/d/topic/julia-users/4pkWhcap1Zg/discussionから)。

ああ、私は#22007でこれを解決しましたか?

ある種– REPLモードでは、表示用の関数の元のソースを隠しておく必要があると思います。

匿名関数を表示するという問題もあります。元のASTを表示できると便利です。

julia> x -> x+1
(::#5) (generic function with 1 method)

あまり役に立ちません。 (談話も参照してください。)

REPLモードで

基本的にはすでに行っていますが、アクセスするのは面倒です。

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

"アクセスするのが面倒" == "解決したと見なされるほど役に立たない"

私はそれが役に立つことを認めます。 私は頻繁に、関数を変更し、さまざまなREPLでさまざまなバリエーションを実行してそれらを比較することでデバッグします。 どのREPLがどのバリエーションに対応するのかわからなくなることがあります。 その場合、現在定義されている関数を印刷すると便利です。

https://github.com/MasonProtter/LegibleLambdas.jlによって提供されるYaoのユースケース

すべてのブロックにはキュービット数の引数があり、繰り返し書き込みたくないので、この数を入力しない場合は自動カレーできます。

julia> using Yao

julia> control(2, 1=>X)
(n -> control(n, 2, 1 => X gate))

したがって、ユーザーはこれがブロックではないことに気付くでしょう。さらに評価するには、この数のキュービットが必要です。 LegibleLambdasを入手する前は、 #42ような数字とはかなり混乱しています。 これは、オプティマイザーが以前にラムダを返したときにもFluxに発生します。

しかし、LegibleLambdasでサポートできないコーナーケースがたくさんあります。externパッケージではなくコンパイラーからのサポートを使用して、REPLでこれらの情報を直接取得できると便利です。

私たちがこれを支持していることはまだ私にはひねくれているようです

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)
; └

この

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
}

この

julia> <strong i="14">@code_typed</strong> 1 + 2
CodeInfo(
1 ─ %1 = Base.add_int(x, y)::Int64
└──      return %1
) => Int64

この

julia> <strong i="18">@code_lowered</strong> 1 + 2
CodeInfo(
1 ─ %1 = Base.add_int(x, y)
└──      return %1
)

しかしこれで

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

Juliaを使用するすべての人が読み取りと書き込みの方法を知っているものを除いて、メソッドのすべての異なる可能なバージョンを内省することができます。 これを「ヘルプ募集」としてマークして、関数のソース表現を記憶するオプションのモードを言語に追加することを歓迎することを示します。 インタラクティブモードではデフォルトでオンにできますが、非インタラクティブモードではデフォルトでオフになります。

同様の機能が、Revise.jlの一部であるhttps://github.com/timholy/CodeTracking.jlによって実装されるようになりました。 少し遊んでみましたが、完璧ではありませんが、うまくいくことが多いです。 ドキュメントには、Reviseも使用する方がはるかに優れていると書かれています。

これは、このディスカッションで提案され

これは、派生物をジュリアコードとして表示できるため、自動微分(https://github.com/FluxML/Zygote.jlなど)と組み合わせると優れている可能性があります。

このページは役に立ちましたか?
0 / 5 - 0 評価