For instance, just consider that you cannot directly access an array that is returned from a function.
How?
For instance, just consider that you cannot directly access an array that is returned from a function.
How?
Matlab:
function [a] = f(a, b, i)
a(i) = b;
end
This cannot be done:
a = [0, 3, 5]
f(a, 1, 1)(1)
In Julia:
a = [0, 3, 5]
f(a, b, i) = (a[i] = b)
f(a, 1, 1)[1]
I see, this is fascinating. Is there any source, where I can find this sort of Julia/MATLAB differences?
I’m a Matlab user since R2012 and I can say it was my first programming language I really used (did some C in college). Here’s my take on Matlab:
One of the things I started to hate about Matlab, after trying Julia, is the lack of namespaces. It has only one “global” namespace and every time you want to make some code available you need to “add it to the path”. This is very risky if you work with different codebases which can conflict with each other.(Matlab has classes and that can alleviate the problem a little, but it’s not as expressive as Julia’s multiple dispatch).
It’s hard to envision these kind of things if Matlab is your only background(as it was my case) and you learn to dance around them, but once you try something else(Julia in this case, Python is similar, but I like Julia’s Pkg much more), you start to realize that there is big world with lots of goodies. This “ease of use” that Matlab promotes is a double edged sword, because as codebases grow, they are harder to maintain and people are educated with the mentality of “everything in one place”(everything in one huge script, everything in one huge repo).
Another cool point in Julia is the keyword arguments of functions and the default values for arguments. This is something that drives me crazy when I use Matlab now, because I have to clutter my code with a lot of if, else, for loops over varargin or even worse, use the horrific input parser.
Then I could add Julia’s consistency when using broadcasting (you add a dot, you have elementwise operation). Matlab uses the dot notation for vectorization, but there are a lot of cases where it broadcasts automatically even if the user didn’t write the code like that. Some might call that convenience, I call it confusing.
You can sort of do metaprogramming in Matlab using the “eval”, but it will be painfully slow and it’s not advised. Julia has efficient macros.
Matlab lacks basic types like tuples and dictionaries (it recently added containers.Map to mimic a dict)
Then there is the hilarious choice of Matlab to output line vectors out of a lot of built-in/user functions, although the language is column major. This forces me to add a lot of checks in my functions to see if my array is a column.
I could go on, but my 2c is that one needs to try stuff in both languages to see their advantages and drawbacks. For me Julia was in eye opener.
And this is really only for .*
, .^
and ./
, you can’t vectorize arbitrary functions or operators.
The implicit expansion thing is a great example.
To be clear, implicit expansion is an extremely useful tool to save a bunch of ugly bsxfun(...)
s littering your code. In a language that demands vectorization for performance code, it totally makes sense why they would introduce it. But… it’s also a terrible source of hidden bugs and code obfuscation, as this link points out.
What you need is something that handles broadcasting that
This is why Julia’s dot broadcasting syntax is so cool. If a
is a length-3 vector and B
is a 3x3 matrix, a .+ B
will broadcast a
to the higher dimension and a + B
will throw an error. All three of the above requirements are met. And Julia doesn’t even need to use broadcasting to have fast code.
Yes! This hit just about all of my worst pain points. Built-in functions sometimes returning row vectors and sometimes column (and having to constantly check for this), containers.Map
almost never does what I want it to, and the input parser is just the worth thing ever (and that is the best way to handle keyword arguments in MATLAB).
I’ll add to the list that cell arrays have to be accessed with different syntax than arrays, so I’m constantly writing if iscell(...)
. This Is especially bad with the whole char arrays as pseudo-strings thing (and now they have real strings, so there is always going to be the issue of supporting both).
Also, for
loops only iterate over a vector if it’s a row vector and pass the whole vector in as a loop variable if it’s a column vector. This combined with not knowing whether you ever have row or column vectors due to the point above makes the nice for thing=things
syntax that is common in Python and Julia pretty dangerous, even though it’s supported.
Here are some points, off the top of my head. Several of them overlap with points raised by other posters:
Whenever you want to define a function, you can’t do it from the command line, or inside a script (except with some major limitations)
Input parsing in Matlab is a nightmare. You have the inputParser
class now, but it seems really heavy and awkward.
This is related to the above. You can `fake’ keyword arguments using two consecutive inputs, one string for the keyword and one for the value. It’s an awful kludge.
You can’t have scalars, so you always have to consider the ramifications of the fact that your value is a container with a shape and linear algebra-like behaviour. Often you want your code to behave one way if it’s a `scalar’ and another if it’s a vector and a third if it’s a matrix. But it’s always a matrix, and it requires a lot of awkward tests and planning. (Is a single number a scalar, is it a vector or is it a matrix?)
When you assign to a variable, the object you assign is copied. So you cannot pass an array into a function to mutate it (Matlab can only somtimes mutate as an optimization if certain cases). Mutation is supported for user classes that inherit from the handle
class.
It’s great!
a[i][j]
or foo(x)[1]
etc are impossible in Matlab, so you must create intermediate variables.
varargin
and varargout
in Matlab is an annoying mess to work with.
Matlab doesn’t have proper iterators, so you will normally have to do for n = 1:length(x)
. You can in principle write for val in x
, but it only works for 1xN vectors, not Nx1. For a matrix each iteration will actually return a column of x
.
Column major language, but almost all internal functions return row vectors. Also, iteration only works for row vectors, as mentioned. Proper flat 1D vectors are amazing.
Vectorizing code is the major coding style in Matlab, but it’s so inconvenient. You have no general map
function, let alone the awsome broadcasting (you have a really pale type of broadcasting that works for +-*/
). Instead you have different and awkward functions, cellfun, arrayfun and structfun for different types of collections.
foo
is a function callYou don’t have to use parens for a function call, so you cannot tell if foo
is a variable or a function call. Passing functions around requires using @
to create a ``function handle’’.
Due to everything being a matrix it is actually really hard to create empty arrays of objects. I struggled to implement this for some classes recently. You can do it, but it’s messy, verbose and hard to understand.
There’s containers.Map
which noone uses.
These are incredible, and there’s nothing like it in Matlab.
Nope.
This is a big mess. Previously strings were char arrays, and they are still what is mostly used throughout the language. Now they have more proper strings, but they are barely used, and also, of course a string is always a [1x1] string array. I can’t really go into this, but it is awkward.
This is a common problem in most programming languages, except Julia, as far as I can tell. ``Sorry, this function only accepts double floats.’’
As @balinus wrote, the prototyping/exploration phase can often be badly slowed down by the computing time required by the numerical experiments to complete. I have witnessed too many times laptops moaning in (relative) silence while they were bravely trying to complete probabilistic computations for hours/days/nights (usually on a single thread).
Such quantity of wasted computing (and electrical) power drives me several time to write C++ kernels for MATLAB users. I may have felt proud and marginally useful doing so
With Julia, the very same mathematicians/scientists can reach high performances on their own. So, probabilists’s laptops of the world say (in their chest) thank you Julia !
Unless they are subfunctions to the main function in the file, in which case you instead cannot access them outside of the main function, making unit testing of those subfunctions a major pain. (Actually I found a way to retrieve subfunction pointers, but it’s most horrible hack I’ve ever done.)
Disclaimer, I haven’t followed Matlab developments since ~2014 so maybe there’s a solution to this problem now.
Not that difficult to workaround
function varargout = mylib(fun_name,varargin)
if (nargout)
[varargout{1:nargout}] = feval(fun_name, varargin{:});
else
feval(fun_name, varargin{:});
end
function fun1
function fun2
...
and call it like
out = mylib('fun1', args);
That appears to be an extraordinarily unpleasant way of defining functions.
It was not meant to be pleasant but to make possible a case that is otherwise not in Matlab
I understand, it’s a clever hack It’s a nice example of what people work out to workaround shortcomings of the language. The fact that you worked out such a solution emphasises how severely limited the matlab language is.
The preferred way to handle namespacing in MATLAB is to put the functions you want (all as separate files) in a folder that starts with ‘+’. So you would have fun1.m and fun2.m in a +mylib folder then you can call mylib.fun1(...)
. To be honest, I don’t find it as awful as everyone else seems to. I mean, it is a little annoying that you have to have all of your externally callable functions in separate files, but in the large space of my MATLAB gripes, this one takes up a pretty small corner.
I think it’s pretty annoying for interactive work, when I just want to define a throw-away function. The overhead of coming up with a name and a location to store the file, and make it available, but avoid all the other old throw-away functions you made, is to me similar to the annoyance of having to come up with a username/password combination for throw-away accounts (that is, the overhead is pretty big.)
Thanks for bringing this thread back alive—I am still learning (and struggling) a lot, but the slack channel really helps with random small questions that I need to ask on a daily basis. My feelings so far: I love the syntax and the community, and when Julia works I am very happy. But often I am frustrated by what I feel “non-programming” issues (which isn’t true, but I am used to MATLAB’s “works out of the box” paradigm), like something breaking, no knowing how to get something to work, developing packages, managing paths, etc. For example, right now I got my analysis script running and formatted nicely but I can’t get weave.jl to produce a report I need to submit (some issue with plotly backend plots not being generated).
I recently bought the book Hands-on Design Patterns and Best Practices with Julia by @tk3369 to get a feel for, as you said “modern software engineering and workflow”. It is not specifically for MATLAB users, and is not a beginner book, but from what I read from the preface seems to cover general principles that are applicable in all domains. I’ve only read it for a day, so can’t vouch for it yet but the general tone of the book is very gentle and encouraging.
I’d love to hear from @tk3369 about what he feels about people coming from propriety languages such as MATLAB and how we can make the journey to effectively using Julia as smooth as possible.
Hey @ElectronicTeaCup, thanks for the tag.
Unfortunately, I am not a Matlab user and I can’t quite feel the pain that everyone else went through. On the other hand, I am always amazed that many people in this community can write very good code even without any computer science background.
I cannot say whether it works for everyone but I can definitely share how I learned Julia:
Let me tell you my favorite story. While reading some string manipulation code in Base during my 2nd month of learning Julia, I came across a bug in rstrip
and I reported it here. It led to a constructive motivational reply for making a PR. The thread went on about what the correct fix should be. Eventually, I got excited and submitted a two-line fix. It feels good to contribute to Base If I can do it, you can do it, too.
Hope it helps.
Tom