Julia: afficher le code source de la fonction de repl

CrĂ©Ă© le 20 mars 2013  Â·  22Commentaires  Â·  Source: JuliaLang/julia

Julia a beaucoup de choses utiles REPL comme methods et help .
Cependant, je finis toujours par devoir simplement regarder le code pour voir ce qu'il fait.
Ce serait cool de pouvoir faire:

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)

C'est un peu comme le code de saut dans certains IDE, mais dans le REPL, et ne montrant qu'une seule fonction.
Cela a évidemment des limites, car vous ne pouvez pas simplement faire défiler vers le haut et voir l'implémentation de _base ou rechercher la définition de dig_syms dans ce fichier, mais cela vous permet de voir quelles sont les valeurs par défaut sont.

Vous pouvez déjà voir la signature pour _base , ce qui rend les implémentations de base plus significatives. (sans avoir besoin de passer du REPL à un éditeur de texte)

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

Étant donnĂ© que les numĂ©ros de ligne / fichiers sont dĂ©jĂ  inclus dans la sortie de methods , il semble qu'il devrait ĂȘtre simple de rĂ©cupĂ©rer les lignes de code appropriĂ©es dans le fichier.

REPL help wanted

Commentaire le plus utile

Il me semble toujours pervers que nous soutenions cela

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

et ça

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
}

et ça

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

et ça

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

mais pas ça

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

Nous pouvons introspecter toutes les diffĂ©rentes versions possibles d'une mĂ©thode Ă  l' exception de celle que tout le monde utilisant Julia sait lire et Ă©crire. Je vais marquer cela comme "aide voulue" pour indiquer que ce serait un ajout bienvenu au langage d'avoir un mode optionnel oĂč nous nous souvenons de la reprĂ©sentation source d'une fonction. Il peut ĂȘtre activĂ© par dĂ©faut en mode interactif mais dĂ©sactivĂ© par dĂ©faut en mode non interactif.

Tous les 22 commentaires

Si nous stockions la source (compressĂ©e) de chaque dĂ©finition de mĂ©thode lors de l'exĂ©cution interactive, cela pourrait ĂȘtre fait assez facilement et fonctionner correctement mĂȘme lorsque les fichiers source changent et mĂȘme lorsque l'annotation de la ligne source n'est pas tout Ă  fait parfaite. Cela aiderait Ă©galement avec le # 265 (voir aussi cette discussion ) puisque vous pourriez utiliser la source pour recompiler les choses. Nous pourrions Ă©galement stocker l'AST sous forme compressĂ©e Ă  la place - six contre une demi-douzaine.

Non, cela n'aidera pas avec # 265. Nous avons déjà toutes les informations, cela ne ressemble plus au code source. Si vous souhaitez consulter le code d'origine, le meilleur moyen est de le lire à partir du fichier.

D'accord avec @JeffBezanson et ce serait un dĂ©part de R oĂč taper la fonction sans parenthĂšses barfs le code source. Si la source fait plus de quelques lignes, elle devient inutilisable (il n'y a aucun moyen de faire dĂ©filer l'afaik de sortie).

+1 avec lecture d'un fichier.
Mieux vaut corriger https://github.com/JuliaLang/julia/issues/2594 , cela tue vraiment les utilisateurs de Windows lorsque start est une commande native cmd et notepad ne peut pas mettre en évidence la syntaxe ni afficher / sauter au numéro de ligne.
edit est vraiment une fonction utile, si nous pouvions la réparer / l'améliorer.

Juste pour comprendre, le sentiment est-il ici qu'il ne devrait pas y avoir de fonction pour faire écho au code source des méthodes, mais plutÎt de s'appuyer sur 'edit' à cette fin? Cela pourrait ne pas bien fonctionner avec le bloc-notes Web IPython qui interagit avec un noyau Julia distant, car je pense que le fichier s'ouvrira sur la machine du noyau au lieu de celle du client.

Pour ce que ça vaut, dans les modes interactifs, j'aimerais conserver le code source, plutÎt que de me fier à ce qui est dans les fichiers. Je veux aussi pouvoir voir le code source des choses qui ont été entrées via le repl. Voir également # 3988.

La prise en charge du pager # 6921 peut annuler certaines inquiétudes quant à son utilité.

Je trouve cela trĂšs pratique dans ipython (via func?? ), bien que - contrairement Ă  ce que pourrait ĂȘtre le cas de julia - certaines fonctions sont cachĂ©es (par exemple les fonctions intĂ©grĂ©es / cython).

De plus, <strong i="5">@less</strong> func(x) fait presque exactement ce que @astrieanna demande (avec pagination), mais cela dépend d'un $PAGER externe.

<strong i="5">@less</strong> func(x) ne fonctionne pas pour les fonctions interactives, mais cela semble ĂȘtre un problĂšme qui devrait ĂȘtre reformulĂ© dans un autre problĂšme.

