I've had times where I was going through my code and the docs code step by step to see where they logically differed and found that I was doing all the same things, but my code didn't work and copy-pasting their code did. Make it make sense!
Let me count the ways it has been for me... Capitalization, using -, not using -, wrong quotes, mismatched quotes, no quotes, reading the command the same wrong way about five times and typing it that way. Well this could take forever to list them all.
I just copy paste first now. That way I learn none of the commands or syntax at all
Been there, found undefined behavior where there should not be any.
Imagine a function that takes a bool param with the following code, but neither branch gets executed:
if (b)
doStuffForTrue();
if (!b)
doStuffForFalse();
In a function that is passed an uninitialized bool parameter, in gcc compiler, both branches can get executed even when b is const.
Reason: uninitialized bool in gcc can have values of a random integer, and while if(b) {} else ({} is guaranteed to execute only one branch, bool evaluations of a bool value take a "shortcut" that only has defined behavior with an initialized bool.
Same code with an uninitialized integer works as expected, btw.
Donāt blame this on gcc or the library/function author - it is 100% user (i.e. programmer) error. Uninitialised memory of any type is undefined behaviour in the C and C++ abstract machine. That means optimising compilers can assume it does not exist.
For example, the compiler could see that your ābā is never initialised. Therefore, using it would be undefined behaviour. So, the optimiser can assume it is never used, and it is as if that code simply does not exist: the behaviour you saw.
Iām not saying that is what happened, nor that it will always happen, but it is a possibility.
Donāt blame this on gcc or the library/function author - it is 100% user (i.e. programmer) error. Uninitialised memory of any type is undefined behaviour in the C and C++ abstract machine. That means optimising compilers can assume it does not exist.
I absolutely do blame this on the C++ standard being not specific enough, specifically for the way in how I learned about this: When writing a trivial function, you would never expect that - for a bool parameter - an "if (b)" branch can be executed as well as an "if (!b)" branch.
So basically, this mechanic sabotages input data validation in functions that test whether plausible parameters were provided. The problem is that a function you write that is bug-free and "perfect code" - despite input data validation - can exhibit undefined behavior due to an uninitialized bool type parameter. Something that can not happen with other uninitialized trivial (numeric) data types (int, float). Simply due to the way boolean checks are translated to x86 assembly:
Note the assembly lines 176-182:
The only difference for the "if (!b)" check is that the lowest bit of the boolean is flipped with an xor - which assumes about the implementation that a boolean can never hold values other than 0 or 1. Which I - as a naive user - also assumed until this happened. Correction: I assumed that negating a bool would result in the inverse boolean value.
So the problem boils down to: The value range of any given (built-in) numerical data type fully encloses the value range that an uninitialized variable of that type can have. This is not necessarily true for boolean: In g++, the value range is [0;1] and the range of an uninitialized bool is [0;255].
Accordingly, I would expect the C++ standard to fix this by stating that an uninitialized bool must have a value for which only one of two conditions evluates to true: b or !b, but not both.
I had something similar to that with Power BI DAX where the same "intuitive" structure (a table definition) had different syntax for two similar purposes.
The inline table constructor for a single column table is {value, value, ...}, with the column just named "value". The constructor for a multi-column table is {(value, value, ...), (value, value, ...), ...}, and the columns are named "value1", "value2" and so on.
The function DATATABLE allows both specifying the column names and types for the data. The syntax for the data argument is {{value, value, ...}, ...}.
If you can spot the difference, you will have figured out why simply transplanting my constructor into a DATATABLE didn't work, but copying an example and replacing the values one by one did. It took me way too long.
Maybe you just missed some nuance your brain skipped over?
The corporate culture does not allow appropriate time for the documentation as it is considered something that cost money without a quantifiable gain.
It permeates in the FOSS space as well since writing good documentation is a skill and it is not fostered in corporations. So devs start great projects with terrible documentation.
One way to contribute to FOSS is to improve bad documentation.
You are correct, of course, and lazy devs write bad code if they do not cultivate good documentation - imho.
Does anyone know of any good resources on writing good documentation? Itās a thing Iām weirdly passionate about and absolutely want to get better at for my own sanity and for others as well if I can contribute.
But it seems like itās a very under discussed subject..
Veronica Explains has a really good video talking about how much of a dead skill it is now from the standards it used to be.
Hold on... Is it flipflop -throw -f=10 -t=b or is it flipflop -throw 10 -f -b? The docs show both work for setting the force to 10 and target to buttocks
Then the doc is so complicated that you spend hours reading stuff just to understand if the page is actually related or not.
Then at some point you get bored try something randomly and it works.
I enjoy it more to figure out on my own. Kinda like disassembling stuff to see how it works and then put it back together. Reading the manual is like copying answers
Whatās the meme for when the documentation is two years out of date?
Or when the documentation IS up to date⦠but the last 4 versions of the docs are still online and look exactly like the new version with no obvious sign of which version they are? (Looking at you, Microsoft)
Tbf, often there either is no proper one, or you don't know where to find it. Or there is just tons to unpack, because one thing leads to another and suddenly you have to read like 10.
To give you an example: I just wanted to create a new btrfs software RAID and dissolve my old one, but without loosing the data or redundancy in the process. To do so, I had to create a new partition table, of course not before using tools to find the right device, add a LUKS2 partition, find its UUID, unlock that partition, add a btrfs partition, mount that partition, copy all data over, then generate a keyfile for auto-unlock, add that to the LUKS, add the according crypttab line, remove a drive from the former raid, not before running a balance of course, then also create LUKS on that, find the UUID again, open that as well, add the keyfile again, add another crypttab line, adding the mapper to the btrfs partition, running a balance that creates a RAID 10, adding an fstab entry for auto-mount, runnning dracut and set up btrfs maintenance.
Even just describing the process is a chore. Imagine trying to learn every stept, one by one, from the manuals.
Edit: Some fixes and steps I skipped added. In case anyone is wondering what the heck I'm doing: I am moving from a RAID 1 with 2 disks to an encrypted RAID 10 with eventually 4
54 Comments
lastunusedusername2@sh.itjust.works · 108 pts · 325d
And then you read the docs and it turns out to be something you already tried.
But now it works.
lemming741@lemmy.world · 47 pts · 325d
Like the USB superposition
hakunawazo@lemmy.world · 12 pts · 324d
danc4498@lemmy.world · 4 pts · 324d
ššš
Jankatarch@lemmy.world · 22 pts · 325d
It doesn't work the first time but you copy paste from the docs example instead of typing the example and it works now
Probius@sopuli.xyz · 14 pts · 325d
I've had times where I was going through my code and the docs code step by step to see where they logically differed and found that I was doing all the same things, but my code didn't work and copy-pasting their code did. Make it make sense!
aaaa@piefed.world · 15 pts · 324d
Let me count the ways it has been for me... Capitalization, using -, not using -, wrong quotes, mismatched quotes, no quotes, reading the command the same wrong way about five times and typing it that way. Well this could take forever to list them all.
I just copy paste first now. That way I learn none of the commands or syntax at all
raspberriesareyummy@lemmy.world · 5 pts · 325d
Been there, found undefined behavior where there should not be any. Imagine a function that takes a bool param with the following code, but neither branch gets executed:
In a function that is passed an uninitialized bool parameter, in gcc compiler, both branches can get executed even when b is const. Reason: uninitialized bool in gcc can have values of a random integer, and while if(b) {} else ({} is guaranteed to execute only one branch, bool evaluations of a bool value take a "shortcut" that only has defined behavior with an initialized bool.
Same code with an uninitialized integer works as expected, btw.
zerofk@lemmy.zip · 2 pts · 324d
Donāt blame this on gcc or the library/function author - it is 100% user (i.e. programmer) error. Uninitialised memory of any type is undefined behaviour in the C and C++ abstract machine. That means optimising compilers can assume it does not exist.
For example, the compiler could see that your ābā is never initialised. Therefore, using it would be undefined behaviour. So, the optimiser can assume it is never used, and it is as if that code simply does not exist: the behaviour you saw.
Iām not saying that is what happened, nor that it will always happen, but it is a possibility.
raspberriesareyummy@lemmy.world · 1 pts · 324d
I absolutely do blame this on the C++ standard being not specific enough, specifically for the way in how I learned about this: When writing a trivial function, you would never expect that - for a bool parameter - an "if (b)" branch can be executed as well as an "if (!b)" branch.
So basically, this mechanic sabotages input data validation in functions that test whether plausible parameters were provided. The problem is that a function you write that is bug-free and "perfect code" - despite input data validation - can exhibit undefined behavior due to an uninitialized bool type parameter. Something that can not happen with other uninitialized trivial (numeric) data types (int, float). Simply due to the way boolean checks are translated to x86 assembly:
Here's an example: https://godbolt.org/z/T3f9csohd
Note the assembly lines 176-182: The only difference for the "if (!b)" check is that the lowest bit of the boolean is flipped with an xor - which assumes about the implementation that a boolean can never hold values other than 0 or 1. Which I - as a naive user - also assumed until this happened. Correction: I assumed that negating a bool would result in the inverse boolean value.
So the problem boils down to: The value range of any given (built-in) numerical data type fully encloses the value range that an uninitialized variable of that type can have. This is not necessarily true for boolean: In g++, the value range is [0;1] and the range of an uninitialized bool is [0;255].
Accordingly, I would expect the C++ standard to fix this by stating that an uninitialized bool must have a value for which only one of two conditions evluates to true: b or !b, but not both.
RampantParanoia2365@lemmy.world · 4 pts · 325d
I find myself saying this about 35 times a day, at nearly every turn, with about everything I interact with.
luciferofastora@feddit.org · 2 pts · 313d
I had something similar to that with Power BI DAX where the same "intuitive" structure (a table definition) had different syntax for two similar purposes.
The inline table constructor for a single column table is
{value, value, ...}, with the column just named "value". The constructor for a multi-column table is{(value, value, ...), (value, value, ...), ...}, and the columns are named "value1", "value2" and so on.The function
DATATABLEallows both specifying the column names and types for the data. The syntax for the data argument is{{value, value, ...}, ...}.If you can spot the difference, you will have figured out why simply transplanting my constructor into a
DATATABLEdidn't work, but copying an example and replacing the values one by one did. It took me way too long.Maybe you just missed some nuance your brain skipped over?
ChogChog@lemmy.world · 7 pts · 324d
Ohhh, so thatās why itās called Docker!
As in āIt works on my systemā so they just copied and pasted the commands for you.
RampantParanoia2365@lemmy.world · 1 pts · 325d
ICastFist@programming.dev · 44 pts · 325d
Then you pick up the manual:
Agent641@lemmy.world · 8 pts · 324d
Reconfabulate the tridepodictaphone by nabulizing the fromgulan with kreevus. If stufingus brawes, then hyfangle the natriuminutaur.
Basic 17th year psycoders can do this.
Whelks_chance@lemmy.world · 39 pts · 325d
I'm not sure there is a correct way to do this
deadbeef79000@lemmy.nz · 17 pts · 325d
That looks like an XY problem.
Whelks_chance@lemmy.world · 8 pts · 325d
Finally, thanks I've been trying to remember the name of this for ages
DasFaultier@sh.itjust.works · 2 pts · 325d
Timtowtdi, doesn't say there's necessarily a correct one.
NeatNit@discuss.tchncs.de · 34 pts · 325d
The funniest thing to me is that any good manual would just say "DO NOT USE SOCKS AND FLIP FLOPS SIMULTANEOUSLY"
HeyThisIsntTheYMCA@lemmy.world · 5 pts · 325d
what if i want to embarrass my nieces and nephews
burntbacon@discuss.tchncs.de · 3 pts · 324d
Finger-pulls and 'remember when...'s
oce@jlai.lu · 2 pts · 324d
What about tabi socks and setta?
Croquette@sh.itjust.works · 25 pts · 325d
The documentation is usually dog shit.
The corporate culture does not allow appropriate time for the documentation as it is considered something that cost money without a quantifiable gain.
It permeates in the FOSS space as well since writing good documentation is a skill and it is not fostered in corporations. So devs start great projects with terrible documentation.
raspberriesareyummy@lemmy.world · 17 pts · 325d
One way to contribute to FOSS is to improve bad documentation. You are correct, of course, and lazy devs write bad code if they do not cultivate good documentation - imho.
ryannathans@aussie.zone · 0 pts · 325d
Then they don't learn the skill for themselves lmao, can't win
ChogChog@lemmy.world · 7 pts · 324d
Does anyone know of any good resources on writing good documentation? Itās a thing Iām weirdly passionate about and absolutely want to get better at for my own sanity and for others as well if I can contribute.
But it seems like itās a very under discussed subject..
Veronica Explains has a really good video talking about how much of a dead skill it is now from the standards it used to be.
IAmNorRealTakeYourMeds@lemmy.world · 17 pts · 325d
that does look less painful than reading documentation
expatriado@lemmy.world · 6 pts · 325d
then documentation instructs it must be used for spanking
LillyPip@lemmy.ca · 9 pts · 325d
Man page me daddy.
ICastFist@programming.dev · 2 pts · 325d
Hold on... Is it
flipflop -throw -f=10 -t=bor is itflipflop -throw 10 -f -b? The docs show both work for setting the force to 10 and target to buttocksburntbacon@discuss.tchncs.de · 16 pts · 324d
WTF is going on in panel 2? Did they cut a hole in the sock?
oce@jlai.lu · 7 pts · 324d
Step 1: cut a hole in the sock
RedStrider@lemmy.world · 3 pts · 324d
Step 2: put your sandal in that sock
psud@aussie.zone · 1 pts · 321d
JasonDJ@lemmy.zip · 14 pts · 325d
Then you look back at your notes a couple years later and you're like "I still don't understand wtf I did it that way".
LillyPip@lemmy.ca · 5 pts · 325d
It works, DONāT TOUCH IT.
Brkdncr@lemmy.world · 12 pts · 325d
It amazes me to see people do everything except 1) rtfm or 2) contact the support line thatās already paid for.
Edit: apparently my coworkers are in this thread.
bleistift2@sopuli.xyz · 6 pts · 325d
As if the goddamn support knew their asses from their asserts.
blarghly@lemmy.world · 5 pts · 325d
The manual: poorly written; indecipherable
Support: reads the manual to you
pylapp@programming.dev · 11 pts · 324d
Thatās vibe coding.
QuantumTickle@lemmy.zip · 9 pts · 325d
"as viewed by the original dev who knows it inside and out"
BuboScandiacus@mander.xyz · 8 pts · 324d
Jokeās on you, the docs donāt exist or are so outdated that they donāt even compile
Landless2029@lemmy.world · 1 pts · 323d
Looking at you Microsoft.
Kystael@lemmy.world · 5 pts · 324d
Then the doc is so complicated that you spend hours reading stuff just to understand if the page is actually related or not. Then at some point you get bored try something randomly and it works.
IDew@feddit.nl · 5 pts · 325d
I enjoy it more to figure out on my own. Kinda like disassembling stuff to see how it works and then put it back together. Reading the manual is like copying answers
Goretantath@lemmy.world · 4 pts · 325d
I mean, thats how i learned to use a computer, was moms so the manual was gone by the time i used it anyway.
magic_lobster_party@fedia.io · 4 pts · 325d
The manual is probably outdated either way
marlowe221@lemmy.world · 3 pts · 325d
Beat me to it.
Whatās the meme for when the documentation is two years out of date?
Or when the documentation IS up to date⦠but the last 4 versions of the docs are still online and look exactly like the new version with no obvious sign of which version they are? (Looking at you, Microsoft)
UnfortunateShort@lemmy.world · 3 pts · 324d
Tbf, often there either is no proper one, or you don't know where to find it. Or there is just tons to unpack, because one thing leads to another and suddenly you have to read like 10.
To give you an example: I just wanted to create a new btrfs software RAID and dissolve my old one, but without loosing the data or redundancy in the process. To do so, I had to create a new partition table, of course not before using tools to find the right device, add a LUKS2 partition, find its UUID, unlock that partition, add a btrfs partition, mount that partition, copy all data over, then generate a keyfile for auto-unlock, add that to the LUKS, add the according crypttab line, remove a drive from the former raid, not before running a balance of course, then also create LUKS on that, find the UUID again, open that as well, add the keyfile again, add another crypttab line, adding the mapper to the btrfs partition, running a balance that creates a RAID 10, adding an fstab entry for auto-mount, runnning dracut and set up btrfs maintenance.
Even just describing the process is a chore. Imagine trying to learn every stept, one by one, from the manuals.
Edit: Some fixes and steps I skipped added. In case anyone is wondering what the heck I'm doing: I am moving from a RAID 1 with 2 disks to an encrypted RAID 10 with eventually 4
ekZepp@lemmy.world · 2 pts · 325d
Did real people really wear slips with socks?
Auth@lemmy.world · 2 pts · 324d
If its cold yea sure
cantstopthesignal@sh.itjust.works · 2 pts · 324d
Now I get AI to summarize the documentation.
MonkderVierte@lemmy.zip · 1 pts · 325d
ogeist@lemmy.world · -2 pts · 325d
What a Loss
squaresinger@lemmy.world · 1 pts · 325d
2008 called, it wants the same old joke back. This is not even loss.