It’s not a concern, more of an annoyance. The point is that if you do not explicitly use areturn
statement in Python your function returns None
, which is almost guaranteed to cause an error somewhere downstream where the function return value is used. In Julia I’ve had multiple times that the last statement evaluated implicitly returned a number (as I screwed up the return
or logic somewhere), which would then happily cause weird behaviour downstream, for reasons unclear at first sight.
I don’t know if this count as a beginner situation, but this is the most obscure one that I had have till today
Race condition with local variable in @threads for loop
Once I got used to the Python way it became more natural to me
Functional programming is, imo, more natural than OO. For someone new to programming it is easier. Of course, with backgrounds that is other story.
Well, let’s not open that can of worms (too far) here
and particularly people used to OO programming tend to start writing inner ones and get confused.
Right, I think that’s because the OO way is to put structure and code in the same class, so it’s natural to want to write the constructur within the struct
definition.
- A weird combination of include files and modules for structuring code, instead of having a Julia file define a module in a predictable way as in Python
I might be guilty of that myself. What is the “correct” Julian way to structure code in a large module that I wish to split into several files? Submodules or includes?
Cannot agree more!
I think suggesting a beginner to read the whole mannual is insane and completely unnecessary.
I might be guilty of that myself. What is the “correct” Julian way to structure code in a large module that I wish to split into several files? Submodules or includes?
That’s the thing, it’s both. The standard way to structure a Julia package is to have a top-level file (e.g. MyModule.jl
) defining the module name and its exports and which loads necessary dependencies, etc. That file then also include()
s several other Julia files that hold the concrete stuff like structs and methods. See for example the Plots.jl module definition.
I just wanted to come here to say that I learnt julia using the manual and docs and as far as I’m concerned the manual is great and I learnt almost everything I know from the manual / docs + experimentation. I wasn’t completely new to programming, since I had done quite a bit of python before, but I definitely wasn’t advanced either.
Sure, reading it back to front is a bit intense, but you can read those sections relevant to you in the moment rather than reading everything. Want to make something iterable? Read the section on iterators / interfaces. Want to make something go faster? Read the performance tips section. Want to make a parametric type? Read that section in the manual. and so on…
How many people do you honestly think read all 1335 pages of the manual?
I think you misunderstand: I am talking about the “Manual” part, not the docs for Base, the standard libraries, or the devdocs. This is about 400–450 pages depending on the formatting as a PDF, but of course HTML may be a better option.
I am not sure why you imagine that I have data on how many people do read the manual. My point is that everyone should.
A very common mistake I observe is not realizing that Julia is a complex tool that is quite different from other programming languages. Failing to read the manual (or a book of equivalent length and complexity) just sets up the reader for a lot of frustration, encountering most of the minor difficulties and differences mentioned in this topic by accident, usually after a lengthy debugging session.
and as far as I’m concerned the manual is great
I do not want to be misunderstood here either. I also agree that the manual is great, but for a new programmer (or even a experienced programmer in a language that does not share the features of Julia), it might be pass the impression that things are more complicated than they actually are, and be discouraging.
A few examples:
The first statement about Characters:
A
Char
value represents a single character: it is just a 32-bit primitive type with a special literal representation and appropriate arithmetic behaviors, and which can be converted to a numeric value representing a Unicode code point. (Julia packages may define other subtypes ofAbstractChar
, e.g. to optimize operations for other text encodings.)
The section on Short-Circuit evaluation (I have complained about this one before when I was starting my way into Julia, and I still think it is over-complicated): “and” and “or” (which for almost every use case are the &&
and ||
operators) should be explained independently, and not with that overly technical nomenclature.
The section on closures (which is not in the Manual, and the search does not indicate anything in the manual): Julia Functions · The Julia Language
(that one should be revised, I think, it is such a fundamental part of Julia and unless you are completely familiar with closures from another language, that section does not help much).
It is because of many examples like these that I suggested reading another book on Julia, more focused on presenting the language in a more natural way.
I have been seriously working with Julia for about a year now, and recently I started reading the manual “as a book”. Now that is a nice experience mostly, because I have already a more consolidated notion of the language (and of computer programming in general, because Julia introduced me to a lot of concepts that I was completely unaware of while working with Fortran).
My issue with the Julia way compared to Python is that included source files do not (in general) explicitly contain all of their dependencies
I think I agree with you here, and that reminds me of a common issue I had while developing packages, which is a beginner mistake and for which perhaps someone can give good advice. If my module includes three files:
module MyModule
include("file1.jl")
include("file2.jl")
include("file3.jl")
end
I have experienced, as the code becomes more complex, the issue of having to include the files in the precise order in which all dependencies are satisfied sequentially. That reminds me of having to compile everything in the correct order for a static language.
One solution (which would emulate what python forces one to do) would be to include the previous files necessary for each other file in every file (for instance, include file1
in file2
and file2
or both files in file3
, but that is of course not reasonable, because these are files being read, not modules being loaded repeatedly (which would be cost-less). Another solution, which would be what it seems that python actually does, is to write a module in every file, and use them instead of including them. But that is also annoying, of course, and if we wanted that, the design of the language would be the pythonic design from start.
Is there a good advice for dealing with such a situation?
I have complained about this one before
Complaints tend to have little lasting effect, while PRs may end up improving the manual.
That thread ended indeed in PRs, and the manual is improved
https://docs.julialang.org/en/v1.7-dev/manual/control-flow/#Short-Circuit-Evaluation
A very common mistake I observe is not realizing that Julia is a complex tool that is quite different from other programming languages . Failing to read the manual (or a book of equivalent length and complexity) just sets up the reader for a lot of frustration, encountering most of the minor difficulties and differences mentioned in this topic by accident, usually after a lengthy debugging session.
To be fair, the description of Julia in the various (high-level) sources does not really warn a user of this complexity, nor fundamental differences with other languages. Examples (my emphasis):
[Introduction section of the manual] Julia aims to create an unprecedented combination of ease-of-use, power, and efficiency in a single language.
[Introduction section of the manual] Julia provides ease and expressiveness for high-level numerical computing, in the same way as languages such as R, MATLAB, and Python, but also supports general programming.
[Julia in a Nutshell on the home page] Julia is dynamically typed, feels like a scripting language, and has good support for interactive use.
[JuliaLanguage Twitter account] Julia is a high-level, high-performance dynamic programming language for technical computing.
To be fair, the description of Julia in the various (high-level) sources does not really warn a user of this complexity, nor fundamental differences with other languages. Examples (my emphasis)
I think those statements are true for Julia as they are for all the other languages mentioned. The syntax of the other ones are not (IMO) easier than that of Julia. To take the most of each language, any of them, of course, one has to learn them deeply.
Float32
literals are written2.0f0
and not2.0f
This is consistent with the notation for Float64
, which is 2e0
, and similar to literal integer prefix syntax like 0x
, 0b
.
The f
doesn’t really stand on it’s own, the same way that you write 2e4
, you write 2f4
, and thus, 2f0
. Throwing away the trailing zero would be a mistake, I think. (Analogously, one should write 2.0
instead of 2.
)
I think those statements are true for Julia as they are for all the other languages mentioned. The syntax of the other ones are not (IMO) easier than that of Julia. To take the most of each language, any of them, of course, one has to learn them deeply.
That wasn’t my point. I don’t consider Python a complex language, which is also why I’m pretty sure it is so popular (same with Javascript). Julia on the other hand looks a bit like Python, but under the hood the complexity due to use of compilation together with the way the type system interactions with it makes it a much more complex one.
the description of Julia in the various (high-level) sources does not really warn a user of this complexity
Julia is not an outstandingly complex language (yes, C++, I am looking at you ). It’s just a mistake to assume that it is another variation on the Python/Matlab/R theme.
nor fundamental differences with other languages
That is covered in
https://docs.julialang.org/en/v1/manual/noteworthy-differences/
under the hood the complexity due to use of compilation together with the way the type system interactions with it makes it a much more complex one.
It might be that when starting to use Julia one is already focused in obtaining very performant code. This is what brings people to Julia in general. And we can have the wrong impression, from start, that can be obtained “for free”, writing code as permissively as in scripted languages.
We can write code that way, but it very likely will not perform as one would naively expect. A common “mistake” of new julia users coming from those other languages is, from this first impresion, start vectorizing everything and searching for “that package” that solves that operation. And then they miss the actual reasons for using Julia.
Julia is not an outstandingly complex language (yes, C++, I am looking at you ). It’s just a mistake to assume that it is another variation on the Python/Matlab/R theme.
I’ve never found the parts of C++ I use (or need) to be extremely complex (i.e. I seldomly write a template, but use them every time through STL), and I’m happy I don’t need to dive into the really complex stuff. With Julia I’m still not sure whether to think of it as a scripting language that happens to have an advanced type system and is compiled, or whether to think of it as a traditional statically compiled language like C++ that happens to allow for more dynamism and run-time flexibility. I.e. my mental model on that is still a bit fuzzy and that also influences somewhat how you approach certain tasks, given prior experiences with the extremes of that spectrum (Python for fully dynamic scripting language, C++ for fully statically-compiled).
That is covered in
Noteworthy Differences from other Languages · The Julia Language
Those overviews per language deal with a lot of syntactical and small semantic differences. Nowhere does it say in those comparison chapters that Julia is fundamentally a different beast than e.g. Python. You can obviously draw that conclusion yourself from the other chapters, but it is left in the middle a bit.
It might be that when starting to use Julia one is already focused in obtaining very performant code. This is what brings people to Julia in general. And we can have the wrong impression, from start, that can be obtained “for free”, writing code as permissively as in scripted languages.
Yes, I got definitely bitten by that. Approaching Julia as “like C++ but I can leave off type declarations” did not really work very well. The same for “like Python but if I add type declarations all will become faster and better”. In fact, the previous “two languages problem” of having to combine Python for high-level stuff and C++ for the performant stuff has now turned into a “three languages problem” for me as it will take more effort to get skilled in Julia for (largely) replacing either of the two