1 hour in Java
1 hour in Java
Java/TypeScript
😒
TypeScript might be fine, if it didn’t typically rely on a JavaScript stack that can and will ignore the nominal types.
TBF you probably don’t have to use any native JS libraries, so it’s kind of user error.
And
++++++++ [>++++++++++++>+++++++++++++<<-] >++++. -. >+++++++. <+. +.in brainfuck
What about spaces made it hard? What language would have been easier? In curly brace languages, 99% of the time, a curly brace is followed by a line break and an indent. Python is similar except it’s typically a colon, line break, then indent.
What I have learned is: If the code is indented too deeply, it’s a code problem, not the language.
Torvalds infamously wrote:
“… if you need more than 3 levels of indentation, you’re screwed anyway, and should fix your program.”
Correct, I linked the source of the quote. My implication is the general idea is applicable here. Is python one of these languages where it is idiomatic to nest code deeply?
Flat is better than nested.
From the python I have seen and written, deep nesting is avoided.
It’s because there is no clear indication of where a block ends.
Here is some sample code. I find it difficult to tell how many indentations I have or where I need to write if I want to continue at a certain level.
import time import aiohttp """ Retreives the data from RSS URL and return the status codes as well as the data. Return -1 if something went wrong. """ async def get_rss_feed(rss_url): async with aiohttp.ClientSession() as session: try: retry_count = 0 while retry_count < 5: async with session.get(rss_url) as resp: if resp.status == 200: return {'status': resp.status, 'data': await resp.text()} else: retry_count += 1 time.sleep(60) if retry_count == 5: raise ValueError('To many failed connection attempts', retry_count) except aiohttp.InvalidURL as error: return {'status': -1, 'data': f"Error: {rss_url} is not a valid URL.", 'error': error} except aiohttp.ClientConnectorError as error: return {'status': -1, 'data': f"Error: Could not connect to {rss_url}.", 'error': error} except ValueError as error: return {'status': -1, 'data': f"Error: Could not connect to {rss_url} after {retry_count} attempts.", 'error': error}especially when u are indenting stuff inside stuff with a bunch of conditions everywhere
That’s an anti pattern in basically every language though. The fix is to simplify those conditionals, not use a curly-bracketed language.
I mainly found it annoying while writing code, because the lack of braces makes it difficult to tell when a scope ends. Plenty times, I’ve wanted to add something to the end of a for-loop, but had too little indentation.
Usually this means I get a runtime error, because it can’t access some variable from the loop-scope. But worst case, it only executes once after the loop and I don’t notice the problem.
Another big thing I miss when not having explicit braces, is opening up new/anonymous scopes to isolate variables, which helps prevent mistakes down the line + reduces code complexity.
For example, this is a thing I do quite regularly:
let client = { let client = new Client() let timeout = config.load("client.timeout") client.set_timeout(timeout) client //implicit return value of this scope when evaluated as an expression } client.request_something()It allows me to visually group the initialization code for the client and I don’t need to have the timeout variable in scope afterwards. Depending on the language, you can also have the client variable mutable inside the scope and then immutable outside.
Yes, this could be pulled out as a function to achieve something similar, but in my experience people (including me) will often just not do that, because it’s only the timeout variable or whatever.
wanted to add something to the end of a for-loop, but had too little indentation
To address this, I prefer reducing length & depth of nested code, so the for/while is rarely ever not visible along with everything inside it. Others have success with editors that draw indentation lines.
opening up new/anonymous scopes
I occasionally use Python nested functions for this purpose
start/end to define scopes.
I’ve been coding around 25 years and got my start in perl. I absolutely hated python when I first used it. I use it all the time now. I still prefer my curly braces but I don’t have any trouble with python or mind the whitespace anymore. I just run it through ruff every save. I do the same with go everything goes through gofumpt. I really think a lot of it is a generational thing. Older people are just used to curly brackets.
I do get peoples complaints about the packaging. Unless you’re a dev already it’s a bit extra to deal with shuffling virtual environments because the system python environments almost never work out of the box, at least in the last few distros I’ve used. Once I adjusted though it’s no problem. I run half my dev stuff in toolboxes with their own environment anyway.
Java feels like McDonald’s and python feels like a grocery store.
Rust feels like a femboi hooters where they offer IVs you don’t think they’re qualified to administer.
My indirect experience with python is that it is slow as hell. Anytime I install an app that includes python it lags 15-30 minutes on that step. Anytime I’m asked to install something with conda it takes 30 minutes to an hour.
I’m sure that is just due to environmental and implementation issues, but the Java fans say the same thing…
Conda actually now uses the Mamba solver under the hood, as of the 23.10.0 release: docs.conda.io/projects/…/release-notes.html#id43
Unfortunately, their release notes page is buggy, so this link will stop pointing to the correct release when they publish their next release…
But one compiling error is Java is 7 run time errors in python.
There is a type error and you couldn’t have known it beforehand? Thanks for nothing
Neither of those provide type inference? Type inference is when you give the compiler only occasional type hints and it can still figure out what the types are behind the scenes.
For example:
name = "World" greeting = "Hello " + name compile_error = greeting / 42In a type-inferred language, the compiler would automatically know that:
Mypy on the other hand can only tell these things, if you give the first two lines an explicit type hint:
name: String = "World" greeting: String = "Hello " + nameHaving to do this on every line of code is extremely noisy and makes refactoring annoying. I can absolutely understand that Python folks think you get productivity gains from duck typing, if this is the version of static typing they’re presented.
And we did excessively use mypy + type hints + pydantic on my most recent Python project. These are not the silver bullet you think they are…