Beautiful. Simple, tight prose, telling a deeply moving story.
Can’t wait to read the next one.
Three things I learned about writing:
- What a society condemns is just as important to making it feel lived-in as what it praises.
- Characters don’t always have to be imposing their will on the world. They can show their inner character by the opportunities they take advantage of, as well.
- In a world of bad choices and flawed people, heroes can be cruel and cowardly, and villains can show mercy.
A strong collection of stories. Connolly moves from near-future sci-fi to alternate world fantasy to present-day witches, populating each story with strong, unique characters.
Will definitely be picking up her novel, Seriously Wicked, which takes place in the same world as one my favorite stories from this collection.
Three things it taught me about writing:
- The thinner the story, the shorter the work should be. Don’t make the reader wade through lots of background or context just to get to the heart of events.
- Writing in the present-day relieves you of a lot of world-building duties, lets you focus on creating great characters.
- Even stories told via journal entries (or texts, or emails) can have a proper buildup to a climax.
A cornucopia of female scientists and engineers that got left out of the history I learned in school.
It’s amazing how much these women accomplished considering how much was stacked against them. Time after time, in these biographies, I read how a brilliant scientist would be forced to work for free, because the university didn’t hire women. Often, they’d find employment in a German university, only to be kicked out once the Nazis took power and started firing Jewish scientists.
That kind of treatment would make me rebellious, want to stop my work completely and find something less important to do.
But these women persisted.
Three of the many things I learned:
- Grace Hopper was the first woman to graduate with a PhD in math from Yale. She invented the compiler, set the foundations for COBOL, and was considered so valuable to the Navy that she was called back from retirement to work another 19 years (!)
- When Einstein needed tutoring in the higher math he needed to pursue his theory of General Relativity, he turned to Emmy Noether, the inventor of abstract algebra. Through the course of teaching Einstein, she invented the equations needed to set General Relativity on a solid mathematical footing.
- Marie Tharp mapped 70% of the ocean floor, and discovered the Mid-Atlantic Ridge. She insisted that it was confirmation of continental drift for years (and was fired for it!) before theory became accepted.
Frustrating and disappointing. Adams’ writing is stuffed with metaphors, giving everything a dreamy quality that makes it hard to take anything seriously.
Didn’t help that I just came off reading Octavia Butler’s Earthseed books, which do a much better job of narrating a woman’s journey through a post-apocalyptic world.
Three things it taught me about writing:
- If readers already know the narrator survives a scene in a flashback, don’t try to wring tension out of their survival.
- Readers need to know not only what your characters are doing, but why, if they’re going to care.
- When writing a character from a different country, do several editing passes to be certain their dialog, analogies, and expressions all match where they’re supposed to be from.
My original plan for editing the first novel turned out to be…rather naive.
I thought it would be enough to fix the female protagonist’s plotline, then make a few description tweaks, and be done.
Instead, I’m looking at making a dozen or more editing passes over the novel, each one picking out a thing to fix and make consistent through the book.
I’ve had to change character appearances, character names, city names, backstory, world history…nearly every element needs to be tweaked one way or another to line up better with what I think the novel should be.
So I’m keeping a running list of things to fix as I go, jotting them down as I find them. That way I can focus on just one editing task at a time, getting one thing right all the way through the book before going back to the beginning and starting on the next fix.
My goal was to have these edits done by the end of the month (for a total of three months of editing), so I could spend the next three months editing my second novel. But we’re a third of the way through March, and, well…my list keeps growing.
Still, I’ll push on. I’m finding I still like this novel, still like the characters. I want to do them justice, give them the best book I can. So I’ll keep working through the list, till the list is done.
Prescient, gripping, and intimidatingly good. Definitely going to read more of Butler’s books.
I’m rather sad that she wasn’t able to complete a new Earthseed series, like she planned, before her death.
Three more things she taught me about writing:
- Perfectly acceptable to have the sequel start out as more “and then this happened”.
- First act turn is a great place to upend what the characters have built previously, have the outside world come in with the force of a storm.
- Editors and compilers of biographies can have agendas just like other characters, and become more interesting when they reveal them
So frustrating. I had high hopes going in that Elixir might be my next server-side language of choice. It’s built on the Erlang VM, after all, so concurrency should be a breeze. Ditto distributed applications and fault-tolerance. All supposedly wrapped in a more digestible syntax than Erlang provides.
Boy, was I misled.
The syntax seems to be heavily Ruby-influenced, in a bad way. There’s magic methods, black box behavior, and OOP-style features built in everywhere.
The examples in this chapter go deeply into this Ruby-flavored world, and skip entirely over what I thought were the benefits to the language. If Elixir makes writing concurrent, distributed applications easier, I have no idea, because this book doesn’t bother working examples that highlight it.
Instead, the impression I get is that this is a way to write Ruby in Erlang, an attempt to push OOP concepts into the functional programming world, resulting in a hideous language that I wouldn’t touch with a ten-foot-pole.
I miss Elm.
- biggest influences: lisp, erlang, ruby
- need to install erlang *and* elixir
- both available via brew
- syntax changing quickly, it’s a young language
- if do:
- IO.puts for println
- expressions in the repl always have a return value, even if it’s just :ok
- looks like it has symbols, too (but they’re called atoms)
- tuples: collections of fixed size
- can use pattern matching to destructure tuples via assignment operator
- doesn’t allow mutable state, but can look like it, because compiler will rename vars and shuffle things around for you if you assign something to price (say) multiple times
- weird: “pipes” |> for threading macros
- dots and parens only needed for anonymous functions (which can still be assigned to a variable)
- prints out a warning if you redefine a module, but lets you do it
- pattern matching for multiple functions definition in a single module (will run the version of the function that matches the inputs)
- can define one module’s functions in terms of another’s
- can use when conditions in function def as guards to regulate under what inputs the function will get run
- scripting via .exs files, can run with iex
- put_in returns an updated copy of the map, it doesn’t update the map in place
- elixir’s lists are linked lists, not arrays!
- char lists are not strings: dear god
- so: is_list “string” -> false, but is_list ‘string’ -> true (!)
- pipe to append to the head
- when destructuring a list, the number of items on each side have to match (unless you use the magic pipe)
- can use _ for matching arbitrary item
- Enum for processing lists (running arbitrary functions on them in different ways, like mapping and reducing, filtering, etc)
- for comprehensions: a lot like python’s list comprehensions; takes a generator (basically ways to pull values from a list), an optional filter (filter which values from the list get used), and a function to run on the pulled values
- elixir source is on github
- mix is built in to elixir, installing the language installs the build tool (nice)
- basic project template includes a gitignore, a readme, and test files
- source files go in lib, not src
- struct: map with fixed set of fields, that you can add behavior to via functions…sounds like an object to me
- iex -S mix to start iex with modules from your project
- will throw compiler errors for unknown keys, which is nice, i guess?
- since built on the erlang vm, but not erlang, we can use macros, which get expanded at compile time (presumably, to erlang code)
- should is…well…kind of a silly macro
- __using__ just to avoid a fully-qualified call seems…gross…and too implicit
- and we’ve got to define new macros to override compile-time behavior? i…i can’t watch
- module attributes -> compile-time variables -> object attributes by another name?
- use, __using__, @before_compile -> magic, magic everywhere, so gross
- state machine’s “beautiful syntax” seems more like obscure indirection to me
- can elixir make me hate macros?
- whole thing seems like…a bad example. as if the person writing it is trying to duplicate OOP-style inheritance inside a functional language.
- elixir-pipes example from the endnotes (github project) is much better at showing the motivation and usage of real macros
- creator’s main language was Ruby…and it shows
- spawn returns the process id of the underlying erlang process
- pattern matching applies to what to do with the messages a process receives via its inbox
- can write the code handling the inbox messages *after* the messages are sent (!)
- task -> like future in clojure, can send work off to be done in another process, then later wait for the return value
- use of Erlang’s OTP built into Elixir’s library
- construct the thing with start_link, but send it messages via GenServer…more indirection
- hmm…claims it’s a “fully distributed server”, but all i see are functions getting called that return values, no client-server relationship here?
- final example: cast works fine, but call is broken (says process not alive; same message regardless of what command sent in (:rent, :return, etc)
- oddly enough, it works *until* we make the changes to have the supervisor run everything for us behind the scenes (“like magic!”)
- endnotes say we learned about protocols, but they were mentioned only once, in day two, as something we should look up on our own
- would have been nicer to actually *use* the concurrency features of language, to, idk, maybe use all the cores on your laptop to run a map/reduce job?