今日精选
HOT最新资讯
共 31896 篇CaptureKit
Keep your desktop clean by auto-organizing screenshots. Discussion | Link
The Hidden Cost of yield in C#: What the Compiler Doesn't Tell You
Most C# developers know how to use yield return. Few understand what actually happens after compilation. If you've ever written something like this: public IEnumerable < int > GetNumbers () { yield return 1 ; yield return 2 ; yield return 3 ; } it looks almost magical. No collection. No list allocation. No iterator implementation. Yet somehow the method returns an IEnumerable. So what is really happening? The answer is one of the most elegant compiler transformations in the entire .NET ecosystem. Let's open the hood. The Illusion Most developers imagine the previous code executes like this: Call method ↓ Return 1 ↓ Pause ↓ Return 2 ↓ Pause ↓ Return 3 That isn't what happens. C# methods cannot actually pause execution. Instead, the compiler completely rewrites your method into something entirely different. The Compiler Creates a State Machine Your tiny method becomes a hidden class similar to this: private sealed class GetNumbersIterator : IEnumerable < int >, IEnumerator < int > { private int _state ; private int _current ; public bool MoveNext () { switch ( _state ) { case 0 : _current = 1 ; _state = 1 ; return true ; case 1 : _current = 2 ; _state = 2 ; return true ; case 2 : _current = 3 ; _state = - 1 ; return true ; default : return false ; } } public int Current => _current ; } Your original method no longer exists. Instead, it simply returns: return new GetNumbersIterator (); Every yield return becomes another state inside MoveNext(). Why Local Variables Don't Disappear Consider this code: IEnumerable < int > Squares () { int x = 1 ; while ( x <= 3 ) { yield return x * x ; x ++; } } After the first yield, the method "pauses." But where is x stored? Not on the stack. The original stack frame has already disappeared. Instead, the compiler promotes local variables into fields: private int _x ; The iterator object now owns every variable that must survive between iterations. This is why iterator methods can remember where they left off. Heap Allocation Happens Ma
I Built an AI App. Eight Months Later, It Became a Skill
When I first wrote about NutriAgent in November 2025, it was a full application. It had a Python backend, a web interface, a Telegram bot, user accounts, Google OAuth, Supabase, and a Google Sheets integration. Recently, I reproduced its core workflow as a skill for my personal AI agent. It took around 15 minutes and two prompts. I didn't build another backend, deploy a service, or implement OAuth again. I explained how I wanted the workflow to behave, tested it, and watched a new row appear in my nutrition spreadsheet. The original application wasn't a mistake. It was how I could deliver that experience with the tools available at the time. Eight months later, the starting point had changed. Eight Months Ago, This Was an App I built NutriAgent because I wanted to track calories and protein without trapping my data inside a nutrition app. I wanted the raw records in a spreadsheet I controlled, where I could create my own reports and eventually connect nutrition with my training data. The first version was a personal n8n workflow. It worked for me, but when a friend wanted to try it, I realized that everything was tied to my accounts. To make it reusable, I rebuilt it in Python and added the parts a real multi-user product needed: authentication, storage, a web interface, Telegram, Google OAuth, conversation history, and account linking. I've already told that story in I Ditched MyFitnessPal and Built an AI Agent to Track My Food , and later wrote about what broke after I used it every day for a month . This article starts after that version. My Gaming PC Became an Agent Box I had a modest gaming PC at home with 16 GB of RAM and a 1 TB drive. Using it through Windows, WSL, and remote desktop from my Mac felt awkward, so I installed Linux and turned it into a remote box for running agents. I'll write about that setup separately. I moved Hermes there from a VPS. Hermes is the personal agent I now run on that machine. It can load reusable skills and use tools connected
The Ground Is Moving
Here's How One Engineer Is Walking on It I want to be upfront about what this post is and isn't. It isn't a list of five things you should do to stay relevant in the age of AI. I've read plenty of those, and I've tried to write one myself more than once. Every time, it came out sounding like advice I didn't actually have the standing to give. So this is the other kind of post — a description of how one person is muddling through, written precisely because I don't have the playbook. The ground moved under me The moment it became real for me was working with Claude Code on an internal project. I came in expecting to do what I've always done: tell the tool, in fine detail, how to accomplish a thing. Instead I found myself describing what I wanted and why , and handing off the details. The shift was quiet, almost embarrassingly small in the moment, and yet it kept nagging at me afterward. I've lived through paradigm shifts before. Web 2.0. Mobile. Each one had its share of "I need to go do the cool new thing for clients." But those were fundamentally about learning a new tool. This one feels different to me. It isn't asking me to learn a new framework. It's asking me to re-evaluate my place in the market and what my job even is. I work as a consultant who helps clients understand and adopt emerging technology, which means I don't get to sit this out in some established niche. The ground is moving, and I'm standing on it. The part I can't resolve Here's the scariest thing, and I'd rather say it plainly than tuck it away: after nearly thirty years of building precise, complex systems, I don't know whether all that experience is an advantage or a trap. I'd love to tell you that three decades of deconstructing hard problems gives me a head start on structuring intent for an AI. Some days I believe that. Other days I wonder whether my deterministic instincts — the habits that made me good at this — are exactly the reflexes I now have to unlearn. I genuinely can't tell yet. B
Functional programming primitives in Javascript
Category theory often sounds like impenetrable academic jargon, but at its core, it is simply the mathematics of composition. In functional programming, we use its concepts to build modular, predictable, and bug-resistant code. JavaScript isn't a pure functional language like Haskell, but it has first-class functions and treats functions as values. This makes it entirely possible to implement category theory primitives. Here is how the theoretical concepts map to practical JavaScript. The Vocabulary of Category Theory Before jumping into code, let's define the fundamental pieces: Categories: A collection of objects and arrows (morphisms) between them. Objects: In programming, these are our types or data (e.g., String, Number, Boolean, Array). Morphisms: These are our pure functions that transform one type into another (e.g., a function that takes a String and returns a Number). The goal of functional programming primitives is to create safe wrappers (containers) around our data so we can compose these functions predictably, without side effects or unhandled errors. 1. Functors: The Mappables A Functor is any type that implements a map method. It is a container holding a value, and map allows you to apply a function to that value without pulling it out of the container. When you map over a Functor, it returns a new Functor of the same type, preserving the container's structure. The native JS Functor: You already use Functors every day. JavaScript Arrays are Functors. const numbers = [ 1 , 2 , 3 ]; // We apply a function to the values inside, and get a new Array back const doubled = numbers . map ( x => x * 2 ); // [2, 4, 6] Building a custom Functor: Let's build a simple Box container to see how this works for single values. const Box = x => ({ map : f => Box ( f ( x )), fold : f => f ( x ), // An escape hatch to get the value out inspect : () => `Box( ${ x } )` }); // Usage: const result = Box ( ' Functional Programming ' ) . map ( str => str . trim ()) . map ( str