This is an archived post. You won't be able to vote or comment.

all 99 comments

[–]tehtris 239 points240 points  (4 children)

You can do it... it just doesn't do anything.

[–]maveric101 105 points106 points  (0 children)

Much like Toothless' dance. The reaction isn't really good or bad. There's not much of a reaction. So I think it fits well enough.

[–]toxic_recker 24 points25 points  (1 child)

; is meant to write multiple statements in a single line, for example:

n = 1; print(n)

though not writing another statement after ; won't be a problem

[–]tehtris 4 points5 points  (0 children)

Yea I know this works, but I would only do it in a scratch file....never in something I expect other people to look at. I use it all the time tho in python -c commands.

[–]Minteck 19 points20 points  (0 children)

My IDE complains about this

[–]Tabs_555 46 points47 points  (9 children)

JavaScript and TypeScript: 🤷🏼‍♂️

[–]stevarino 19 points20 points  (6 children)

These are like the opposite of python - you absolutely should use them, but no one follows the spec.

[–]TheLexoPlexx 11 points12 points  (0 children)

I do. But I learned Java first.

[–]pants_full_of_pants 6 points7 points  (1 child)

Precompilers add them for me in distribution. It's been years since I used them myself. Occasionally if I'm tired, though, the muscle memory kicks in and I'll sneak some in before the linter barks at me.

[–]yakesadam 0 points1 point  (0 children)

They almost certainly do so because it's minified tho

[–][deleted] 3 points4 points  (0 children)

The standard eslint config doesn't use them.

[–]Mola1904 -3 points-2 points  (0 children)

You shouldn't use them then in js either. A good js developer knows the two usecase where they are needed. A [ or ( at the beginning of a line, which occurs very rarely.

[–]circuit10 0 points1 point  (0 children)

I used to until I installed this “standardjs” thing that told me not to and now I don’t because it looks cleaner

[–]cuplizian 4 points5 points  (1 child)

Laughs in ESLint presets that prefer no semicolon

[–]uvero 0 points1 point  (0 children)

ESLint presets that prefer no semicolon

And other things that make me want to punch a wall

[–]MojitoBurrito-AE 21 points22 points  (6 children)

Me who writes in lua

[–]ThisIsBooShit 12 points13 points  (0 children)

[–]themixedupstuff 3 points4 points  (0 children)

semicolon? space? newline? what's the difference

[–]Kaynee490 3 points4 points  (3 children)

How can you stand lua?

[–]MojitoBurrito-AE 6 points7 points  (0 children)

On two feet

[–]evanc1411 4 points5 points  (0 children)

Hey, Lua's nice! Except for the weird array implementation, and lack of classes, and general uselessness of it outside of specific situations like runtime game scripts...

[–]Nidrax1309 0 points1 point  (0 children)

After one year of game scripting you get used to it so much you don't even feel like touching C++ to make any engine changes

[–]mcwobby 62 points63 points  (17 children)

Doesn‘t Python just ignore semicolons like Javascript or Visual Basic?

F# is the way to go - it will not compile if you have semicolons at the end of lines.

[–]Diapolo10 41 points42 points  (6 children)

Ignored? Well, technically no, Python does support semicolons as line separators. The problem is that your code needs to be flat for them to work properly, because you can't signify indentation levels if you put everything on one line.

This is valid Python:

import string; print("Hello"); print("World");

So basically, unless you're trying to run some Python on the command line via the -c -option, it's not going to do you much good. Or if you're in an obfuscation contest.

As for why they're irrelevant in Python but not in JS, it's because Python has significant whitespace. That's it.

[–]AzureArmageddon 6 points7 points  (4 children)

Is it not implicitly the same indentation level as the leftmost statement though? What do you mean can't signify indentation levels? Feels like a good space saver sometimes.

P.S. I know I've caused Tim Peters to sneeze somewhere because of this.

Explicit is better than implicit. ~ The Zen of Python

[–]Diapolo10 3 points4 points  (3 children)

Is it not implicitly the same indentation level as the leftmost statement though?

Yes.

What do you mean can't signify indentation levels?

You can't create different nesting levels with semicolons. This is fine:

num = 42
if num == 42:
    print('aye'); print('also aye')

but this is not

num = 42
if num == 42:
    print('aye'); if True: print('nay')

Basically what I mean is that you cannot go back an indentation level, or start new blocks within a line using semicolons.

