# Discussion on "Why I no longer recommend Julia" by Yuri Vishnevsky

**URL:** <https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151>\
**Category:** Community\
**Tags:** discussion\
**Created:** [May 16, 2022, 2:33pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151 "2022-05-16T14:33:38Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![ChrisJefferson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisjefferson/32/18576_2.png) [@ChrisJefferson](https://discourse.julialang.org/u/ChrisJefferson)\
**Post date:** [May 17, 2022, 8:00am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/42 "2022-05-17T08:00:04Z")

</div>

I wonder if the issue is not with OffsetArrays specifically, but that `@inbounds` is both easy to use, and very dangerous. Perhaps it should be deprecated / more strongly discouraged? I personally wouldn’t get too upset if I passed an `OffsetArray` and received an assertion/error, it’s the silent invalid memory accesses which are super-upsetting.

In Rust (I know it might be an over-done comparison, but it’s another language I currently use), the intention (not saying it is always met) is only code in `unsafe` should risk memory corruption. I actually didn’t realise until this conversation that I need to look through packages I use for `@inbounds`, to check for possible serious issues. Are there other things I need to look out for? How can I find out what they are?

---

<div class="post-metadata">

**Author:** ![willtebbutt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/willtebbutt/32/6790_2.png) [@willtebbutt](https://discourse.julialang.org/u/willtebbutt)\
**Post date:** [May 17, 2022, 8:03am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/43 "2022-05-17T08:03:40Z")

</div>

> My conclusion is - in accordance to what @Henrique_Becker has written - that the crucial problem is `eachindex` docstring. The issue is that IMHO we need to carefully review contracts that Base Julia functions provide to make sure they are precise and easy to understand for developers so that when they add methods to such functions they can correctly implement them. Unfortunately this task is quite hard to achieve in practice.

It would be great if Base Julia published both test fakes (e.g. subtypes of `AbstractArray` which can be consumed by functions which expect an `AbstractArray`, but which are carefully designed to satisfy only the assumptions laid out in the AbstractArray interface) and test suites (e.g. a function which consumes an `AbstractArray` and checks that it satisfies the AbstractArray interface) for its interfaces – Invenia had a good [blog post](https://invenia.github.io/blog/2020/11/06/interfacetesting/) about this kind of thing a while back.

---

<div class="post-metadata">

**Author:** ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)\
**Post date:** [May 17, 2022, 8:05am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/44 "2022-05-17T08:05:03Z")

</div>

It’s tricky… There is a price we pay for having interfaces _evolving_ according to consensus and need, and this post points right at it. But I think what we are doing is also quite powerful in combination with multiple dispatch and interoperability. That positive side is more difficult to explain and grasp, so it’s important to be very conscious about it

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 17, 2022, 8:34am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/45 "2022-05-17T08:34:09Z")

</div>

Standardized interface tests sound great, and the easier they are to pass around, the better. But adding tests isn’t the whole solution. Take the example where the author ran into StatsBase.jl still assuming 1-based indexed arrays for `@inbounds` code. That assumption isn’t just there; for example, you can also find it in matrix multiplication. The functions `require_one_based_indexing` and `has_offset_axes` exist to throw errors if people try to use some code with non-1-based arrays, very much instead of editing that code. My guess is it’s going to take a LOT of developer-hours to make all those changes and test, and developers are likely spread thin on more pressing priorities; each cited bug or enabling `OffsetArrays` may seem critical in isolation, but they seem small if you put them next to many of the other issues.

For now, it might be better just to document limitations more clearly: for example, “The AbstractArray interface intends to allow non-1-based indexing and you could fully leverage this in your own code. However, some AbstractArray code in Base or other packages have not been updated to match, so it may not be possible to fully compose that code with yours.”

---

<div class="post-metadata">

**Author:** ![willtebbutt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/willtebbutt/32/6790_2.png) [@willtebbutt](https://discourse.julialang.org/u/willtebbutt)\
**Post date:** [May 17, 2022, 8:35am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/46 "2022-05-17T08:35:18Z")

</div>

@mcabbott I broadly agree with this, but I also believe it would be extremely useful to try and figure out _what_ the quirks of these packages are, and isolate them in a standard set of tests in the stdlibs / Base, or some other _minimal_ package (preferably with no deps outside the stdlibs) called `AbstractArraysTesting.jl` or something.

To my mind the limitations with asking people to test using a collection of arrays found in the wild on an ad-hoc basis is that it complicates their test deps, and it requires everyone to go hunting for interesting arrays for their package, which is a pain and will presumably lead to different people testing on different things and getting different levels of robustness / coverage. Of course, you could fix the latter limitations by just collecting and publishing a collection of recommended arrays in a package like `AbstractArrayTesting.jl` or something, but that wouldn’t get you around having loads of additional deps.

---

<div class="post-metadata">

**Author:** ![abulak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abulak/32/28314_2.png) [@abulak](https://discourse.julialang.org/u/abulak)\
**Post date:** [May 17, 2022, 9:04am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/47 "2022-05-17T09:04:49Z")

</div>

one way of solving the (2) part is to define the interface by tests. E.g. create a package “AbstractArrayInterface.jl” that defines functions and the correct behaviour of abstract arrays and gives you the canonical examples how to use them correctly (and maybe even implements a trivial example). Then you have a versioned and test-able interface which you can use for testing the compliance of your arrays or summon for your own tests to test the functions.

As a poc I created this package: [GitHub - kalmarek/GroupsCore.jl: Interface for abstract groups](https://github.com/kalmarek/GroupsCore.jl) which standardises/sets in place something called “GroupInterface”. If I implement a structure representing a group I immediately test the interface, e.g. [Groups.jl/group\_constructions.jl at 2e544d623f490da9997a751c7ad02f1a5c313903 · kalmarek/Groups.jl · GitHub](https://github.com/kalmarek/Groups.jl/blob/2e544d623f490da9997a751c7ad02f1a5c313903/test/group_constructions.jl#L10)

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [May 17, 2022, 10:20am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/48 "2022-05-17T10:20:51Z")

</div>

> [@ChrisJefferson](#):
>
> I wonder if the issue is not with OffsetArrays specifically, but that `@inbounds` is both easy to use, and very dangerous. Perhaps it should be deprecated / more strongly discouraged?

Hi new Chris, it wasn’t very dangerous (more so than no checking in e.g. C/C++), until `OffsetArrays`, and then only in that scenario, so lets not throw the baby out with the bathwater. But you made me think, I think we should disable it is that case.

Note, all user can disable globally:

```julia
--check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations)

```

So you can test your `OffsetArray`-using code with a package that wasn’t assuming it used, already. I would just want “yes” answered there for any non-1-indexed array, otherwise “no”. My question is it possible, yes, I think it is, the macro has access to the array, knows it’s of the `OffsetArray` type.

What would be ideal is that if the `OffsetArray` is actually indexed by an index given by `eachindex(A)` then the current behavior is retained. But it returns an `Int64` (i.e. `Int`), the same as e.g. `1:length(A)`, so it seems impossible. But could `eachindex` be made to return a new type `Int64_safe_array_index` just to signal that to the macro, and indexing (i.e. `getindex`) be made to accept it?

Testing (and bounds checking is testing), can show the presence of bug, but not absence of. In a lot of cases it would and we could fix the package ecosystem. The problem would be when we do, OffsetArrays would be slower and second-class that way. We might need to make up a new macro `@oinbounds` (might not be needed if the `Int64_safe_array_index`-idea works) that keeps the current semantics of `@inbounds`, and/or add a global user-setting to similar effect.

---

<div class="post-metadata">

**Author:** ![rikh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rikh/32/204104_2.png) [@rikh](https://discourse.julialang.org/u/rikh)\
**Post date:** [May 17, 2022, 10:23am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/49 "2022-05-17T10:23:23Z")

</div>

> [@juliohm](#):
>
> _The subset of the Julia community that is capable of developing relevant packages is too small_ . You often see the same faces maintaining 10 different packages in 5 different organizations. They cannot research, develop, document, maintain, fix bugs… of all these efforts at the same time and **alone**.

I get this completely. Honestly, I find contributing to Julia packages very unrewarding in most cases except for a few. Due to this, I think that few people actually have the chance to learn and grow into becoming a great software developer/maintainer.

Contributing is often unrewarding because if the PR is not good enough, it is ignored or feedback is given in one sentence. You could have spent multiple hours trying to do your best on something and all you get back is two thumbs down and a “Doesn’t work. Will fail when X”. At the same time, many repositories have CI now disabled by default for new contributors and reviewers don’t often spent a few minutes on actually modifying the PR if it is at 80%. This disabled CI and having to fix minor styling issues is a tremendous waste of time for the person who opens a PR. Nobody likes to spend 30 minutes on a style change, then wait 24 hours to get CI approved, spend 30 minutes fixing a Windows 32-bit problem, wait 24 hours for another review comment and spend 30 minutes on fixing a minor detail. I don’t get this. Re-reading a PR again and again is also a waste of effort for the reviewer. Allowing newcomers to run CI automatically takes 1 minute once if you know where to find the setting.

Why not take the following as the guideline for merging: If the PR is an improvement over the current state or can be easily reverted, then merge or finish it and merge. This would motivate newcomers much more. Chris Rackauckas already does this and I don’t understand why this isn’t the main philosophy under reviewers.

And, yeah, sure. I admit that I have submitted some terrible PRs, created terrible packages and terrible issues. I should have spent much more time on some PRs to think about things and what not. In my defense, let’s bring in the quote from Michael Jordan:

> I’ve missed more than 9,000 shots in my career. I’ve lost almost 300 games. Twenty-six times I’ve been trusted to take the game-winning shot and missed. I’ve failed over and over and over again in my life. And that is why I succeed.

So, let’s all try to be more supportive of people who open terrible PRs or issues. Let’s support them to try again, so that they can succeed.

EDIT: Tim Holy posted some insight on why reviewing PRs is not as easy as it may sound: [Improving the Julia issue tracker - #4 by tim.holy](https://discourse.julialang.org/t/improving-the-julia-issue-tracker/83365/4).

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [May 17, 2022, 11:38am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/50 "2022-05-17T11:38:10Z")

</div>

> [@rikh](#):
>
> I get this completely. Honestly, I find contributing to Julia packages very unrewarding in most cases except for a few. Due to this, I think that few people actually have the chance to learn and grow into becoming a great software developer/maintainer.

Fully agree. A mechanism to solve the issue should consider some reward system.

> [@rikh](#):
>
> Why not take the following as the guideline for merging: If the PR is an improvement over the current state or can be easily reverted, then merge or finish it and merge. This would motivate newcomers much more.

I don’t know if I fully support this guideline. The real problem is not that we have too many terrible PRs. The problem as I see it is that the Julia community is comprised of two extreme profiles:

1. _Extremely qualified researchers with excellent software skills_ that can follow good software development practices by heart. They usually come from advanced HPC, linear algebra, stats communities and have programmed in C, C++, Fortran, … in the past. They know how to cope with the complexity of major projects.

2. _Very beginner users who never programmed in low-level languages before_. They were not exposed to these software development issues in their past projects, which are usually short scripts or tiny packages that combine existing packages.

We lack the profile in the middle of the scale: professionals in the industry who are capable of contributing PRs of good quality. They have experience working in large projects in teams and value the mechanisms adopted to reduce the noise in peer review (e.g. code style, file tree structure).

My conclusion is that we need to target the middle profile more in our social events.

**How to convert an intermediate user into a maintainer?**

That is the main question in my opinion.

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [May 17, 2022, 11:54am UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/51 "2022-05-17T11:54:56Z")

</div>

> [@juliohm](#):
>
> The problem as I see it is that the Julia community is comprised of two extreme profiles:
> 
> 1. _Extremely qualified researchers with excellent software skills_ that can follow good software development practices by heart. They usually come from advanced HPC, linear algebra, stats communities and have programmed in C, C++, Fortran, … in the past. They know how to cope with the complexity of major projects.
> 2. _Very beginner users who never programmed in low-level languages before_ . They were not exposed to these software development issues in their past projects, which are usually short scripts or tiny packages that combine existing packages.

It’s almost as if you get users from both ends of the two-language spectrum 😉

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 17, 2022, 12:48pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/52 "2022-05-17T12:48:29Z")

</div>

> [@Palli](#):
>
> But could `eachindex` be made to return a new type `Int64_safe_array_index` just to signal that to the macro, and indexing (i.e. `getindex` ) be made to accept it?

Do you mean like this?

```julia
for i in eachindex(A) 
    B[i] = 0
end

```

😉

---

<div class="post-metadata">

**Author:** ![jisutich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jisutich/32/33342_2.png) [@jisutich](https://discourse.julialang.org/u/jisutich)\
**Post date:** [May 17, 2022, 1:45pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/53 "2022-05-17T13:45:01Z")

</div>

Hi everyone,

As a new user of julia, I have some questions about this article. (I need to apologize that I didn’t understand most part of this article) Personally I want to use julia to do some calculation about physics and math. In this article, the author mentions some issues about StatsBase, does it mean that the results can be inaccurate when I use functions from StatsBase? Also, can I think that most of the problems from the package OffsetArrays? If I define my abstract array carefully, I can avoid these problems, right? Thanks.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [May 17, 2022, 1:53pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/54 "2022-05-17T13:53:27Z")

</div>

Well, normally there is no need to define your own abstract array…

If you use one based arrays there should be no problem at all.

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [May 17, 2022, 2:01pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/55 "2022-05-17T14:01:44Z")

</div>

I think this is the most unfortunate thing about Yuri’s article – you are now globally worried about StatsBase, but the examples that Yuri gave work fine with standard arrays – they are just failing if you use non-standard indexing like OffsetArrays allows.

---

<div class="post-metadata">

**Author:** ![NumHack](https://avatars.discourse-cdn.com/v4/letter/n/f07891/32.png) [@NumHack](https://discourse.julialang.org/u/NumHack)\
**Post date:** [May 17, 2022, 2:24pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/56 "2022-05-17T14:24:20Z")

</div>

> [@juliohm](#):
>
> We lack the profile in the middle of the scale: professionals in the industry who are capable of contributing PRs of good quality. They have experience working in large projects in teams and value the mechanisms adopted to reduce the noise in peer review (e.g. code style, file tree structure).
> 
> My conclusion is that we need to target the middle profile more in our social events.
> 
> **How to convert an intermediate user into a maintainer?**
> 
> That is the main question in my opinion.

“Professionals in the industry”, which “industry” do you have in mind ?

One other issue is that many professionals can not contribute to Julia without entering a conflict of interest : Julia Computing and other businesses around Julia are considered as a competitors by their employers.

Am I the only one is that situation ?

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [May 17, 2022, 2:35pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/57 "2022-05-17T14:35:57Z")

</div>

> [@NumHack](#):
>
> “Professionals in the industry”, which “industry” do you have in mind ?

No particular industry.

> [@NumHack](#):
>
> One other issue is that many professionals can not contribute to Julia without entering a conflict of interest : Julia Computing and other businesses around Julia are considered as a competitors by their employers.

Can you give an example of conflict you experienced?

---

<div class="post-metadata">

**Author:** ![NumHack](https://avatars.discourse-cdn.com/v4/letter/n/f07891/32.png) [@NumHack](https://discourse.julialang.org/u/NumHack)\
**Post date:** [May 17, 2022, 2:56pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/58 "2022-05-17T14:56:14Z")

</div>

> [@juliohm](#):
>
> Can you give an example of conflict you experienced?

My trade is in Electrical Design Automation, and [JuliaSpice](https://pretalx.com/juliacon2021/talk/QUCAK3/) aims to compete with tools from my company.

---

<div class="post-metadata">

**Author:** ![tobydriscoll](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobydriscoll/32/1843_2.png) [@tobydriscoll](https://discourse.julialang.org/u/tobydriscoll)\
**Post date:** [May 17, 2022, 2:59pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/59 "2022-05-17T14:59:26Z")

</div>

This is a great point about the “sticks” or barriers to contributing. But the “carrots” are just as big a problem. Maybe bigger, when you consider what obstacles people endure to publish papers.

In academia there are no incentives or rewards for making minor or mundane contributions to a software project, at least outside of CS. It fails on many counts: it’s not a paper, it’s not original, it’s not intellectually dazzling, you’re not the leader, it’s not X (where for me, X = math). Software contributions are more akin to referee work than research, but it doesn’t even get proper service recognition.

Even though I’m at a career stage where I can mostly ignore the consequences of that attitude for myself, such work makes me undesirable to work with, especially for students and postdocs who think they want a research career. Never mind that I have been credited with 49,000 downloads on the MathWorks file exchange, while most math papers are lucky to get 2 non-self-citations: the system, and the culture that thrives on it, are bent on perpetuating themselves.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [May 17, 2022, 3:05pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/60 "2022-05-17T15:05:24Z")

</div>

> [@NumHack](#):
>
> My trade is in Electrical Design Automation, and [JuliaSpice](https://pretalx.com/juliacon2021/talk/QUCAK3/) aims to compete with tools from my company.

If you can separate the commercial components from the open source components, then you can contribute to the open source components maybe? I am assuming that you still rely on many open source dependencies that are not only used for Electrical Design Automation?

Previously when I was working for IBM I had to submit forms to the company to contribute to specific open source projects. You may request a similar process at your company so that everyone is on the same page. I believe you will be able to contribute to open source components without compromising your competitive advantage.

---

<div class="post-metadata">

**Author:** ![NumHack](https://avatars.discourse-cdn.com/v4/letter/n/f07891/32.png) [@NumHack](https://discourse.julialang.org/u/NumHack)\
**Post date:** [May 17, 2022, 4:09pm UTC](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/61 "2022-05-17T16:09:21Z")

</div>

Thank you for your advice.

> [@juliohm](#):
>
> If you can separate the commercial components from the open source components, then you can contribute to the open source components maybe? I am assuming that you still rely on many open source dependencies that are not only used for Electrical Design Automation?
> 
> Previously when I was working for IBM I had to submit forms to the company to contribute to specific open source projects. You may request a similar process at your company so that everyone is on the same page. I believe you will be able to contribute to open source components without compromising your competitive advantage.

From what I was told, It seems that when Julia Computing was in the early rounds of funding, many companies were approached for some kind of partnership.

Unfortunately (for me) mine decided not to go along, having their own solution(s) to promote.  
I do use Julia at my company, but it’s clear I can’t use it for things that get shipped outside.

I had no issues contributing device drivers to Linux long ago without even checking with my employer, understanding that I wasn’t hurting their business. But in my case, anything I know related to modeling, simulation and system identification is considered strategic and sensitive.

[Previous page](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151.md?page=2)

[Next page](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151.md?page=4)
