Blog TODO#

  • OOP polymorphism post
    • Post to this-week-in-Rust
  • emplace isn’t as powerful as you think
  • Things they didn’t teach me at university
    • Different states of code
      • Is it code complete?
      • Is it merged?
      • Is it released?
      • Is it tested? What tests?
      • What versions is the feature in?
    • What is a breaking change?
    • How to git?
      • Why do you merge like that?
        • There’s two merges
          • trunk into feature branch
          • feature branch into trunk
        • Why?
          • Merge conflicts should be resolved in feature branch
          • Merged version should be tested
      • Git is super complicated
        • XKCD link
  • Book of C++ vs Rust
  • Blog post about Rust in the Linux kernel
  • Write simple simple Reflex example
    • First two of the 7 GUIs
    • Or use simple one from reflex-examples
  • Follow up reflex-examples repo
  • “Words committed” per month tool
  • Rotate through categories and books

Books TODO#

  • Finish C++ book
  • Just rotate between them and keep writing
    • Individual TODOs in individual repos
  • Find better names
  • Figure out pitch strategy
  • Include public books on website
    • Figure out how to add Google Analytics
    • Figure out licensing/contributions
    • Move “How to Run a Programming Shop” from secret into not-secret
    • Blog post announcing books
      • “Gardens and streams” outline
      • Link books page
        • With non-secret books only?
      • Also obvs link other garden-like stuff

Blog Outlines#

Rust#

  • Programming languages as fandoms
  • Rust vs Python experience
    • I don’t program in dynamically typed langauges very often
    • Rust makes you say a lot more things explicitly
      • Disadvantage: You have to understand all those things
      • But it helps you get them right
        • Including many things that are run-time errors in Python
      • Advantage: You can let the compiler do a lot of the work for you
        • Just change the part you want to change
        • And then let the compiler errors form a TODO list
        • Writing error-free code the first time is not a goal
          • If you make it a goal, it will be too tedious
      • New code versus maintaining code
        • Writing new code in Python is easier
        • Making changes is harder
          • You generally have to change code in a bunch of corresponding places
          • The Rust compiler will find them for you!
          • It’s OK to rely on this, that’s part of its job
          • Some extreme examples of type safety are to help programmers rely on this
            • e.g. bunch of newtypes for integers, this is why
            • Similar to keyword arguments
              • But checked ahead of time
  • Rust safety, again
    • Criticisms of Rust safety mechanism
    • Responds to a naive concept of what safety is
      • Actual safety is nuanced
      • Responds to an oversimplified concept of what a “safe” PL is
        • Not quite a straw man
        • Since Rust fans sometimes misunderstand in the same way
          • Or promote the oversimplification
        • Rust detractors maliciously promote it
          • And refuse to learn more, which would disillusion them about the goals
      • The straw man concept of a “safe” PL is incompatible with a systems PL
        • But just because Rust can’t achieve it, doesn’t mean Rust is useless
        • Because Rust gives you tools to manage potentially memory-corrupting features
          • Whereas C++ is just a dumpster fire
    • So what IS Rust’s deal with safety?
      • Compilers provide ways of proving things about your code
        • C++ does this too
        • Most properties are IF you don’t do X, THEN you will have this property Y
        • The IFs for C++ are ridiculous
        • The Rust ones are more contained
      • Rust concept of safety is list of properties it can prove
        • As long as you don’t use unsafe, OR
        • As long as you follow VERY strict rules with unsafe
        • Yes, the definition of “safe” is defined by the PL
          • It’s the list of things you can prove Rust won’t do!
          • It doesn’t correspond exactly with “not crashing”
          • It does correspond well with “no memory corruption”
          • It is a very useful set of guarantees
  • Async and threading explanation
    • Threading:
      • Multiple cooks
      • Implementation
        • Multiple per CPU
        • Single per CPU
      • Cook per task
      • Meeseeks
      • Thread pools
    • Async:
      • Single cook
      • Has to keep track of what they’re doing
        • Lots of post-its
  • Garden idea: Errors I hate
    • Presence or absence
    • Async recursive errors
    • No error for binding unit
    • Underexplained error
      • File not found
        • But why?
        • Which file?
          • OS errors often don’t include this
            • C/POSIX errors are single integer
        • What were we trying to do?
      • Mitigations
        • map_err
        • wrap_err
  • How serde works
    • Generic, monomorphized programming with the policy pattern
    • Case study: serde_json
  • serde dbus
    • A flaw in serde
    • zbus’s solution
  • Unwraped Extra: Unchecked Assertions for Performance
    • Benefits of undefined behavior from C++, if wanted
    • debug_unwrap could exist
    • Would potentially eliminate unconditional checks backwards
    • Found out someone wrote it:
      • unsafe_unwrap crate
  • New Series: Long-form explanation of how to implement a single function or class
    • https://docs.rs/tokio/latest/tokio/io/fn.split.html
    • std::function
      • Link previous post
      • Demonstrate IntFn implementation
      • Demonstrate IntFn implementation using hack
      • Look into how std::function is in fact implemented
        • hobby/llvm-project/libcxx
      • Try to retrofit hack
      • Compare actual performance
    • crossbeam write up
      • std::thread::spawn takes a ‘static closure
        • It has to!
        • Even though you might immediately call join
        • Because they’re separate calls with no connection
      • crossbeam connects them
        • And uses unsafe internally to do so!
  • The policy pattern
    • retry policy example
    • come up with a second example
      • maybe string formatting for streaming data
    • implementations:
      • booleans
        • bad
      • enums
      • OOP-style interface or inheritance-based polymorphism
      • FP-style: use functions
      • trait-based polymorphism
        • dyn, the Rust analogue of the OOP way
        • impl Trait, which compiles away
    • serde as a huge case study
  • GC’d Rust converges to Haskell
    • See: https://boats.gitlab.io/blog/post/notes-on-a-smaller-rust/
    • Memory as a resource is too low-level for most people
      • Long live GC!
    • Lifetimes is fundamentally tied up with call stacks
      • A low level concept
    • Mutation, and how Rust tracks it
      • Is similar to low level memory management mechanisms
        • We can mutate when we don’t have references to old version
        • Similarly, we can drop
    • Haskell has mutation all over the place
      • More literally (ST monad)
      • Less literally (Reflex’s Dynamic)

