HNHacker News
TopNewBestAskShowJobs

nsm

1,435 karma · joined August 3, 2009

I work at Skydio. Opinions here are my own.

Website: https://nikhilism.com

submissionscomments
nsm··on I still like Sublime Text
IDEs can have just as powerful keyboard shortcuts. IdeaVIM within Jetbrains is probably the most feature complete vim emulation?

What sets IDEs apart from trying to convert an editor to an IDE with a bunch of plugins is:

- somebody somewhere is hopefully sitting down with a cohesive vision of tying these tools together, instead of an assemblage of plugins each with their own visions. I would very much prefer to use their vision (a la macos/windows/Ubuntu) vs trying to configure each plugin to my own (arch/Gentoo). It could be an age thing, but at this point I really don't have the enthusiasm to become an expert at 12 different config file syntaxes and read the docs for all the options for each plugin i would need to tweak.

- an IDE is all encompassing in certain ways that is amazing. For example, Jetbrains is not only a fantastic code editor/refactoring swiss knife, it also has excellent git integration, and can leverage the same code navigation capabilities within diffs and PRs. It will autostash in branch specific stashes, and I can visually browse and diff these. I can attach to databases and get full SQL query and view capabilities, so it isn't just about general purpose programming languages.

- it can be hard to explain to people who haven't used a language specific IDE, how much further along its refactoring capabilities are compared to any LSP. Note that this applies much more to Java/C# than to something like python, both because of static typing and decades of investment.

- as an example of integration, say you add a new function in a file. Not only does Jetbrains highlight the modified file in the Git commit panel, but the structure panel will actually color that function differently and so on.

- due to widespread use of Jetbrains in certain communities, people will build valuable plugins to relatively niche things. So Jetbrains has excellent CMake support and decent Bazel support.

- I like the keyboard, but I also like and acknowledge that the mouse is much better at certain things. For interactive reading, I like I can right click on a commit and say "rebase from here" instead of looking up, copying and posting the red into my git rebase -i command. Conflict resolution, line by line inclusion etc. is also easier with a mouse.

I am very competent at the command line, but beyond a certain project size, IDEs just make sense to me.

nsm··on The past, present, and future of UI at GitHub
I am curious to understand what bearing "lots and lots of regular people solely use their cellphone to conduct consumer transactions" has on GitHub, whose audience is significantly different than median and cannot otherwise function without a laptop/desktop.
nsm··on Why I Chose Common Lisp
Racket's Chez Scheme backend, which is the default for several years is faster than python and ruby, and raco distribute gets you a smallish package with just your program, portable to the major OSes. Smallish = 40mb, which is probably comparable to other dynamic lands that don't come preinstalled.

I find the "I tried it years ago and it wasn't as nice then, so I'm not gonna look at it again" attitude quote off-putting. It's the same reason Java still gets so much hate after over a decade since Java 8.

I agree that CL and Closure probably has more real world shipped products. However, if you are considering a newer and smaller ecosystem like Janet... you owe it to yourself to look at Racket with fresh eyes.

nsm··on CockroachDB license change
Yep! I actually far prefer closed source software, made by non-VC funded companies, where there business is to create good software that actually adds value for the license I'm paying for. Something like Sublime Text or JetBrains.

Sure <VC funded editor company> can have people spend years of their life working on something, but release it as open source because VCs are paying for it, and that leads to more mindshare, but it leaves a bad taste in my mouth. Similar reasons to not use VSCode (commoditizing the complement by using billions of dollars from other products).

The "must be open source (I think they actually mean free as in $$) at all costs" crowd baffles me because the money to support the humans creating the software in the real world doesn't just magically appear.

nsm··on Defense of Lisp macros: The automotive field as a case in point
I agree with your comment for the most part (particularly the IDE situation)

I do want to callout that while Racket started off from Scheme (and still maintains compatibility with a bunch of it), it should be considered a different platform at this point and solves a bunch of the problems you called out with Scheme - macros are apparently much better, continuations are usually delimited, has user-mode threads and generators, so you very rarely need to reach for raw continuations, a very nice concurrency system, large stdlib, and Typed Racket also adds static typing.

The DrRacket/SLIME experience is great for smaller projects. I do agree that the language server needs more love. However I still think it gets a lot of stuff right, and is much faster than Python/Ruby due to being powered by Chez Scheme.

nsm··on Ontario Science Centre to close immediately due to risk of roof collapse
I know nothing about architecture/construction, but how much of these timelines and costs are due to the massively inefficient construction costs in Anglophone countries? Like, does it really take double digit millions and >2 years to fix some roof panels, when we can repair bridges in a fraction of that time? How much of this is going to be permitting, excess proceduralism and "environmental assessment" crap and how much of it is our current technological limitations?
nsm··on Pharo 12
I think Pharo would benefit a lot from having lots and lots of screen casts, since so much stuff is visual. I don't think something like ESUG is a sustainable way to spread techniques. A lot of stuff that is well documented in the Pharo ecosystem is old. A lot of the new stuff doesn't have great docs. Just reference docs and code is not enough. There has to be a coherent narrative around an API to put it together.

