Are there concepts ingrained by 30 years of using Pyhon in my brain which I need to throw away and get rid of because they will lead to issues with understanding how to read and write Julia code (except zero-based indexing, which I didn’t get friend of after 30 years of using it)?
By the way: such question is never “solved” so feel free to contribute any further hints beyond what is already documented in the link provided by the “solution”.
Yesterday I wasted more than a few minutes learning that Python ranges don’t include the numbers you supply.
Yes … this is one of my reasons why I am ready for the change … it was annoying for me in Python … I didn’t get used to it, so … this is no problem for me in Julia as I expect from code to include the upper value of the range into the range. Another reason is that my gut feeling is that the most smart of the smart are no more engaged in supporting Python … so maybe they are now supporting Julia instead? Or where are they went leaving the Python community? What I am not satisfied with are the response times in Julia REPL … I am used to instant response time, where Julia REPL needs up to a full second to come up with the response to simplest instructions.
https://docs.julialang.org/en/v1/manual/noteworthy-differences/#Noteworthy-differences-from-Python
Edit: fixed link to last updated docs
It’s more likely inspired by Matlab than Python, but regardless it’s the only sane way to number diagonals. It’s more interesting how they are placed relative to the main diagonal than how far they are from a corner.
Yes … the main diagonal is a special one: the one with the index equal to number of rows. Numbering from zero and especially with negative numbers is what is in my eyes insane. The concept of a ZERO as something special is just insane … There isn’t such thing as zero … why cope with something that does not exist? Focusing on what something is NOT instead of looking what it IS? Saying YES to what is, instead listing of some of the endless options to say NO, this is not this and not that. The most important has the label: “zero”. Isn’t this insane??? Would you prefer to be a “Special Leading ZERO” instead of being “The ONE”?
I’m new to Julia too and the first time Julia performs a function, it can be very long, indeed…
Apparently it’s due to how functions Julia…
Here a page can interest you:
https://docs.julialang.org/en/v1/manual/performance-tips/
Python follows the established C convention of looking at offsets and not indices. There isn’t a zero index, but there very much is a zero offset that corresponds to the first index.
What I am missing in the list of differences between Julia and Python ( Noteworthy Differences from other Languages · The Julia Language ) is how Julia slices differ from Python. If I got it right a Python slice has a form [start : stop : step] where a Julia slice is [start : step : stop]. Strange that this is not mentioned …
I think mathematics accepted zero as well as negative and complex numbers a few centuries ago. It’s a bit special as a neutral element for addition. Just like 1
is neutral element for multiplication. The smallest infinite cardinal is even named ℵ₀. So 0 and negative numbers are definitely something one should get used to.
In the case of julia you can find the diagonal of a matrix A
with diag(A)
, there is no zero. Off-diagonals are numbered by their offset from the main diagonal, the positive direction being upwards. You are free to create your own function which uses a different convention, e.g. mydiag(A, i=size(A,2)) = diag(A, size(A, 2)-i)
.
you’re referring to an out of date version of the documentation?
The updated doc is here: Noteworthy Differences from other Languages · The Julia Language
- Julia’s range indexing has the format of
x[start:step:stop]
, whereas Python’s format isx[start:(stop+1):step]
. Hence,x[0:10:2]
in Python is equivalent tox[1:2:10]
in Julia. Similarly,x[::-1]
in Python, which refers to the reversed array, is equivalent tox[end:-1:1]
in Julia.
The biggest stumbling blocks always come from the concepts for which you have a slight misunderstanding of in the original language itself or are mistakenly transferred to a slightly different concept in the new language.
Zero-based indexing is an actually fairly good example. An index i
in a zero-based language is not identifying the i^{th} element (starting the count at zero). It’s saying you are i
steps away from the start of the array. But this isn’t obvious — many folks want to think of indexing as counting, so instead of using offset imagery in their head they change their mental models to “count from zero” instead. And that often works. But then when faced with a new language that detangles the two, it can be quite confusing why diagonal indices should “count from” zero and other indices “count from” one.
But the answer is right there — the reason the main diagonal is “index zero” is because it is definitionally an offset! And you want to be able to talk about the +1 and -1 diagonals that are offset one above and one below.
Or another great imagery to have in mind is that of a fence with fenceposts — you count the number of posts and measure the number of spans.
If you’ve changed your mental model to always think of 0^{th} elements as counting from zero, you’re going to have a hard time detangling the number of fence posts from the number of fence spans any time you’re faced with problems that contain both.
Here is a nice comparison of Python and Julia syntax for some basic things.
Classes and inheritance
In Python, everything is an object…
So it’s not difficult to know which functions can be applied to an object… I don’t remember what command it is, you can have a list of all the functions that can work…
I don’t think such list exists with Julia…
Python’s approach to OOP (with its classes, inheritance, methods, dot-oriented programming, etc) definitely stands in contrast to Julia’s separation of data and functions, but I’d still say it makes for a very useful (and strong!) foundation for learning what Julia does. It’s in learning a second language that you generalize your understandings.
The hardest things to generalize are the concepts where your first language led you down roads that were prone to get your mental model subtly wrong (because then it’s not just learning, it’s un-learning), and places where Julia happens to use the same vocabulary for a slightly different concept.
A very common example is around variable naming/labeling/binding/boxing/passing/scoping rules and function evaluation strategies. There are many ways to do things subtly differently here — but Julia and Python are in great harmony on the trickiest points.
I’m struggling to think of actively harmful confusing concepts in Python — most core concepts are directly transferable. But perhaps one is in how you structure large Python codebases vs. Julia: each individual .py
file is implicitly a (sub-)module whereas Julia’s .jl
s are not.
Well, you can find the methods
applicable to an object. Don’t think its possible to also find the functions
which might apply to your object, e.g., via duck-typing – the type declarations recently introduced in Python might help though.
In Julia it’s indeed harder to find methods as types can be used in many different combinations and especially built-in types often dispatch to many methods. There are methodswith
and apropos
though which often help – but, admittedly are not as well integrated as hitting tab
a couple of times. On the other hand, you get a lot of mileage out of generic code and often just need to memorize a few functions along the way.
Overall, I guess the best approach for Julia has not yet been found, but I suspect it might be very different from other (OOP) languages. Inspiration can maybe taken from Common Lisp – which is more similar than other languages – and relies on introspection via its runtime for obtaining information (still finding Slime quite nice, but maybe the commercial IDEs, e.g., by Allegro might be even better – anyone has experience with them?). Also, LLMs hold a lot of potential here – maybe it would be enough to just index all doc-strings, function signatures etc. in a vector DB and have the IDE run integrated queries on that?
This inspired me to check, and there is a similar function that know about: methodswith
.
struct ABC
x
end
foo(y::ABC) = y.x
methodswith(ABC)
This shows all methods that require an ABC
type.
In Python you use dir(objectName)
to get a list of all supported methods and properties and from there you can recourse deeper for nested ones.