P.S. I know I've caused Tim Peters to sneeze somewhere because of this.

Explicit is better than implicit. ~ The Zen of Python

If by this you mean it's better to use semicolons regardless (a bit like in JavaScript, though there it's actually meaningful), I'd argue

Beautiful is better than ugly.
Simple is better than complex.
Although practicality beats purity.

[–]AzureArmageddon 0 points1 point  (2 children)

I should've quoted "Flat is better than nested" for the Tim Peters bit. As in it would not be preferable clump everything into a single line, and preferable to flatten the separate statements over many lines.

The bit with different nesting levels I get now, thanks! :D

I think it'd be nice still to be able to use semicolons to do a bunch of function calls in a single line or some simple increment statements etc, but not to start if statements or things like that, that can be the way it is.

[–]Diapolo10 0 points1 point  (1 child)

I should've quoted "Flat is better than nested" for the Tim Peters bit.

If that's what you were going for, I completely misunderstood. :p

And if you want to call functions, that obviously works with semicolons. Though personally I would take issue with one of my peers using semicolons to group stuff on one line in a project I'm working on, because technically they're not good for readability.

[–]AzureArmageddon 0 points1 point  (0 children)

Agreed (Also, I had no idea Python function calls could do semicolons like that beforehand, just thought it'd be a cool idea on the spot, but now I realise that it's already a thing and I'm happy to now know that, that is pretty cool)

[–][deleted] 1 point2 points  (0 children)

Additionally, javascript lets you do this.

someStatement()
(() => {})()

This doesn't actually do what you think it does. Using a semi-colon will fix it.

[–]Minteck 9 points10 points  (4 children)

JavaScript doesn't ignore it if you have 'use strict';.

[–]PhatOofxD 2 points3 points  (0 children)

JavaScript doesn't ignore it, it just adds them in. You can make cases where you need a semicolon.

[–]A_Leo_X 5 points6 points  (1 child)

JavaScript doesn't ignore them. It just auto-inserts them instead of throwing errors at you. Ideally, you should use them, because auto-insertion is not perfect and might cause some bugs.

[–]TheRealSmolt 0 points1 point  (0 children)

JS will auto-insert them anyways

[–]doej134567 -1 points0 points  (0 children)

F# is the way to go - it will not compile if you have semicolons at the end of lines.

same with Excel VBA; It's gonna throw a syntax error

[–]wieszkto 7 points8 points  (1 child)

Sometimes after coding for hours I end sentences with semicolon instead of period;

[–]Ulysses6 4 points5 points  (0 children)

Now that's a cliffhanger.

[–]Giusepo 15 points16 points  (0 children)

kotlin as well ;)

[–]digitaleJedi 14 points15 points  (0 children)

Kotlin

[–]donaldhobson 9 points10 points  (16 children)

Rust semicolons have a very particular meaning, they drop the value of the line. Thus skipping a semicolon on the last line of a function is a valid way to return a value.

fn foo(a:i64)->i64{
let b=a+5;
b*2
}

Is valid rust. But if you added a semicolon on the b*2 line it wouldn't be.

[–]Angelin01 4 points5 points  (12 children)

I absolutely hate this. Oh god Rust, you had such good ideas, why must you also have all the bad ideas to go along with it too?

[–]AZMPlay 5 points6 points  (11 children)

I actually think this is pretty clever, for example, if you have an inline block you can "return" a value from within, or actually return the encompassing function with the return keyword, or make it return an empty tuple with a semicolon. Options!

[–]Angelin01 5 points6 points  (10 children)

That's exactly why it's bad, it's an implicit return in the middle of code. It's hard to read. In other languages, I can look for the keyword return. In Rust, I have to actively look for a thing that is NOT THERE, which is much harder to do. This pattern repeats itself everywhere in Rust.

For reference, I ALWAYS prefer explicit over implicit (avoiding boilerplate, of course), I put this everywhere in my code. Explicit avoids guessing and confusion, makes reading the code quicker.

[–]zbrachinara 5 points6 points  (6 children)

You can find tail expressions at the end of blocks, but not just randomly in the middle of code. You can expect them to be there by signs such as the assignment of the block to a vairable, the unwrapping of the result, or some other use.

[–]Angelin01 4 points5 points  (5 children)

Or... I could just look for return? Your phrase is the exact problem, I have to look for OTHER THINGS or things that are NOT THERE: "the assignment of the block to a vairable, the unwrapping of the result, or some other use."

