HN user

DNF2

325 karma
Posts0
Comments204
View on HN
No posts found.

First of all, I think this sort of aggressive tone is unwarranted.

Secondly, I think it's on you to clarify that you were talking specifically and exclusively about static compilation to standalone binaries. Re-reading your first post strongly gives the impression that you were talking about the compilation strategy in general.

I would also remind you that Julia always does does-ahead-of-time compilation.

Furthermore, my limited understanding of the static compiler (--trim feature), based on hearsay, is that it does pretty much what you are suggesting, supporting dynamic dispatch as long as one can enumerate all the types in advance (though requiring special implementation tricks). Open-ended type sets are not at all supported.

I'm not exactly sure what you don't believe, your comment is hard to follow, or relies on premises I haven't detected. What you are describing in your first paragraph is somewhat reminiscent of dynamic dispatch, which Julia does use, but generally hampers performance. It is something to avoid in most cases.

Anyway, performance in Julia relies heavily on statically inferring types and aggressive type specialization at compile time. Triggering the compiler later, during actual runtime, can happen, but is certainly not beneficial for performance, and it's quite unusual to claim that it's central to the performance model of Julia.

If you are asking why Julia allows recompiling code and has dynamic types, it's not for performance, but to allow an interactive workflow and user friendly dynamism. It is the central tradeoff in Julia to enable this while retaining performance. If performance was the only concern, the language would be very different.

This is not how I understand the performance model. Allowing invokation of the compiler at runtime is definitely not something that is done for performance, but for dynamism, to allow some code to run that could not otherwise be run.

In performant Julia code, the compiler is not invoked, because types are statically inferred. In some cases you can have dynamic dispatch, but that doesn't necessarily mean that the compiler needs to run. Instead you can get runtime lookup of previously compiled methods. Dynamic dispatch does not necessitate running the compiler.

Lenses in Julia 9 months ago

Julia is fastest with immutable structures--why provide a built-in syntax for complex assignment to mutable types, but then relegate lenses to a library that only FP aficionados will use?

This is not really accurate. Performance in Julia is heavily organized around mutability, in particular for arrays. The main reason Julia does not fully embrace immutability for everything is, simply, performance.

Typst 0.14 9 months ago

Interesting. I have not experienced that, except when trying out the pre-release version of tinymist, and did some messy multiple view+cropping into a big pdf (testing out the new pdf-image stuff.) I chalked it up to it being new and beta.

Admittedly, I have still not created large documents in Typst.

Typst 0.14 9 months ago

2. (minor compared to Overleaf) typst compiles faster.

I would argue that this isn't minor. At least in my opinion, it makes a big difference.

Overleaf, already 3 pages into a document, with a couple of TikZ figures, was getting slow, as in multiple seconds wait for each save.

Typst, on the other hand (Tinymist in VS Code) is really realtime. Text updating within some tens of milliseconds, and figures included in far below a second. It really _feels_ instant, and to me that changes the experience a lot.

Typst 0.14 9 months ago

As long as Typst is on version 0.x,you should probably expect breaking changes. There is talk about changing even part of the parsing rules.

This is the risk of being an early adopter.

Once v1.0 is out, I hope it will stabilize for the long term.

That is not really correct. Type instabilities tend to disappear at function boundaries, which is one of the reasons why using functions is so heavily promoted in Julia, it helps keep type instabilites 'localized'.

Then you are back to the "two language problem". I'm sure that's not a problem for you and for many others, but there is a reason it has its own, widely known name. It really is a problem for people who are mostly not software developers, but instead engineers or researchers.

"Clanky"? That is a word I would use when comparing Julia and Python, but I would reverse the roles. I mean, python works well, and has almost everything, but it really feels, well, clanky.

I didn't even mention the dot operator syntax (.*,.^,./) used in Matlab, while numpy uses only implicit broadcasting. On the other hand, numpy can partially leverage map, filter, comprehension (though with performance loss). Julia has both much expanded dot-syntax and (multidimensional) comprehensions/map/filter with full performance.

What else? Matlab indexes with end, while numpy just leaves it open (e.g. 3:). Numpy allows negative indices, not Matlab. n:m is both a standalone range and an indexing expression in Matlab, not in numpy. Also numpy uses open ranges, Matlab closed ranges. And A[2:2:10] has dramatically different meaning in Matlab and numpy.

