Why are there all these strange stumbling blocks in Julia?

Why concatenate at all? It’s overrated (often not needed) and slower than e.g. if you can do:

julia> println("I'm on ", "cloud ", 9)
I'm on cloud 9

It’s superficially similar but not the same as:

Note, you can most often change commas, as there the first one, to *, e.g. while doing using println, but not for the latter, since * only joins strings, not numbers, on either or both sides. String interpolation is another option, but also slower (while handy), since, I believe, it does an implicit concatenation.

C++ has >> (and <<) for streams, hacking those shift operators to do different things, e.g. when printing…

Yes, you should know about * for concatenation (and ^ the logical extension of that, though rarely used) at least to know both for reading other peoples code, but I wouldn’t even teach it first as something important, since concatenation is far from free in any language. So if you can simply print the strings separately in order as I did, without concatenating first, it’s faster (less tress on the garbage collector, also a reason to prefer << in C++).

if you want to only join, not print you CAN do cat_string = string("I'm on ", "cloud ", 9), or alternatively join(["I'm on", "cloud", 9], " ").

Such is logical to me, and when you need to join with a separator above, it’s completely illogical to me in Python:

>>> " ".join(["Hello", "world!"])
'Hello world!'

If that’s natural to you then it’s only single dispatch bias that was beating into you!

Why is there no short and simple floor division operator like in Python //?

It’s been answered what the alternative is, but why not? It isn’t a hugely used operator, and // is taken for rational in Julia (while maybe not used a lot, they are useful and could be used more often, can be made faster and then maybe they will be used more…they are they’re the default in Raku, former name Perl 6). I can easily justify / being a regular (float) division, that’s what you use usually, much more important, why Python 3 changed to that from integer division of Python 2.

Many language, also e.g. MATLAB is 1-based, I support that, but note Julia also supports 0-based (though a package), or arbitrary. You most often shouldn’t care, and use begin and endandeachindex` (at least in generic code, packages for others).

1 Like

You are absolutly right.
When I saw that Julia could return several things at once, I realized that I have to change a few habbits.
But the old reflex are still there. For instance, I have a function returning 4 Float64. Well, I defined the function as returning a Vector{Float64} of 4 elements instead of simply returning a b c and d. This is ridiculous and I need to evolve.
Don’t worry, I’m working on myself.

5 Likes

Beleive it or not

I’m used to finish a main() with exit(0) just to conclude that all end well.

When I started using MPI I realized how it worked because an exit() will simply kill the whole thing on all servers at once. The the MPI compiler (kind of) is simply changing your main() into a function. So you have to return, not exit, once the server is done with its part.

Working on myself…

Thing is, the function doesn’t really return 4 things, but a tuple of length 4, (a, b, c, d). You can write it without the parentheses, but it’s really a tuple. If you like, you can write

return (a, b, c, d) 

and that’s perfectly idiomatic.

(Don’t return a vector, though, that’s horribly wasteful.)

1 Like

Shocked and horrified, I had to try it for myself:

julia> if(false) return(1) else(return(2)) end()
ERROR: syntax: extra token "(" after end of expression

Faith in humanity restored.

What version are you using? 1.8 and 1.9 on my end.

P.S. I wouldn’t be opposed if the final () invoked a function call, but doing nothing is obviously bad.

2 Likes

I would write generally, without thinking much: return (; a, b, c, d) , then you can use it any of the multiple ways:

(; a, b, d) = foo(x1) # correspondence by name
c = foo(x2).c
e = foo(x3).[2]
f = foo(x4).[:d]
g, _, h, j = foo(x5) # correspondence by position
7 Likes

12 posts were split to a new topic: Return value of findmin/findmax

The “naturalness” of 1-based numbering is not just the result of familiarity and habit. It also has to do with having consistency between cardinal and ordinal meanings of numbers.

For example, if we have 1 (cardinal) apple, we call it “apple 1 (ordinal)”. When we add another apple, so that now we have 2 (cardinal) apples, we call the new one “apple 2 (ordinal)”, etc.

We’re also just as adept at “0-based” sorts of numberings when it comes to things like birthdays and other durations or lengths. We don’t even realize we’re doing it, which leads to all sorts of confusions when the two conventions collide in real life, too.

16 Likes

Yep

julia> Dates.default.([Year, Month, Week, Day, Hour, Minute, Second, Millisecond, Nanosecond])
9-element Vector{Period}:
 1 year
 1 month
 1 week
 1 day
 0 hours
 0 minutes
 0 seconds
 0 milliseconds
 0 nanoseconds
9 Likes

Even in those cases, that’s not how we number them. When you’re 11 years old, you’re in your 12th year. And year 2023, contrary to popular belief, is the 2023d year of the era.

5 Likes

PerfectPopcornGIF

4 Likes

Yup! The first century only had 99 years!

3 Likes

Fun fact: In South Korea, they use 1-based counting for age :slight_smile: But apparently they’ll get rid of this system this summer which leads to everyone becoming younger:

9 Likes

Very interesting.

However, if you look at the code below, don’t you think the error on “c” is strange? It’s kind of there, but not.

julia> function test()
       a = 1
       b = "b"
       c = 3.0
       d = "α"
       return( ; a, b, c, d)
       end
test (generic function with 1 method)

julia> (; a, b, d) = test()
(a = 1, b = "b", c = 3.0, d = "α")

julia> a
1

julia> c
ERROR: UndefVarError: c not defined

julia> b
"b"

Further, I have this:

julia> toto = test().[2]
ERROR: syntax: invalid syntax "test().[2]" around REPL[8]:1
Stacktrace:
 [1] top-level scope
   @ REPL[8]:1

julia> toto4 = test().[:d]
ERROR: syntax: invalid syntax "test().[:d]" around REPL[10]:1
Stacktrace:
 [1] top-level scope
   @ REPL[10]:1

What am I doing wrong?

a=b returns b, so (; a, b, d) = test() is printing out the result of test() which has c, but isn’t assigning it to a variable.

3 Likes
julia> test()[2]
"b"

julia> test()[:d]
"α"
1 Like

I know this is contrary to popular usage, but the first century ended with Y100, and the 21st century started on 2001-01-01.

My favorite off-by-one error is Swedish rapper Markoolio’s 1999 song “Millennium 2”, which celebrated the arrival of the year 1001 a year short of a millennium late.

3 Likes

Aw. I thought you were in agreement with me, that the first century was ‘short’, and the second started on 100-01-01, bringing things into proper order. But you were making the opposite point.

My impression was that popular usage agreed with you, while correct usage agreed with me😉

If you want to be technically correct while maintaining your usage of centuries, you can say “the 1500s” etc. The 2000s started on 2000-01-01, and the 21st century one year later.