I was doing this a lot in US whenever I’d see construction work speed limits and had similar experience. Realized no one cares about these custom signs.
Yeah it always wigs me out going through those super narrow "55 mph" construction zones on US highways. I'm not in a hurry and want to slow down, but if I did I'd have semis blowing past at 75 which feels even more unsafe. Honestly I think they should put up speed cameras.
In my corner of the world it was the workers who demanded section control limiting speed to 70kmph in a segment of highway that was being renovated.
Authorities later said that they only went after 30% of the worst offenders, because otherwise the sheer number of tickets would be to high to process in a reasonable timespan.
Once word got out that the limit was actually enforced, speeds dropped. Now we have section control on some highways and personally I'm a fan, as I was always going around the speed limit anyway.
What do you mean by "section control"? A did a quick search and founds lots of possibilities but none that seem to apply to construction zone speed control.
Average speed camera. "Section control" is how they were named in Austria where I've first encountered them and the term translates to something similar in my language, so I assumed that was the English term, but it appears to be a case of Önglish.
Yeah, Average Speed Camera is definitely the terminology in the UK.
This is distinct from just a Speed Camera which is measuring over a very short interval from a single camera, the Average Speed Camera involves two or more cameras, recording people passing different points and working out how fast, on average, they must be travelling to have done so.
Enforcement of traffic laws for public safety?!? Clearly you don't have American priorities. You need to focus more on level of service and only level of service.
Given that Zig has functions which can return functions, maybe you could capture the top level io and allocator and return a struct with a bunch of functions that now have the top scope io and allocator visible.
Don’t know.
That’s how people usually get rid of repeat arguments (or OOP constructor).
I have an exactly opposite preference. Give me a big change to review. Going commit by commit or any imposed steps is not how I write code or how I understand code.
If you did not approach it through literate programming, I just prefer all of the thousands of lines at once.
Reviewing individual changes that may not even build properly is a waste of time; reviewing thousands lines of lines at once is also a bad idea.
Each unit of code (PR, commit, CL, whatever you want to call it) you send for review should be able to stand on its own, or at the very least least not break anything because it's not hooked into anything important yet.
(And for me as well — both the individual commits and the PR-level summary are useful.)
So, those of us who prefer commit-sized chunking don't have to do anything special to accommodate your preference.
It doesn't go the other way, of course, if you present one big commit to me. But so long as your code is well-commented (heh) and the PR isn't too huge (heh heh) and you don't intersperse file renamings (heh heh heh) or code formatting changes (heh heh heh heh) which make it extremely difficult to see what you changed... no problem!
> or code formatting changes (heh heh heh heh) which make it extremely difficult to see what you changed...
One of the "individual commits saved me" cases was when one of these introduced a bug. They tried to cut the number of lines in half by moving conditions around, not intending to make any functional changes, but didn't account for a rare edge case. It was in a company-shared library and we didn't find it until upgrading it on one of our products a year or two after the change.
One of the reasons I don't like a policy of "every commit must pass CI" is that I prefer to perform verbatim file moves in a dedicated commit (which inevitably breaks CI) with no logical changes at all, then modify code as necessary to accommodate the move in a separate commit. It makes review and debugging much easier.
This is my main use for branches or pull requests. For most of my work, I prefer to merge a single well-crafted commit, and make multiple pull requests if I can break it up. However, every merge request to the trunk has to pass CI, so I'll do things like group a "red/green/refactor" triplet into a single PR.
The first one definitely won't pass CI, the second one might pass CI depending on the changes and whether the repository is configured to consider certain code quality issues CI failures (e.g., in my "green" commits, I have a bias for duplicating code instead of making a new abstraction if I need to do the same thing in a subtly different way), and then the third one definitely passes because it addresses both the test cases in the red commit and any code quality issues in the green commit (such as combining the duplicated code together into a new abstraction that suits both use cases).
That's not how exchanges or prediction markets work. They need - and welcome - sharp action.
Some bookmakers are marketing companies that will kill unprofitable accounts, but not all of them. It does not take a lot of work and research to work out who is who if you want to take this seriously, or how to make sure your account stays under the radar long enough, or even how to get around those mechanisms - some of those techniques may ultimately be considered fraud, however.
And if you don't want to take it seriously, what are you doing throwing huge wads of cash at it?
I don't see how try-catch promotes single responsibility principle. I feel like this principle is just arbitrary.
If I have Result<Error, Value> and I change the Error, I have to change all places that are using the Error type and tweak the error handling in mapLeft or flatMapLeft.
If I instead raise Error and change it, I have to look at all the places where this error explodes and deal with it, not to mention, most languages won't even give me a compile time warning if I still keep the previous error type.
I agree that if language does not have do-notation, that it's a bit ugly to sprinkle map and flatMap everywhere. Good example of ugliness is https://github.com/repeale/fp-go
I think only an effect system, or a big environment object, places everything at 1 place, and when types change you have 1 place to edit the code. But starting immediately with an effect system (to abstract away control flow) or big env (to lift all ifs up) is premature.
Async-await in JS is sometimes used to swallow exceptions. It's very often used to do 1 thing at a time when N things could be done instead. It serializes the execution a lot when it could be concurrent.
if (await is_something_true()) {
// here is_something_true() can be false
}
And above, the most common mistake.
Similar side-effects happen in other languages that have async-await sugar.
It smells as bad as the Zig file interface with intermediate buffers reading/writing to OS buffers until everything is a buffer 10 steps below.
It's fun for small programs but you really have to be very strict to not have it go wrong (performance, correctness).
That being said, I don't understand your `is_something_true` example.
> It's very often used to do 1 thing at a time when N things could be done instead
That's true, but I don't think e.g. fibres fare any better here. I would say that expressing that type of parallel execution is much more convenient with async/await and Promise.all() or whatever alternative, compared to e.g. raw promises or fibres.
I replied directly to you. There are valid arguments as to why async-await sucks, even after you're deeply familiar with how it works. Even though it's just generators/coroutines beneath, async-await pollutes the code completely if you're not strict about its usage.
`is_something_true` is very simple, if condition is true, and then inside the block, if you were to check again it can be false, something that can't happen in synchronous code, yet now, with async-await, it's very easy to get yourself into situations like these, even though the code seems to yell at you that you're in the true branch. the solution is adding a lock, but with such ease to write async-await, it's rarely caught
My comment was responding only to the person who equated threads and async. My comment only said that async and threading are completely orthogonal, even though they are often conflated
> `is_something_true` is very simple, if condition is true, and then inside the block, if you were to check again it can be false, something that can't happen in synchronous code
It can happen in synchronous code, but even if it couldn't - why is async/await the problem here? what is your alternative to async/await to express concurrency?
Here are the ways it can happen:
1. it can happen with fibers, coroutines, threads, callbacks, promises, any other expression of concurrency (parallel or not!). I don't understand why async/await specifically is to blame here.
2. Even without concurrency, you can mutate state to make the value of is_something_true() change.
3. is_something_true might be a blocking call to some OS resource, file, etc - e.g. the classic `if (file_exists(f)) open(f)` bug.
I am neutral on async/await, but your example isn't a very good argument against it
Seemingly nobody ever has any good arguments against it
> async-await pollutes the code completely if you're not strict about its usage
This is a good thing, if a function is async then it does something that won't complete after the function call. I don't understand this argument about 'coloured functions' polluting code. if a function at the bottom of your callstack needs to do something and wait on it, then you need to wait on it for all functions above.
If the alternative is just 'spin up an OS thread' or 'spin up a fiber' so that the function at the bottom of the callstack can block - that's exactly the same as before, you're just lying to yourself about your code. Guess what - you can achieve the same thing by putting 'await' before every function call
Perhaps you have convinced me that async/await is great after all!
Async and threading are applied to similar problems, that's how I understood OP.
`if (file_exists(f))` is misuse of the interface, a lesson in interface design, and a faulty pattern that's easy to repeat with async-await.
> I don't understand this argument about 'coloured functions' polluting code.
Let's say you have some state that needs to be available for the program. What happens in the end game is that you've completely unrolled the loads and computation because any previous interface sucks (loading the whole state at the beginning which serializes your program and makes it slower, or defining `async loadPartial` that causes massive async-await pollution at places where you want to read a part of the state, even if it is already in cache).
Think about it, you can't `await` on part of the state only once and then know it's available in other parts of code to avoid async pollution. When you solve this problem, you realize `await` was just in the way and is completely useless and code looks exactly like a callback or any other more primitive mechanism.
A different example is writing a handler of 1 HTTP request. People do it all the time with async-await, but what to do when you receive N HTTP requests? The way to make code perform well is impossible with the serial code that deals with 1 request, so async-await just allowed you to make something very simple and in an easy way, but then it falls apart completely when you go from 1 to N. Pipelining system won't really care for async-await at all, even though it pipelines IO in addition to compute.
I think "how to express concurrency" is a question I'm not even trying to answer, although I could point to approaches that completely eliminate pollution and force you to write code in that "unrolled" way from start, something like Rx or FRP where time is exactly the unit they're dealing with.
> `if (file_exists(f))` is misuse of the interface, a lesson in interface design, and a faulty pattern that's easy to repeat with async-await.
It's even easier to repeat without async-await, where you don't need to tag the function call with `await`!
> Think about it, you can't `await` on part of the state only once and then know it's available in other parts of code to avoid async pollution. When you solve this problem, you realize `await` was just in the way and is completely useless and code looks exactly like a callback or any other more primitive mechanism.
I don't understand why you can't do this by just bypassing the async/await mechanism when you're sure that the data is already loaded
```
data = null
async function getDataOrWait() {
await data_is_non_null(); // however you do this
return data
}
function getData() {
if (data == null) { throw new Error('data not available yet'); }
return data;
}
```
You aren't forced into using async/await everywhere all the time. this sounds like 'a misuse of the interface, a lesson in interface design', etc
> I think "how to express concurrency" is a question I'm not even trying to answer
You can't criticise async/await, which is explicitly a way to express concurrency, if you don't even care to answer the question - you're just complaining about a solution that solves a problem that you clearly don't have (if you don't need to express concurrency, then you don't need async/await, correct!)
> point to approaches that completely eliminate pollution and force you to write code in that "unrolled" way from start, something like Rx or FRP where time is exactly the unit they're dealing with.
So they don't 'eliminate pollution', they just pollute everything by default all the time (???)
> You aren't forced into using async/await everywhere all the time. this sounds like 'a misuse of the interface, a lesson in interface design', etc
Exactly, async-await does not allow you to create correct interfaces. You cannot write code that partially loads and then has sync access, without silly error raises sprinkled all over the place when you're 100% sure there's no way the error will raise or when you want to write code that is 100% correct and will access the part of the state when it is available.
Your example is obvious code pollution. For "correctness" sake I need to handle your raise even though it should not ever happen, or at least the null, to satisfy a type checker.
> So they don't 'eliminate pollution', they just pollute everything by default all the time (???)
That's not the case at all. They just push you immediately in direction where you'll land when you stop using async-await to enforce correctness and performance. edit: you stop modelling control flow and start thinking of your data dependency/computation graph where it's very easy and correct to just change computation/loads to batch mode. `is_something_true` example is immediately reframed to be correct all of the time (as a `file_exists` is now a signal and will fire on true and false)
> You can't criticise async/await, which is explicitly a way to express concurrency, if you don't even care to answer the question - you're just complaining about a solution that solves a problem that you clearly don't have (if you don't need to express concurrency, then you don't need async/await, correct!)
I'm critical of async-await, I'm not comparing it to something else, I can do that but I don't think it is necessary. I've pointed to FRP as a complete solution to the problem, where you're forced to deal with the dataflow from the start, for correctness sake, and can immediately batch, for pipelining/performance sake.
IMO, just like file_exists is a gimmick, or read_bytes(buffer), or write_bytes(buffer) is a leaky abstraction where now your program is required to manage unnecessary wasteful buffers, async-await pushes you into completely useless coding rituals, and your throw is a great example. The way you achieved middleground is with code pollution, because either full async load at the beginning is not performing well, or async-await interleaved with computation pollutes everything to be async and makes timeline difficult to reason about.
This late in the game, any concurrency solution should avoid pointless rituals.
I'm pretty sure they keep internal internal checksums at various points to make sure the data on disk is intact - so does the filesystem, I think they can catch when memory corruption occurs, and can roll back to a consistent state (you still get some data loss).
But imo, systems like these (like the ones handling bank transaction), should have a degree of resiliency to this kind of failure, as any hw or sw problem can cause something similar.
reply