I forgot to mention the difference in function passing, the fact that Matlab passes arguments by value (unless it's a `handle` class) makes it really hard to do in-place transformations, as in passing an array to a function and modifying it, since the modifications are not visible outside the function.

In some cases, applying a limited set of basic operations might make up a significant part of development time, but in my experience most of the time is spent designing algorithms, parsing function input and managing the flow of vectorized expressions across function boundaries. And that is generally more efficient in the context of multiple dispatch with efficient loops.

For example, writing a function that works on scalars, then mapping or broadcasting it over array input is very good for productivity (and is efficient in Julia). On the other hand, designing an inherently array-based algorithm is often a headache that one must contend with for the sake of performance in numpy.

So, if you design somewhat complex or novel algorithms, I don't think object-dot notation, or the lack thereof, has a significant impact on productivity.

Yes, python exposes a limited list of names that map to operators, like __add__, __sub__, __ne__, __or__, etc. The list is large enough that it covers most normal usage, but the semantic meaning of the operators is normally fixed, so creating your own more specialized operators with new meanings is not very convenient (I mean, in principle, you can overload __xor__ to do something inventive, but it's probably a bad idea to veer from the established meaning of 'exclusive or'.)

In contrast, julia provides a nearly endless list of operators to use for whatever you like, allowing you to adopt mathematical operators from your field of study, for example.

Also, I am not aware of any type promotion mechanism in python, which, in Julia, makes e.g. binary operators on different types convenient to implement. The inherent multiple dispatch also seems more natural than the __roperator__ stuff you need to do in python.

Both zero-based and one-based indexing is common in mathematics, for example polynomials, exponential series, transforms, etc. are often zero-based.

But in most of the literature that I've seen, vectors and matrices tend to number elements starting with 1.

I must agree with the other poster that there are key differences between numpy and Matlab (and Julia).

All 1D/2D arrays in both Matlab and Julia come endowed with linear algebra semantics, so that `A*B` is a matrix product, while in numpy it is not, you have to create an actual `numpy.matrix`, which is a different class. Matlab is not consistent, though, so exp(A) in matlab will work element-wise, as will numpy (both for array and matrix), while julia returns a matrix exponential. The same difference goes for other functions like sqrt, sin, etc.. In Matlab, reduction functions typically work column-wise, so for example sum(A) returns the sum of each column as a 1xN matrix, while in julia and numpy the sum functions will return a sum over all the elements as a scalar. The same goes for max/min, etc.

Both Python and Julia have actual scalars, and with numpy, both have actual vectors, while Matlab has neither. Numpy's matrices, on the other hand are, conceptually, vectors of vectors (even though they are stored as contiguous memory) meaning that for example iteration behaves very differently in numpy than in Julia. Numpy iterates row-by-row, Julia iterates element-by-element. Matlab iterates column-by-column, though I rarely see that used in the wild.

Indexing, too, is different (and I skip the zero-vs-one-based stuff): indexing (with a single index) into a 2d array in numpy produces a row-vector, indexing into a julia or matlab 2d array produces an element (even though iteration in matlab produces column, as mentioned). Another point is that numpy slices return views, while the other two languages return copies (or, actually, matlab returns views that are copied if you try to modify them...)

Numpy arrays have restrictions on the sort of types they will accept. Elements must either be built-in numpy types, or the catch-all `object`, which is basically an untyped container that holds pointers to `anything`. In contrast, everything is a matrix in Matlab, so even user-class objects are held in homogenously typed matrices. Julia arrays will allow anything you like. Built-in types, user-types, homogenously, abstractly or heterogeneously typed (unions). And bitstypes are stored inline, not as pointers.

There are many differences, both semantic and practical, both between matlab and numpy, matlab and julia, and julia and numpy, this is just off the top of my head.

(Actually, I should have gone more into the syntax stuff, constructor syntax is way different in numpy, as is the way you do operations, with numpy using `obj.method()` to a large extent, unlike matlab and julia, which use regular function call syntax for array operations.)

You are mostly correct, though I want to point out that N-dim arrays are different from matrices. In Matlab everything is a matrix, unless it is a higher-dimensional array. This means that any 'scalar value' is actually a 1x1 matrix, which you can verify by calling the `size` function on scalars, vectors, and matrices, but higher-dimensional arrays it do not fit this pattern. In fact, N-d arrays are the 'odd man out' in Matlab. The article you link to is actually a bit inaccurate in this regard.

Well, it's called JuPyteR (my capitalisation), and originally supported Julia, Python and R. The exact provenance of the name is a bit unclear, but it's either deliberate or a happy coincidence.

Pluto.jl is also 'like Jupyter', but better and more popular among Julia users, as far as I know.

First of all, Mojo is quite new. Secondly, there might not be much CPU performance left on the table for that benchmark, no matter how much money you throw at it.

You must mean REPL, not notebook. I've been following the community since before the move to Discourse, and "use the REPL" surely outnumbers "use a notebook" by orders of magnitude.

I can confirm that there were multiple (heated) arguments on Discourse, where some posters completely dismissed the need for debuggers in general. I remember it quite well.

It was very strange, but I don't think it says anything about the community, except that people have different opinions and preferences, like in any community.

It's really all down to your tone and attitude. If you're hostile, demanding and negative, you will indeed get pushback, but that's human nature.

Some people feel that they should get to act like a prick, while everyone else should be humble and courteous.

If you act like a decent person person, there's no problem pointing out weak points in Julia and request help to work around it. If your only input is "Julia kinda sucks", what kind of feedback do you feel that you are owed?

You make it sound a bit like they optimized the heck out of Julia, while the Mojo sample was a naive little thing in a new innocent language.

The reality is that the Julia optimization was just a rewrite to use the same algorithm as Mojo, and that the Mojo code was heavily optimized.

I don't really believe you ran either the Mojo or the Julia code. There's no way your single-threaded C code outperformed multi-threaded simd optimized Julia or Mojo. It's flat out impossible.

The only other explanation is if you ran the non-simd Julia version under a single thread.