When something just isn't clicking in my brain I move on from it! Then some time later (not a fixed time) I happen across it and read through it again with a fresh mind.
This has happened too many times for it to be a coincidence, that the 2nd attempt ALWAYS makes things click very naturally. It has happened with probability concepts such as Bayesian networks or HMMs, optimization algorithms like EM, Monte Carlo sampling, bootstrap, functional programming concepts like monads, C++ move semantics; the list goes on.
Whenever you're stuck, just take a break! And not a 30 minute coffee break but still at the back of your mind kind of break - completely forget about it and come back in a few days, a few weeks or even a month or 2 later
I’m probably a slow thinker, but there are so many concepts from my engineering textbooks that make perfect sense now that were baffling at the time. There’s something about studying those topics in a relaxed, low stakes environment that makes understanding them much easier.
What I did was I gave up and no longer click those articles.
Then, try store your programs state by passing it as a function argument to every function so it stays available for the lifetime of the program (no mutable state? This is basically what happens)
After realizing what a pain this is and wishing for boilerplate, look at the State monad. This is what did it for me :)
I'm honestly not even sure what function composition is, or why you would compose two functions instead of just explicitly making a new function that calls the two original ones.
The second one makes more sense because of the rumored bug-freeness of side effect free apps, but it seems like for that too, you'd need to understand a lot more than just monads.
Or in javascript:
function f(x) { return x + 1 }
function g(x) { return x + 2 }
f(g(1)) === 4
In functional languages like Haskell function composition is made easy, because functions can be partially applied. Partial application means that given a function that takes two arguments, I can call it with one argument and it will return a function that takes one argument which returns the result. Whereas in languages like javascript it is difficult because functions can have different numbers of arguments and there's no way to partially apply them or flip their arguments, so it is difficult to chain functions together. And because javascript functions aren't pure, they may not have any result which can be composed with other functions. In a functional language, functions are more like the functions in math. In most non-functional languages, functions are more like a procedure of commands. For example, the javascript function logMe(x) { console.log(x) } doesn't return anything. So it can't be composed functionally, and is not like a "real" function.
When we want to "compose" two functions, there's f(x){return a(b(x))}.
It doesn't matter if the signatures are different, you don't need any nice logical idea of composition, you just explicitly build the new function that does what you want.
I would say that is a lot easier than real composition, because real composition requires you first learn to see and think in terms of patterns you would want to compose in the first place.
Also, function chaining doesn't use intermediate variables. Named variables are like free documentation. With composition you have to actually remember what you're doing. Making everything explicit makes it easier to comment what's happening.
Regular programming is to math as cooking is to chemistry. Functional brings the math back to programming. Math is useful but also hard.
In OOP, more often you're doing the equivalent of:
if crinkle(a(b(x,68), modes.FOO).bar.baz(9)): x = foo() else: x = wipe(7).bar()
And I think it's a lot nicer to just spell it out with meaningful variable names, instead of trying to compose it like an equation.
let batter = mix(water, flour)
let saltedBatter = add(salt, batter)
let risenSaltedBatter = letToRise(saltedBatter)
let bread = bake(batter)
on the other hand: let bread = bake(letToRise(add(salt, mix(water, flour)))
The first example leads to awkward names and useless variables. The second example feels cleaner to me. Interesting that you take cooking as an example: recipes usually don't name most of the intermediate steps, they describe the actions you take and the ingredients you use. Most recipes also use composition a lot. You start with your actions/functions (cut, cook, bake, dice, etc) and you do a recipe out of them. You don't create new "functions" (actions) specifically for each recipe.You have standard functions like bake and boil, and they don't tell you to use clean utensils or how to turn the stove on, because an cooking is basically just a few dozen standard functions, end condition rules, etc.
If you think of them as programs, the composition they use isn't the same as functional languages, because the individual steps are unstructured and there's no generalized abstract pattern defining what a RecipeStep is or what composing two of them means.
You wouldn't say add(flour(add(salt,empty))), you would say "add flour, salt, water, and yeast".
"add" can take either an ingredient or a list, and it's pretty encapsulated, since it dynamically selects a way to measure the ingredient based on what it is, what utensils you have, etc.
It could trigger dozens of unrelated code paths based on state, and probably includes error recovery.
Functional might be nice for implementing the internals of that add() function, but in OOP the idea seems to be that it's a pretty minor detail, since add() is only written once and rarely changed, but used millions and millions of times all over the world for a decade.
Usually when people talk about "the beauty of functional" I get the impression that they're not really doing a whole lot of "One really smart function that knows exactly what to do" level abstraction.
It seems like they'd literally be composing together their own variations of what "add" is, as needed from the raw findMeasuringStrategy and checkPantry functions instead.
That second example tells the reader that it is doing, which may or may not be what it was supposed to be doing.
As a maintainer, I prefer knowing that:
(add(salt, mix(water, flour))
is supposed to result in a salted batter, which the first code block tells me but the second one does not.For write-only code, sure, that's great.
It's irrelevant when I am tracking down a bug - the label 'saltedBatter' tells me what that intermediate result is supposed to be.
If, when debugging, I find that `add(salt, batter)` results in something else[1], using your convention it is literally impossible to tell that the value is supposed to be `saltedBatter`.
There is literally no way to tell if the intermediate values are correct. Maybe each caller in the composition chain can throw an Exception?
The point is, the variable names are helpful.
> but only the first and last step have a name because the intermediate steps are just that.
That describes the entire program :-)
In all seriousness though, it's because you intend to describe steps in the process that throwing away all labels for the intermediate steps makes sense.
You're describing verbs. We don't need to know the in-between verbs for a verb. When you call `driveTo()`, it is not necessary to know all the verbs involved in that action, it is enough to know that it will attempt a certain action.
Verbs answers the "what we are doing" questions.
Variable names answer the "Why we are doing it" questions - `saltedBatter = foo (bar(), baz);` tells the reader why foo is being called.
We don't even need to know the steps involved or even what the other variables (used as parameters) should be. Assigning the result of a function to a variable ensures that the maintainer knows if that variable ever holds the wrong value.
I think where a lot of this value (variable-names) is lost is in enterprise development - the names are never helpful, they're just a differently-cased version of the type. Like these gems I see daily:
SomeClass someClass = foo();
List<OtherClass> otherClassList = bar();
....
return baz(someClass, otherClassList);
So, yeah, I see your point if all you ever see is enterprise-grade naming conventions. OTOH, if those above two lines were written as: SomeClass needle = foo();
List<OtherClass> haystack = bar();
...
return baz(needle, haystack);
you, as the maintainer, know exactly what that last line is supposed to do, and if it isn't doing that, then you know it's a bug.Compare with this:
return (foo(), bar());
Or, if you wanted descriptive function names: return (calculateResult(), userSubmittedList());
Brevity is not a virtue in programming languages and/or programs. It's probably why Haskell is still not even a rounding error as far as popularity goes.[1] Maybe `doubleSaltedBatter`, in case an upstack caller used `saltedWater` in place of `water`, or perhaps `pepperedBatter` in case a caller switched out the salt for pepper.
Real world Haskell code isn't the codegolf you are implying.
In fact, I think real world Haskell devs overcorrect and make code too verbose.
Also, "brevity is not a virtue in programming languages" is something I disagree with.
Walls of verbose code are just so damn mentally taxing. Especially hen you finish reading and saybto yourself "all that code just to do X?".
So is working with an edifice of unprincipled ad-hoc abstractions, but many seem to prefer pushing that debt on tomorrow them or others.
I'm not clear why the next function in the pipeline would need to know about the error rather than the caller, but that happens with promise chains too
Exceptions usually aren't typechecked.
All I know is they contain values and you can pass them functions, and somehow by doing this you can write fully pure programs with supposedly fewer bugs, and Haskell programmers seem to not understand why this is hard.
The way I understand monads: some data structure plus 2 functions, "return" and "join":
- "return": wraps something with the data structure. (no relation with the return keyword you are used to in most languages)
- "join": joins 2 layers of the _same_ data structures into one.
And that's it. It's just that simple what a monad is: in java it would be an interface with just these two methods.
Examples:
- "return" for List: takes a value and returns a List containing just that value.
- "return" for Maybe: takes a value and returns Maybe value.
- "join" for List: takes a List of Lists and returns a flattened List (2 outer layers joined).
- "join" for Maybe: takes Maybe Maybe value and returns Maybe value.
I think what makes these functional programming concepts hard to grasp most of the times is that communicating the boundaries of abstract concepts is hard in general, even if the concept itself is really simple, like a monad can be for a programmer.
As for why monads are useful, the explanations you can find online give a lot of examples. Just think of all the times you may have used flatmap for arrays: that's just map followed by the "join" for arrays, which is sometimes called flatten. The other operators you see used in haskell, like "bind" (>>=), can be derived from "join" and vice versa and are just conveniences to write code with less noise, like flatmap is.
Recap: monad is the name of the concept for things that have a "join" and a "return" functions defined. Basically "join" is the distilled concept of what a monad is.
(edit: formatting)
It explicitly tries to answer the question: "I’m a C# programmer with no “functional programming” background whatsoever. What is this “monad” thing I keep hearing about, and what use is it to me?"
I have an article i'm about to publish that will have a lot more real world examples... hopefully it can bridge the gap.
It'll also have exercises, which are honestly the most important part of understanding.
- How opamps work and how they're used to make a differentiator.
- How quantum computing works. I want understand it to understand why factoring and discrete log fall to QC but not the post-quantum algorithms. I never make it past the intro chapters.
- What exactly makes cryptographic hash functions have desirable properties like collision resistance? Bits go in, bits go out, why can't full observation of the process not yield a method to construct inputs for a target output? Similar questions for block ciphers. It is much easier to "see" the impossibility in public key schemes because you can play and experiment with the math. In symmetric algorithms it looks like just a bunch of arbitrary bit operations.
EDIT:
- Relativity. I accept things like time dialation and nothing can go faster than the speed of light. But I have no idea why you would experience less time passing than me after a high speed rocket trip when, from your perspective, you saw me on a high speed planet trip. Or what prevents a rocket in space with 3m/s^2 acceleration from reaching the speed of light after 100,000,000 seconds.
An op-amp is just a very high gain amplifier. It senses the difference in signal levels and just amplifies that difference by a large amount, usually between 1000 and 10,000,000 times.
The first op-amp circuit you usually use is a negative feedback linear amplifier. In this circuit, the positive input to the op-amp is simply grounded. The input voltage is put through a resistor R1 into the negative (AKA inverting) input. The resistor limits the current into the negative input to Vin/R. As soon as the voltage on the input becomes non-zero, the output of the op amp becomes a quite large signal, of the opposite sign. If you feed a small amount of that signal back to the same negative input, (through a feedback resistor R2) the signal will rise until the feedback current balances out the input current.
Now it's not exactly in balance, as there is a very small deviation that has to drive the amplifier to keep its output up, but for most uses the higher the gain of the amplifier, the lower that deviation has to be.
This circuit has a gain of -R2/R1
If you replace the input resistor in the above circuit with a capacitor. It will pass a current proportional to the change in voltage/time and the capacitance. If you feed in a steadily rising voltage, you'll get a current into the negative input of the amplifier that is proportional to the derivative of the input voltage, the feedback current will balance this out, and you'll thus end up with a scaled up derivative of the input.
This circuit has a gain of dv/dt * -R2/(1/c)
If you start with the first circuit and replace the feedback resistor with a capacitor, you'll find that the output has to rise at a rate proportional to the input voltage to balance the input, making an integrator. This only works up to the limit of the output voltage, and there may be a small amount of uncorrected input bias.. to counteract this, a large resistance will be placed in parallel to the capacitor, to keep the output from becoming pegged with no input.
This circuit has a gain of -Integral(Vin)* (1/C) / R1
Notice in all of these equations, the gain is the ratio of the -feedback impedance/input impedance
Does that make sense?
You can derive the behavior of op amp building blocks from these rules and Kirchoff's laws. It also makes things obvious, like ideal vs practical integration.
I'm going through the same learning curve with quantum gates. Nobody shows the physical layout of the devices involved, signals going through them, etc.
At least in my EE undergrad we were taught why you would want an op amp before we were taught how to design multi stage amplifiers with discrete transistors. In fact most of the real world limitations of op amps don't require knowledge of what's going on under the hood, least of all the physical layout of the chip. Even a schematic diagram of the simplified model for a UA741 is more than you'd ever need except for a shitty SPICE emulation.
I empathize with what you're getting at, but I've seen that mentality turn into the bane of practical or working knowledge of many technical topics. It is a skill to be able to learn just what you need to learn and decide what level of detail is enough, and most of the time that skill is only provided through instruction and mentorship.
Everybody talks about how increasing the money supply means increased demand, which drives prices up. But nobody explains how does this *practically* happen. Prices don't go up on their own, it's the retailers who increase them at some point. So if the retailers' perception of the reality is not accurate (Suppose for example that money was printed "secretly", or that the increase in demand wasn't very apparent) prices won't magically go up, no?
There is a common knowledge component in all those equations that's missing and nobody talks about it. Maybe it's too obvious that I'm overlooking it.
Money supply isn't the only thing that does it, but when demand goes up sales go up, the additional production to keep pace with the sales has higher per-unit cost (because marginal costs increase), and everyone in the supply chain raises prices as a result. (That's simplified, a lot of price changes are anticipatory based on predictive singles, but that's the basic process that ultimately acts to align prices even if the anticipatory pricing misses movements.)
Commodity and base resources go up—>retail prices go up
Very simplified explanation.
More food will be sold (because why not buy the extra whatever since you can afford it) the better workers will demand more pay (otherwise they can go somewhere else that can afford them.)
It's much like gas exchange/osmosis/pressure. Sure the individual particles aren't "thinking" about the behavior of the macro system but their velocity changes every time they bump into each other and that creates the macro effects of osmosis, pressure, heat etc. In the same way inflation is a macro thing that results from the behavior of individuals.
You can see it with boats and cars today: lots of people now have spare money and buy boats/cars -> people selling see that they can charge more (because there are fewer being sold, the ones that do get sold go for more etc) -> boats/cars are more expensive.
In a normal room, the hottest air goes to the top of the room and the coldest air settles to the bottom, right?
However, if the room were to keep expanding, then there is more room at the top for the warmer particles to escape to. Since you stay the same height, the room will feel colder and colder to you even though the total amount of heat in the room stays the same.
As time goes on, unless the room's expansion is stopped or reversed, or temperature treated air is blown into the room to compensate for the difference or, failing that, platforms are provided that will raise you up from the colder areas into the warmer areas, you will eventually freeze to death as the ceiling steals all of the heat of the room, all because you cannot grow with the room.
Inflation isn't about the cost of goods or services actually costing more. They don't. If anything, the cost of production today is far less than it was 50 to 100 years ago because of advances in technology and automation.
It's about the value of the dollar becoming less and less - because there are too many dollars in circulation, which aren't backed by anything real to begin with. "Real" could be something which has a finite supply that we attach an arbitrary value to, like precious metals, or it could be something vitally (needed for life) necessary in today's world like wheat or oil. But for decades now, newly created currency is just an entry in the Fed's ledger book, created out of thin air, backed by nothing.
In your example both the size of the room and the heat represent aspects of currency (note I did not say "money"). The size of the room is the purchasing power of dollars leveraged against the actual effectiveness of the heat. The heat itself, is the value of the currency. The size of the room represents the price of goods.
As the room gets bigger, the heat becomes less effective (it loses value). So pumping in more heat becomes required. When more heat than necessary gets pumped in (on purpose - and it is done on purpose), the room will begin to overheat and no one will want anymore (so it loses its value again). The sane solution would be to stop pumping in more heat - but instead, the same people supplying the heat decide to enlarge the room again, because they are in the business creating heat and charging a fee to deliver it ("they" would be the Federal Reserve - or any private, western central bank).
So the room (i.e. price of goods) must be enlarged over and over again (artificially and unnecessarily) in order for a new infusion of heat to have any value to the people in the room. This in turn, requires the occupants of the room to keep forking over more money in delivery fees to keep the room at a comfortable temperature. If this becomes unfeasible, they may be forced to take out loans to have more usable heat. Now they're paying money for both the heat itself, plus interest on the loan for supplying it in the first place (and they owe it to the same people).
Once you wrap your ahead around the fact that the enlarging of the room and the supply of heat are actually controlled by the same people (who make their money creating heat and charging to deliver it), you then understand that the entire financial system we currently enjoy, is nothing but a giant, legalized system of usury. That delivery fee you owe for supplying the heat is called "interest".
This type of system will always (and is designed to) collapse at pretty regular intervals. When it does, those who control the flow of heat will shut it down, and have legal authority to confiscate the room from the occupants who took out loans for more heat, but couldn't afford to pay it back.
What makes the whole thing more insidious, is that the people supplying the heat never actually owned it to begin with, nor did they create it. It would be as if the room (once upon a time) had a natural heat supply from, say, and underground geothermal source. But some strong-armed, outside entity stepped in, capped that off, and started charging the people in the room for access to what was once naturally available - free of charge.
While academically, it is not a precise concept of what happens in practice, as there are multiple factors at play, printing money nonetheless does have this effect.
Organizations’ ability to increase prices as a result of inflated money supply is governed by competitive forces. So, it’s not as simple as seeing money supply increase 40% and thusly increasing your prices, but there is some truth to it.
I’m a self-taught programmer, so have probably missed lots that might help, but every time I come across anything OO, it always seems unnecessarily complicated and awkwardly structured. It always seems (to me) that everything could be done more simply procedurally. I don’t get why.
Further, while I can follow OO code that others have written, as a beginner, how to structure something simple I’m writing de novo in an OOP style has a very steep learning curve.
Some people are really good it but it's a skill for sure and learning it is rough. It is some really abstract thinking shit, and difficult even to evaluate how well it has been done until much time has passed with it.
I think when people joke about naming in programming this is what they mean. Needing to clearly define relations that are not necessarily clear yet. OOP does demand a lot of that so is hard and exhausting in a particular way.
That said nothing against OOP I use it every day and Sandi Metz is the code book writer I learned the most useful stuff from. Just it's hard in a different way from most of the rest of coding.
Android development is the classic example - it's ALL OO - and most of the time, that's pushing the proverbial uphill. Instead of just initialise something, everything is pushed into constructors. The model works sometimes, but for many things it just adds work. AND ADDS ENORMOUS AMOUNTS OF BOILERPLATE. Aarrgghhh.
But in modern OOP, understanding and simplicity are not what it's all about.
It's all about pushing the complexity into the language runtime stuff where it is no longer your problem.
OOP is popular because we can do stuff like port=DBConnection(); port.connect("foo.baz") and document= port.request("x").
Then, later on, when port and document are inaccessible, garbage collection will get them.
An OOP programmer doesn't think "Oh, the port.connect must make a socket and do a handshake and then..." they just think "It does all the port connect stuff".
As a student when the goal is to understand, OOP makes no sense, because encapsulation literally is all about making it so you don't need to think about things.
It lets you treat objects the same way we treat physical devices. Black boxes someone else built.
There's no beautiful reasoning or amazing objective logic saying OOP is better than I know of, or anything that even makes any sense at all if you think about it.
It just happens to work pretty well when people with a wide range of skill levels do large projects and nobody understands anything beyond their tiny part, and nobody really cares if things are simple under the hood.
If you want beauty and logic, learn a pure functional language or go study math.
And if you want to structure stuff in an modern OOP style, you just stop thinking in terms of simplicity and unified wholes and start thinking in terms of black boxes to be used by people who would be annoyed if they actually had to read the code.
Any entity you would talk about when describing the code is something that could be represented as an object.
Any collection of a variable number of a ton of entities like customers is something you could do as some kind of database connection object.
Any periodic task might be a "Machine" that is a class that manages a thread.
It's(In theory) a 1 to 1 mapping of ideas to classes, although some things just aren't worth a whole inventing object for and should probably be a data dict+procedural.
But, some would say this whole thing is nonsense for idiots who can't think, so maybe if you find yourself actually able to do procedural well you should try something more logical like haskell.
doX(data, args)
Here is OO:
data.doX(args)
The only difference is that you can stop doX(data, args) from modifying parts of data. However you can do the exact same thing in non-OO languages like C or Haskell by using void* (in C) or (in Haskell) modules with hidden constructors.
The only true OO language out there is Erlang. C++/Java/C# etc. are not OO languages.
The idea that OO is modelling the world is BS. You don't ask your shoe to tie itself or ask a tree to chop itself.
And you don't ask an integer to display itself in a dialog in an "OO" language unless you are a bad software designer.
Spin can then arise from enhancing the Schrödinger equation with a relativistic description of mass and impulse [0].
For example, finding a word in a dictionary. One algorithm is to start at the beginning and read all the way through until you find it. Worst case scenario, you read all N records, thus it's O(N). A binary search would start 1/2 way through, then repeat with either half, depending on which branch you take, and you wind up with a worst case scenario of O(log N). Nested for loops often wind up as O(n^2).
Beyond that... I have a hard time being any more detailed than the ones I just mentioned.
For the sake of simplicity, it's just all about getting a ballpark of the resources an algorithm take (often time, can be memory too) without taking into account the specificity of the machine the program runs into.
Let say the algorithm is x+1, x being a number. Now, you can certainly tell that whatever is the computer, it should be fast right. It's O(1). 1 here means, we know it takes one number (x) to compute the result. Wait you gonna say, it takes 2 actually, x and 1. Well yeah, it's 2 then. But it's always gonna be 2. Its not gonna be 3, its not gonna be 4, its gonna be 2, always.
Lets take another example of O(1): x+y+1. How many operations here? 3. Always 3.
So its always a constant number of operation and we call that O(1).
Now let say we have the following algorithm: result = 0, for each x in L: result += x
How many operations? Well now, it depends on the size of L and if L is big, its gonna take a while to compute. Its not a constant anymore. We call that O(N). N here means: the ballpark is: the size of a list. Its not a constant number of operation, its a number of operation the size of a list.
Now, say you have: result = 0, for each i in L: for each j in M: result += i-j
Whats the ballpark here? The size of a list multiplied by the size of another list. So O(N*N) or O(N2).
Now youll find some algorithm runs at O(log N) on average for example. It means its in the ballpark of the size of a list but...no; weve been able to prove that its quite better than that. Say you search in a binary tree, on average, chances are you wont visit all nodes. On average the ballpark is better than the size of a list. Its log N. Why log? Because its a binary tree and binary trees divide by 2 the size of the remaining list after each step or operation.
for each x in L: result += x
for each x in M: result -= x
(Loops arent nested here but done sequentially)
Whats the ballpark? O(2N) you might say. Nah, its like saying that x+1 is O(2), you re not giving me the ballpark here. What matters is how fast it grows when we put in more inputs. We dont care how many operations there is exactly.
It's O(N). Think of it like, whatever are the details, we have traversed one list, the concatenation of L and M. Weve just traversed lists sequentially, its in the ballpark of traversing one (think of it as a big one if you need too) list. O(N).
There is a bit I dont get in there. Namely, its relative but its not. I also have to admit I never tried hard to learn more about it.
I don't know if it will help you, but the explanation that worked for me was: "If two events occur at the same place in an inertial reference frame, the time between the events will be shorter than in any other inertial reference frame."
In other words, each observer sees time slow down on/in objects that are moving fast relative to them (i.e. greater time between events).
For example, if a spaceship zips past Earth at nearly the speed of light, someone on Earth will see the clocks nearly stopped on the spaceship, but someone on the spaceship will also see clocks nearly stopped on Earth. As you said, it's all relative - including time.
Edit: As you brought up the twin paradox in a now deleted question, I should point out that this is indeed "wrong" (or just not applicable) to that scenario. This analysis is only for inertial reference frames and ignores perceptual differences due to moving toward or away. The twin paradox introduces a really mind blowing idea called the relativity of simultaneity. Basically, all the asymmetry in the twin paradox is introduced while turning around.
Cause light goes at speed of light. Nice.
Im intrigued by matter now. What is it exactly it does to a photon if I attach some to it. Edit: or more like, time must be why a photon doesnt teleport (or even exists), so matter does something to time. Matter and gravity must be the same thing or something.
I wish I had time to study, love it.
I recently tried to implement a basic compound interest calculation to graph something and understanding the formula did not come easily. By that, I mean that exactly what the terms represent and what each operation is achieving was something I really had to focus on. Being a dev, most of my counterparts have always seemed very comfortable with this stuff and I'm usually 30s behind.
I'm really astounded when I see complex formulae - I just can't imagine ever understanding them, let alone coming up with them in the first place. It's easiest for me to just imagine that I didn't develop a brain that's good at this stuff. It seems ironic to me because one of the enjoyable parts of writing code for me is modelling scenarios, assigning responsibility, laying out entities, etc which seem (to me) like activities that exist in the same 'abstract thinking' kind of space that math is in. Maybe that's another thing I don't understand :)
Also, how people are able to practice and improve at something, like practicing guitar and eventually being able to hit every note, or being able to never leave their wallet behind, or stopping at every stop sign and never forgetting which pedal is the gas.
The fact that people are capable of developing true "skills", where they can do every detail of something, every time, rather than just the vague familiarity a modern programmer needs to get by, just amazes me.
I don't think I've ever truly acquired a new skill in the sense people usually talk about. I can't draw, paint, carve, drive, juggle, dance, etc. I can't cook without a timer, unless I stay in the room and don't do anything else.
If something has a way to fake it with more tech, I'm pretty good at that. As long as I can hide behind the screen with my undo button, where my ability with my own hands is irrelevant, I'm fine.
But there's nothing I can just do without thinking.
I never know where I am. I run into tables all the time. It must be super cool to be able to just do stuff without planning every moment, and still succeed most of the time.
Practicing and actually getting better just by doing something, rather than through research and accumulating a library of patterns, is a totally foreign idea.
That is something I can relate to. I do most things without really thinking and usually do pretty well, but this makes building skills in the long run very hard since I don't really think much. I don't really know why but I feel like thinking while doing things in the moment is hard for me.
I also can't really rotate something. When I spent a few hours with a driving simulator game to see if it was at all possible one big issue I had was not being able to figure out which side was the right side of the road, relative to the new perspective after a turn. So I turned straight into traffic more than once.
But there's GPS apps now so aside from driving and math it's not that limiting. If they ever fix the public transit here I'd probably be fine...
The complexity comes from the many layers of detail that get added.
First, we don't encrypt the document directly, because public key operations on arbitrarily sized data can be slow, require padding, etc. So we hash the document, and encrypt the hash: Hashes are fast, they produce fixed sized output (mostly), etc.
Second, the document itself isn't an arbitrary document, it contains very specific, structured pieces of information. The two most important things are a) the public key being certified and b) the identity of the owner of that key.
We need "b", the identity, so that when we decrypt a signature using "a", the certified public key, we can have some assurance as to who the holder/owner of the private key was.
Identity gets complicated: A person? A machine? An email address? Etc. The original X.509 spec had directory names (think LDAP names) only; later revisions added email addresses, machine identifiers, etc.
Third, why should we trust a certificate? And what for?
Above, I wrote that the important things were "a", the certified public key, and "b", the owner's/holder's identity. Well, we also need "c", the certifier's identity.
The original X.509, e.g., basically had a, b, and c, and some date information (during what period is/was the certified key, a, considered valid); we date-limit keys for security assurance, because we cannot guarantee that key pairs generated today won't be cracked tomorrow or next year or next decade. The bigger we make the keys, the more resistant they are, but the slower is the crypto, so we strike a balance and go for more frequently generated and certified smaller keys, unless we really need long-term, in which case we use bigger keys. But hash algorithms get cracked too, so, again, a tradeoff.
So I've got a certifier's identity. Great. How do I verify the certificate they issued? For that, I need THEIR public key. Now we start getting into chains.
Somehow, I have to have a trustworthy copy of the public key of the certifier, the so-called certification authority (CA). The CA's certificate looks like mine and yours, a document containing a (key), b (identity), and c (CA), and some date info, etc.
I use that trustworthy copy of the CA's public key to verify a certificate, and that lets me know that I can rely on a, the key in that certificate, for some purpose.
But what purpose? In the original X.509, it was "fill your boots", whatever purpose you like.
Does that mean I can verify with that key? Encrypt with it? Use it for email, ssh, TLS, or even acting as a CA myself?
Later versions of X.509 addressed these questions by adding various markers that a CA includes to say to relying parties "I say this certificate is good only for these purposes". You are free to use it for other purposes, but if you get burned, you cannot go back to the CA, because those markers basically told you the certificate wasn't to be relied on for that.
Three of the most common restrictions are 1) is/isNot a CA (that is, does the CA recognize the certificate subject, the b, as a CA themselves? mostly the answer is no, this is an end-user or end-device; while there is nothing we can do to stop them from issuing certificates on their own, we DO NOT recognize them - the chain ends here); 2) encrypt/verify, used in two-pair cryptosystems, e.g.: the CA is saying that THIS key is good for verification, but don't encrypt with it, while THAT one is good for encryption, don't verify with it (there can be policy and security and operational reasons for all of those); and 3) purpose, e.g., this certificate is good for email only, that certificate is good for TLS only, this certificate represents a person, that certificate represents a machine, etc.
Fourth, what about that trusted copy of the CA's public key? Where does that come from? That requires a specific action OUTSIDE the overall infrastructure, outside the chain of trust. In many cases, it is a certificate import: We specifically say to our system "trust this specific certificate". How it gets used, the purposes for which it gets used, depend upon where it was imported (into a root certificate store, an intermediate store, a machine store, a user store) and upon the certificate properties previously discussed.
Fifth, and probably last, what if something goes wrong along the way? What if, despite my best precautions, a private key is compromised during the valid lifetime of the certificate?
How do I let people know? That's where revocation lists and online status checkers come in. I cannot remember who said it, but they described revocation lists as wandering anti-matter for certificates.
The basic idea of an RL is that it is a signed list of zero or more certificate identifiers - turns out certificates also include serial numbers which are intended to be unique within the set of all certificates issued by a specific CA. If the certificate is compromised, the CA writes the certificate's serial number on an RL.
Part of verifying a certificate is verifying that it isn't on an RL. Like certificates, RLs have validity periods, so one has to verify that the RL is also valid.
And that's pretty much what the original X.509 said about RLs. The expectation was that they would be in the directory (the whole point of X.500), in the CA's entry (the CA's certificate contains their directory name as their "b"; cf "a" and "b" way above). Original X.509 did make one distinction, between an RL for end-users, a CRL, and one for authorities, an ARL, but that distinction wasn't well described.
What if I am not using a directory? What if I want to have multiple RLs, maybe for different purposes? What if they get very large? How do I segment them? How do I tell people where to look for the RL that would apply to a given certificate?
And how do I know I have the right RL? If I am using a directory, what if an attacker replaces the RL I am expecting with another valid one? E.g., puts the ARL where I expect to find the CRL? Absent other information, the ARL will validate and of course the enduser certificate I am validating won't appear on it (it's on the CRL, the one the attacker hid), so it will appear valid.
Finally, what if the reason for revocation doesn't affect my purpose? The simplest example would be revoking certificates because of a change in business purpose. Maybe the business went out of business in July, so anything signed by them after July is invalid, but anything signed before then might still be.
Later versions of X.509 addressed all of these questions by including reason markers, revocation time markers, and a few other things.
Most importantly, these later versions of X.509 included the distribution point concept, the most important applications of which are 1) segmenting RLs so that instead of having a single monolithic CRL, a CA can maintain many smaller, perhaps more frequently issued RLs, and 2) tying a certificate to a specific RL BEFORE it is compromised.
In other words, the certificate contains a marker that says "if ever I am compromised, the CA will list me on an RL in this place", wherever that is. It goes one step further (since we trust signatures, not places): RLs themselves contain issuing distribution points that identify where they are from or are/were expected to be: The IDP on an IRL should/must watch the RL distribution point identified in the certificate itself.
That way you can know for sure that this is the right RL: If this certificate is NOT listed on this specific RL, then the CA has NOT revoked it.
This gets around attacks on the storage place, e.g., the directory, etc.
And that's just the management side of PKI, Public Key Infrastructure, and doesn't touch the crypto side, which is as complex.
So, yeah, it's a complex ball of wax.
(I worked for a PKI company for many years in the 1990s, did some PKI work before then, some X.500 work before that, and an awful lot of PKI, security, compliance, audit, and directory consulting in the first two decades of this millennium, but right now I mostly write code, either for high assurance network security devices or for an integrated risk and compliance management software product; this quarter is mostly the hardware product....)
Kubernetes is a different beast. Most people think of it as a cluster manager: instead of managing your own nodes, then running scripts or automation on them, you write a bunch of yaml and K8s deploys and runs it. While that is fine and true, that's not why Kubernetes was built.
Instead, k8s is a platform for building platforms. You don't run your microservices on it, you run your clouds on it, which in turn run your stuff. At this level, you can see why you need the comical amount of complexity.
It's like a lot of other strong constraints on complex endeavors. If you run with it you can get surprisingly far, but only by twisting your understanding of how to do things. Whether that's good or not seems highly personal though.
1. In traditional (imperative) languages you can have functions that deliberately or accidentally either modify the data they were given or do some other stuff that changes data somewhere else in your program or the computer. Let's take an example of each. Say you have a function that adds two numbers a and b. In imperative languages you could return a+b into b. In other words the sum(a,b) operation would change b. That's not cool in FP: you are (almost never) allowed to change the input you received. This way whenever the function is called with a and b it always returns the sum (otherwise if you call sum(a,b) again you will pass in a modified b).
This makes every function guaranteed to always return the same value for the same arguments. If you accidentally try to change a parameter in your code it will fail.
But you still need to make changes to the world - you do so by chaining these functions and using the output from one as input to the next and so on.
Last but not least, functions that have side effects (e.g. print to the screen) are marked differently and usually their effect is isolated.
FP is basically making all of your inputs and outputs explicit. In OOP if you have some bool on a class that affects what a method does, that private bool is technically an extra parameter for that method, even if it doesn't get passed in. Similarly if a method changes some integer on its parent class, in a sense that integer is technically part of what gets returned by the method.
Functional programming forces you to actively think about all of the extra inputs and outputs of your code. In turn, this helps you avoid unintended side effects from the internal workings of a method etc. and the bugs that they can cause.
While the ideas behind FP are useful and can help you think about your coding in a cleaner way, I also think they can be overdone and taken to almost religious extremes. And it can come with a cost of worse performance, more difficult to write/maintain code, etc. , though done right it can have the opposite effect. Done right, it can also make certain aspects of asynchronous and parallel programming easier to work with.
FP, OOP, and all of the other programming paradigms have useful concepts, but purism for any paradigm can lead to all kinds of problems. The obsession with "state" that you see from some FP evangelists is especially annoying, because it ignores that in almost any useful program there will be an irreducible amount of state that has to be tracked and dealt with.
You are essentially working with functions that receive input and return output, and are not allowed to change anything outside them.
The simplicity is in that you create multiple levels of abstractions by only combining functions: low-level functions do some "dirty" work that the program needs to perform (slice cucumber, open oil, pour oil, add salt, etc); you then combine a couple of such low-level functions in another set of functions - making it a bit more abstract (make salad, prepare table); then you combine these abstract functions into even more abstract ones(prepare dinner), etc. There will be also some "helper" abstract functions that can be reused in different contexts (slice something, open something, put some food on the table, etc).
Because each function - no matter the level of abstraction - only takes input and produces output - it's very simple to write, read, reason about, and test.
Obvious question you might have right now: how can you write a useful program if you can't change anything outside the function or interact with the outside world? Well, that's the "dirty" part of writing a FP program. You just write your program trying to keep it as "pure" as possible, pushing the "dirty" parts away as much as possible. Think Layered Architecture but for programs. You keep the "outer layers" of your program "dirty" - reading/writing to the DB, making network calls, etc - and preserve the "purity" of as many "inner layers" as possible. For example, when you want to write to a DB in one of "inner layers" which should stay "pure" - you can return your "desire to write to a DB" as a string(or however you encode it) to your outer layers, which will then perform the actual operation by actually talking to the DB. The inner function stays pure because it doesn't actually talk to the DB, it only returns instructions for outer layers to talk to the DB.
Depending on the language you are using it might be either beautiful and easy, or extremely awkward and overly complicated. Most of the time it's something in between.
Hope this helps.
https://physics.stackexchange.com/questions/497923/is-convec...
What do you mean? A parser is just a program that parses input following a grammar into some kind of internal representation. Did you mean you can't write a compiler? A parser is just a small part of that.
I did an whole B.S. in physics and I could just never get it.
Make sure you’re merging changes from your upstream regularly.
When two people change the same area of code, you get a merge conflict.
So sync often and merge often. Don’t wait until you’re ready to push to merge upstream or you’re gonna have a bad time.
[0]: https://tom.preston-werner.com/2009/05/19/the-git-parable.ht...
>"Is there a specific topic, concept, etc.. that no matter how many times you try to wrap your head around, you can't ever seem to get it? "<
Yes, <edit>Russian political thought patterns</edit> Make that 'Political thought patterns' or hell, maybe just "Thought."
>"If you were in this situation, what would you do?"<
Go to war? Kill the enemy?
But seriously, I'm completely flummoxed by human group behavior vs individual behavior [i.e., the crowd vs the individual]. We have no meaningful way of extrapolating from one to the other. The closest complete model is thermodynamics, which is so primitive as to be useless in this context.
Consider a linear transformation from Rn to Rm. i.e. T[x1,...,xm] = [y1,...,yn].
Let's simplify the left-hand side with what we know about linear transformations: T[x1,...,xn] = T[x1,0,...0] + ... + T[0,...0,xn] (by 1). And T[x1,...,xn] = x1T[1,0,...,0] + ... + xnT[0,...,0,1] (by 2)
We don't know what T[1,0,...,0],...,T[0,...,0,1] will be (cause we're generalizing for any linear transformation) so let's just assume the values will be [c11,c12,...,c1n],...,[cm1,cm2,...,cmn].
So now we have: [y1,...,yn] = x1[c11,c12,...,c1n] + ... + xn[cm1,cm2,...,cmn]
And using the properties of linear transformations we can revert it back to the original form: [y1, ..., yn] = [x1c11 + x2c12 + ... + xnc1n, ..., x1cm1 + x2cm2 + ... + xncmn]
So no matter the linear transformation, all entries yi of the vector you output will be equal to a linear combination of x1,...,xn. So if all linear transformations satisfy this condition, what makes a linear transformation different from the others? It will be the set of coefficients [c11,c12,...,c1n],...,[cm1,cm2,...,cmn] that multiply with the x values.
This set of coefficients is unique to every linear transformation from m to n (it's what defines it), this means that we can set up a one-to-one correspondence between these coefficients [c11,c12,...,c1n],...,[cm1,cm2,...,cmn] and any linear transformation (from m to n)!
So let's make it easier for ourselves to describe every single linear transformation from m to n by setting up a rectangular array of the coefficients with m rows and n columns: [[c11,c12,...,c1n],...,[cm1,cm2,...,cmn]].
And so if we find a matrix [[A,B],[C,D]] then we immediately know it corresponds to the linear transformation [y1, y2] = [Ax + By, Cx + Dy]
Note: You won't find a one-to-one correspondence between a matrix and a non-linear transformation with this method because non-linear transformations could have terms like xy, x^a, sin(x), etc... that can't be captured by a linear combination.
SaaS is useful inside enterprises because you don't have to provision software on machines.
SaaS is useful for entrepreneurs to build businesses by chaining APIs together.
SaaS viz a vi Shopify is useful because smaller business can leverage larger Amazon like tooling.
You either have to be in an industry and see the “next major iteration”, “now that this tech exists let’s make it simpler” or you have to talk to a lot of people to find a common trend.
Once you have that you start talking and showing your MVP to people. They will give you product excuses not to buy. Use those excuses to slowly iterate your product to remove those excuses.
If at the end there are no excuses and people aren’t buying your value prop isn’t strong enough.
Start with “why are people allocating budget here when they could allocate it to something else” … it needs to affect the bottom line somehow because someone who’s buying your product needs to make a business case internally.
So find a trend, iterate on the product, make sure there’s a “reason to spend money on your product instead of another product”
- the mathematical formulation and simulation of relativistic systems and the standard model
- quantum anything
- axiom independence proofs/"forcing"
- the shader pipeline
- historical mindsets that caused religious schisms
- why individual particle decay is truly random
- how to reason about complex electronic circuits
- why it makes sense for countries to artificially devalue their currency
- how the execution of passed laws is organized
- how dna recombination works
- p-values and tests of randomness
- mathematical induction
it's an unavoidable tax. if there are 100 bills in circulation and I print 100 more, I took 50% of the purchasing power of the bills that were originally in circulation.
https://en.wikipedia.org/wiki/Oberth_effect
I understand the math, but I cannot form an intuitive understanding of why it works. My brain just insists that it shouldn't matter how fast you're going, you have a certain amount of energy in your fuel, and that's all there is to it.
> at 1 m/s, adding 1 m/s increases the kinetic energy from 1 J to 4 J, for a gain of 3 J;
> at 10 m/s, starting with a kinetic energy of 100 J, the rocket ends with 121 J, for a net gain of 21 J
From here it could go two ways:
a) The craft does nothing. The full mass continues to get higher and the kinetic energy the reaction mass gained is turned back into gravitational potential energy.
b) The craft ejects (maybe by burning) the reaction mass. The kinetic energy of the reaction mass is transferred to the craft. Ejecting the reaction mass slows it down and that speed is transferred to the craft. Now the craft continues with all the energy it had going in, but because it is much lighter less of that kinetic energy is transformed back into gravitational potential energy.
Or think of it this way. You have a big rock at the top of a hill. You roll that rock down the hill and convert 100 units of energy in to kinetic energy.
At the bottom of the hill is a see-saw. The big rock hits it and launches a small pebble. That pebble still only has 100 units of energy, but it's moving much faster than the big rock did.
It is not about getting more energy, it is about shedding mass at the right time to transfer (what starts as gravitational) energy from the fuel to the craft.
I know that time prevents all things happening at once... but what _is_ time? How does it work? How did it start? Mind-boggling...
[0]: https://reddit.com/r/explainlikeimfive/comments/n9v01r/_/gxp...
I think we should talk force/work/energy/material structure.
Force is just force, how hard you push something. Work is force times distance you moved that thing - moving something 10 meters is twice as much work as moving it 5 meters. Energy is the abstract term that is basically Work, but normalized so we can define energy of any action (not only pushing something but like heating this, or spinning that). Power is energy output per second. (not relevant here)
Person holding 1kg first uses energy to pick this up, then unfortunatelly because we're squishy uses energy to stabilise muscles (chemical energy) holding it against gravity.
Magned uses electric field energy (either static or dynamic cos there's two types of magnets) to pick up something - but once grabs it, it's no longer using energy (there's no movement) - things get 'frozen in time' and that thing magnet is holding just becomes part of the magnet. If you separate them - the thing "gives back" the energy to the magnet (you supply the energy by using force to separate them).
Now the thing that hold the magnet holds both - as long as it's not squishy human but for example the metal bar - it does not use energy to hold stuff (thanks to internal metal structure that's stiff enough to not move under magnet's weight, of course there's a border value of weight a metal bar can withstand without collapsing)
Think of a lamp post holding a lamp above a road - the post does the holding for 0 energy but someone had to use the energy to install the bulb up there. Person holding the same lamp would use energy because we're not stiff as metal.
But if I have some super telescope here on earth, and I'm looking through it now, the photon that hits the eyepiece of the telescope also was ejected 13bn years ago.
I don't see how magnification allows me to see even older photons.
Not really, as a turing machine is fully able to simulate any other turing machine.
The problem is not that the "termination checker" may not run the program it's checking (it is allowed to do that). The problem is that if that program runs forever then the "termination checker" program will also run forever and thus never return "yes" or "no".
(You could say, well just output "no" if the program runs for longer than x days / weeks / months / years, but it's quite easy to write programs that run for a very long time but do eventually terminate. At best, you'll manage to write a checker that can output "yes" or "I don't know").
Some people misrepresent the halting problem and its corollaries as "we can under no circumstance predict any aspect of the behaviour of any program", which is in fact wrong.
What is true is that, for every property we may want to assert about a program, there exists a program (on a Turing machine or in a Turing-complete language, so excluding any of the total programming languages) for which you will fail to tell if it has that property.
Water has one oxygen and two hydrogens, this makes for a pretty polar molecule. At a purely mechanistic level, you can think of polar molecules like how magnets work. N is attracted to S and vice versa. In polar molecules, + is attracted to -.
When water loses energy (like through cooling down which is just when it runs into other molecules and loses energy) it doesn't have enough momentum to not stick to other water molecules. When this happens they start clumping together and can fall out of the (gas) solution.
Water in air is moving around pretty fast and this overcomes the attractive force of the polar interactions with water molecules, so no clumping (water droplets)
Since amount of energy (temperature) determines how much water the solution (air) can hold, dew point is the temp at which the air is fully saturated with water molecules and can't hold any more. Water will condense if the temp is lowered past the dew point if we assume a constant water content and air pressure
So, when I have a cold glass of beer and there's condensation on the outside of it, it's because molecules of water vapour bouncing around, cool down rapidly, lose their kinetic energy and end up being captured by the existing water on the outside of the glass?
on the contrary if you boil the water like madman you're giving water molecules so much energy it flies away as steam :)
I get the description of planets in gravity wells and can understand the basic technical explanations.
But it still just doesn't make rational sense on any level to me since I view time and gravity as static concepts from my experiences.
My first major step was to really understand that gravity is a law and not a force.
This is totally counterintuitive since we feel gravity as if it were a force, and because many people use the expression "force of gravity".
So a mass should be viewed as a "tag" that an object has - and the higher the number on the tag, the higher it deforms the space-time around it.
My second major step was to understand that all objects, for example planets, always go straight along a line. They appear to have an orbit because they move in a space-time that is deformed by other planets and mainly stars or black holes.
The moon goes along a straight line in its space-time. But the latter is deformed by the mass of Earth so it looks to us living in Earth's space-time that the moon is orbiting around Earth.
The third major step is to understand that the two space-times mentioned (the Moon's and Earth's) are not "related". Someone on the moon lives in a different space-time than someone on Earth.
So the duration of time that person lives on the Moon as measured by an atomic clock he/she brought will diverge with an atomic clock on Earth.
The difference won't be huge, in truce very very small - but measurable.
Everyone of us lives in its own space-time. Because the gravity is not equal on the point of Earth surface. Because of mountains, and because the Earth itself is not homogeneous, and because we move around and up and down all the time.
In final, this means to get rid of two related notions that appear so self-evident that it is almost impossible to really get over with: - there is a common 3D space that we all share ; - there is such a thing called time that is totally independent and flows continuously.
What really exists - for each person or object or planet - is its own space-time.
And all these space-times are unrelated to each other.
The proof of it is that there is a maximum speed limit to any existing thing. That maximum speed does not vary whatever are the speeds of two considered space-times.
The only thing we know that reach that maximum speed happens to be the light in space.
If the two space-times were related, then the speed of light would vary if one space-time is moving in a different direction and/or speed relatively to the second considered space-time.
But it doesn't. So you and me don't share the same space-time. So, between two encounters, we won't have lived exactly the same duration of time. Our personal atomic clock, if synchronized at the first meeting will have diverged when we meet again.
Of course, the difference will be so super small that it's unnoticeable to us (but measurable with today's technology).
GPS satellites orbite at around 36,000 kms from Earth. That's far enough to make GPS calculations quite wrong if Einsten's relativity is not taken into account (by around 50 meters). That is noticeable.
By the way, Einstein deeply regretted his poor choice of words. Because its theories of "relativity" precisely demonstrate that the different space-times are NOT related.
We need to understand that space and time don't exist. Only unrelated space-times co-exist, within which time as we feel it flows at a different pace than in other space-times.
But there is only one "Reality", right? Well... that really depends what we mean by that. The only common point among space-times is the respect of causality.
That sort of reinstates time as we feel it. If A causes B, then B can not precede A.
In a sense, events creates time as we know it. After all, we are all very often surprised by the time it is on our watch. So this "unstoppable Time that flows no matter what" that we think as self-evident in our representations ... just doesn't match our very variable perception of time in our lives.
Isn't it weird that we commonly consider obvious a notion that contradicts directly our daily experience of it?
Maybe it is time to reconsider the way we teach physics at school ; we learn Newton's laws and then we are supposed - much later if ever - to unlearn it in order to grasp Einstein's relativity.
Some will argue that Newton's laws are good enough for our daily lives. Well... not anymore since we use GPS all the time. And Newton's law can't explain Mercury's orbit either so why are we taught Newton to explain the orbital system when 1 planet among 9 contradicts what we are taught?
Science is by principle a work on ourselves to deconstruct reality as we perceive it spontaneously, through our senses, our biases and also the inherited paradigms from the established Science.
It is super difficult to unlearn. If you play tennis for years without taking lessons, it is super difficult to train our body to unlearn the bad habit and learn the proper way taught by a professional.
So maybe let's stop calculating where will land a cannonball without even taking into account the effect of the air! This is not even a practical teaching of everyday life since the major effect of air on the cannonball is obliterated to teach us Newton's laws that are not totally true either.
Let's learn Einstein first. That the nucleus of an atom is 100 000 times smaller that the atom ; that no graphical representation of a nucleus composed of neutrons and protons is possible ; all these illustrations with agglomerated spheres of different colors are ... just wrong. Phycists don't know how to represent a nucleus, which is not a static thing but rather something that is animated by opposite forces but kept close by a vastly superior force.
Physics is like History. We keep on learning at school things that we know to be at best approximate and very often just plain oversimplification that leads to misrepresentations that are super difficult to correct.
Hence the so many Russians, including Putin himself, considering that Ukraine and Russia are historically one nation. Totally ungrounded but war nonetheless.
You have thought about this plenty. The only thing I'll add is that all objects live in the same spacetime. The metric of that spacetime is a mathematical object that obeys known laws under coordinate transformations, and the parameters of those transformations depends on the energy momentum tensor (likewise an object that transforms...).
Trouble with GR is that the "trivial" solutions are heavy shit. So it goes.
However, think about insane it sounds.
Like if we didn't have the subject physics or if you had to explain it to a medieval king in the 1300's.
They would think we are totally insane.
Because it is different than what our everyday hairless monkey lizard brain sensory organs are reporting to our brains.
That's why I struggle with it.
Cool example of satellites. That actually grounds it in an understandable example.
Also does relativity discount Newton?
Or can it be viewed as an extension?
> Physics is like History. We keep on learning at school things that we know to be at best approximate and very often just plain oversimplification that leads to misrepresentations that are super difficult to correct.
I think all of science is like that. It's continually advancing and changing our views of the universe which is beautiful.
Im going to tell my boss next time I'm late that I'm not late it's just that our space times are subjective and aren't currently synchronized.
I knows this is a dumb question but please pardon me as my knowledge of physics is very limited.
So for example, if two bits are entangled, you flip one bit, the other bit flips at a completely unpredictable way.
Hence, no rule is technically broken.
The key word being: "usable".
You can have two bits of quantum information entangled together so they are always opposite values. Then (while keeping the two bits entangled) separate the two bits and place each inside a box without looking at the bits. Then move the boxes apart to the other side of the world.
Quantum Entanglement says that we can open one box to look at the value of the bit inside that box and know that the opposite box has the opposite value.
Alice opens her box and sees the bit "0", so she knows that inside Bob's box is a bit with the value "1".
So depending on which quantum mechanics interpretation you're using, Alice's bit has to share some information with Bob's bit to determine what each bit's value is.
Depending on the time that the boxes are opened, we have experimentally proved that if information is getting transmitted between the two bits and if it is travelling through the space between the two bits, then it must be transmitted faster than the speed of light.
The problem with trying to use this "transmission speed" to send information is that there is no actual way to send any usable information with it.
We can open a box on our end to see which value we got, but we don't know if we got value because we opened the box first, or if the other person opened their box first. The only way to tell is to go and talk to the other person to tell them the time that we opened the box which in and of itself is slower than light.