# My mental load using Julia is much higher than, e.g., in Python. How to reduce it?

**URL:** https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902
**Category:** General Usage
**Tags:** question, python, workflow
**Created:** [December 21, 2018, 3:49pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902 "2018-12-21T15:49:44Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [December 21, 2018, 3:49pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/1 "2018-12-21T15:49:44Z")

</div>

Hi,

I’m new to the language, and although I like so many aspects of Julia, I am struggling to start using it. I come from Python mostly, but have been looking for an alternative in which low-level function speed can be accomplished easily if needed, but high level implementation speed is also high. Julia seemed to fit the bill, at least on paper. In Swift, I loved how clean my code became because XCode helped my by scanning all my arguments and complaining beforehand that something wouldn’t fit. Also I made tons of use of extending existing objects, for chains like `line.mirror(along: axis).drawInContext(ctx)` and I thought this would be similarly possible in Julia, when you are already annotating types and often know exactly what to expect in a certain place. (Of course keeping it general wherever possible.)

I mostly do data analysis, experiment design and plotting in Python, or specifically in Jupyter Lab. With all the packages that there are, it’s hard to keep track of all the available functionality. Especially using matplotlib, numpy, and comparable big modules.

So my usual process is iterative. I might plot a figure like this:

```python
fig, ax = plt.subplots(1)
scat = ax.scatter(x, y)

```

Now I have the `fig` and `ax`, and `scat` objects, which of course have tons of methods bundled. So often, I will type `scat.` and then tab to give autocomplete suggestions. This way I can really quickly scan the available functionality, basically only stuff that has to do with this specific object. I might learn that there is a function to set marker color, or whatever.

In Julia, this is much harder. Because methods never come bundled with the kinds of objects they’re meant to be used on, I see myself in front of a sea of functions without an idea what I have available. I know that there is `methodswith`, but this gets tiresome pretty fast if you have to use it a lot. My mental load is always relatively high, trying to remember, what was this function that I could call with a `DataFrame` as the first argument that did something related to aggregating, instead of doing `df.` and filtering the suggestions quickly.

In many code examples I see that people are pulling tons of functions into the global namespace with `using`, which is comparable to do `from xxx import *` in Python. This is pretty bad practice in my opinion, because reading the code you can often not know where a certain function being called is from, you would have to execute and trace which method was dispatched.

How do you deal with these issues, maybe there are better workflows that I’m not aware of? This together with the sometimes very long precompilation times make Julia hard to justify for myself, even if I love the type mechanisms and would like to harness the high performance.

Thanks for your suggestions!  
Julius

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [December 21, 2018, 3:53pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/2 "2018-12-21T15:53:26Z")

</div>

Are you using `?` liberally in the repl to get help?

---

<div class="post-metadata">

### Author: ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)
#### Post date: [December 21, 2018, 4:05pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/3 "2018-12-21T16:05:13Z")

</div>

> [@jules](#):
>
> In many code examples I see that people are pulling tons of functions into the global namespace with `using` , which is comparable to do `from xxx import *` in Python. This is pretty bad practice in my opinion, because reading the code you can often not know where a certain function being called is from, you would have to execute and trace which method was dispatched.

You can do `import PackageName` instead of `using PackageName`, then all the methods have to be prefixed with `PackageName.__method_name`.

---

<div class="post-metadata">

### Author: ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)
#### Post date: [December 21, 2018, 4:32pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/4 "2018-12-21T16:32:27Z")

</div>

> [@jules](#):
>
> In Julia, this is much harder. Because methods never come bundled with the kinds of objects they’re meant to be used on, I see myself in front of a sea of functions without an idea what I have available. I know that there is `methodswith` , but this gets tiresome pretty fast if you have to use it a lot. My mental load is always relatively high, trying to remember, what was this function that I could call with a `DataFrame` as the first argument that did something related to aggregating, instead of doing `df.` and filtering the suggestions quickly.

Yeah, the problem of method discovery has been discussed before, but I don’t think that a solution has been found. You just have to get used to reading the documentation. It’s one of the drawbacks of multiple dispatch.

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [December 21, 2018, 4:59pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/5 "2018-12-21T16:59:27Z")

</div>

I think these are all reasonable points, but I hope I can help a little bit.

> [@jules](#):
>
> I made tons of use of extending existing objects, for chains like `line.mirror(along: axis).drawInContext(ctx)` and I thought this would be similarly possible in Julia

I think what you’re talking about is “fluent interfaces”, and it’s true that we don’t really do that in Julia, at least not in the same way. You might find the `|>` operator useful, since you can do:

```julia
x |> f |> g

```

as an alternative notation for `g(f(x))`. This should become even better when we (eventually) get [RFC: curry underscore arguments to create anonymous functions by stevengj · Pull Request #24990 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/24990) which would allow you to write:

```julia
line |> mirror(_, along=axis) |> drawInContext(_, ctx)

```

which is pretty close to the fluent interface but is in some ways even better. Notably, in a fluent interface, there is no way to chain a function that _isn’t_ a method of the returned object. So if `sort()` is a generic function (and not a method of whatever drawInContext returns), then you can’t do:

```julia
line.mirror.drawIncontext(ctx).sort()

```

but in Julia, you certainly can:

```julia
line |> mirror |> x -> drawInContext(x, ctx) |> sort

```

or, in the future:

```julia
line |> mirror |> drawInContext(_, ctx) |> sort

```

This actually gets at something that I definitely struggled with when coming from Python, and which you’ve mentioned as well, which is that it can be hard to figure out what you’re supposed to _do_ with a given object in Julia. It’s true that in Python I would often type `ax.<tab>` to get some sense of what I can do with an object. But there’s a downside of that: the things you see when you do `ax.<tab>` are almost never a good representation of all the things you can do with `ax`, they’re just the methods it happens to define.

For example, given a `list` in python, we can sort it with its `sort` method and reverse it with its `reverse` method. But what if we want to enumerate it? Well, that’s actually `enumerate(x)` instead of `x.enumerate()`, but you’d never find that from `x.<tab>`. And what if we want a reversed copy of the list, instead of doing it in-place? That’s `reversed(x)`, but not `x.reverse()`. In Julia things are more consistent: we have `enumerate(x)` and `sort(x)` and `sort!(x)`. One isn’t somehow more special than the other by virtue of being a method rather than a generic function.

I do agree that `methodswith` is kind of an awkward tool to use–this seems like exactly the kind of thing that better editors and interfaces will help with. We’re not there yet, but I think it can be done.

> [@jules](#):
>
> In many code examples I see that people are pulling tons of functions into the global namespace with `using` , which is comparable to do `from xxx import *` in Python. This is pretty bad practice in my opinion, because reading the code you can often not know where a certain function being called is from, you would have to execute and trace which method was dispatched.

Yeah, I don’t love this. Inside packages I try to have between 0 and 1 plain `using Foo` statements, with all other imports done explicitly as:

```julia
using Foo: bar, baz

```

which makes it easier to see where things come from. However, it’s worth noting that `using` is not _nearly_ as bad as `from Foo import *` would be in Python. `from ... import *` in Python is bad because:

1. It makes it hard to tell where things come from
2. It can _silently replace things_ in your current namespace and break your code in crazy ways. If package Foo has a function called `sin` and you do: `from Foo import *`, you’d better hope you weren’t relying on some other definition of `sin`.

Issue 1 still applies to Julia, but issue 2 does not. Julia won’t let you accidentally blow away things in your current namespace just by `using` some package:

```julia
julia> module Foo
       export sin
       sin(x) = 1
       end
Main.Foo

julia> using .Foo

julia> sin(5)
WARNING: both Foo and Base export "sin"; uses of it in module Main must be qualified
ERROR: UndefVarError: sin not defined

```

for that reason, I think `using` in Julia is perfectly acceptable, but I agree that we should limit our use of it in packages.

---

<div class="post-metadata">

### Author: ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)
#### Post date: [December 21, 2018, 5:05pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/6 "2018-12-21T17:05:24Z")

</div>

Excellent advice!

---

<div class="post-metadata">

### Author: ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)
#### Post date: [December 21, 2018, 5:06pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/7 "2018-12-21T17:06:41Z")

</div>

> [@rdeits](#):
>
> for that reason, I think `using` in Julia is perfectly acceptable, but I agree that we should limit our use of it in packages.

Also in code examples. When an example has several `using Foo` statements up top, it’s really hard to know which parts of the example come from which package. Sometimes you can figure it out from context, but if you’re using a few packages that are related to each other it’s often ambiguous.

---

<div class="post-metadata">

### Author: ![airpmb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/airpmb/32/7826_2.png) [@airpmb](https://discourse.julialang.org/u/airpmb)
#### Post date: [December 21, 2018, 5:25pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/8 "2018-12-21T17:25:02Z")

</div>

> [@jules](#):
>
> Now I have the `fig` and `ax` , and `scat` objects, which of course have tons of methods bundled. So often, I will type `scat.` and then tab to give autocomplete suggestions. This way I can really quickly scan the available functionality, basically only stuff that has to do with this specific object. I might learn that there is a function to set marker color, or whatever.

Same here, I miss that functionality from Python (or even other languages in IDEs). I wonder if a simple improvement could be to make tab in the REPL show the results of methodswith, at least if done right after the mention of a defined symbol. When one of the offered methods is chosen the REPL then it would insert the method (including parens) around the symbol.

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [December 21, 2018, 5:39pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/9 "2018-12-21T17:39:49Z")

</div>

Yes, I think that could absolutely be done and would be quite helpful. All that’s needed is for someone to want it badly enough to do it 🙂

---

<div class="post-metadata">

### Author: ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)
#### Post date: [December 21, 2018, 5:47pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/10 "2018-12-21T17:47:51Z")

</div>

Juno already does something similar (shows a list of possible argument types for a given function). It even re-displays the list (filtered by the type of the first argument) after you type `,` and are ready to write the 2nd argument. Very slick.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/3/7/3705d82f81a3ae7ef139b70e8b3ca31c334473ef.png)

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [December 21, 2018, 5:52pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/11 "2018-12-21T17:52:18Z")

</div>

> [@airpmb](#):
>
> I wonder if a simple improvement could be to make tab in the REPL show the results of methodswith, at least if done right after the mention of a defined symbol. When one of the offered methods is chosen the REPL then it would insert the method (including parens) around the symbol.

I’m not sure I would want to see this every time I hit tab, but one option would be to do it when you tab complete `(symbol,` or maybe just `symbol,` … requiring a comma would cut down on accidental calls to `methodswith`, since you are unlikely to want to tab-complete a comma normally.

---

<div class="post-metadata">

### Author: ![airpmb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/airpmb/32/7826_2.png) [@airpmb](https://discourse.julialang.org/u/airpmb)
#### Post date: [December 21, 2018, 5:54pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/12 "2018-12-21T17:54:32Z")

</div>

Which is great but you still need to know the function name in the first place. What I suggested would leverage the existing methodswith in a way that would help discovery even more as it would as has been pointed out provide methods that work with the type of the symbol at the cursor and not just those that belong to a class instance.

Another related idea: in the REPL if you type “something?” (Or maybe just hit return) then a combined summary of something’s type as well as its methods pops up. A lot more work than the fist suggestion to be sure, just brainstorming here. I’d be willing to help implement some of this stuff with guidance btw.

---

<div class="post-metadata">

### Author: ![airpmb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/airpmb/32/7826_2.png) [@airpmb](https://discourse.julialang.org/u/airpmb)
#### Post date: [December 21, 2018, 5:56pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/13 "2018-12-21T17:56:23Z")

</div>

Fair point. My suggestion would be since this is a newbie oriented feature to make the default whatever is most useful for such a user but configurable to the needs of more experienced users.

---

<div class="post-metadata">

### Author: ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)
#### Post date: [December 21, 2018, 8:17pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/14 "2018-12-21T20:17:54Z")

</div>

I agree that the absence of easy tab completion really hurts discoverability. See [https://github.com/JuliaLang/julia/issues/30052](https://github.com/JuliaLang/julia/issues/30052). I had a working patch that did method completion, but a problem is that many methods just accept `Any`, and it’s difficult to know what the user wants from just “tab”. The code to get completions is not complicated, but someone needs to sit down and figure out a proper UI for this.

---

<div class="post-metadata">

### Author: ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)
#### Post date: [December 21, 2018, 10:52pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/15 "2018-12-21T22:52:21Z")

</div>

> [@jules](#):
>
> So often, I will type `scat.` and then tab to give autocomplete suggestions.

I did Python programming a lot before using Julia so I missed this feature too. That’s why I made [ANN: InteractiveCodeSearch.jl --- Interactively search Julia code](https://discourse.julialang.org/t/ann-interactivecodesearch-jl-interactively-search-julia-code/17657) (sorry, no intention for a plug). I don’t think `object.<hit tab>` is the only interactive method discovery UI. `InteractiveCodeSearch` is a quick hack at it but I think we can do more. For example, it would be nice to have a keyboard shortcut to find a minimal subexpression surrounding a cursor, inference the type of it, and then run `@searchmethods` on it.

(As for the star import, @rdeits did a perfect answer so I have nothing important to add.)

---

<div class="post-metadata">

### Author: ![Ken-B](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ken-b/32/1780_2.png) [@Ken-B](https://discourse.julialang.org/u/Ken-B)
#### Post date: [December 22, 2018, 1:01am UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/16 "2018-12-22T01:01:18Z")

</div>

> [@jules](#):
>
> Now I have the `fig` and `ax` , and `scat` objects, which of course have tons of methods bundled. So often, I will type `scat.` and then tab to give autocomplete suggestions. This way I can really quickly scan the available functionality, basically only stuff that has to do with this specific object. I might learn that there is a function to set marker color, or whatever.

Obviously not a real substitute, but I sometimes type e.g. `Plots.`+TAB to see what methods and types are defined in a particular package.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [December 22, 2018, 1:29pm UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/17 "2018-12-22T13:29:50Z")

</div>

> [@ssfrr](#):
>
> When an example has several `using Foo` statements up top, it’s really hard to know which parts of the example come from which package.

In “scripts”, ie non-reused, non-packaged code, mostly for interactive exploration, I prefer just plain `using Foo`, and stick to `using Foo: bar` in packages (yes, even with `LinearAlgebra` 😉). I think both are useful, and looking up the module of a function is rather easy.

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [December 23, 2018, 1:48am UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/18 "2018-12-23T01:48:11Z")

</div>

Thanks for the responses everybody, I see that I’m not alone with my struggles 🙂

I think that an autocomplete feature could suggest methods on `variable.` + TAB (to mimick the common form of acessing bound methods) and then a list appears that shows all methods that operate on objects of this specific type, or maybe supertypes other than `Any`. The `Any` methods could come after the others, so they don’t crowd everything. And upon selection this would be transformed to `method(variable`. Of course this is more of an IDE thing anyway…

The underscore anonymous function idea is great! I hope this gets merged soon, it seems to be stuck in discussion currently… Right now piping is not so useful, it being restricted to the first argument.

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [December 23, 2018, 2:54am UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/19 "2018-12-23T02:54:15Z")

</div>

The underscore anonymous function thing will be nice, but in the mean time you should maybe check out [Lazy.jl](https://github.com/MikeInnes/Lazy.jl) for its threading macros. They can be quite useful. In particular, the `@as` macro essentially does this with more control:

```julia
# @as lets you name the threaded argmument
@as _ x f(_, y) g(z, _) == g(z, f(x, y))

```

---

<div class="post-metadata">

### Author: ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)
#### Post date: [December 23, 2018, 3:17am UTC](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902/20 "2018-12-23T03:17:48Z")

</div>

This is really a tooling issue. I’m no expert in jupyter or Juno, but theoretically it would be possible to make jupyter/ide to capture `<variable>.TAB` the same way and display methods that can operate on the variable, and when it’s chosen it just need to replace the whole expression? Someone please correct me if I’m wrong.

[Next page](https://discourse.julialang.org/t/my-mental-load-using-julia-is-much-higher-than-e-g-in-python-how-to-reduce-it/18902.md?page=2)
