

That’s still confusing to me. My parents had the water heater tank in the bathroom, between the shower/bath and the sink. The kitchen sink had a separate small water heater.


That’s still confusing to me. My parents had the water heater tank in the bathroom, between the shower/bath and the sink. The kitchen sink had a separate small water heater.


hot water circulation systems should be more common
That just sounds like a waste of energy. Why not have the water heater right next to your shower, so that there’s no wait? It’s how it was set up in my parents home. Really enjoyed that setup, never had to wait for hot water.


It was used to deliver the comic to you in the first place.
The intended use-case is for bit-banging, i.e. sending electricity to places according to certain algorithms. Think about simple automation, like the control chip in your washing machine which executes the selected program by sending enable/disable signals to the water pump, valves, and the motor. Well, the same basic principles could apply to a lot of industrial processes and such, helping us rebuild the civilization.
It would also be really fucking great for helping post-collapse engineers do various calculations. Those chips are really slow by modern standards, but insanely fast compared to an abacus, a slide rule, and a sheet of paper.
BTW there’s also dusk OS, which follows similar principles but is targeted for more advanced hardware, like the abundant x86 and ARM chips. It has a way more user-friendly interface, a basic GUI, filesystem drivers, and IIRC even networking capabilities, all possible to run on a PC from the early 90s. It also has great bootstrapping flow, allowing you to rebuild itself from source, flash itself to other computers, and flash Collapse OS onto microcontrollers.
Basically like a Linux install with all the dev-tools and sources already there, except much simpler, to the point that you probably can figure out how every component of the system works yourself, and fix issues when they happen. This knowledge will also directly translate into writing programs for collapse OS, because they share the programming language and many OS paradigms.


I like how the rememes of this only get more complicated and less stable with time; hopefully this means the collapse is approaching, or else I’m learning forth for nothing!
It’s like a clown. Funny to watch it goof about from afar, but when it comes to you OH FUCK OH SHIT THERE’S A CLOWN STARING AT ME FROM THE WINDOW AND PLOTTING A RIGHT-WING COUP


The file that’s in use may not survive.
Yes, but at least the rest of the filesystem will


I’m not too versed in the intricacies of Windows, but I don’t think that’s the case on Linux at least.
There’s a difference between telling the processes to “fuck off” (by using umount -f) and actually yanking the drive.
umount -f will at least flush the caches to drive, including all filesystem metadata and journaling, while just yanking the drive off will definitely not, and if you’re unlucky you can ruin the FS (especially if it’s not a journaling one). I’ve lost data like that before, been using umount -f ever since.


We actually have two, for both of us to ride on. It’s the main way we get around the city. They cost us ~$80 combined (I’m not in the US tho), plus maybe another $50 in spare parts over the year or so we’ve had them. Also, as a proud 30yo shitbox owner, what’s a monthly car payment?


I’m assuming not many suburbanites have bikes.


Ah yeah, that makes sense. However, if all roads are fully jammed, most people would be able to walk to a grocery store - it’s likely not insanely far away from you (quick search suggests average straight-line distance to a grocery shop in the US is ~4 km = 50 min, which sounds very far away from a non-US perspective but still not completely unreachable), it’s just that usually there’s a highway full of traffic between you and the store.


You are overestimating the danger of a punctured tire. It is easy to notice, usually gives you plenty of time (on the order of minutes) to come to a complete stop before the tire is deflated, and even after the tire is fully deflated it still allows you to stop relatively safely for a short while (until it is cut through completely). It would probably result in a few crashes (because in carbrained places many drivers don’t know how to operate a vehicle at all), but the worst outcome from this is ambulances/firetrucks being stuck in traffic jams.


