<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>zero width jschear</title><description>Jonathan Schear&apos;s website.</description><link>https://www.jschear.dev/</link><item><title>AI Vibecheck, Q2 2025</title><link>https://www.jschear.dev/blog/2025-04-26-ai-vibecheck/</link><guid isPermaLink="true">https://www.jschear.dev/blog/2025-04-26-ai-vibecheck/</guid><description>I would like to keep my job please</description><pubDate>Sat, 26 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;We&apos;re solidly in the &lt;a href=&quot;https://maxread.substack.com/p/the-ai-backlash-backlash&quot;&gt;AI backlash backlash&lt;/a&gt;. Here are some thoughts about using large language model-based tooling (like &lt;a href=&quot;https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview&quot;&gt;Claude Code&lt;/a&gt;, &lt;a href=&quot;https://www.cursor.com/en&quot;&gt;Cursor&lt;/a&gt; and &lt;a href=&quot;https://github.com/block/goose&quot;&gt;Goose&lt;/a&gt;) for software development in 2025.&lt;/p&gt;
&lt;h3&gt;On determinism&lt;/h3&gt;
&lt;p&gt;One thing that drew me to computing in the first place was the sense that, however complex computers were, they were fundamentally understandable. &lt;a href=&quot;https://speakerdeck.com/bcantrill/things-i-learned-the-hard-way?slide=9&quot;&gt;Computers aren&apos;t magic&lt;/a&gt;. I always find it extremely empowering when I can figure out a tricky bug by peeling back a few layers of abstraction.&lt;/p&gt;
&lt;p&gt;LLMs are closer to magic. Unless I&apos;ve missed some new development in interpretability, you can&apos;t stare at the matrices powering them to figure out &lt;em&gt;why&lt;/em&gt; a model has given you a certain response. If you&apos;re having trouble with a tool, the solution is fuzzy: try a different model; try to stuff more relevant code in the context window; IDK, have you tried writing your prompt in all caps or asking more nicely? I would find it frustrating to be responsible for the quality of such a system. Maybe &lt;a href=&quot;https://www.distributional.com&quot;&gt;someone&lt;/a&gt; will figure out how to make useful assertions about the quality of their output.&lt;/p&gt;
&lt;p&gt;Nondeterminism isn&apos;t new: probabilistic data structures are useful, and everything these days is asynchronous and distributed and horrifyingly complex. But do we have to inject &lt;em&gt;more&lt;/em&gt; chaos into everything? I am heartened by newer tools that use LLMs to write a script or plan for invoking deterministic tools.&lt;/p&gt;
&lt;p&gt;Also, just an aesthetic objection: dealing with tools that are confidently and cheerily wrong is annoying! Have some shame!&lt;/p&gt;
&lt;h3&gt;AI as anti-expertise&lt;/h3&gt;
&lt;p&gt;LLM tools are great at creating greenfield, prototype apps. I support the democratization of software engineering: I&apos;m excited for more people to try building software, even if they vibe-code their way to victory.&lt;/p&gt;
&lt;p&gt;But some of the excitement around AI tools feels like it&apos;s trying to devalue software engineering broadly. If a CEO can clone a SaaS app in a few days, who needs those highly-paid engineers? Part of what I love about writing software is understanding a topic deeply and crafting something that will stand the test of time, and I think that will still require deep expertise.&lt;/p&gt;
&lt;p&gt;There&apos;s undoubtedly some &quot;kids these days&quot; energy here -- people have long made similar arguments whenever a new technology makes the practice of programming more approachable. &quot;&lt;em&gt;Real&lt;/em&gt; engineers write in assembly code.&quot; &quot;How can you call yourself a programmer if you&apos;ve never done manual memory management?&quot; &quot;These web developers are ruining the desktop with their Electron apps.&quot; I don&apos;t want to gatekeep software development.&lt;/p&gt;
&lt;p&gt;I just hope that the vibe-coders still have curiosity about the systems they&apos;re building on top of. In the near future, I see a lot of haphazardly built software, in desperate need of people to understand and maintain it. Maybe not all that different from today.&lt;/p&gt;
</content:encoded></item><item><title>First Steps with OCaml</title><link>https://www.jschear.dev/blog/2024-03-12-first-steps-with-ocaml/</link><guid isPermaLink="true">https://www.jschear.dev/blog/2024-03-12-first-steps-with-ocaml/</guid><description>First Steps with OCaml</description><pubDate>Tue, 12 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;These days, everyone is talking about ML. They mean &lt;a href=&quot;https://en.wikipedia.org/wiki/ML_(programming_language)&quot;&gt;Meta Language&lt;/a&gt;, right? (Let&apos;s pretend they do.)&lt;/p&gt;
&lt;p&gt;Last year I attended the &lt;a href=&quot;https://www.recurse.com/&quot;&gt;Recurse Center&lt;/a&gt;,[^1] a retreat for programmers, and one of my goals while at RC was to get more comfortable and productive writing in a functional programming language.&lt;/p&gt;
&lt;p&gt;I was first exposed to the functional paradigm in college, while taking a programming languages course. At that time, my experience and understanding of programming were entirely influenced by Java and Python, and my poor uninitiated brain practically melted the first time we transformed an imperative loop into a recursive function. I finished that course excited about functional programming, but also intimidated by the jargon that came along with it (and these curly fellas: λ).&lt;/p&gt;
&lt;p&gt;I&apos;ve spent the past few years writing &lt;a href=&quot;https://kotlinlang.org/&quot;&gt;Kotlin&lt;/a&gt; (often using &lt;a href=&quot;https://reactivex.io/&quot;&gt;RxJava&lt;/a&gt;) in the context of an Android application, and have been increasingly convinced that many of the priorities of typed functional programming (using algebraic data types to model your domain, immutable data structures -- or at least judicious use of mutable state) are well-suited for developing software that is both understandable and evolvable. Even in languages that don&apos;t particularly encourage a functional style, limiting the use of mutable state minimizes implicit dependencies between parts of a program, making it easier to understand those parts in isolation and compose them without fear. And the general concepts seem to keep popping up in other areas I&apos;m interested in, like &lt;a href=&quot;https://bazel.build/basics/artifact-based-builds#a_functional_perspective&quot;&gt;build systems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All that to say, I was eager to try out a more functional language. So why OCaml? Why not Haskell, Clojure, Scala, Elm, Scheme, Racket, Idris, Koka, Roc, Common Lisp?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OCaml has proven industry usage inside of Jane Street and Facebook. Regardless of whether you&apos;d want to work at one of these places, they definitely have a track record of writing software that accomplishes stuff in the real world. (Has side-effects?)&lt;/li&gt;
&lt;li&gt;OCaml has a pragmatic approach towards functional purity that I appreciate. You can reach for mutable state when you really need it, and evaluation is eager, so you don&apos;t have to learn a new evaluation strategy alongside a new language like you do with Haskell.&lt;/li&gt;
&lt;li&gt;I&apos;d been vaguely following along with &lt;a href=&quot;https://dl.acm.org/doi/10.1145/3408995&quot;&gt;the journey to add parallelism to OCaml&lt;/a&gt; after hearing about it on Jane Street&apos;s &lt;a href=&quot;https://signalsandthreads.com/&quot;&gt;Signals and Threads podcast&lt;/a&gt;, and wanted to better understand OCaml&apos;s runtime system.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a more complete discussion of &quot;Why OCaml&quot; and how it compares to other popular languages, I&apos;d recommend reading &lt;a href=&quot;https://queue.acm.org/detail.cfm?id=2038036&quot;&gt;this paper&lt;/a&gt; from Yaron Minsky of Jane Street (or watching &lt;a href=&quot;https://www.youtube.com/watch?v=v1CmGbOGb2I&quot;&gt;his similar talk&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Tooling&lt;/h2&gt;
&lt;p&gt;One of my first priorities when learning a new language is setting up a comfortable development environment. Maybe I&apos;m old fashioned -- I feel like the latest hotness is shoving all this stuff into a docker container or running it in the cloud somewhere -- but having a solid understanding of what tools are available, how they interact, and how to set them up on my machine is important to me.&lt;/p&gt;
&lt;h3&gt;Package management&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;opam&lt;/code&gt; is the OCaml package manager[^3]. &lt;code&gt;opam&lt;/code&gt; can manage multiple side-by-side installations of the OCaml compiler, in environments it calls &quot;switches&quot;. So there&apos;s no need for a separate tool to manage multiple compiler versions like &lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;&lt;code&gt;nvm&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://github.com/rbenv/rbenv&quot;&gt;&lt;code&gt;rbnenv&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://github.com/pyenv/pyenv&quot;&gt;&lt;code&gt;pyenv&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://asdf-vm.com/&quot;&gt;&lt;code&gt;asdf&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://cashapp.github.io/hermit/&quot;&gt;&lt;code&gt;hermit&lt;/code&gt;&lt;/a&gt; or (if you&apos;ve reached true enlightenment) &lt;a href=&quot;https://nixos.org/&quot;&gt;&lt;code&gt;nix&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My appreciation for the functional paradigm hasn&apos;t yet spread to my package management habits[^2], so on macOS I installed opam with &lt;code&gt;homebrew&lt;/code&gt;, and followed the instructions it spit out to modify my shell environment.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ brew install opam
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Building, creating a project&lt;/h3&gt;
&lt;p&gt;The most popular build system for OCaml is &lt;a href=&quot;https://dune.readthedocs.io/en/latest/quick-start.html&quot;&gt;dune&lt;/a&gt; (née &lt;code&gt;jbuilder&lt;/code&gt;) created by (you guessed it) Jane Street. Dune itself is distributed as an &lt;code&gt;opam&lt;/code&gt; package, so go ahead and install it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ opam install dune
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One thing dune provides is an &lt;code&gt;init&lt;/code&gt; command, which will create some reasonable project scaffolding:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ dune init proj project_name
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;~/ocaml/
$ tree project_name
project_name
├── _build                    // Build artifacts. You&apos;ll want to .gitignore this.
│   └── log
├── bin                       // Where code for your application&apos;s entry point will live.
│   ├── dune
│   └── main.ml
├── dune-project              // Project-level dune configuration.
├── lib                       // Where library code will live. Create an .ml file in here to define a new module.
│   └── dune
├── project_name.opam         // An opam configuration file, should you ever want to publish your project. This is generated from the dune config.
└── test                      // Where test code will live.
    ├── dune
    └── test_project_name.ml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Last but not least, let&apos;s create a new switch.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;opam switch create ./ 4.14.1 --deps-only
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates a &lt;a href=&quot;https://opam.ocaml.org/blog/opam-local-switches/&quot;&gt;local switch&lt;/a&gt;, i.e. one that is stored in an &lt;code&gt;_opam/&lt;/code&gt; directory within the project instead of the default location. I prefer using local switches to isolate my project environments from one another, at the cost of having multiple installations of the toolchain on my machine.&lt;/p&gt;
&lt;h3&gt;Editing&lt;/h3&gt;
&lt;p&gt;You can grab the ocaml LSP server and formatter with &lt;code&gt;opam&lt;/code&gt;. You&apos;ll have to create an &lt;code&gt;.ocamlformat&lt;/code&gt; file to activate the formatter.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;opam install ocaml-lsp-server ocamlformat
touch .ocamlformat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&apos;re using VSCode, the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ocamllabs.ocaml-platform&quot;&gt;OCaml Platform Extension&lt;/a&gt; will hook up the OCaml LSP to your editor, giving you type hints inline.&lt;/p&gt;
&lt;h3&gt;The &quot;standard&quot; library&lt;/h3&gt;
&lt;p&gt;After writing a bit of code, I naturally found myself on Stack Overflow, the OCaml forums, and the OCaml discord, trying to find answers to my beginner questions. (I almost bothered a guy wearing a Jane Street shirt that I saw at the gym, but I resisted.) The first question experienced OCaml programmers seem to ask beginners who are soliciting help is &quot;are you using &lt;code&gt;Base&lt;/code&gt; and &lt;code&gt;Core&lt;/code&gt;?&quot; To the uninitiated, that sounds a lot like &quot;are you using the standard library?&quot;&lt;/p&gt;
&lt;p&gt;One of the stranger aspects of the OCaml ecosystem is that it&apos;s sort of bifurcated into two worlds: code that uses the (standard) standard library, and code that uses Jane Street&apos;s &lt;code&gt;Base&lt;/code&gt; and &lt;code&gt;Core&lt;/code&gt; libraries, which are a wholesale replacement for the standard library. There are good reasons for following either path, and I don&apos;t feel particularly opinionated yet, but it&apos;s worth keeping this distinction in mind when encountering OCaml code in the wild or choosing libraries to use in your project. &lt;a href=&quot;http://ocamlverse.net/content/standard_libraries.html&quot;&gt;More on this topic on OCamlverse.&lt;/a&gt; There&apos;s also another popular stdlib-shaped library, &lt;a href=&quot;https://github.com/ocaml-batteries-team/batteries-included&quot;&gt;batteries&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Lastly, a pile of helpful links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cs3110.github.io/textbook/cover.html&quot;&gt;The textbook for CS 3110 Data Structures and Functional Programming at Cornell.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.realworldocaml.org/&quot;&gt;Real World OCaml&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stanford-cs242.github.io/f19/labs/ocaml&quot;&gt;The OCaml lab from Stanford&apos;s CS242 Programming Languages class (Fall 2019)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;https://www.baturin.org/docs/ocaml-faq/&lt;/li&gt;
&lt;li&gt;https://borretti.me/article/two-years-ocaml&lt;/li&gt;
&lt;li&gt;https://osa1.net/posts/2023-04-24-ocaml-thoughts.html&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;[^1]: If you&apos;re reading this, it&apos;s extremely like that you either a) have already attended RC b) should apply to RC. &lt;a href=&quot;https://www.recurse.com/apply&quot;&gt;Do it!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[^2]: This was true at the time of writing, but now I&apos;ve gone down the &lt;code&gt;nix&lt;/code&gt; rabbit hole. Oops!&lt;/p&gt;
&lt;p&gt;[^3]: There&apos;s also &lt;a href=&quot;https://esy.sh/&quot;&gt;esy&lt;/a&gt;, and alternative package manager that appears to try to be a bit more friendly for those coming from the &lt;code&gt;npm&lt;/code&gt;/&lt;code&gt;yarn&lt;/code&gt; world. It also appears to encourage using lockfiles to pin dependencies which I certainly support, but it wanted me to install it via &lt;code&gt;npm&lt;/code&gt; so I decided to stick with opam. If I was building a serious project in OCaml I&apos;d probably reevaluate, and throw &lt;a href=&quot;https://www.tweag.io/blog/2021-07-01-obazl/&quot;&gt;Bazel&lt;/a&gt; in the ring too.&lt;/p&gt;
</content:encoded></item><item><title>iOS focus app</title><link>https://www.jschear.dev/blog/2023-05-30-ios-focus/</link><guid isPermaLink="true">https://www.jschear.dev/blog/2023-05-30-ios-focus/</guid><description>iOS focus app</description><pubDate>Tue, 30 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m working on an app to solve a tiny frustration I have with iOS.&lt;/p&gt;
&lt;p&gt;iOS&apos;s new-ish &quot;focus&quot; feature lets you create a notification allow- or deny-list while in a &quot;focus&quot; mode. Meanwhile, &quot;Screen Time&quot; lets you block applications entirely, based on daily time limits or a nightly &quot;Downtime&quot; mode.[^1]&lt;/p&gt;
&lt;p&gt;But what I&apos;d like to do is allow-/deny-list entire apps on demand (a la &lt;a href=&quot;https://selfcontrolapp.com/&quot;&gt;SelfControl&lt;/a&gt; -- which helped me get through college), all from control center. There are a few apps that fill this gap, but they&apos;re all subscription based. Fair enough, get paid, but I don&apos;t need a ton of features and slick UI here.&lt;/p&gt;
&lt;p&gt;Most of my iOS experience has been focused on developer productivity and CI -- so these are some notes on getting started in app development in 2023.&lt;/p&gt;
&lt;h3&gt;Tooling&lt;/h3&gt;
&lt;p&gt;I&apos;ve been moving towards managing all of my development tooling with nix, but Xcode can&apos;t be installed via nix (as far as I can tell -- I imagine there are licensing issues), and Xcode really wants to manage the entire Swift toolchain. So no nix flakes here.&lt;/p&gt;
&lt;p&gt;At a previous job I used &lt;a href=&quot;https://github.com/bazelbuild/rules_apple&quot;&gt;bazel&lt;/a&gt; to build a large iOS codebase, but that feels overkill for a project with single-digit source files. Plus, &lt;code&gt;.pbxproj&lt;/code&gt; merge conflicts aren&apos;t too bad when you&apos;re developing solo.&lt;/p&gt;
&lt;h4&gt;Code formatting&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/apple/swift-format&quot;&gt;swift-format&lt;/a&gt; is nice. I built it from source and threw it in &lt;code&gt;~/bin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To format all swift code in a directory (&lt;code&gt;-i&lt;/code&gt;n place, &lt;code&gt;-r&lt;/code&gt;ecursively):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ swift-format -i -r .
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;SwiftUI&lt;/h4&gt;
&lt;p&gt;I&apos;m watching a few videos from &lt;a href=&quot;https://cs193p.sites.stanford.edu/&quot;&gt;a Stanford course&lt;/a&gt; to get up to speed on SwiftUI and how it fits into general app architecture.&lt;/p&gt;
&lt;p&gt;[^1]: I do not envy the folks who had to figure out how to reconcile the overlapping concepts of &quot;Do Not Disturb&quot;, &quot;Sleep&quot;, &quot;Screen Time&quot; and &quot;Downtime&quot; with &quot;Focus.&quot; There&apos;s a default &quot;Sleep Focus,&quot; which is a pretty funny way of describing what sleep is all about.&lt;/p&gt;
</content:encoded></item><item><title>It begins</title><link>https://www.jschear.dev/blog/2023-02-28-it-begins/</link><guid isPermaLink="true">https://www.jschear.dev/blog/2023-02-28-it-begins/</guid><description>Baby’s first blog post</description><pubDate>Tue, 28 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve built and thrown away more personal blogs than I’ve written blog posts. Maybe this time will be different!&lt;/p&gt;
&lt;h3&gt;Tech stack&lt;/h3&gt;
&lt;p&gt;This blog is a lightly-customized clone of the &lt;a href=&quot;https://github.com/withastro/astro/tree/latest/examples/blog?on=github&quot;&gt;Astro blog template&lt;/a&gt; and is hosted and deployed using &lt;a href=&quot;https://vercel.com/dashboard&quot;&gt;Vercel&lt;/a&gt;. I may later manage content with a headless CMS, but at the moment I’m authoring posts in markdown (or &lt;a href=&quot;https://mdxjs.com/&quot;&gt;mdx&lt;/a&gt;) and using Astro’s static site generation.&lt;/p&gt;
&lt;p&gt;I find the abundance of full-stack web frameworks to be both overwhelming and exciting (especially coming from mobile development). I’m heartened by the industry-wide adoption of &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt; because I’m not sure how to be productive in the long term when using dynamically-typed languages.&lt;/p&gt;
&lt;p&gt;After puttering around with &lt;a href=&quot;https://nextjs.org/&quot;&gt;Next.js&lt;/a&gt;, &lt;a href=&quot;https://remix.run/&quot;&gt;Remix&lt;/a&gt;, and a few other frameworks (meta-frameworks?), I decided to move forward with &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;, which I learned about on an episode of the &lt;a href=&quot;https://devtools.fm/episode/14&quot;&gt;devtools.fm podcast&lt;/a&gt;. This wasn&apos;t a particularly well-considered decision; I mainly just wanted to throw something online. (This was a case of vibe-driven-development.) &lt;a href=&quot;https://htmx.org/&quot;&gt;htmx&lt;/a&gt; and &lt;a href=&quot;https://fresh.deno.dev/&quot;&gt;fresh&lt;/a&gt; are also on my list of web technologies to explore.&lt;/p&gt;
&lt;p&gt;The blog’s title comes from one of my favorite Unicode codepoints, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Zero-width_joiner&quot;&gt;zero width joiner (U+200D)&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item></channel></rss>