Also, I'm all onboard having a UI environment for programming, but it needs to have great keybindings that follow platform HIGs, and at least my Pharo 10 experience of the window management was really bad.

I wrote about this some https://nikhilism.com/post/2021/experiencing-smalltalk/

nsm··on Coroutines and effects
I am not an expert on this either, although very interested. Note that delimited continuations, which are a superset of coroutines are identical to effects in the sense of yielding control to the handler, not the caller. In languages like Racket/Scheme which allows associating tags with handlers, you can also model the same function having multiple effects.

In general, coroutines seem vastly easier to understand/type compared to effects unless your language can do a lot of effect inference.

nsm··on We Need to Talk About the State of Calendar Software on Desktop
This post started of really well and then fell pray to classic "developer mindset" of picking a technology to build on before even coming up product requirements.

After identifying that people are willing to pay money for good software on Mac, finding a funding model that leads to sustainable software seems a more important goal than whether it is open source. I bet that 90% of the reason web based calendar software is miles better than desktop is because it is locked away behind a sustainable stream of funding.

This "everything should be open source" thing is starting to trump building useful software that is created by good designers, that you know, want to be paid. To the point where people are willing to take VC funding with vague business plans (Astral, Zed) instead of, I don't know, making people pay for the fucking product they are getting.

nsm··on [dead]
Every generation brings us closer to a day where we can actually eliminate suffering?
nsm··on Proteins let cells remember how well their last division went
This is a fantastic lay person explanation of how it works. https://jsomers.net/e-coli-chemotaxis/
nsm··on Recording and visualising the 20k system calls it takes to "import seaborn"
Related to this, if you set the env var `PYTHONPROFILEIMPORTTIME=1` or run python with `-X importtime`, it will print out the cumulative and self times to import various modules.

There is then this neat tool to visualize the data. https://kmichel.github.io/python-importtime-graph/

Highly recommend to find the worst imports affecting your program startup time.

In general, the python community values tend towards functionality over performance. For example, large modules (looking at networkx here) will often import a bunch of there submodules in their __init__.py, which means all modules now end up loaded even if you didn't need them.

I've never tried https://pyoxidizer.readthedocs.io/en/stable/oxidized_importe..., but it compiles all the imports into one, memory mapped file, that _may_ speed up the importing.

Having everything compiled to bytecode also helps a bunch.

nsm··on Let futures be futures
I meant Andy Wingo, damn autocorrect!
nsm··on Let futures be futures
Your point is entirely valid. I had not thought of it. Makes sense for resource consumption.

I think selection is about what is visible to your program. I.e. that even if that packet arrives, if you choose another path in the select, then the recv() is guaranteed not to happen. You are right that a program doing this has to handle this case correctly, which I think is what the whole Rust future cancellation conversation is about.

nsm··on Let futures be futures
> this of course does not prevent the other promises from getting resolved, because that would happen in some other piece of code, perhaps in response to a network i/o event or a filesystem i/o event; knowing whether a particular turing-complete event handler is going to resolve a particular promise (so you could avoid running it) would require solving the halting problem

It does not if you control the implementation of the language primitives ;) I’m not smart enough to answer exactly how, but Andy Winford explains how CML does it using the notion of optimistic and pessimistic stages. https://wingolog.org/archives/2017/06/29/a-new-concurrent-ml

nsm··on Let futures be futures
I’m not familiar with E’s promises, but as far as I know, JavaScript promises have no equivalent of heterogeneous selects (select in Go, select! in Tokio, sync in ConcurrentML) that guarantee that when one channel/future/event is chosen, the others definitely do not make progress (I.e. a select on a read and a write means only one of them happens on each turn). That seems important.

Promises don’t prevent data races. They only don’t exist in JavaScript because the runtime is implicitly single threaded.

nsm··on Let futures be futures
Take a look at ConcurrentML and its implementations in Racket and Guile. Schemes have stackful coroutines (as a side effect of supporting delimited continuations), and CML builds green thread like semantics on top of that with a small set of elegant primitives, including cancellation.

As an aside, when folks mention algebraic effects in statically typed languages, delimited continuations and effects are equally powerful (possibly identical?). IMO effects seem to be about type safety and static typing, which does allow some neat optimizations.

nsm··on Compiling Pattern Matching
I'm not sure how efficiently it compiles, but Racket's match form is implemented using macros and is stunningly powerful!

https://docs.racket-lang.org/reference/match.html

nsm··on Neovide – A simple, no-nonsense, cross-platform GUI for Neovim
If you are happy and productive with your current editor(s), no, you don’t need to spend valuable time picking up and configuring another one. Save the effort for when you actually need it.

Despite what others may say to convince you otherwise, this is the only correct answer ;)

nsm··on A Tour of the Lisps
I would like to disagree with this view of Racket.

I'm a fairly experienced professional programmer with a lot of systems experience, and I find Racket an extremely well thought out, competently implemented and high performance (particularly with the switch to Chez Scheme) language.