Haskell#

  • Why Reflex? Blog post
    • Write simple example set in Reflex
  • How Reflex? Blog post
    • Walk through setting up examples repo
  • Walk through a more complicated example
    • Chess
  • Why callbacks are bad
  • Reflex resources page
  • Haskell: Simpler typeclass than functor
    • Typeclasses series:
      • Type class 101
      • Monoid
      • Functor
      • Applicative
      • Monad
  • Implementing Wordle in Reflex

Other#

  • Internet corporatization
  • PL doesn’t matter, subject matter does
    • Thoughts
      • One-off scripts don’t require error handling
      • I didn’t know what data frames are
  • The ironic way that bugs work
    • The more bugs you fix, the more bugs you’re likely to have to fix
  • Why we leave code crappy?
    • A counterpoint to “if it ain’t broke, don’t fix it”
    • Sometimes, it’s too dangerous to fix
      • This means there’s insufficient tests
    • Sometimes, it’s too expensive to fix
      • People don’t factor in the technical debt often here
  • Hotspot mode-based connection
    • Last look vs not last look
  • Write garden/stream blog post
    • Facebook, Twitter… Wikipedia
      • Is Wikipedia a social network?
        • Kind of!
      • There’s several reasons Wikipedia is less trashy
        • Non-profit
          • Only goes so far
        • Focussed on topics
          • Not individuals
          • Shares with Reddit
        • Posts live forever
          • And improve with time!
    • Garden vs stream
      • Basic concept
      • Cite sources
      • Give examples
      • Benefits
        • Encourages revision
        • Allows bigger things to be built
        • Allows organization
  • Row vs column oriented (enums and Dynamics)
    • Basic concept
    • Smalltalk code browser
      • Supported typical “all methods in a class”
      • But also “all receivers of this message”
      • Neither felt like the “real” way to organize
        • Because the code wasn’t in files
      • Very easy to add new methods to existing classes
        • If we had a new class-based decision to make
    • Example inheritance hierarchy
      • A bytecode-esque representation for a simple DSL
      • List of things to do, can take various shapes
      • Runtime heterogeneous list, seems perfect for polymorphism
    • Enums/switch vs inheritance
      • Silly small inheritance hierarchies
        • And adding dozens of little methods
        • Disrupt the flow of where the program is going
        • Java instanceof
      • Rust enums
    • Reflex Dynamics/foldDyn
      • FRP blog post on Reflex
        • Compare to callbacks
        • How the code is organized:
          • “These are the things that happen when you click this button”
          • “These are the things that are allowed to change this value”
          • Sample program that has buttons that do something to some numbers
          • vs callbacks that update shared state directly
          • when event X happens, Y value is updated
            • sort by events or updated values?
  • Binary has no intrinsic meaning
    • In elementary school, people asked if I could “read binary”
      • Pop culture messages in binary
      • Usually encoded as ASCII
        • “Science, bitches”
      • But of course, ASCII text is not the only encoding
    • Comparison
      • Asking if you can read binary is like asking if you can read “Roman letters”
        • But those can be used for German instead
        • The more relevant question is, can you read English?
        • Roman letters is analogous to binary
          • But language is analogous to “encoding”
    • Example
      • Do out “Hi!” as string (including terminating null)
        • Write out in endian-neutral fashion, one line per byte
      • List out interpretations rapid-fire
        • Interpreted as u32
        • Interpreted as i32
        • Interpreted as C string
        • Interpreted as f32
        • Other interpretations, in context?
      • How do we assign what binary gets what meaning?
        • What operations are run on it.
        • PL’s responsibility to run right ones
          • Different PLs use different book-keeping
          • Rust and C++ do their book-keeping at compile time
      • Demonstrate with Rust example code
        • unsafe means “allow you to override book-keeping”
      • Demonstrate with C++ example code
        • reinterpret_cast means “book-keeping: new interpretation”
      • These book-keeping systems are called “type systems”
  • The history of flow control
    • Batch jobs vs interactive CLI vs event-based programming
      • vs Reflex!
  • What’s slow and what’s fast
    • Other Tower-book based blog posts
  • Fail fast, fail often
    • Why error messages should still signal even if the compiler “knows what you mean”
  • The Specialness of the Number Zero
    • Zero is unnatural for humans
      • Pick up all the cards on the table
        • Human: “There are none.”
        • Computer: “It is done.”
      • All immortal humans have three eyes.
        • Is this true? False? Not even true or false?
        • Mathematician: True!
    • Math
      • No elements in sums
        • n * 0 = 0
      • Products
        • n ** 0 = 1
    • Programming equivalent
      • foldl
      • sum, product
      • foldl1
      • Outside of math:
        • Need an identity
        • AND –> true
        • OR –> false
    • Regular expressions
      • | does OR
      • But… "" matches everything, not nothing
  • Code is not a matter of personal taste
    • Convention is actually a good thing
      • Be conventional when you can
  • Alternatives to traditional call stacks
    • Stacks are an assumption of C/C++
      • Often glossed over
      • Supported directly in hardware (Intel)
      • And ABIs (which assume C)
    • Investigate C++ co-routines
    • Cite “state machines” section in Hubris and Humility post:
    • Credit John Ericson
    • C is not “portable assembly”
      • Normal assembly allows you to control the stack
      • Operating system implementation of stacks
      • Processor implementation of stacks
    • Sometimes, stacks don’t work right
      • Upward/downward funarg
        • Smalltalk
        • GC’d linked list
          • With invalidated “return” pointers
      • Co-routines
      • Async
  • HTML4 vs HTML5 spec
    • HTML5 spec had a much broader scope
      • Included parsing
      • Included complete parsing, including how to fail
      • This was a source of incompatibilities in practice
    • Why was this important?
      • Authors were unwilling to migrate to XHTML
        • Especially with XML mime types
      • HTML4 could have mandated complete failure for malformed HTML
        • This would have maybe worked, maybe not
        • Reigning in the Internet wild west would have been difficult
        • There was already lots of precedent for ignoring the spec
    • This was a codification of HTML as a practice
      • And a standard for implementations to deal with it
      • Included quirks mode!
    • Relevance
      • What does this mean?
      • What does this mean for Rust?
    • Formal specs often exist in an alternate universe
      • Influenced by mathematics
      • Prioritizes:
        • Rigor
          • It’s either valid or invalid
          • This is more commonly a spectrum
            • Link previous related essay
        • Conceptual clarity
          • There is one right way to do each thing
      • These things are good things overall
        • Appreciate that Rust enforces safety
      • But a bad match for the web
        • Which had already developed a wild west culture