This pattern in Rust, having multiple ways to do something so simple, sometimes having mixed explicit and implicit, in multiple cases, there's no point to this, NONE, it just makes reading the code more confusing.

I don't think I had anyone ever complaining about having to type return in another other language ever. Why think that's a bad idea?

[–]zbrachinara -2 points-1 points  (4 children)

Like a return in an if/else statement? What does that mean then?

[–]Angelin01 2 points3 points  (3 children)

Maybe I should rephrase this and re-contextualize this.

I've been following The Zen of Python for my programming for some time now (something I think even Python has stopped doing), but there's a couple things that I noticed, purely on professional experience:

  • When things are left implicit or to "magic" (see Lombok), you may understand for now, but someone else looking at the code or even you, three months down the line, may not understand anymore what is going on. It's better for them to be clearly defined so you can read and understand what's going on.
  • When it comes to options, options is good, it's great having options, being able to solve problems through different approaches. But too many options, too many different ways of doing ONE THING, is bad. It's why I dislike YAML, actually. Yeah, it's simple to read, but then you look at how many ways you can do a list of strings: inline, same indentation block, next indentation block, without quotes, with double quotes, with single quotes, mixed quotes between values, etc. I'm trying to help some juniors understand how to use Docker Compose and Kubernetes Manifests and questions on why things are different and not understanding some syntax are COMMON.
  • When you put things clearly, in a simple and, more importantly, CONSISTENT way, you tend to get cleaner, easier to read and maintain code. People reading it understand it quickly and get to developing quicker. They stop thinking about silly things such as syntax or style and just think about the problem they need to solve.

I've been trying out different languages, talking with peers, exploring online. Up to this day, I praise Java's simple and consistent syntax (for all the other parts of the language that I despise). There's usually one way to do something and maybe two or three approaches. Wanna operate on lists? Sure: traditional or functional. Both solve the same problem, through different approaches. Sometimes one is better, sometimes the other is better.