I wrote a bit about it at https://nikhilism.com/post/2023/racket-beyond-languages/ and Bogdan Popa and Alex Hirsanyi have done amazing stuff with the language https://defn.io/ https://alex-hhh.github.io/index.html including a sophisticated web framework, a Kafka GUI client and so on.

I think the only deficiency for a "pragmatic for a seasoned programmer" (beyond the standard "no FAANG is sponsoring it" related lack of resources and presence in popular discussion) is the lack of good editor integration beyond emacs. That said, I've found DrRacket perfectly reasonable for my uses, although clunky. I'm not saying it can replace something like Python, but that is more because of the smaller ecosystem and contributor base than anything wrong with the language itself.

nsm··on Embracing Common Lisp in the modern world
(I only read the pdf outline)

As someone who is neither a Common Lisp nor a JVM programmer, I’m genuinely curious to hear from experts whether the old trope of “JVM is slow and bloated” is even remotely true any more. Based on hearsay, the JVM often competes in language performance closer to C++, and has probably the best garbage collectors in the world as well as the best developer and operational tooling. How much do other platform developers leave on the table by ignoring the JVM these days?

As an aside, even the trope about us running out of energy, or energy usage directly corresponding to planetary destruction is becoming less and less true. With solar PVs and the sun, we truly do have a shot at a future with limitless energy and resources.

nsm··on The bane of my existence: Supporting both async and sync code in Rust
Async/await is a _concurrency_ mechanism, and concurrency is certainly naturally useful. However async/await is certainly not the best implementation of concurrency, except in the narrow design space Rust has chosen. If you have a language with a runtime, green threads/fibers/coroutines, along with a choice mechanism is really the way to go. It trades off some performance for much better ergonomics. Go, Java, Racket all use this. It is unfortunate that Python picked async/await.
nsm··on Why the Culture Wins: An Appreciation of Iain M. Banks (2017)
There is also “the culture series of Iain M. Banks” by Simone Caroti that I highly recommend.
nsm··on Implementing Interactive Languages
One option is to write your language as a transpile to Racket and then leverage the existing ChezScheme implementation for performance. Racket is usually faster than Python although initial process startup is slightly slower than CPython.
nsm··on Asyncio, twisted, tornado, gevent walk into a bar
Great summary.

This paper from one of the Lua creators digs into this in the paper Revisiting Coroutines. It is a very readable paper. https://www.inf.puc-rio.br/~roberto/docs/MCC15-04.pdf

nsm··on Ask HN: Any interesting books you have read lately?
Recoding America by Jennifer Pahlka. A technologist who helped the US federal government for several years looks backs and describes all the problems with government adopting digital interfaces in a way that actually helps users. Also a commentary on how the waterfall model of governance, where grandiose legislation is passed, without taking feedback from those implementing it, leads to accretion of convoluted regulations and horrible user experiences for the most disadvantaged of us.
nsm··on Most in U.S. (57%) prefer big houses, even if amenities farther away
One of the problems with mainly anglophone countries is that they have made other kinds of housing so difficult or even illegal to build in large swathes of major cities that single family homes - big, with everything far apart, is the only reality. No one is saying everyone has to live in apartments. But people who want to live in apartments should be able to where there is demand. Nearly all new apartment stock in, say SF, is "luxury" instead of just being straightforward apartments or multi family dwellings.
nsm··on Predictive Debugging: A Game-Changing Look into the Future
I don't know if the sort of deep refactoring and other integrations they offer in their IDEs would be possible in the LSP protocol as it exists today. I believe debuggers for vscode have a similar DAP protocol. Any way, my point is, they have something great that works well for their users, so it doesn't seem like a very large market to make a less powerful version for a small set of new users. I also suspect that the sort of developers who don't use their IDEs but instead use an LSP based editor that is free/open-source would be unlikely to _pay_ for Jetbrains LSP based offering, however high quality/unique it might be.
nsm··on Researchers find evidence of a 2000 year old curry, oldest ever found in SE Asia
This is so funny to read and really reflects how availability of ingredients and tacit knowledge really changes perception. Plus having a pressure cooker.

Western interpretations of curry are always elaborate affairs.

There are many varieties of extremely simple curries on the subcontinent. For example, the Maharashtrian amti. My mom or grand moms can make amti in less than 30 minutes and most of that time is waiting for things to cook and not active participation .

nsm··on Threads and Goroutines
I am aware of epoll_wait and friends (select/poll) accepting timeouts, and how that plugs into a general event loop like in libuv.

However if memory serves, these calls are reasonably expensive (on the order of microseconds, and _worse_ if readiness requires putting the current thread to sleep and then waking it up again). However https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part... says goroutines are closer to 200ns.

However the same source above does a decent job of explaining how epoll is being called "out of band". I am guessing when they talk about context switching costs, they are doing some sort of amortization of these system call costs. Since the actual OS threads try to remain CPU-affine (thread-per-core, LMAX disruptor etc. etc.), a lot of the OS scheduling costs can be skipped.

Thank you for the pointer to the source code. It gives me a starting point.

← PreviousPage 2 of 10Next →