New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

show function source code from repl #2625

Open
astrieanna opened this Issue Mar 20, 2013 · 18 comments

Comments

Projects
None yet
@astrieanna
Contributor

astrieanna commented Mar 20, 2013

Julia has a lot of useful REPL things like methods and help.
However, I still end up needing to just look at the code to see what it's doing.
It would be cool to be able to do:

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)

It's kind of like the jump-to code stuff in some IDEs, but in the REPL, and only showing the one function.
This obviously has limitations, since you can't just scroll up and see the implementation of _base or search for the definition of dig_syms in that file, but it does let you see what the default values are.

You can already see the signature for _base, which makes the implementations of base more meaningful. (without needing to switch from the REPL to a text editor)

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

Considering that the line numbers/files are already included in the output of methods, it seems like it should be straightforward to grab the appropriate lines of code from the file.

@StefanKarpinski

This comment has been minimized.

Member

StefanKarpinski commented Mar 20, 2013

If we stored the source (compressed) of each method definition when running interactively, this could be done rather easily and work correctly even when source files change and even when source line annotation isn't quite perfect. That would also help with the #265 (see also this discussion) since you could use the source to recompile things. We could also store the AST in compressed form instead – six vs. half a dozen.

@JeffBezanson

This comment has been minimized.

Member

JeffBezanson commented Mar 20, 2013

No, it won't help with #265. We already have all the information, it just doesn't look like source code anymore. If you want to look at the original code, the best way is to read it from the file.

@milktrader

This comment has been minimized.

Member

milktrader commented Mar 23, 2013

Agree with @JeffBezanson and this would be a departure from R where typing the function without parens barfs out the source code. If the source is more than a few lines long, it becomes unusable (there is no way to scroll through the output afaik).

@wlbksy

This comment has been minimized.

Member

wlbksy commented Mar 23, 2013

+1 with read from file.
Better fix #2594 , it really kills windows users when start is a native cmd command and notepad cannot highlight syntax nor show/jump to line number.
edit is really a useful function, if we could fix it/make it better.

@malmaud

This comment has been minimized.

Contributor

malmaud commented Oct 25, 2013

Just to understand, is the feeling here that there shouldn't be a function to echo the source code of methods, but rather to rely on 'edit' for that purpose? That might not play well with the IPython web notebook that's interacting with a remote Julia kernel, since I think the file will open on the kernel's machine instead of the client's.

@StefanKarpinski

This comment has been minimized.

Member

StefanKarpinski commented Oct 25, 2013

For what it's worth, in interactive modes, I'd like to keep source code around, rather than rely on what's in files. I want to be able to see the source code of things that were input via the repl too. See also #3988.

@hayd

This comment has been minimized.

Member

hayd commented May 31, 2014

pager support #6921 may negate some concerns on the usefulness of this.

I find this very convenient in ipython (via func??), although - unlike could be the case of julia - some functions are hidden (e.g. built-in/cython functions).

@mbauman

This comment has been minimized.

Member

mbauman commented May 31, 2014

Also, @less func(x) does almost exactly what @astrieanna asks for (with paging), but it's dependent upon an external $PAGER.

@ivarne

This comment has been minimized.

Member

ivarne commented May 31, 2014

@less func(x) does not work for interactive functions, but that seems to be a problem that should be rephrased in a different issue.

@hgkamath

This comment has been minimized.

hgkamath commented May 2, 2015

If the following two features were available

  • getting pre-lowered AST code i.e. source from the repl or at runtime
  • redefining/clearing variables/types/functions/types

then it may be possible to do run time code listing/traversal/manipulation/generation.

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

in response to comment : JeffBezanson commented on Mar 20, 2013
"No, it won't help with #265. We already have all the information, it just doesn't look like source code anymore. If you want to look at the original code, the best way is to read it from the file."

So you think this is possible ? What happens where there are include/require statements and other things ?

// # 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
@ihnorton

This comment has been minimized.

Member

ihnorton commented May 3, 2015

@hgkamath I'm afraid I don't understand the question, but it seems better-suited for the users mailing list. Please do read the metaprogramming and reflection sections of the manual.

@simonbyrne

This comment has been minimized.

Contributor

simonbyrne commented Feb 11, 2016

Another use case would be @generated functions (from https://groups.google.com/d/topic/julia-users/4pkWhcap1Zg/discussion).

@fredrikekre

This comment has been minimized.

Contributor

fredrikekre commented May 31, 2017

Oh, did I solve this in #22007 ?

@StefanKarpinski

This comment has been minimized.

Member

StefanKarpinski commented Jun 1, 2017

Sort of – I still think that in REPL mode we should stash the original source for functions for display.

@stevengj

This comment has been minimized.

Member

stevengj commented Jun 5, 2017

There is also the question of displaying anonymous functions, where it would be nice to be able to display the original AST.

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

is not super useful. (See also discourse.)

@vtjnash

This comment has been minimized.

Member

vtjnash commented Jun 5, 2017

in REPL mode

we already basically do, it's just annoying to access:

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
@StefanKarpinski

This comment has been minimized.

Member

StefanKarpinski commented Jun 6, 2017

"annoying to access" == "not useful enough to be considered solved"

@jebej

This comment has been minimized.

Contributor

jebej commented Jun 6, 2017

I admit that it would be useful. I frequently debug by modifying a function in and running different variations in different REPLs to compare them. Sometimes I lose track of which REPL corresponds to which variation. Printing the function that is currently defined would then be nice to have.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment