C++2026 vs Julia syntax comparison

Are you kidding, guys?

C++


vs. Julia

7 Likes

The function body is only 2 extra lines if you ignore the include statements, and the extra lines seem to be for constructing the range. This doesn’t seem that bad to me.

5 Likes

To be honest having executors as a first class feature in Julia, as shown in that example, would be fantastic. Transducers.jl has them of course, but it’s not quite the same. Similarly a lot of the STL container features recently are really well thought out. It would be nice to have a similarly constructed container set up in Julia.

8 Likes

It is not just about how many lines, is it?

2 Likes

it’s a different language with a different set of strengths

julia, are you kidding?

N = 40
x = float.(0:1:N-1)
x .*= 2
x .*= 3.0
for (i, e) in enumerate(x)
    @assert e == 6.0 * (i - 1)
end

vs spoken english:

multiply the numbers from 0 to 39 by 6 without error
6 Likes

What do you find objectionable about the code?

1 Like

Parallel broadcasting syntax would be nice to have. I’m not sure what parallel means here though.

7 Likes

That’s what the executors are nice for, you can exactly specify what resources are used etc

3 Likes

collect(0:39 .* 6)

Not up-to-speed on the difference, and why does it need to be in Julia? In C++ you want a stdlib because of many compilers, in Julia you want as just much as possible out of the stdlib, only what Julia needs for itself and to hide platform differences. Actually I want OpenBLAS (and LinearAlgebra and more, already on the way) gone.

because the semantics in Base does not allow such extention. If people already wrote their code with a .=* b, it won’t be possible to enable parallel or even distributed execution without re-writing the code.

The Julia container ecosystem is very fragmented because the container interfaces are both underdefined and underdocumented.

Julia’s AbstractArray interface is fantastic, and provides much of what C++ is only now just catching up to. It’s still better in a lot of ways. But for all the extensibility that Julia provides, we lack rigorous interfaces for what an AbstractArray actually is, what it can do, and how it’s allowed to do it. Even more so for iterators and Dicts etc. Because we lack even guidelines around a lot of this it’s difficult to parallelize automatically, and to do STL style executors and abstract algorithms.

In Julia you get so much of this for free, but in many ways that freedom has led to stagnation vs the STL. There have been many attempts to solve this: ArrayInterface, ArrayIteration, KernelAbstractions, Swizzles, the wonderful Transducers, etc all address some part of this.

Julia can do these things, I think much better than the juggernaut that is C++. In particular we don’t need to be as strict as C++ in a lot of ways. But it would be a Julia 2.0 level change, with an absolute ton of work.

11 Likes

Those don’t look equivalent to me, and in a way that makes Julia only a bit more concise. The Julia version doesn’t const N, there’s no main, the scaling by 3.0 doesn’t take a parallelization trait.

Sure, happy to oblige.

using Folds
const N = 10
x = float.(0:1:N-1)
x .*= 2
Folds.map!(a -> 3 * a, x, x, ThreadedEx())
for (i, e) in enumerate(x)
    @assert e == 6 * (i-1)
end

I will take the Julia version over the C++ bloviating anytime.

4 Likes
Folds.map!(a -> 3 * a, x, x, ThreadedEx())

Is that safe? I don’t think it would be safe with Base.map!.

IIRC unlike the functions with reductions, map! operations are safely independent when the indices of the aliased input and output match, but evaluation order matters when the indices are not aligned. I don’t know why this wasn’t added to the documentation for map! specifically along with the warning against output-input aliasing that was recently added to this class of functions.

2 Likes

I realize I kind of answered a different question in my initial reply. The reason you want something similar to this in Base is that iteration is a fairly core part of most languages. We don’t necessarily want a ton of actual algorithms in the standard libraries, but having the definitions of the iteration framework for the language is a fairly uncontroversial idea. Executors are a small but equally sensible extension to that idea, allowing you to write generic algorithms that abstract the where (device vs. host), the what (container), and the how (executor) of an iterator.

This would get us two things:

  1. Massively decreased code size across the ecosystem, by greatly increasing the genericity of iterator based algorithms. Think how much code has to treat SparseArrays differently from Arrays for instance, simply because an iterator will densify the SparseArray by default.
  2. Those algorithms that are included in Base can do magic things like Chapel auto-parallelizing simply by passing in a new executor.

Of course settling on the universal minimum interface for good generic iteration is really difficult, as seen in the dozens of packages that try to make a bit of progress here. There’s no one size fits all, for instance flattening nested for loops into one iterator works for some codes but leads to tons of extraneous if statements for other codes. Luckily for us we can always write specialized dispatches for maximum speed where needed :slight_smile: .

2 Likes

Perfect translation of the C assert into Julia @assert :wink: (both being an antipattern for this kind of checks since they can compile to nothing at all depending on the optimization flags).

As @Palli noted it’s funny that Julia tries to excise LinearAlgebra from Base while C++ adds it…

3 Likes

It never compiles away in Julia, I checked. Hypothetically, that could change and I do want a debug mode, but unsure if it should be compiled away without it.

I remember when the STL arrived (the more interesting part of C++, better then the OO part), but you are talking about recent STL containers, i.e. it took a very long time for C++ to develop to that point. I don’t know, maybe stuff was available earlier, in Boost, and I believe some stuff from Boost got into the C++ standard. More than strictly needed? People can and do use Boost (maybe never all compilers could use it), now they raise the minimum a certain C++ version compiler must support. I’m just saying Julia doesn’t have that same issue, and Base could add stuff after it’s been developed and perfected elsewhere, but strictly doesn’t need to.

I like the idea of telling the scale function how to execute. It reminds me of Chris’ talk “LinearSolve.jl: Because A\b is Not Good Enough”.

2 Likes

exactly this!

Quite often we have a forward model which contains some parallel functions (FFTs, …).
But then the loss function evaluation is some broadcasting syntax and hence single-threaded.
Tullio.jl kinda solves this for CPUs but then the code does not run very well with AD on GPUs.