Scatter random tire spikes on the roads. 10k would probably get you quite a few
Personally I’m more partial to nom. Serde is quite verbose and complex for a parser.
I’m not coming to my parents for this new year’s because I might get arrested and/or sent to die in a war. But once Putin dies, yes, I am
I decided to write it myself for fun. I decided that “From Scratch” means:
read from PreludeHere is what I came up with (using my favourite parsing method: parser combinators):
import Control.Monad ((>=>), replicateM)
import Control.Applicative (Alternative (..), asum, optional)
import Data.Maybe (fromMaybe)
import Data.Functor (($>))
import Data.List (singleton)
import Data.Map (Map, fromList)
import Data.Bifunctor (first, second)
import Data.Char (toLower, chr)
newtype Parser i o = Parser { parse :: i -> Maybe (i, o) } deriving (Functor)
instance Applicative (Parser i) where
pure a = Parser $ \i -> Just (i, a)
a <*> b = Parser $ parse a >=> \(i, f) -> second f <$> parse b i
instance Alternative (Parser i) where
empty = Parser $ const Nothing
a <|> b = Parser $ \i -> parse a i <|> parse b i
instance Monad (Parser i) where
a >>= f = Parser $ parse a >=> \(i, b) -> parse (f b) i
instance Semigroup o => Semigroup (Parser i o) where
a <> b = (<>) <$> a <*> b
instance Monoid o => Monoid (Parser i o) where
mempty = pure mempty
type SParser = Parser String
charIf :: (a -> Bool) -> Parser [a] a
charIf cond = Parser $ \i -> case i of
(x:xs) | cond x -> Just (xs, x)
_ -> Nothing
char :: Eq a => a -> Parser [a] a
char c = charIf (== c)
one :: Parser i a -> Parser i [a]
one = fmap singleton
str :: Eq a => [a] -> Parser [a] [a]
str = mapM char
sepBy :: Parser i a -> Parser i b -> Parser i [a]
sepBy a b = (one a <> many (b *> a)) <|> mempty
data Decimal = Decimal { mantissa :: Integer, exponent :: Int } deriving Show
data JSON = Object (Map String JSON) | Array [JSON] | Bool Bool | Number Decimal | String String | Null deriving Show
whitespace :: SParser String
whitespace = many $ asum $ map char [' ', '\t', '\r', '\n']
digit :: Int -> SParser Int
digit base = asum $ take base [asum [char c, char (toLower c)] $> n | (c, n) <- zip (['0'..'9'] <> ['A'..'Z']) [0..]]
collectDigits :: Int -> [Int] -> Integer
collectDigits base = foldl (\acc x -> acc * fromIntegral base + fromIntegral x) 0
unsignedInteger :: SParser Integer
unsignedInteger = collectDigits 10 <$> some (digit 10)
integer :: SParser Integer
integer = asum [char '-' $> (-1), char '+' $> 1, str "" $> 1] >>= \sign -> (sign *) <$> unsignedInteger
-- This is the ceil of the log10 and also very inefficient
log10 :: Integer -> Int
log10 n
| n < 1 = 0
| otherwise = 1 + log10 (n `div` 10)
jsonNumber :: SParser Decimal
jsonNumber = do
whole <- integer
fraction <- fromMaybe 0 <$> optional (str "." *> unsignedInteger)
e <- fromIntegral . fromMaybe 0 <$> optional ((str "E" <|> str "e") *> integer)
pure $ Decimal (whole * 10^log10 fraction + signum whole * fraction) (e - log10 fraction)
escapeChar :: SParser Char
escapeChar = char '\\'
*> asum [
str "'" $> '\'',
str "\"" $> '"',
str "\\" $> '\\',
str "n" $> '\n',
str "r" $> '\r',
str "t" $> '\t',
str "b" $> '\b',
str "f" $> '\f',
str "u" *> (chr . fromIntegral . collectDigits 16 <$> replicateM 4 (digit 16))
]
jsonString :: SParser String
jsonString =
char '"'
*> many (asum [charIf (\c -> c /= '"' && c /= '\\'), escapeChar])
<* char '"'
jsonObjectPair :: SParser (String, JSON)
jsonObjectPair = (,) <$> (whitespace *> jsonString <* whitespace <* char ':') <*> json
json :: SParser JSON
json =
whitespace *>
asum [
Object <$> fromList <$> (char '{' *> jsonObjectPair `sepBy` char ',' <* char '}'),
Array <$> (char '[' *> json `sepBy` char ',' <* char ']'),
Bool <$> asum [str "true" $> True, str "false" $> False],
Number <$> jsonNumber,
String <$> jsonString,
Null <$ str "null"
]
<* whitespace
main :: IO ()
main = interact $ show . parse json
This parses numbers as my own weird Decimal type, in order to preserve all information (converting to Double is lossy). I didn’t bother implementing any methods on the Decimal, because there are other libraries that do that and we’re just writing a parser.
It’s also slow as hell but hey, that’s naive implementations for you!
It ended up being 113 lines. I think I could reduce it a bit more if I was willing to sacrifice readability and/or just inline things instead of implementing stdlib typeclasses.
You could probably write a very basic parser combinator library, enough to parse JSON, in 100 lines of Haskell
You gotta admit though, Haskell is crazy good for parsing and marshaling data


If we can ignore “checks and balances” for real,
Step 0: declare the US constitution mostly void, to prevent stupid hacks like “states rights” or “fed can only regulate interstate commerce” or whatever. Keep its remnants around to ensure institutional knowledge and capabilities are preserved, until a transition to better institutions is implemented. Declare all capitalist parties illegal, seizing their assets. Then move on to the plan:
If we manage to push through all these changes, I wouldn’t want to be reelected for any amount of terms.
Oh, yeah, that makes much more sense actually. Now I kinda want that setup, but I bet it’s expensive.