TODO in order:

  • Binary has no intrinsic meaning
  • Begin Reflex tutorial
  • Fix reflex-examples CI
  • C++ Post
    • Pro-RAII
    • Pro-template metaprogramming
  • Finish Wordle
    • Add to reflex-examples
  • Add unit tests to chess app
  • Garden related idea:
    • RFCs/Rust proposals I’m a fan of
    • Errors I hate
    • Opinions I have
  • Script to publish posts
    • Two repos, one public one private
    • Script verifies we’re on master or main branch
    • Script verifies we’re pushed up to date on private repo
    • Script refuses to do a force-push of public repo
      • User must manually resolve
    • Make sure stale files are not left in place
      • Use renames?
  • Try to fix error from Reflex error post:
  • Reflex frontend “book”
  • serde_dbus/zbus post
  • Unwrap post
  • Rows vs. columns
  • Why dyn is the way it is post (short)
  • Choose a section and write it from book
    • Not exactly, make it feel more like a blog post
    • Java-style getters and setters are dumb?
    • serde discussion
      • with serde_dbus
  • Pitch books
    • Write pitch for “Beyond OOP”
    • Write pitch for “Organization of Memory”

Other:

  • ADHD-friendlier git
    • What was this??
  • Write up of this feature: https://rust-lang.github.io/rfcs/3058-try-trait-v2.html
  • Write about optimizaion
    • What’s slow and what’s fast
    • Configure time vs run time, what’s in a tight loop
  • Why C++ std::unique_ptr and Rust’s Box
    • Why is unique_ptr or Box used instead of by-value?
      • Benefits of indirection besides aliasing
        • Variable size
          • Inheritance in C++
            • Pointer can point to different parts of same object
          • !Sized in Rust
            • Including dyn, Rust’s inheritance analogue
            • Pointer can be fat
        • Copies (or even just moves) can be expensive
          • Large type
          • Manages large type
        • Passing up the call stack
      • Downsides of indirection
        • Slower
          • More operations
            • Both dereferences and alloc/free
          • Cache incoherency
          • Memory fragmentation
    • Why is unique_ptr nullable?
      • Let’s try to write a non-nullable moveable pointer
  • C++ Indirection: Use Raw Pointers Rarely
    • See: https://www.reddit.com/r/cpp/comments/uwrpb1/class_construct_arg_lifetimeownership_assumptions/
    • Raw pointers are the most primitive expression of indirection in C++
      • Direct representation of a processor-level concept
      • No additional information on top of that
        • Too many possibilities, is confusing
      • Let’s talk about all the use cases for them
        • And alternatives
    • As non-owning aliases
      • Use references
        • References can only do this
        • Makes ownership semantics clearer
      • What about optional references?
        • Pointers are nullable
        • I basically used to use pointers for this
        • But you can use std::optional<T&>
    • As owning handles
      • Use std::unique_ptr
    • As handles for multiple T
      • new[]/delete[]
      • Any reason not to use std::vector instead
        • Um, OK, use std::unique_ptr<T[]>
    • As iterators into some array
      • If you use std::array or std::vector, you can use real iterators
    • As C API compatibility
      • This kind of needs to be raw pointers
      • Interfaces with C only
    • As implementation detail of std type
      • std::unique_ptr at the least needs pointers internally
      • std::shared_ptr, std::vector, etc easier to write with pointers
  • C++ vs Rust pointer comparison
    • Properties of a pointer
      • Nullability
      • Ownership (lots of options here)
    • Rust pointers
    • C++ pointers
  • Async errors post
    • Intro
      • Async is great
      • Polish
    • Errors
      • e.g. Blocking function example
        • Function colors are great
          • No errors for calling blocking function is bad
          • Even FasterThanLime gets tripped up
      • Recursive example
        • Recursive functions are impossible in async
          • Why? Stackless
        • But these errors are ridiculous
          • Reduced example of watchman at 8515c475c
    • Sample program (TheCodedMessage/static/async-example)
      • nc based command processor
      • two commands: echo, and uppercase
      • add new command, listen, which adds another listening port
        • implement naively and recursively
        • how to fix?
  • Async problems in Rust
  • Write about this:
  • C++ vs Rust: Signed and unsigned arithmetic
  • Nullability is actually bad
  • Musing on Results/enums
    • Problem statement (mostly done)
    • Techniques to handle it:
      • Special error codes (C)
        • Numbers/values that just won’t come up
          • ssize_t and -1
        • Taking advantage of nullability
          • Can interact poorly with other exceptional conditions
          • Error vs “not found”
          • Objective-C implicit nil bubbling
        • Out-of-band mechanisms to indicate what error
          • errno
        • Case-by-case
          • Requires lots of reading docs
      • Returning multiple values
        • C/C++ out parameters
          • Return value is success/failure
            • So if statement can wrap around function call!
              • Because we want to branch on it
            • Also, so erroring can short-circuit inside implementation
          • Out parameter is desired information
        • Can just forget to check
        • Go (_, err) tuples
          • Basically equivalent
      • Exceptions
        • Checked exceptions
          • Java
          • C++ attempt
        • Unchecked exceptions
        • Really hard to code around
          • Entire books on C++ exception-safety
        • Perform really poorly
        • Doesn’t handle “unexceptional” cases
          • Poor performance for them
          • Like finishing a loop
          • Or “didn’t find the thing”
        • In any case, banned in many C++ platforms
        • Closer to Rust panic than Rust Result
          • … which brings us to …
      • Algebraic Data Types
        • Haskell
        • Rust
        • Handles other situations
          • “Not found”
          • enums also handle queries
            • Where often we want to do something, depending
          • Iterator/loops
            • “Unexceptional exception” for loop end
            • Similar to return enum
            • Discuss type-state based iterator
              • slight side topic
              • maybe a separate blog post
              • next consumes
              • gives you either a new iterator and a value
              • or nothing – you’re done!
                • Propagation operator
                • #[must_use]
                  • Almost never treated as a value
                    • Except to propagate upward
                  • Ignoring it is almost certainly a bug
                  • The match (or ?) and the return type
                    • … seem intertwined
      • Continuation passing
        • NodeJS
        • Lisp
        • Equivalence of returning an enum
          • With having different return continuations
        • Compiler representation
        • Theoretical ABI
          • Credit MenuetOS
          • Credit John Ericson
          • What ABI does Rust, in fact, use?
  • Subroutine history
    • And abstraction generally
    • Do something with that draft
  • Knight Capital disaster
  • What if BeOS were open source?
    • https://www.howtogeek.com/696193/what-was-beos-and-why-did-people-love-it/
    • What is BeOS?
      • BeOS in programmer culture
      • Never used it myself
        • Cost money, was a teen
          • (Do some research into timelines)
        • Read and treasured the BeOS Bible
    • Almost became macOS
      • But NeXTStep stepped in instead
      • Common fantasy among Be fans
    • Palm bought Be
      • But what if they’d open sourced it?
      • Haiku is struggling
        • Lost the technical edge with the gargantuan task of re-impl
      • There could be a viable OS desktop operating system
      • A true workstation Unix
        • Linux on the desktop is a shit show
          • Linux is a great server operating system!
          • Linux desktop users
            • Out of touch
            • Trying to get the kernel to prioritize the desktop
              • They don’t want to
        • macOS has corporate issues
    • Copyright policy
      • Source code should have to be registered
      • If you’re not using it commercially, you should have to OS it
      • It should automatically be open sourced on a tight time-scale
  • serde_dbus
  • Function overloading is bad, actually
  • The big kernel refactor:
  • Stacks as PL abstraction
    • Investigate C++ co-routines
    • Cite “state machines” section in Hubris and Humility post:
    • Credit John Ericson
    • C is not “portable assembly”
      • Normal assembly allows you to control the stack
      • Operating system implementation of stacks
      • Processor implementation of stacks
    • Discuss Smalltalk linked list of activation records
    • Discuss async
  • GC’d Rust converges to Haskell
    • See: https://boats.gitlab.io/blog/post/notes-on-a-smaller-rust/
    • Memory as a resource is too low-level for most people
      • Long live GC!
    • Lifetimes is fundamentally tied up with call stacks
      • A low level concept
    • Mutation, and how Rust tracks it
      • Is similar to low level memory management mechanisms
        • We can mutate when we don’t have references to old version
        • Similarly, we can drop
    • Haskell has mutation all over the place
      • More literally (ST monad)
      • Less literally (Reflex’s Dynamic)
  • serde (research project)
    • Generic, monomorphized programming with the policy pattern
    • Case study: serde_json
  • History of user interfaces and how that interacts with programming
  • Fail fast, fail often
    • Why error messages should still signal even if the compiler “knows what you mean”
  • Scour Tower textbook for blog posts

Tech reading/research: