Why are there all these strange stumbling blocks in Julia?

I have programmed in Python so far and find the Python syntax very convenient. When learning Julia I constantly notice things that I can not understand:
Why is there no short and simple floor division operator like in Python //?
Why is the type conversation not as short and sweet as in Python int(“4”)?
Why do I concatenate strings with * instead of + ? (that makes no sense to me at all)
Why does the indexing start with 1 instead of 0 as in most established languages?
What was wrong with the simple dict syntax of Python? {“Hello”: “World”}
Why elseif and not elif?

There are two: div and ÷, the latter being an infix operator.

Type conversion is completely straightforward: Int(x). If you are talking about parsing strings into numbers, that is not conversion, but parsing, and is, appropriately, called parse.

This is a big discussion, but string concatenation is more like multiplication than like addition, therefore * does in fact make more sense, but it is more unfamiliar to new users.

0-based indexing is good in some places, 1-based in other places. I scientific programming 1-based is better, and frankly, IMO, it also makes a lot more sense in general. It’s too much to get into here, though.

Nothing wrong with that syntax, but braces was used for a different purpose in Julia, which was more important. Also, dictionaries are probably less important and less used in Julia than in Python.

55 Likes

I think there is a more fundamental answer than @DNF’s. Julia is not a python clone. It was not intended to be a python clone. Julia takes inspiration from a large number of languages (C, python, lisp, Matlab, Fortran, APL, and probably a bunch of others).

50 Likes

Just to elaborate a bit on why * and not + for string concatenation. Whereas for most if not all mathematical objects + is symmetric *, depending on the type, is not (think about matrices products). Obviously string concatenation is not symmetric in general.

9 Likes

In my opinion the real question should be “why elif?” :slightly_smiling_face:

I like Python a lot, but seriously all of these points are just as weird, or even weirder, if you go the opposite direction (except 0-based vs 1-based, to me it’s just indifferent). Julia’s keywords make complete sense: want a function? function. Want “else if”? elseif

23 Likes

Please note that these two clauses are very much correlated. Do you feel like these stylistic choices were obvious to you when first learning Python? Maybe if your first programming experience ever had been with Julia then you would find its choices more convenient and Python’s more cumbersome?

In fact, the implicit statement that these are the largest stumbling blocks you’ve encountered is a testament to me about how relatively seamless it is to move to Julia from Python. Imagine how much more difficult and “inconvenient” you might find it when trying out a language with a steeper initial learning curve, like e.g. OCaml

20 Likes

Not really trying to pile on, but I just got curious so I compiled a list of string concatenation operators across a bunch of languages. If any of these are incorrect, blame ChatGPT :slight_smile:

Some languages (C,, Lisp-y ones) do not have infix operators for string concatenation at all.

  • Maple uses ||
  • Mathematica and Gap use <>
  • Agda, Idris, Erlang, Haskell, Elm, Zig all use ++
  • F#, OCaml use ^
  • Ada, Nim use &
  • Fortran uses //
  • Lua has ..
  • Perl has .
  • Smalltalk has ,

And of course many popular languages use +, including C++, Python, Java, Go, Ruby, Typescript, Rust, Solidity, R, Swift etc.

So while it does seem to be true that Julia is a bit of an outlier in using specifically *, there are plenty of other examples of languages choosing to diverge from +.

9 Likes

When I learned Spanish, I found all sorts of quirks that were unintuitive and frustrating. I found it hard to turn my English words into something coherent.

Likewise, when I came from Python to Julia, I frequently had problems that were generally of the form “How to I translate X thing from
how I’d write it in Python to Julia?”

Why does Spanish have so many verb conjugations? Why does Julia use full length keywords? There are reasons for both, but more importantly, it just is what it is.

The important thing to do when learning any language is to learn the fundamentals well enough that you aren’t thinking in your native tongue and then translating.

16 Likes

I think the more interesting question to ask here is: why do most established languages use zero-based indexing?

When you understand that, and then you learn how modern compilers make it unnecessary, then the question should become: why don’t more modern languages use 1-based indexing instead, as we do naturally in life anyway?

Indexing an n-dimensional collection is so much more natural with 1:n than 0:n-1 or Python’s 0:n with last element excluded.

6 Likes

Overloading the multiplication operator for concatenation doesn’t make that much sense, I don’t think it’s worth defending. Better than + though.

Btw @adienes Where did you get that impressive list?

You should probably read Noteworthy Differences from other Languages · The Julia Language.

2 Likes

I asked ChatGPT to "please translate Python code ‘a’ + ‘b’ into language XYZ " :sweat_smile:

8 Likes

The word you are looking for is “commutative”, I believe.

This is a Julia FAQ: Why does Julia use * for string concatenation? Why not + or something else?

9 Likes

Except that div is not floor division, fld is. This is one of two points where I’m jealous that Python has got it right but Julia hasn’t.

4 Likes

Why is that wrong?

Because having the rounding change direction when the first argument passes zero is bug trap. Maybe not that much for the division itself but when it comes to the corresponding remainder operator, %, it has (in Julia terminology) rem semantics in Julia and mod semantics in Python. A frequent use of the remainder is to model cyclic behaviors and having that suddenly switch sign is a bug waiting to happen. (If you are guaranteed that both arguments are positive, mod or rem doesn’t matter, which covers at least 90% of the uses of %. The real danger is when you thought they both were but there turns out to be a corner case where the first argument becomes negative. Or you later change the code and forgot the assumption.)

10 Likes

I like *. Strings with concatenation do form a noncommutative semigroup, for which the operation would conventionally be written as multiplication. Starting out with Julia, my reaction was along the lines of “Nice choice. Good call not using +.” I assumed that someone involved in that choice likes algebra and was persistently annoyed at seeing + used for something noncommutative. But I’m sure there is something to be said for not trying to relate string operations to algebra and going with a special operator. I’d imagine * does look odd to a lot of new users.

9 Likes

Huh, I thought it was because concatenation is distributive over alternation.

String concatenation and regular expression concatenation are consistent:

julia> match(r"abc"*r"def", "abc"*"def")
RegexMatch("abcdef")

Interestingly though, we don’t have a regexp alternation operator implemented:

julia> r"abc" * r"def" # concatenation ok
r"(?:abc)(?:def)"

julia> r"abc" + r"def" # alternation not implemented
ERROR: MethodError: no method matching +(::Regex, ::Regex)
3 Likes

Are there any practical differences between using + and * for string concatenation, apart from the abstract argument that “it communicates the right algebraic properties”? For instance, certain generic implementations that work for strings, too?

Try "hello" ^ 5

1 Like