617 karma · joined January 4, 2011
At the time there were two widely used software packages for phylogenetic inference, PAUP* [2] and MrBayes [3]. The source code for MrBayes was available, and although at the time I had some pretty strong criticisms of the code structure, it was immensely valuable to my research, and I remain very grateful to its author for sharing the code. In contrast the PAUP* source was not available, and I struggled immensely to replicate some of its algorithms. As a case in point, I needed to compute the natural log of the gamma function with similar precision, but there was no documentation for how PAUP* did this. I eventually discovered that the PAUP* author had shared some of the low-level code with another project. Based on comments in that code I pulled the original references from the 60s literature and solved these problems that had plagued me for months in a matter of days. Now, from what I could see in that shared PAUP* code, I suspect that the PAUP* code is of very high quality. But the author significantly reduced his scientific impact by keeping the source to himself.
[1]: https://github.com/canonware/crux
Here's a poignant anecdote. At one point while working on HHVM at Facebook I finally snapped, spent 2-3 days doing nothing but optimizing the build system to speed up trivial incremental compilation (e.g. a whitespace change). My efforts resulted in... 24 seconds best case. I spent years on that project pipelining my coding, that is, making a small change, asynchronously launching a build, fixing issues from the previous build attempt, ad nauseam, and the pipelining was oftentimes 3+ deep due to latency. That cognitive load severely impacted productivity.
That said, I agree that C++ has a lot of other terrible problems too!
[1] https://www.adventurecycling.org/routes-and-maps/adventure-c...
- An awful lot of the problems have to do with ownership semantics. If ranges are immutable, referentially transparent, those problems go away.
- The author suggests (in the "Where to from here" section) that ranges should be convertable to iterators, rather than inherently iterators themselves. In my experience this works very well. Ranges can always be integer-based, and, as long as the collection can efficiently be mapped onto integers, conversion to/from iterators is trivial.
- The notion of "directional" ranges seems ill-posed. As described, such a range would actually be more like a vector. Also, in a language which uses wrap-around integer types (modular arithmetic semantics), a "backwards" range is still well-defined and finite. For example, an 8-bit 6..3 range is 6..=255 + 0..3 (the complement of 3..6).
The caveat to my perspective is that I don't care where hotkeys are. I minimize mouse use, and with both hands on the keyboard it just doesn't matter very much. I've used emacs and vim with both layouts. My faded recollection with respect to emacs is that it was equivocal, and Dvorak is actually a bit better for vim.
I put over 7,000 miles on a Surly Big Dummy, much of it hauling my son from age <1 to 7. It was far safer and more comfortable for him than a trailer would have been. I've also ridden thousands of miles with a B.O.B. cargo trailer and a Tout Terrain trailer, and I would always choose the cargo bike if at all suitable to the conditions. The only thing I prefer the trailer for is hauling gear for trail maintenance.
Regarding the worry of visual distraction of selections slowing down editing, I found the opposite to be the case as I became more fluent with Kakoune. Motions modify the selection, and it is quite common for the selection to serendipitously contain what I want to modify. Constantly visible selection(s) lead me to implicitly take advantage of motion and use fewer keystrokes.
Regarding multiple selections outside the visible window, you are right that there's no visual feedback for those selections, which is a degraded experience compared to when all selections are visible. But that's no worse than the experience of a global search/replace in vim. You are arguing that in an edge case, Kakoune is no better than vim, which doesn't seem like a meaningful detraction.
As for batteries included, there are several options for foundational libraries; I found there to be too many choices rather than too few when I first started developing in OCaml.
Multiple selection has surprised me in its usefulness. It took a bit to get used to multi-step operations (select, then move/expand/match, then modify, etc.), but the beauty of this is that it's possible to incrementally undo these steps, unlike having to get the whole thing right in one go in vim. I find myself using regex captures in multiple selection -- another example of how I confidently use basic kakoune functionality where I used to rely on recorded macros in vim.
kakoune provides a limited orthogonal toolset that composes extremely well. After a week using kakoune I felt at least as confident with its command language as I did with vim's after years of use. Aside from a few vim plugins that were super helpful, I didn't miss anything after transitioning, except for the 'R' command (and to a lesser extent proper integration between the 'r' and '.' commands).
I worried that kakoune's multiple selection paradigm wouldn't scale well, that it wouldn't be routinely useful, etc. On the contrary, I use multiple selections heavily, often as a more ergonomic alternative to recorded macros, constantly for rectangle-based operations (whether multi-line editing, indenting, ASCII art creation, whatever).
Oh, for you tmux lovers out there, kakoune integrates amazingly well. All of its multi-window functionality directly uses tmux panes, with a server application (think emacs-server) tying everything together.
In terms of ecosystem, vim is much richer. But kakoune is a practical, beautifully designed tool.
First, my CS background. I started programming in 1991, and have used dozens of languages major and minor over that time. At one time or another, I developed especially deep knowledge of the following: C, Perl, PostScript, Python, C++, and PHP. Functional languages always hovered at the edge of my interest, but never seemed practical enough to apply to the sorts of systems programming I love.
In 2017 I decided to spend some time broadening my understanding of language concepts, and made a list of languages to learn more about: OCaml, Julia, Clojure, Scala, Scheme, Haskell, Rust, Erlang, Go, Swift, and Kotlin. Learning OCaml ended up being such a transformative experience that I use it almost exclusively now. As an aside, I must say that it wasn't easy; it took the better part of a year to acquire the knowledge and experience necessary to feel productive.
Why is OCaml (and presumably Haskell) so good? The resulting programs feel like beautiful self-consistent crystalline structures rather than balls of mud. Furthermore, the powerful type system allows refactoring from one crystalline structure to another such that inconsistent hybrid crystals rarely occur. This is a much different experience from reshaping a ball of mud. The routine elegance and safety of these program representations aid in discovering the essences of solutions, and I have written programs I never would have discovered in other languages.
Killer features: - The powerful type system clarifies design, aids refactoring. - The module system (in combination with generics) enables truly modular design. - Effectless computation (pure functions, immutable data) simplifies reasoning about state.
I have some complaints about OCaml (and every other language I know), but it stands out as by far the most fulfilling to use. Going forward I will prefer to spend my programming time using languages more like OCaml, Haskell, Rust, etc. than those I used for the first 25 years.