Si les deux fonctionnalités suivantes étaient disponibles

  • obtenir le code AST prĂ©-abaissĂ©, c'est-Ă -dire la source du repl ou au moment de l'exĂ©cution
  • redĂ©finition / effacement des variables / types / fonctions / types

alors il peut ĂȘtre possible de faire une liste / traversĂ©e / manipulation / gĂ©nĂ©ration de code temporel d'exĂ©cution.

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

en réponse au commentaire: JeffBezanson a commenté le 20 mars 2013
"Non, cela n'aidera pas avec # 265. Nous avons déjà toutes les informations, cela ne ressemble plus au code source. Si vous voulez regarder le code d'origine, la meilleure façon est de le lire à partir du fichier . "

Alors vous pensez que c'est possible? Que se passe-t-il lĂ  oĂč il y a des dĂ©clarations d'inclusion / exigence et d'autres choses?

// # 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 J'ai bien peur de ne pas comprendre la question, mais elle semble mieux adaptée à la liste de diffusion des utilisateurs. Veuillez lire les sections métaprogrammation et réflexion du manuel.

Un autre cas d'utilisation serait les fonctions @generated (Ă  partir de https://groups.google.com/d/topic/julia-users/4pkWhcap1Zg/discussion).

Oh, ai-je résolu ça dans # 22007?

En quelque sorte - je pense toujours qu'en mode REPL, nous devrions cacher la source d'origine pour les fonctions d'affichage.

Il y a aussi la question de l'affichage des fonctions anonymes, oĂč il serait bien de pouvoir afficher l'AST d'origine.

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

n'est pas super utile. (Voir aussi discours .)

en mode REPL

nous le faisons déjà fondamentalement, c'est juste ennuyeux d'accéder:

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

"ennuyeux d'accĂšs" == "pas assez utile pour ĂȘtre considĂ©rĂ© comme rĂ©solu"

J'avoue que ce serait utile. Je débogue fréquemment en modifiant une fonction et en exécutant différentes variations dans différents REPL pour les comparer. Parfois, je perds la trace de quelle REPL correspond à quelle variation. L'impression de la fonction actuellement définie serait alors intéressante.

Un cas d'utilisation dans Yao fourni par https://github.com/MasonProtter/LegibleLambdas.jl

Chaque bloc a un argument de nombre de qubits, et nous ne voulons pas l'Ă©crire Ă  plusieurs reprises, donc il peut ĂȘtre auto-curry lorsque vous ne fournissez pas ce nombre, par exemple

julia> using Yao

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

Ainsi, l'utilisateur sera conscient que ce n'est pas un bloc, il a besoin de ce nombre de qubits pour une évaluation plus approfondie. Avant d'avoir LegibleLambdas, il est assez déroutant avec juste un nombre comme #42 . Cela arrive également à Flux lorsque les optimiseurs retournent un lambda avant.

Mais il y a beaucoup de cas secondaires que nous ne pouvons pas supporter dans LegibleLambdas, ce serait bien, que nous puissions obtenir directement ces informations dans REPL avec le support du compilateur au lieu du package externe.

Il me semble toujours pervers que nous soutenions cela

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

et ça

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
}

et ça

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

et ça

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

mais pas ça

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

Nous pouvons introspecter toutes les diffĂ©rentes versions possibles d'une mĂ©thode Ă  l' exception de celle que tout le monde utilisant Julia sait lire et Ă©crire. Je vais marquer cela comme "aide voulue" pour indiquer que ce serait un ajout bienvenu au langage d'avoir un mode optionnel oĂč nous nous souvenons de la reprĂ©sentation source d'une fonction. Il peut ĂȘtre activĂ© par dĂ©faut en mode interactif mais dĂ©sactivĂ© par dĂ©faut en mode non interactif.

Une fonctionnalitĂ© similaire est dĂ©sormais implĂ©mentĂ©e par https://github.com/timholy/CodeTracking.jl , qui fait partie de Revise.jl. J'ai jouĂ© un peu avec, et mĂȘme s'il n'est pas parfait, cela fonctionne le plus souvent. La documentation dit que c'est beaucoup mieux quand on utilise Ă©galement Revise.

Cela a été suggéré dans cette discussion .

Cela pourrait ĂȘtre excellent en combinaison avec la diffĂ©renciation automatique (comme https://github.com/FluxML/Zygote.jl), car vous pouvez ensuite afficher le dĂ©rivĂ© sous forme de code julia

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

sbromberger picture sbromberger  Â·  3Commentaires

StefanKarpinski picture StefanKarpinski  Â·  3Commentaires

manor picture manor  Â·  3Commentaires

i-apellaniz picture i-apellaniz  Â·  3Commentaires

musm picture musm  Â·  3Commentaires