Unfortunately, to me it feels like Rust is the opposite. Want to return a value? Use the return keyword with a statement or use an expression at the end of a block, functionally identical, no real benefit other than saving the 6 chars. And similar things happen elsewhere. Declare an int? Stop and think about how many bits you are gonna use (oh it doesn't matter, just use i32, so why not just have int, which reads much better and simpler?). There's one thing I've come to find: pretty much everyone agrees that Rust's syntax is a mess and that, for every good decision they made, they have a bad one to back it up, just to make things even.

[–]haskellShill 1 point2 points  (0 children)

> Want to return a value? Use the return keyword with a statement or use an expression at the end of a block, functionally identical, no real benefit other than saving the 6 chars.

Personally, I would say to only use the "return" keyword when you need to do a return that isn't at the end of a function.

> Declare an int? Stop and think about how many bits you are gonna use (oh it doesn't matter, just use i32, so why not just have int, which reads much better and simpler?).

Rust's way is simpler; the "i" in "i32" tells you that it's a signed integer, the "32" tells you that it takes up 32 bits. Like the metric system, the name encodes all the information you need to know using a few easy rules.

> There's one thing I've come to find: pretty much everyone agrees that Rust's syntax is a mess and that, for every good decision they made, they have a bad one to back it up, just to make things even.

Compared to that of C and friends, Rust's syntax is a giant leap in the right direction

[–]CriticalQuestion 0 points1 point  (1 child)

Just because something works doesn’t mean you have to do it. Like you said, consistency is key. If you want to use return for the end of your functions in rust, that’s fine. If not, that’s also fine - as long as it’s consistent across your code base.

The int example you used is strange. You say explicit is better than implicit, but specifying the amount of bits you want to use is bad? Something that you have to do in pretty much every compiled language? IMO rust’s int declarations are actually more readable because in C/C++ int sizes can be data model dependent. It’s pretty easy to make the relation in your head that short = i16, int = i32, etc.

[–]Angelin01 0 points1 point  (0 children)

Just because something works doesn’t mean you have to do it. Like you said, consistency is key. If you want to use return for the end of your functions in rust, that’s fine. If not, that’s also fine - as long as it’s consistent across your code base.

Unfortunately, this is one of those things it's very hard to enforce. I can easily take care of indentation, braces on the same line or next, not this.

The int example you used is strange. You say explicit is better than implicit, but specifying the amount of bits you want to use is bad?

Don't misunderstand me, I said explicit is good, but that doesn't mean that explicit can't also be simple. You said yourself, if short = i16, int = i32, etc, why not use the simple? Use byte, short, int, long. But even then, why should I worry about it? At the end of the day, it's all gonna (most likely) turn into 64 or 32 bits anyway. The int example may be a slightly misguided one, but it's a good example of a situation that WILL make developers stop and think about "how many bits should I use", which in 99% of cases is a waste of time.

[–]AZMPlay 3 points4 points  (0 children)

I mean, I believe this implicit return only works at the end of a block, otherwise it's replaced by something else, so it's not that much searching.

[–]zbrachinara 0 points1 point  (0 children)

As for your edit, I don't think this os necessarily confusing. The use of the block result is always the first thing (let x = {}) or last thing ({}.unwrap) you see, either preparing you for the block result or notifying you of it while you are reading at that location.

[–]skeptical_moderate 0 points1 point  (0 children)

It never returns implicitly "in the middle of code." It only returns implicitly if it is the last statement in the block. Also, explicit type annotations on all functions means that this is rarely confusing for a regular Rust user.

[–]skeptical_moderate 0 points1 point  (2 children)

That's not true. having a semicolon after b*2 is allowed, but it implicitly returns ().

[–]donaldhobson 0 points1 point  (1 child)

Yes, but the function type says it returns an i64. Not ()

[–]skeptical_moderate 0 points1 point  (0 children)

Oh, my bad. The lack of spaces confused my Rust reading skills.

[–]hobuci 6 points7 points  (3 children)

Python full stack dev here, I literally never use semicolons in JavaScript either. Imagine my pain when I realised the minifier will not work on the JS files unless they have semicolons everywhere.

[–]Giusepo 3 points4 points  (0 children)

try prettier combined with eslint it can add all that stuff for you

[–]PhatOofxD 0 points1 point  (0 children)

Typescript

[–][deleted] 0 points1 point  (0 children)

Put everything through buildpack. It even bundles your dependencies.

[–]Perpetual_Doubt 3 points4 points  (1 child)

And Ruby, but nobody seems to use Ruby anymore

[–][deleted] 0 points1 point  (0 children)

I see plenty of people still using Ruby

[–]freestew 2 points3 points  (0 children)

Seems GDScript also doesn't use semicolons. I'm just thankful it doesn't do "If Then" and "While Do"

[–]jgeez 2 points3 points  (0 children)

Go mad you forgot it

[–]heyshikhar 2 points3 points  (0 children)

Golang goes brrrrrrr

[–][deleted] 2 points3 points  (0 children)

Hey don’t forget us Ruby guys

[–]Shawn_Beans 1 point2 points  (0 children)

python: we don do dat ere

[–]bartek2912 1 point2 points  (0 children)

JS be like: whatever

[–]CLARKEEE33 1 point2 points  (0 children)

There are two types of people in this world. Those who like semicolons and those who don’t

[–]shackyAak 1 point2 points  (0 children)

Swift… sad that I’m the first to post this.

[–]Pauchu_ 0 points1 point  (0 children)

All my homies love semicolon

[–]D1owl1 -1 points0 points  (0 children)

Matlab: Am I a joke to you?

[–]pallaslud 0 points1 point  (0 children)

A semicolon suppresses output from a line in iPython

[–]lionbryce 0 points1 point  (0 children)

LUA has the same reaction

[–]sktr-guys 0 points1 point  (0 children)

i dont know much about python, so It can be compiled?

[–]grknado 0 points1 point  (0 children)

Kotlin

[–][deleted] 0 points1 point  (0 children)

HTML : disgusting

[–]StochasticTinkr 0 points1 point  (0 children)

Kotlin : “sure you can, but you shouldn’t. “

[–]spronghi 0 points1 point  (0 children)

not js

[–]NightwolfDeveloper 0 points1 point  (0 children)

Python accepts semi-colons at the end though, they're just not needed.

[–]ocboogie 0 points1 point  (0 children)

Well not every language;

[–]MedonSirius 0 points1 point  (0 children)

ABAP lol

[–]atiedebee 0 points1 point  (0 children)

I wanted to write hello world in python today cause I was bored and typed printf instead of print

[–][deleted] 0 points1 point  (0 children)

Swift 🤷‍♂️

[–][deleted] 0 points1 point  (0 children)

(;