[{"data":1,"prerenderedAt":12833},["ShallowReactive",2],{"tags-pages-list-blog":3},[4,171,257,401,429,544,576,750,835,985,1198,1353,1533,1857,2015,2120,2255,2456,2557,2669,2800,3013,3091,3167,3282,3364,3450,3589,3696,3802,3890,3957,4047,4130,4394,4481,4547,4624,5895,5973,6292,6468,6516,6587,6913,7685,7785,7832,7923,7985,8257,8356,8394,8462,8546,8583,8609,8642,8695,8829,8913,8930,8953,8995,9033,9075,9152,9312,10718,10792,10924,10974,11209,11292,11322,11401,11435,11481,11541,11614,11683,11781,11877,11922,11947,12013,12042,12198,12223,12318,12407,12437,12479,12514,12595,12625,12685,12720,12787,12804],{"id":5,"title":6,"body":7,"createdAt":159,"description":13,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":163,"navigation":164,"path":165,"seo":166,"stem":167,"tags":168,"updatedAt":159,"__hash__":170},"content\u002FTLT - 2026.05.16 - Summer Job Samba Interview.md","Summer Job Samba Interview",{"type":8,"value":9,"toc":155},"minimark",[10,14,17,23,26,29,32,35,42,45,48,51,54,56,59,62,65,68,71,74,77,80,83,86,89,91,94,97,100,103,106,109,112,115,118,120,123,126,129,143,146,149,152],[11,12,13],"p",{},"First you get the job Fixing Samba. Then you get the book so you can learn how to Fix Samba. Then you figure out what the actual job entails (... which is not Samba).",[15,16],"hr",{},[11,18,19],{},[20,21,22],"em",{},"Names and identifying details have been changed to protect the innocent. I'm probably not making this up.",[11,24,25],{},"Once upon a time, one summer in college, I was staying in Tempe with my girlfriend's family and I needed to get a summer job. I didn't really have any particular ideas about what job I should get. I was even thinking, I don't know, maybe a hotdog stand at the mall or something.",[11,27,28],{},"I was walking down Mill Avenue when I saw one of these businesses that exist inside of a cottage house, with a sign out front that said \"Web Design.\" A couple of people were leaning up against a car talking, and I sauntered up and asked if they were hiring.",[11,30,31],{},"They said, well, what do you know? What do you do?",[11,33,34],{},"I told them I know a little bit of this, a little bit of that - some web applications, some maybe a little sysadmin Linux-y stuff.",[11,36,37,38],{},"And they asked if I knew Samba. ",[39,40,41],"span",{},"ed: Samba is more or less a Linux application that acts as a Windows file server. Like the L: drive at your work",[11,43,44],{},"And I said, sure.",[11,46,47],{},"They said, well, tell you what. Nice to meet you. My name is Mark. Come over tomorrow at 10 AM, and if you can get our Samba server back up and running, you've got yourself a job.",[11,49,50],{},"I said, great. Sounds like a plan. See you tomorrow.",[11,52,53],{},"And I walked on. Two or three blocks over to Barnes and Noble, to the computer section, where I got myself a book on Samba and started reading. I had surely done something with Samba before, but it had been a little while. I don't think I actually bought the book, but it was helpful to er ... refresh some details.",[15,55],{},[11,57,58],{},"The next day I showed up, awkwardly knocking on the door. Someone let me in and took me back to Mark. They had sort of a front of house and a back of house, and way in the back was where Mark's office was. I imagine this was originally a 2-bedroom cottage.",[11,60,61],{},"He took me around to the server room - a literal closet, but it had a keyboard and a screen and a pretty nice rack-mounted Dell server. He gave me the root password.",[11,63,64],{},"Up front they had computers all wired into a network with a shared drive. The machines were all Windows, and they couldn't access the drive. So I poked around the machines a bit, messed with Samba a bit, and just kept digging around until I finally found some configuration option that wasn't quite right. Got it working. Went and chatted with Mark.",[11,66,67],{},"He was pretty happy.",[11,69,70],{},"He said, well, what kind of money are you looking for? We hadn't actually discussed that up to this point.",[11,72,73],{},"I said, well, I'm looking for something that's an alternative to a hotdog stand.",[11,75,76],{},"He said, how about $10 an hour?",[11,78,79],{},"I said, sure. That'll do.",[11,81,82],{},"What kind of hours?",[11,84,85],{},"He said, well, we usually start a little late, stay a little late. It'll be PHP web development.",[11,87,88],{},"Congratulations. I got the job. Start tomorrow.",[15,90],{},[11,92,93],{},"I can't remember if they gave me a key or if the door was just unlocked. But either way, it was a good thing because I rolled in the next day around 9 AM, wanted to get a good start. Nobody there. I had a machine Mark had put on a table which I assumed was mine, and I started doing all my setup.",[11,95,96],{},"Around 10. Nobody.",[11,98,99],{},"Around 11, Mark finally came in and started telling me about the different projects we'd be working on.",[11,101,102],{},"He had a collection of clients, each with their own specific project setup - usually PHP, sometimes a little WordPress. He'd give me the specifics and give me access to the files, sometimes through an FTP server. Usually I had to almost start from scratch on the development setup, then push up to their server once I had something running.",[11,104,105],{},"The weird thing, though, was that I would get just one or two bugs fixed and he'd have me move on to another client. Get one or two bugs fixed, then on to a different client. Each one getting a relatively tiny amount of work.",[11,107,108],{},"What I realized was that he was putting off all of these folks. There had previously been some developers, and I don't know how long it had been since they left, but he was scrambling to stay ahead of angry customers. It seemed like all of his clients were angry clients - over-promised and under-delivered - and I was doing just enough work on each of them to make them think progress was being made.",[11,110,111],{},"Meanwhile, I started to get familiar with the secondary (or was it primary?) business: a nightlife lifestyle magazine operated out of the front of house. They had a couple of graphic designers, photographers, and an editor, and there was an endless stream of both beautiful people and beautiful photos and lots and lots of advertisements going into these glossy pages. They published weekly or maybe biweekly.",[11,113,114],{},"The magazine ran on Photoshop and PageMaker. And sitting right there on that shared drive - the same drive I'd spent my trial interview getting back online - was not only all of their content, but all of their software. With clearly cracked serials. Lots of password.txt and registration_keytxt.crackz files. Lots and lots of professional-grade software, very much not paid for.",[11,116,117],{},"It was increasingly obvious that this place operated using any means necessary to cut corners and get things out the door.",[15,119],{},[11,121,122],{},"The front of house was run by another guy named Marc - Marc with a C - who was in charge of the magazine. Mark with a K was in charge of the web stuff, the investor, the business partner. There was also a main layout editor who did a lot of the heavy lifting. Sometimes when I came in around 8am or 9am, he'd already be there.",[11,124,125],{},"I'd say, you got an early start?",[11,127,128],{},"He had not, in fact, left from the night before. Pounding energy drinks (and who knows what else). Printer deadline!",[11,130,131,132,142],{},"Meanwhile, the biggest perk I had was a fridge full of Sobe ",[39,133,134,135],{},"ed: A sugary fruit drink in a glass bottle with some cool lizards; see ",[136,137,141],"a",{"href":138,"rel":139},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSoBe",[140],"nofollow","SoBe on wikipedia",". I am partial to orange Sobe, and I had an unlimited supply. They tended to play house and techno music, pretty loud, all the time.",[11,144,145],{},"It was cool. A little weird. Had sort of a shady vibe. OK maybe very shady.",[11,147,148],{},"Between the beautiful people in the front of the house and me stuck way in the back, this random guy who just handed me his root password as a trial interview, helping rob Peter to pay Paul in terms of software development, the heavy ad-based front business - I never really felt like I quite knew what was going on.",[11,150,151],{},"And I didn't realize it would just keep going, getting stranger as we went all summer.",[11,153,154],{},"Definitely more interesting than working at a hotdog stand in the mall.",{"title":156,"searchDepth":157,"depth":157,"links":158},"",2,[],"2026-05-16",false,"md",null,{},true,"\u002Ftlt-2026.05.16-summer-job-samba-interview",{"title":6,"description":13},"TLT - 2026.05.16 - Summer Job Samba Interview",[169],"blog","msvQ8HmDs8fqjpIlWAWGNjISvulwxcU2B7T6yC_a2rU",{"id":172,"title":173,"body":174,"createdAt":249,"description":250,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":251,"navigation":164,"path":252,"seo":253,"stem":254,"tags":255,"updatedAt":249,"__hash__":256},"content\u002FTLT - 2026.03.08 - Agent-Researcher Helping With reMarkable Ghostwriter.md","Agent-Researcher Helping With reMarkable Ghostwriter",{"type":8,"value":175,"toc":247},[176,184,187,238,241,244],[11,177,178,179,183],{},"With ",[136,180,182],{"href":181},"\u002Fghostwriter","Ghostwriter"," I inject pen input on the device to show the output of LLM (Claude, ChatGPT, Gemini, etc) on-device. But the result is a bit messy. So here I give Claude Code some direction and access to the device to iterate experimentally!",[11,185,186],{},"Here is my initial prompt:",[188,189,190,198,201,204,232,235],"blockquote",{},[11,191,192,193,197],{},"I would like to perfect drawing on the reMarkable using the pen, which can then be used to more quickly draw SVG or images to the screen using the injected pen input. Toward this end, I want you to set up an experiment loop. I have the remarkable available via ",[194,195,196],"code",{},"ssh rmpp"," where you can run remote commands, including test commands that we scp over. We could also set up a remote-control that can act as a tool, so like a cli debug version of ghostwriter that runs one command and exits or accepts commands over http or something like that. In any case, you can run code on the thing and treat it like a remote-computer-use situation -- take screenshots, inject input, take a screenshot to verify the result. You can send pen and touch input. You can get a new page by swiping from right to left and then tapping the new-page icon that comes up on the right side, for example. You can tap on the tools menu, the tiny circle in the upper-left, and use that to see tools. You can tap with two-fingers at once to undo.",[11,199,200],{},"So what I want is for you to bootstrap up some experiments to verify your capabilities, ultimately leading to an improvement in the drawing tools for ghostwriter -- especially the ability to accurately render SVG and png content using the injected pen input.",[11,202,203],{},"For example, you could iteratively (by a series of screenshots and pen\u002Ftouch injection) verify that you can accurately:",[205,206,207,211,214,217,220,223,226,229],"ul",{},[208,209,210],"li",{},"Draw a horizontal line",[208,212,213],{},"Draw a vertical line",[208,215,216],{},"Draw a diagonal line",[208,218,219],{},"Draw a dot at any x\u002Fy coordinate",[208,221,222],{},"Draw a triangle",[208,224,225],{},"Draw a single dot",[208,227,228],{},"Draw a png as a bunch of dots",[208,230,231],{},"Trace an SVG",[11,233,234],{},"Between each you could send a bunch of undo-touches or try to go to a new page so that you can see what is happening. You can also experiment with being able to quickly change between tools. There are two pens, so one idea is that pen-1 is for the human and pen-2 is for ghostwriter.",[11,236,237],{},"From these series of built up experiments we should be able to document how to interact accurately and reliably with the screen to render content via pen input.",[11,239,240],{},"That got it going really well. I had to give it a bunch of permissions to get the loop going, but soon it was trying something, taking a screenshot, deciding on the result, and then trying something else. I also had to steer it a bit to be more precise... it kept concluding \"give or take 5px is fiiinneeee\".",[11,242,243],{},"It built an \"experiment\" binary that takes cli commands to draw. I had to coach it a bit on clearing the screen or getting a new screen, and how to avoid (or on purpose utilize) the tool menu. Now step by step it is getting better and better at pen drawing. We are working our way up to drawing smooth polylines from svgs and even outline fonts.",[11,245,246],{},"The general technique of giving Claude Code a way to observe results and an overall goal (even a vague one like \"be better\" or \"increase accuracy\") works really well. Now it is chomp chomp chomping on tokens and doing small experiments to find bugs and alternate techniques for operating the reMarkable.",{"title":156,"searchDepth":157,"depth":157,"links":248},[],"2026-03-08","With Ghostwriter I inject pen input on the device to show the output of LLM (Claude, ChatGPT, Gemini, etc) on-device. But the result is a bit messy. So here I give Claude Code some direction and access to the device to iterate experimentally!",{},"\u002Ftlt-2026.03.08-agent-researcher-helping-with-remarkable-ghostwriter",{"title":173,"description":250},"TLT - 2026.03.08 - Agent-Researcher Helping With reMarkable Ghostwriter",[169],"ht_IK0l0Npj059K9TkPPJdFBiirwkyf8-cQT5XUTY4w",{"id":258,"title":259,"body":260,"createdAt":394,"description":264,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":395,"navigation":164,"path":396,"seo":397,"stem":398,"tags":399,"updatedAt":394,"__hash__":400},"content\u002FTLT - 2026.02.22 - Modern Coding Discomfort, or, Four Colors Suffice.md","Modern Coding Discomfort, or, Four Colors Suffice",{"type":8,"value":261,"toc":386},[262,265,270,273,276,279,282,285,289,292,295,298,301,304,307,311,314,317,320,323,326,329,332,335,339,342,345,348,351,354,358,361,364,367,370,374,377,380,383],[11,263,264],{},"Some thoughts on modern generative code discomfort and the Four Color Problem",[266,267,269],"h2",{"id":268},"four-colors-suffice","Four Colors Suffice",[11,271,272],{},"There is this little puzzle called the map coloring problem. If you have a map - let's say of countries - and you have some different colored crayons, you need to fill in each country so that no two countries touching each other share the same color.",[11,274,275],{},"In the 1970s, mathematicians finally worked out a proof that you only need four colors. The problem is that, unlike many proofs before it where you'd come up with some cool underlying pattern or elegant structure, the proof they came up with was to first enumerate all of the different possible equivalent configurations of a map. This is pretty cool - but it came out to something like just under 2,000 different combinations. Using 1970s computing technology, the proof was to get a computer to go through every single combination and demonstrate, for every single one, that you could color it with only four colors directly or through a simplifying transformation.",[11,277,278],{},"Mathematicians at the time found this very, very unsatisfying. The only way to understand the proof was to read through every possibility, which was kind of crazy. There was nothing special in the solution - it felt like a coincidence that four colors suffice. It boiled down to pages and pages of \"I tried combination one. That one worked. I tried combination two. That one worked.\" All the way through, with no underlying structure, no unique beauty, and nothing you could really build anything else on top of.",[11,280,281],{},"Here we are in 2026, and in software engineering people keep putting up pull requests which are not small and elegant. They solve the problem, and yet they are dissatisfying. They are too long to read. Submitting the pull request makes us feel like we have not provided meaning, only an answer. A maintainer trying to work through a flood of large pull requests is like looking for the pattern in the four color theorem. It is not there - because it turns out it doesn't need to be there in order to solve the problem.",[11,283,284],{},"In programming we've had this problem of unreviewable details before, but now we need a new way to build trust.",[266,286,288],{"id":287},"the-glass-box","The Glass Box",[11,290,291],{},"Software has always been a kind of layered glass box. You could peer inside, see what was happening, understand how the machine was doing what you asked of it.",[11,293,294],{},"When I first learned to program, I did it across multiple levels - high-level languages, medium-level languages, and assembly. I used to program on TI graphing calculators in assembly, often hand-translating the op codes to hexadecimal. I made a compiler that could take TI Basic and translate it down into assembly, which was pretty cool - though it would write assembly that wasn't as optimized as what I was writing by hand. It would spit out so much that I couldn't really read it, and that made me worry about inefficiency, about losing nuance, about the code losing the aesthetic of the system. Soon better hardware came into my life, more high-level systems, and I moved on.",[11,296,297],{},"After a while, you don't really want to constantly be thinking about whether memory is growing from the bottom up or the top down, where the stack and heap are, how to manage pointers. After a while, you don't even want to worry about garbage collection. You just want stuff to work.",[11,299,300],{},"As you move up these levels of abstraction, it's like you take each lower level and put it in a box. Maybe it's a semi-transparent box where you know roughly what's happening underneath, but you care less and less. Then you take that level and put it inside another box. You can squint through and sort of see, but you see less and less. You can open the boxes when you need to - you can get back inside and see what's going on. But for the most part, if it's a good box, you don't really care what's going on inside.",[11,302,303],{},"What makes people eventually stop worrying is that you build up trust. Your tools build up capability to where you can write a smaller, more abstract chunk of code, and it does what you need with less fiddling. Less control, but usually less control in dimensions you don't really care about - like where specifically the bytes are in memory. Sometimes it constrains you in ways you do care about, like vertically centering text in CSS being a real pain. But most of the time, you're able to build up trust in your higher level system because it lets you move faster, get your idea out on screen, let people interact with it faster than you could have before.",[11,305,306],{},"Less control in dimensions you don't really care about. That's the deal you keep making, one abstraction layer at a time.",[266,308,310],{"id":309},"whats-actually-happening-with-ai-generated-code","What's Actually Happening With AI-Generated Code",[11,312,313],{},"Here's the thing people get wrong about AI-generated code: it's still just code. You can look at it, peel it apart, figure out how it works, figure out what it's doing and what it's not doing. The issue isn't that it's mysterious or non-deterministic in any fundamental sense. The issue is quantity. There is simply more code than anyone can read.",[11,315,316],{},"This is exactly where the overlap with the four color theorem comes in. There were so many individual cases that the proof was more or less to enumerate all of them - and that made it too much to fit in a human brain. It doesn't take away from the fact that this is still ultimately deterministic. Things can be sloppy without losing determinism.",[11,318,319],{},"People get distracted because LLMs generate code somewhat non-deterministically - ask the same prompt three times and you'll get three different implementations. But if you judge the solutions based on their behavior, if you look at all three and pick the one that behaves most like what you want, you still have a system. You still have execution you can run and observe.",[11,321,322],{},"So when you have some monster pull request and you're a little nervous about merging it, what do you actually do? You pull it down and start treating it as a more opaque box. Check out the behavior. Check out whether it works, whether it does the original thing. Try out a few edge cases and see how it feels. I still sometimes scan the code looking for something obvious that's trying to escape its little box, a view page with SQL embedded or something - the more contained it is, the better. But for the most part, you treat it more like a found object than a beautifully constructed theorem.",[11,324,325],{},"This is also where a tempting instinct leads you astray. You might think: \"They generated that code through prompts, through some kind of English-level specification - let's hold on to that.\" The problem is that your prompts are already trying to account for your current situation, the capabilities of your model, the assumptions it has, the rest of the codebase at that time. Your prompt is not really something worth saving in the way source code is worth saving. If you run the same prompt multiple times, you get different results. Run it against different models, you get different results.",[11,327,328],{},"The prompt isn't like high-level JavaScript compared to assembly. If you take your high-level JavaScript and execute it, you end up with pretty much the same thing each time. Take your high-level prompt, and you could end up with something quite different. Your LLM is adding something to it - it's adding a snapshot of its current data and style, its taste based on the training and context.",[11,330,331],{},"This means the whole world is flipped on its head. Historically, you should not commit build artifacts - they don't belong in your tree. Now it feels like the opposite. There is no point in committing the construction; you're only committing the build artifact. Your version history becomes much more like a transaction log of your artifact than a journal of an engineer.",[11,333,334],{},"You might save a prompt as documentation, as inspiration if you ever wanted to start over - but it isn't an artifact. You can't validate behavior at the prompt level. You have to validate it at the resulting code level, at the behavior level.",[266,336,338],{"id":337},"rigor-doesnt-disappear-it-relocates","Rigor Doesn't Disappear - It Relocates",[11,340,341],{},"So where does that leave us? We have these generated artifacts and throw-away prompts, and we need to start shifting how we think about the whole situation. We need to treat the artifacts as found pieces - things generated more like material science than traditional engineering. We can't depend on the underlying construction since we did not construct anything ourselves. We need to pressure test the actual thing, the actual result.",[11,343,344],{},"We can look to other disciplines for guidance here. Material science? Structural engineering? Folks who do testing on things to see how well they work. You can still gain a lot of insight if you understand how something works - that knowledge should give you better ideas about how to break it, how to pressure test it, how to make sure it fits your actual goals, and even what compromises you might be making. But even without that knowledge you can hit something a few times with a hammer to see if it breaks.",[11,346,347],{},"In practical terms: you might observe through real usage that a piece of AI-generated code isn't going to scale because of memory constraints, or you hit it with more than a couple dozen concurrent users and it falls apart. That might then lead you to find out exactly when it does fall apart, and to spend more of your time prodding at the outside of the black box rather than trying to comprehend it and build it up from first principles on the inside. More of a behavioral science than a dissection or construction.",[11,349,350],{},"Like the Four Color Problem, we must give up elegance and embrace observation.",[11,352,353],{},"The rigor applied toward validation has always been in service of building trust. If you can build trust through behavioral evidence instead of through reading the source, the rigor hasn't gone away - it's just relocated. The person who understands crystalline structures doesn't run the stress test any differently than someone who doesn't, but they know which stress tests to run. Deep knowledge of how things work still gives you an advantage. It just expresses itself differently now.",[266,355,357],{"id":356},"the-new-practitioner","The New Practitioner",[11,359,360],{},"I think about how much it actually matters that I know how a NAND gate works at the transistor level. It's genuinely fun to know. I can draw inspiration from it for higher-level concepts. But I can build a lot of things without ever having lifted a soldering iron.",[11,362,363],{},"A lot of people new to building software haven't had the background and traditional skills that would let them peer inside these boxes. Up until now, they could operate as QAs, as users, as people able to judge results - but generating the artifact itself was hard to do without years of accumulated knowledge. That's changing.",[11,365,366],{},"Someone coming to coding now should use tools like Claude Code to generate artifacts. They need to be technical, working through details on top of their creative prompting. They'll still need to think about how things fit together. But they can start from the other end, from the imagined outcome, more extremely than ever before. They can generate, magic-wand an artifact into existence, and then push on it with interactive and even real-world testing.",[11,368,369],{},"As they do this, the more they scratch into it - thinking about edges, failure modes, how other people are going to interact with it - the better they'll get. If they can get all the way down into the fundamentals, down into the black box a bit, they'll have more powerful techniques. But they might not need that. They will be able to trial-and-error their way into some really amazing things.",[266,371,373],{"id":372},"the-invitation","The Invitation",[11,375,376],{},"In the end, Four Colors Suffice.",[11,378,379],{},"We don't need to understand why from first principles; we can convince ourselves via other means. Grab a couple maps, a couple crayons. Give it a try. You might not be able to get through all 2,000-ish combinations, but you can get through a few and build up your faith that it's probably fine. You end up with some very beautiful little maps.",[11,381,382],{},"You might not be able to see all the way through these layers of abstraction, these boxes inside of boxes. But you can build some amazing things. You can share some amazing things. You can make ideas and visions come to life that never could have made it through before - not because the tools are magic, but because the barrier to making something real has changed.",[11,384,385],{},"And if you do have the ability to get down into the details, you can still help other folks out when they get stuck. You can design better experiments, ask smarter questions, push on edges in ways that matter.",{"title":156,"searchDepth":157,"depth":157,"links":387},[388,389,390,391,392,393],{"id":268,"depth":157,"text":269},{"id":287,"depth":157,"text":288},{"id":309,"depth":157,"text":310},{"id":337,"depth":157,"text":338},{"id":356,"depth":157,"text":357},{"id":372,"depth":157,"text":373},"2026-02-22",{},"\u002Ftlt-2026.02.22-modern-coding-discomfort-or-four-colors-suffice",{"title":259,"description":264},"TLT - 2026.02.22 - Modern Coding Discomfort, or, Four Colors Suffice",[169],"UHdZ2HPCzp46Ppn3C-8mmasz9f9gK0anufFdAiJlqgo",{"id":402,"title":403,"body":404,"createdAt":394,"description":408,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":423,"navigation":164,"path":424,"seo":425,"stem":426,"tags":427,"updatedAt":394,"__hash__":428},"content\u002FTLT - 2026.02.22 - Pierre Menard in the House.md","Pierre Menard in the House",{"type":8,"value":405,"toc":421},[406,409,418],[11,407,408],{},"I've just finished reading House of Leaves in a book club.",[11,410,411,412,417],{},"One of my favorite bits from the House of Leaves is that all through the whole thing there's all these footnotes and they're basically all just made up references to random academic journals or speeches or things that don't exist. And then out of nowhere in one of the citations, they are talking about the Frenchman ",[136,413,416],{"href":414,"rel":415},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FPierre_Menard,_Author_of_the_Quixote",[140],"Pierre Menard"," and mentioning it as fact, someone who is attempting (succeeding) to recreate Don Quixote.",[11,419,420],{},"This is actually a Jorge Louis Borges quote and a piece of one of his writings, which is completely unattributed inside of the House of Leaves footnote. It's like they are citing the fictional book, not the actual Borges book, but they didn't even cite the fictional book. Maybe both stories are set in the same universe.",{"title":156,"searchDepth":157,"depth":157,"links":422},[],{},"\u002Ftlt-2026.02.22-pierre-menard-in-the-house",{"title":403,"description":408},"TLT - 2026.02.22 - Pierre Menard in the House",[169],"GYbBaGH7PEDRyKYt3kgRFtQ2rUeu4PiMNjs0xfjkZgU",{"id":430,"title":431,"body":432,"createdAt":536,"description":436,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":537,"navigation":164,"path":538,"seo":539,"stem":540,"tags":541,"updatedAt":536,"__hash__":543},"content\u002FTLT - 2026.01.08 - Jamuary 8.md","Jamuary 8",{"type":8,"value":433,"toc":534},[434,437,450,457,470,482,493,505,517],[11,435,436],{},"So Damn Cute",[11,438,439,444,445,449],{},[440,441],"audio",{"controls":164,"preload":442,"src":443},"metadata","\u002Fdocs\u002Fmusic\u002Fso_damn_cute_v1.mp3"," (",[136,446,448],{"download":447,"external":156,"href":443},"docs\u002Fmusic\u002Fso_damn_cute_v1.mp3","download",")",[11,451,452,453],{},"Practice using ",[136,454,456],{"href":455},"\u002Frotae-versantur","Rotae Versantur",[11,458,459,460,463,464,466,467,469],{},"Well I love you",[461,462],"br",{},"\n'cause you're so damn cute",[461,465],{},"\nand when the people ask me why",[461,468],{},"\nwell the question is moot",[11,471,472,473,475,476,478,479,481],{},"because I love you dearly",[461,474],{},"\nfrom your head to your toe",[461,477],{},"\nand if you're going somewhere",[461,480],{},"\nwell that's where I'll go",[11,483,484,485,463,487,489,490,492],{},"because I love you",[461,486],{},[461,488],{},"\nand you might ask why",[461,491],{},"\nwell I'll tell you the truth",[11,494,495,496,498,499,501,502,504],{},"It's 'cause you're so cool",[461,497],{},"\nand you're so nice",[461,500],{},"\nand if you asked me on a date",[461,503],{},"\ndon't need to ask twice",[11,506,507,508,510,511,513,514,516],{},"when you come a round",[461,509],{},"\nI just lose my head",[461,512],{},"\nwhen I hear your name",[461,515],{},"\nmy whole face turns red",[11,518,484,519,463,521,523,524,463,526,523,528,463,530,523,532,463],{},[461,520],{},[461,522],{},"\nbecause I love you",[461,525],{},[461,527],{},[461,529],{},[461,531],{},[461,533],{},{"title":156,"searchDepth":157,"depth":157,"links":535},[],"2026-01-08T00:00:00.000Z",{},"\u002Ftlt-2026.01.08-jamuary-8",{"title":431,"description":436},"TLT - 2026.01.08 - Jamuary 8",[169,542],"music","f4NxganlEMFK0FL1np0B3dsVVPAdrPcw0uZOB7IXjAE",{"id":545,"title":546,"body":547,"createdAt":568,"description":569,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":570,"navigation":164,"path":571,"seo":572,"stem":573,"tags":574,"updatedAt":568,"__hash__":575},"content\u002FTLT - 2026.01.02 - Jamuary 2.md","Jamuary 2",{"type":8,"value":548,"toc":566},[549,558],[11,550,551,552,557],{},"Practice on my norns-powered digital four track: ",[136,553,556],{"href":554,"rel":555},"https:\u002F\u002Fthelackthereof.org\u002Fdocs\u002Fmusic\u002F2026-01-02%20Rotae%20Practice%20-%20Hotel%20Yorba.mp3",[140],"Hotel Yorba cover"," (including mistakes, heh)",[11,559,560,444,563,449],{},[440,561],{"controls":164,"preload":442,"src":562},"\u002Fdocs\u002Fmusic\u002F2026-01-02%20Rotae%20Practice%20-%20Hotel%20Yorba.mp3",[136,564,448],{"download":565,"external":156,"href":562},"docs\u002Fmusic\u002F2026-01-02%20Rotae%20Practice%20-%20Hotel%20Yorba.mp3",{"title":156,"searchDepth":157,"depth":157,"links":567},[],"2026-01-02T00:00:00.000Z","Practice on my norns-powered digital four track: Hotel Yorba cover (including mistakes, heh)",{},"\u002Ftlt-2026.01.02-jamuary-2",{"title":546,"description":569},"TLT - 2026.01.02 - Jamuary 2",[169,542],"sP0Ix9OFA-57WHWwCy0oB8LiIVaZkxyC2JC3Nh0nwxs",{"id":577,"title":578,"body":579,"createdAt":743,"description":583,"draft":160,"extension":161,"image":590,"mastodonThread":162,"meta":744,"navigation":164,"path":745,"seo":746,"stem":747,"tags":748,"updatedAt":743,"__hash__":749},"content\u002FTLT - 2025.07.12 - Gremllm.md","Gremllm",{"type":8,"value":580,"toc":741},[581,584,591,598,604,713,720,727,737],[11,582,583],{},"A project which puts LLM-powered gremlins right into your runtime!",[11,585,586],{},[587,588],"img",{"alt":589,"src":590},"Gremllm cartoon","img\u002FGremllm_cartoon.png",[11,592,593,594,597],{},"As previously mentioned, I enjoy trying out new tech like claude-code, making esoteric and ill-advised libraries that are maybe-jokes, pushing on meta-models and run-time ",[194,595,596],{},"eval",", and like many others I don't mind 5 minutes of fame. So by that measure, TOTAL SUCCESS!",[11,599,600,601,603],{},"Let's start with what this new ",[194,602,578],{}," library that I made can do:",[605,606,610],"pre",{"className":607,"code":608,"language":609,"meta":156,"style":156},"language-python shiki shiki-themes github-light github-dark monokai","from gremllm import Gremllm\n\ncounter = Gremllm('counter')\ncounter.value = 0\ncounter.increment()\ncounter.increment(5)\ncounter.add_seventeen()\nprint(counter.current_value)\nprint(counter.value_in_hex)\ncounter.reset()\n","python",[194,611,612,630,635,654,666,672,683,689,699,707],{"__ignoreMap":156},[39,613,616,620,624,627],{"class":614,"line":615},"line",1,[39,617,619],{"class":618},"sC2Qs","from",[39,621,623],{"class":622},"sMOD_"," gremllm ",[39,625,626],{"class":618},"import",[39,628,629],{"class":622}," Gremllm\n",[39,631,632],{"class":614,"line":157},[39,633,634],{"emptyLinePlaceholder":164},"\n",[39,636,638,641,644,647,651],{"class":614,"line":637},3,[39,639,640],{"class":622},"counter ",[39,642,643],{"class":618},"=",[39,645,646],{"class":622}," Gremllm(",[39,648,650],{"class":649},"sstjo","'counter'",[39,652,653],{"class":622},")\n",[39,655,657,660,662],{"class":614,"line":656},4,[39,658,659],{"class":622},"counter.value ",[39,661,643],{"class":618},[39,663,665],{"class":664},"s7F3e"," 0\n",[39,667,669],{"class":614,"line":668},5,[39,670,671],{"class":622},"counter.increment()\n",[39,673,675,678,681],{"class":614,"line":674},6,[39,676,677],{"class":622},"counter.increment(",[39,679,680],{"class":664},"5",[39,682,653],{"class":622},[39,684,686],{"class":614,"line":685},7,[39,687,688],{"class":622},"counter.add_seventeen()\n",[39,690,692,696],{"class":614,"line":691},8,[39,693,695],{"class":694},"sTrkL","print",[39,697,698],{"class":622},"(counter.current_value)\n",[39,700,702,704],{"class":614,"line":701},9,[39,703,695],{"class":694},[39,705,706],{"class":622},"(counter.value_in_hex)\n",[39,708,710],{"class":614,"line":709},10,[39,711,712],{"class":622},"counter.reset()\n",[11,714,715,716,719],{},"To be clear -- each of those methods is completely made up. At runtime when you invoke a method it is ",[20,717,718],{},"at that moment"," sent over to the LLM (ChatGPT in this case) to generate the python code, which is then executed. It's like claude-code, but at runtime!",[11,721,722,723,726],{},"Speaking of which, I built Gremllm ",[20,724,725],{},"using"," Claude Code, which I've been using a lot lately. I'm not always convinced that it is faster, and I'm not always convinced that it is slower, but it is fun enough that I am making stuff that I might not make otherwise at the very least.",[11,728,729,730,732,733,736],{},"Using Claude Code did have some trickery. The biggest thing is that it kept wanting to run my ",[194,731,596],{}," (or in Python it is actually ",[194,734,735],{},"exec",") in some sort of sandbox, and I had to be like \"no... please do this dangerous thing. Really!\". Even now it is doing some things that are more safe than I would have done if it was completely written by hand.",[738,739,740],"style",{},"html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sTrkL, html code.shiki .sTrkL{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#66D9EF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":156,"searchDepth":157,"depth":157,"links":742},[],"2025-07-12T00:00:00.000Z",{},"\u002Ftlt-2025.07.12-gremllm",{"title":578,"description":583},"TLT - 2025.07.12 - Gremllm",[169],"borhbqEkc1p9O0yyBOzuUcYL7mnj9wY2SY6eyRgC-eM",{"id":751,"title":752,"body":753,"createdAt":827,"description":828,"draft":160,"extension":161,"image":768,"mastodonThread":162,"meta":829,"navigation":164,"path":830,"seo":831,"stem":832,"tags":833,"updatedAt":827,"__hash__":834},"content\u002FTLT - 2025.03.28 - Helped That One.md","Helped That One",{"type":8,"value":754,"toc":825},[755,763,769,771,774,777,782,785,798,803,806,811,814,819],[11,756,757,758,762],{},"Taking inspiration from ",[136,759,761],{"href":760},"\u002Fthe-star-thrower","The Star Thrower","; Action, even in the face of futility, is the path I take.",[11,764,765],{},[587,766],{"alt":767,"src":768},"The Ocean","img\u002FThe_Ocean.png",[15,770],{},[11,772,773],{},"I recall from childhood church sermons the story of the Starfish Thrower. One of my favorite parables, it tells the story of two people walking along a beach. One of them bends down now and again to pick up a living starfish and fling it into the sea. The second person asks why? What is the point? There are millions of these things on the beach - you cannot save them all. The first person reaches down, picks up a starfish and tosses it with a flick of their wrist far out to sea, then they look at their companion and they say, simply, \"Saved that one.\"",[11,775,776],{},"Dozens of variations of this story are told. I've always loved it, and like to think that I live by the simple idea that one contribution, one bit of effort, has value even in the face of overwhelming opposition to success.",[188,778,779],{},[11,780,781],{},"\"The stars,\" he said, \"throw well. One can help them.\"",[11,783,784],{},"I like to help people. The other day I took a call to help someone as they look for a job, just starting out their career and finding themselves in the worst job market of my lifetime. I can't do much directly, but I try to advise, give some ideas, review their resume, give some context on the right words to use. I put them in contact with some resources; I plan on vouching for them when I get the chance. Yet I know that I could spend all day every day having the same conversation with person after person, with no end. There are always more starfish. Still, I hope to help the ones I can each time I take a stroll on the beach.",[11,786,787,788,793,794,797],{},"Thinking about this story, I decided to look it up -- I discovered that the short version is a VERY choppity chopped allusion to a (longer) short essay, ",[136,789,792],{"href":790,"rel":791},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FThe_Star_Thrower",[140],"The Star Thrower by Loren Eiseley (wikipedia)",". After quite some searching, I found the original version and you can ",[136,795,796],{"href":760},"read a copy of the full Star Thrower essay here",".",[188,799,800],{},[11,801,802],{},"Long ago, when the future was just a simple tomorrow, men had cast intricately carved game counters to determine its course, or they had traced with a grimy finger the cracks on the burnt shoulder blade of a hare.",[11,804,805],{},"The movie \"Blade Runner\" is similarly inspired by \"Do Androids Dream of Electric Sheep\" by Philip K. Dick. Please read the book! You will find that the book is not \"better\" so much as \"bigger\". Deeper, darker, wider. It is existential well beyond the android identity struggle. I find that the original Star Thrower essay has a similar relationship to the short parable I learned in church. It feels more like reading a piece by Borges instead of an inspirational bookmark.",[188,807,808],{},[11,809,810],{},"Things, in the words of G. K. Chesterton, were to grow incalculable by being calculated. Man's powers were finite; the forces he had released in nature recognized no such limitations. They were the irrevocable monsters conjured up by a completely amateur sorcerer.",[11,812,813],{},"The Star Thrower essay touches upon science, spirituality, death, life, meaningfulness, Darwinistic selfishness, and on and on. Reading it during the thrash of current politics, reading it during the rise of language-using AI, even reading it during a life transition (I got a new job!) casts a different sort of light on the day-to-day and cosmic struggles I, we, find ourselves in.",[188,815,816],{},[11,817,818],{},"I picked up a star whose tube feet ventured timidly among my fingers while, like a true star, it cried soundlessly for life.",[11,820,821,824],{},[136,822,823],{"href":760},"Give it a taste",". Maybe toss a starfish or two.",{"title":156,"searchDepth":157,"depth":157,"links":826},[],"2025-03-28","Taking inspiration from The Star Thrower; Action, even in the face of futility, is the path I take.",{},"\u002Ftlt-2025.03.28-helped-that-one",{"title":752,"description":828},"TLT - 2025.03.28 - Helped That One",[169],"Ci52YRPu0wzSqQ_exie1_KAIWUC8uigzhUtcO6aQieE",{"id":836,"title":837,"body":838,"createdAt":977,"description":978,"draft":160,"extension":161,"image":957,"mastodonThread":162,"meta":979,"navigation":164,"path":980,"seo":981,"stem":982,"tags":983,"updatedAt":977,"__hash__":984},"content\u002FTLT - 2025.03.27 - Generative Chuapin.md","Generative ChuhuaPin",{"type":8,"value":839,"toc":975},[840,849,851,854,865,868,958,966],[11,841,842,843,848],{},"Using the ",[136,844,847],{"href":845,"rel":846},"https:\u002F\u002Fopenai.com\u002Findex\u002Fintroducing-4o-image-generation\u002F",[140],"new ChatGPT GPT-4o Image Generation"," to incrementally generate a photo of Hoda! (A \"Chipin\" is a 50-50 Chuhuahua and Mini-Pincer. Hoda is 70-20, so is a ChuhuaPin!)",[15,850],{},[11,852,853],{},"Previously if you asked ChatGPT to generate you an image it would switch over to DALL-E, a separate image generation model. Each time it generated a new image it would more or less start from the beginning, maybe, and it was a challenge to get small incremental changes to an image.",[11,855,178,856,860,861,864],{},[136,857,859],{"href":845,"rel":858},[140],"ChatGPT GPT-4o Image Generation Update"," it now uses the ",[20,862,863],{},"same model"," to generate the image as it is contextualizing your prompt, which makes it much more capable of things like incremental changes (it isn't starting from scratch each time). At least, that's how I understand it.",[11,866,867],{},"As a fun experiment, I tried to generate a dog that looks like hoda! Here is every step that I took. I had to brighten\u002Fsharpen the images quite a bit.",[869,870,871],"table",{},[872,873,874,888,898,908,918,928,938,948],"tbody",{},[875,876,877,882],"tr",{},[878,879,881],"td",{"style":880},"vertical-align: middle;","Create an image of a dog that is 70% Chihuahua, 20% mini pincer, and 10% mutt",[878,883,884],{},[587,885],{"src":886,"width":887},"img\u002Fbright_chatgpt_gen_chihuahua_1.png",400,[875,889,890,893],{},[878,891,892],{"style":880},"Give it a slightly brindle coloring. Still with a black base coat, but the brindle highlights closer to grey",[878,894,895],{},[587,896],{"src":897,"width":887},"img\u002Fbright_chatgpt_gen_chihuahua_2.png",[875,899,900,903],{},[878,901,902],{"style":880},"Close, but went a bit too far. Make one halfway between these two!",[878,904,905],{},[587,906],{"src":907,"width":887},"img\u002Fbright_chatgpt_gen_chihuahua_3.png",[875,909,910,913],{},[878,911,912],{"style":880},"More black. Also give her a blue harness",[878,914,915],{},[587,916],{"src":917,"width":887},"img\u002Fbright_chatgpt_gen_chihuahua_4.png",[875,919,920,923],{},[878,921,922],{"style":880},"Make her a liiiitle thinner",[878,924,925],{},[587,926],{"src":927,"width":887},"img\u002Fbright_chatgpt_gen_chihuahua_5.png",[875,929,930,933],{},[878,931,932],{"style":880},"The body and color are good. Make the head a little more chihuahua",[878,934,935],{},[587,936],{"src":937,"width":887},"img\u002Fbright_chatgpt_gen_chihuahua_6.png",[875,939,940,943],{},[878,941,942],{"style":880},"Make her hair on her neck a little bald",[878,944,945],{},[587,946],{"src":947,"width":887},"img\u002Fbright_chatgpt_gen_chihuahua_7.png",[875,949,950,953],{},[878,951,952],{"style":880},"Really close! Make her ears just a little bit smaller.",[878,954,955],{},[587,956],{"src":957,"width":887},"img\u002Fbright_chatgpt_gen_chihuahua_8.png",[11,959,960,961,963],{},"This is a lot like what I imagine working with a crime sketch artist would be like! Here is the final image a bit bigger. I think this is what Hoda looked like when she was young!",[461,962],{},[587,964],{"src":957,"width":965},600,[11,967,968,969,971],{},"And here is Hoda from a real camera IRL. A bit older, a bit blinder :)",[461,970],{},[587,972],{"src":973,"width":974},"img\u002Fhoda-20250327.png",800,{"title":156,"searchDepth":157,"depth":157,"links":976},[],"2025-03-27","Using the new ChatGPT GPT-4o Image Generation to incrementally generate a photo of Hoda! (A \"Chipin\" is a 50-50 Chuhuahua and Mini-Pincer. Hoda is 70-20, so is a ChuhuaPin!)",{},"\u002Ftlt-2025.03.27-generative-chuapin",{"title":837,"description":978},"TLT - 2025.03.27 - Generative Chuapin",[169],"rqAUoXFsthSeWQAAnJebTB7r4bvsBqEdZUJgbO2yWm0",{"id":986,"title":987,"body":988,"createdAt":1189,"description":1190,"draft":160,"extension":161,"image":1126,"mastodonThread":162,"meta":1191,"navigation":164,"path":1192,"seo":1193,"stem":1194,"tags":1195,"updatedAt":1189,"__hash__":1197},"content\u002FTLT - 2025.03.14 - The Four Squares of Agency.md","The Four Squares of Agency",{"type":8,"value":989,"toc":1182},[990,1009,1011,1015,1024,1033,1038,1041,1048,1051,1056,1059,1062,1068,1071,1076,1080,1092,1098,1105,1111,1118,1121,1127,1136,1145,1154,1171,1179],[11,991,992,996,997,1002,1003,1008],{},[993,994,995],"strong",{},"Agency"," (a more useful concept of Free Will), has two important ingredients -- the ability to ",[20,998,999],{},[993,1000,1001],{},"predict"," outcomes and the ability to ",[20,1004,1005],{},[993,1006,1007],{},"influence"," outcomes -- both of which come in a spectrum of possible degrees. We can lay these out into a visualization that breaks down naturally into a four-square grid.",[15,1010],{},[266,1012,1014],{"id":1013},"the-two-ingredients","The Two Ingredients",[11,1016,1017,1018,1021,1022,797],{},"Lately there has been a lot of thrash in the AI world around ",[194,1019,1020],{},"Agents",", like what one is or what differentiates an Agent from an Algorithm and things like that. Let's take this from another angle, and talk through a concept of ",[993,1023,995],{},[11,1025,1026],{},[1027,1028,1029],"small",{},[1030,1031,1032],"i",{},"(Note that there is nothing new under the sun; my thoughts here are largely (probably incorrect and mis-remembered) inspirations from Daniel Dennett and others. I struggle with knowing how to cite these ideas that have been rolling round my head for a long time.)",[1034,1035,1037],"h3",{"id":1036},"prediction","Prediction",[11,1039,1040],{},"Given the state of the world, how far out and how accurately can you predict what comes next? Drop an apple from shoulder height and you can work out pretty accurately how long it'll take to hit the ground. Flip a coin and you can get it right .... half the time. Guessing what the weather will be in 5 minutes is quite a bit different from 5 hours or 5 years.",[11,1042,1043],{},[587,1044],{"alt":1045,"src":1046,"style":1047},"Prediction scale","img\u002FPrediction_scale.png","width: 100%",[11,1049,1050],{},"Your ability to predict outcomes, to predict the future, varies based on the thing being predicted and how good your model is of the world. It gets more complicated when there are other Agents around changing things, but even without that some things are harder to predict and some things are easier to predict. You can also, at the very least, narrow down the range of possible or probable outcomes.",[11,1052,1053],{},[993,1054,1055],{},"Prediction is a context-specific spectrum",[1034,1057,1058],{"id":1007},"Influence",[11,1060,1061],{},"You have some control, some influence, over the world around you. Generally you can move about, interact with things, push buttons and open doors, etc. The result is that you are changing the state of the world, or possibly even preserving the state of the world. Typing on a keyboard, talking to other people, shouting on a street corner -- these all count too, and can have an outsized effect. Sticks and stones may break my bones, but words can build an army.",[11,1063,1064],{},[587,1065],{"alt":1066,"src":1067,"style":1047},"Influence scale","img\u002FInfluence_scale.png",[11,1069,1070],{},"Making changes to the world, similar to prediction, varies on magnitude and accuracy. This includes how much control we have over our own bodies -- I can stand on a skateboard but I can't do a flip from a half-pipe. I can hold a knife, but I can't use it to repair a heart. The current state of the world also locks down what changes are available -- the heart surgeon can't operate if the patient isn't physically accessible to them.",[11,1072,1073],{},[993,1074,1075],{},"Influence is a context-specific spectrum",[266,1077,1079],{"id":1078},"the-four-squares","The Four Squares",[11,1081,1082,1083,1085,1086,1088,1089,1091],{},"Put simply -- the amount of ",[993,1084,995],{}," you have is built on the degree of ",[993,1087,1037],{}," and the degree of ",[993,1090,1058],{},". Neither ingredient is all-or-nothing, and Agency itself is not all-or-nothing. Let's lay this out into a diagram:",[11,1093,1094],{},[587,1095],{"alt":1096,"src":1097,"style":1047},"Four Square Agency Model Blank","img\u002FFour_Square_Agency_Model_Blank.png",[11,1099,1100,1101,1104],{},"Along the bottom axis we plot the ability to ",[993,1102,1103],{},"Predict"," outcomes. On the left you have zero ability to predict what-comes-next, and as you move to the right your predictive powers increase in both accuracy and distance into the future.",[11,1106,1107,1108,1110],{},"Along the left axis we plot ",[993,1109,1058],{},". At the bottom you have zero ability to influence (change) the world, and as you move up your influence increases. A small action might make for a big change, and this axis is meant to capture the magnitude of the resulting change.",[11,1112,1113,1114,1117],{},"Thinking about this in a two-dimensional space gives us some idea of a feedback loop on a fundamental concept -- to have ",[993,1115,1116],{},"meaningful Agency"," you need to not only be able to influence the world, but have an idea about how that influence is going to actually impact things.",[11,1119,1120],{},"We can break this space into four quadrants and label each of them to get some intuition on the combination between Prediction and Influence.",[11,1122,1123],{},[587,1124],{"alt":1125,"src":1126,"style":1047},"Four Square Agency Model","img\u002FFour_Square_Agency_Model.png",[11,1128,1129,1130,1135],{},"Starting in the upper-left quadrant, ",[20,1131,1132],{},[993,1133,1134],{},"Low Prediction, High Influence -- The Gamble",". Here you are able to perform an action, make a change to the world, but really have no idea what is going to happen. It is like being on a game-show and you can pick a door, any door, but you don't know what is behind the door.",[11,1137,1138,1139,1144],{},"Jumping down to the lower-right quadrant, ",[20,1140,1141],{},[993,1142,1143],{},"High Prediction, Low Influence -- The Inevitable",". Being on the high-end of the prediction range, you have a VERY good idea about what is going to happen. But very little of what you do will have any influence on the world, on the outcome. This is the fatalistic and inevitable end that is well known in advance.",[11,1146,1147,1148,1153],{},"Moving to the left bottom, we have ",[20,1149,1150],{},[993,1151,1152],{},"Low Prediction, Low Influence -- The Lack Thereof",". Here you have no control and no idea what is going to happen. This might be some form of transcendent peace, an acceptance and simplistic state of being. It could also be that you are a pet rock with googly eyes. This is pretty much the opposite of having a lot of Agency.",[11,1155,1156,1157,1162,1163,1166,1167,1170],{},"Finally, in the upper-right, we find ",[20,1158,1159],{},[993,1160,1161],{},"High Prediction, High Influence -- Agency",". This is a meaningful and useful idea of Agency. You both have the ability to influence the world ",[993,1164,1165],{},"AND"," a good idea of the outcomes from that influence. Here is where you can ",[993,1168,1169],{},"\"Call your shots\"",", performing some action and having a good idea about the result.",[11,1172,1173,1174,797],{},"From this basic framework, which we can probe in various ways to build more intuitions, we can derive a lot of interesting questions and conclusions. Chief among them -- if Agency is built on two variable ingredients, and we can change these variables, then ",[20,1175,1176],{},[993,1177,1178],{},"we can change our degree of Agency",[11,1180,1181],{},"I will leave you with that thought :)",{"title":156,"searchDepth":157,"depth":157,"links":1183},[1184,1188],{"id":1013,"depth":157,"text":1014,"children":1185},[1186,1187],{"id":1036,"depth":637,"text":1037},{"id":1007,"depth":637,"text":1058},{"id":1078,"depth":157,"text":1079},"2025-03-14","Agency (a more useful concept of Free Will), has two important ingredients -- the ability to predict outcomes and the ability to influence outcomes -- both of which come in a spectrum of possible degrees. We can lay these out into a visualization that breaks down naturally into a four-square grid.",{},"\u002Ftlt-2025.03.14-the-four-squares-of-agency",{"title":987,"description":1190},"TLT - 2025.03.14 - The Four Squares of Agency",[169,1196],"agency","EmuOmW6RUGNOGHt0aa5HShh1dh9JP3Uo6SBNnRbLHFM",{"id":1199,"title":1200,"body":1201,"createdAt":1344,"description":1345,"draft":160,"extension":161,"image":1223,"mastodonThread":162,"meta":1346,"navigation":164,"path":1347,"seo":1348,"stem":1349,"tags":1350,"updatedAt":1344,"__hash__":1352},"content\u002FTLT - 2025.03.04 - Nerd Snipe - Task time tracking.md","Nerd Snipe - Task time tracking",{"type":8,"value":1202,"toc":1339},[1203,1218,1224,1231,1235,1238,1260,1264,1283,1291,1295,1314,1319,1325],[11,1204,1205,1206,1211,1212,1217],{},"Since I'm going some consulting work I have to do a bit of time tracking. And you know what that means! Playing with my ",[136,1207,1210],{"href":1208,"rel":1209},"https:\u002F\u002Ftaskwarrior.org\u002F",[140],"taskwarrior"," and ",[136,1213,1216],{"href":1214,"rel":1215},"https:\u002F\u002Ftimewarrior.net\u002F",[140],"timewarrior"," config!!!",[11,1219,1220],{},[587,1221],{"alt":1222,"src":1223},"stopwatch oil painting","img\u002Fstopwatch_oil_painting.png",[11,1225,1226],{},[1027,1227,1228],{},[1030,1229,1230],{},"openai: Generate an image of a stopwatch in the style of an impressionist oil painting with thick bold brush strokes",[266,1232,1234],{"id":1233},"what-would-you-say-you-do-here","What would you say you do here?",[11,1236,1237],{},"It's pretty easy for me to focus on something but it takes effort to make sure that I'm focused on the right thing, don't forget stuff, and keep track of what it is that I did. I have been using taskwarrior for quite a while, I even have it integrated in with my gmail-starred emails which is handy.",[11,1239,1240,1241,1243,1244,1247,1248,1251,1252,1255,1256,1259],{},"But I also need to keep track of billable hours. There is a separate but corresponding ",[194,1242,1216],{}," project for this, and a hook that ties them together. So once configured, if you do ",[194,1245,1246],{},"task 123 start"," it will start the clock for task 123, and if you do either ",[194,1249,1250],{},"task 123 stop"," or ",[194,1253,1254],{},"task 123 done"," then it will stop the clock. You can use ",[194,1257,1258],{},"timew"," reports to see the total time.",[266,1261,1263],{"id":1262},"start-the-clock-immediately","Start the clock immediately",[11,1265,1266,1267,1272,1273,1278,1279,1282],{},"Sometimes, often, I want to note a task and immediately begin working on it. I modified the ",[136,1268,1271],{"href":1269,"rel":1270},"https:\u002F\u002Fgithub.com\u002FGothenburgBitFactory\u002Ftimewarrior\u002Fblob\u002Fdevelop\u002Fext\u002Fon-modify.timewarrior",[140],"on-modify.timewarrior"," to be a ",[136,1274,1277],{"href":1275,"rel":1276},"https:\u002F\u002Fgist.github.com\u002Fawwaiid\u002F6963af7895005f7fa839b1663ec48a7e",[140],"on-add.timewarrior"," and then add this alias into ",[194,1280,1281],{},".taskrc",":",[605,1284,1289],{"className":1285,"code":1287,"language":1288},[1286],"language-text","alias.doing = add start:now\n","text",[194,1290,1287],{"__ignoreMap":156},[266,1292,1294],{"id":1293},"only-one-clock-stop-it","Only One Clock. Stop \"it\".",[11,1296,1297,1298,1300,1301,1303,1304,1307,1308,1310,1311,1313],{},"While there might be fancier ways to use ",[194,1299,1216],{},", how I'm using it basically assumes there is only one task happening at a time. If you ",[194,1302,1250],{}," then it stops the clock. If you ",[194,1305,1306],{},"task 456 start"," then it stops the old one (in ",[194,1309,1216],{},", not in ",[194,1312,1210],{},") and starts the new one. Fine. But let's make a handy shorthand for stopping\u002Ffinishing the \"current\" task.",[11,1315,1316,1317,1282],{},"Altogether, I now have this in my ",[194,1318,1281],{},[605,1320,1323],{"className":1321,"code":1322,"language":1288},[1286],"# These use on-add.timewarrior and on-modify.timewarrior hooks\n\n# Shortcuts to both add and start\nalias.doing = add start:now\n\n# Shortcuts to stop or complete the currently started\nalias.stopit = start.not: stop\nalias.doneit = start.not: done\n",[194,1324,1322],{"__ignoreMap":156},[11,1326,1327,1328,1331,1332,1251,1335,1338],{},"Now I can ",[194,1329,1330],{},"task doing \"working on something\""," and then either ",[194,1333,1334],{},"task stopit",[194,1336,1337],{},"task doneit","!",{"title":156,"searchDepth":157,"depth":157,"links":1340},[1341,1342,1343],{"id":1233,"depth":157,"text":1234},{"id":1262,"depth":157,"text":1263},{"id":1293,"depth":157,"text":1294},"2025-03-04","Since I'm going some consulting work I have to do a bit of time tracking. And you know what that means! Playing with my taskwarrior and timewarrior config!!!",{},"\u002Ftlt-2025.03.04-nerd-snipe-task-time-tracking",{"title":1200,"description":1345},"TLT - 2025.03.04 - Nerd Snipe - Task time tracking",[169,1351],"nerdsnipe","hmFK8s6YHsLTQDuPoN0JtCMYKKb7rtjlodWByDnNgBg",{"id":1354,"title":1355,"body":1356,"createdAt":1524,"description":1360,"draft":160,"extension":161,"image":1366,"mastodonThread":1525,"meta":1526,"navigation":164,"path":1527,"seo":1528,"stem":1529,"tags":1530,"updatedAt":1524,"__hash__":1532},"content\u002FTLT - 2025.01.31 - Link Roundup (LLM-AI).md","Link Roundup (LLM\u002FAI)",{"type":8,"value":1357,"toc":1522},[1358,1361,1367,1519],[11,1359,1360],{},"My friend Brad asked about what I've been reading lately in the AI\u002FLLM space to keep up. Here's my link roundup! Things that have been on my rotation lately.",[11,1362,1363],{},[587,1364],{"alt":1365,"src":1366},"LLM Newspaper Dog Cartoon","img\u002FLLM_Newspaper_Dog_Cartoon.png",[205,1368,1369,1379,1389,1402,1412,1422,1437,1453,1479,1493,1503],{},[208,1370,1371,1378],{},[993,1372,1373],{},[136,1374,1377],{"href":1375,"rel":1376},"https:\u002F\u002Fwww.amazon.com\u002Fdp\u002F1098166302",[140],"AI Engineering: Building Applications with Foundation Models",": Great January-2025 catch up on consuming LLM\u002FAI usage in real world applications; enough background to Get It without being distracted by details",[208,1380,1381,1388],{},[993,1382,1383],{},[136,1384,1387],{"href":1385,"rel":1386},"https:\u002F\u002Fsimonwillison.net\u002F",[140],"Simon Willison Website",": Follow for great links and chasing the dragon of new releases and thoughts",[208,1390,1391,1398,1399],{},[993,1392,1393],{},[136,1394,1397],{"href":1395,"rel":1396},"https:\u002F\u002Fllm.datasette.io\u002F",[140],"LLM CLI (Datasette)",": From Simon Willison, a very handy CLI tool for interfacing with LLMs. Once set up, I use this as a unixy native tool. Like ... ",[194,1400,1401],{},"cat some_file.txt | llm -s 'Turn this into a CSV of street, city, state, zip' > data.csv",[208,1403,1404,1411],{},[993,1405,1406],{},[136,1407,1410],{"href":1408,"rel":1409},"https:\u002F\u002Fwww.reddit.com\u002Fr\u002FLocalLLaMA\u002F",[140],"\u002Fr\u002FLocalLLaMA",": Reddit community all about running local LLMs; even if you only ever run things on other people's computer (API) it is interesting to know what might be happening on the other side",[208,1413,1414,1421],{},[993,1415,1416],{},[136,1417,1420],{"href":1418,"rel":1419},"https:\u002F\u002Fwww.reddit.com\u002Fr\u002FClaudeAI\u002F",[140],"\u002Fr\u002FClaudeAI",": Latest and Greatest with Claude Stuff",[208,1423,1424,1431,1432,449],{},[993,1425,1426],{},[136,1427,1430],{"href":1428,"rel":1429},"https:\u002F\u002Fgroq.com\u002F",[140],"Groq",": Hardware accelerated LLM (also see ",[136,1433,1436],{"href":1434,"rel":1435},"https:\u002F\u002Fcerebras.ai\u002F",[140],"Cerebras",[208,1438,1439,1446,1447,1452],{},[993,1440,1441],{},[136,1442,1445],{"href":1443,"rel":1444},"https:\u002F\u002Faider.chat\u002F",[140],"Aider",": Open source CLI coding assistant. They've been building up an ",[136,1448,1451],{"href":1449,"rel":1450},"https:\u002F\u002Faider.chat\u002Fdocs\u002Fleaderboards\u002F",[140],"Aider LLM Leaderboard"," which is interesting, especially the highlighted polyglot board (one model for architecture plan, another for low-level coding)",[208,1454,1455,1462,1463,1468,1469,1472,1473,1478],{},[993,1456,1457],{},[136,1458,1461],{"href":1459,"rel":1460},"https:\u002F\u002Fsourcegraph.com\u002Fcody",[140],"Sourcegraph Cody",": There are several VSCode-embedded code assistants in this space, Cody is one to keep an eye on. Recently ",[136,1464,1467],{"href":1465,"rel":1466},"https:\u002F\u002Fcode.visualstudio.com\u002Fdocs\u002Fcopilot\u002Fcopilot-edits",[140],"Copilot Edits"," has stepped up to a similar cross-file assistant too. There are a bunch of others; I'm not really psyched about switching from vim to vscode, and I ",[20,1470,1471],{},"certainly"," don't want to switch to a proprietary editor, so I haven't spent much time with things like ",[136,1474,1477],{"href":1475,"rel":1476},"https:\u002F\u002Fwww.cursor.com\u002F",[140],"Cursor"," (yet)",[208,1480,1481,1488,1489,1492],{},[993,1482,1483],{},[136,1484,1487],{"href":1485,"rel":1486},"https:\u002F\u002Fwww.youtube.com\u002F@matthew_berman\u002Fvideos",[140],"Matthew Berman (YouTube)",": He does videos with some demos and commentary that is pretty fun; I may not always agree, but even knowing what the latest ",[20,1490,1491],{},"topics"," are is very helpful!",[208,1494,1495,1502],{},[993,1496,1497],{},[136,1498,1501],{"href":1499,"rel":1500},"https:\u002F\u002Fchangelog.com\u002Fpracticalai",[140],"Practical AI Podcast",": I listen to podcasts when I commute or go for longer drives, which isn't often but often enough that I've listened to some good episodes both here and on other ChangeLogs.",[208,1504,1505,1512,1513,1518],{},[993,1506,1507],{},[136,1508,1511],{"href":1509,"rel":1510},"https:\u002F\u002Fwww.latent.space\u002Fpodcast",[140],"Latent Space: The AI Engineer Podcast",": I've only listened to a few of these, but it is on top of my feed list in ",[136,1514,1517],{"href":1515,"rel":1516},"https:\u002F\u002Fantennapod.org\u002F",[140],"AntennaPod"," currently",[11,1520,1521],{},"... I think that'll do for now!",{"title":156,"searchDepth":157,"depth":157,"links":1523},[],"2025-01-31","https:\u002F\u002Fmastodon.social\u002F@awwaiid\u002F113928577927928238",{},"\u002Ftlt-2025.01.31-link-roundup-(llm-ai)",{"title":1355,"description":1360},"TLT - 2025.01.31 - Link Roundup (LLM-AI)",[169,1531],"share","-xVWZ-BRMop2ee0RMuWeZXqIXg2FZdpv3gwiZUaOW-s",{"id":1534,"title":1535,"body":1536,"createdAt":1524,"description":1540,"draft":160,"extension":161,"image":1559,"mastodonThread":162,"meta":1851,"navigation":164,"path":1852,"seo":1853,"stem":1854,"tags":1855,"updatedAt":1524,"__hash__":1856},"content\u002FTLT - 2025.01.31 - VisiData XDG.md","VisiData XDG",{"type":8,"value":1537,"toc":1847},[1538,1541,1545,1554,1560,1575,1582,1586,1589,1595,1604,1617,1654,1657,1841,1844],[11,1539,1540],{},"Figured out how to make opening a CSV in firefox pop open a terminal running VisiData (vd)",[266,1542,1544],{"id":1543},"visidata","VisiData!",[11,1546,1547,1548,1553],{},"I like ",[136,1549,1552],{"href":1550,"rel":1551},"https:\u002F\u002Fwww.visidata.org\u002F",[140],"VisiData","! If you are working with tabular data, like a CSV file, it is a lovely slicer and dicer. It's a pretty terminal-keyboard-heavy program, like a vim family thing. Like many of these power tools, I find that you can get into it best by finding ONE use-case and then gradually introducing new tricks from there. So the simple use-case for VisiData is simply viewing CSV files.",[11,1555,1556],{},[587,1557],{"alt":1558,"src":1559},"VisiData a simple CSV","img\u002FVisiData_a_simple_CSV.png",[11,1561,1562,1563,1566,1567,1570,1571,1574],{},"After that you can learn some new commands, such as selecting rows with ",[194,1564,1565],{},"|gilbert"," (regex select rows containing \"gilbert\") and then zooming in on them with ",[194,1568,1569],{},"\""," (view only selected rows). You can press ",[194,1572,1573],{},"\u003Center>"," on a row to see it vertically.",[11,1576,1577,1578,1581],{},"After a while you get addicted to this sort of manipulation and you find yourself downloading CSVs from Firefox and then opening a terminal, navigating over to your downloads folder, and opening it with ",[194,1579,1580],{},"vd data.csv"," or whatnot. So I wanted to cut out the middle bits.",[266,1583,1585],{"id":1584},"xdg-terminal-wrapping","XDG, Terminal Wrapping",[11,1587,1588],{},"First make a .desktop file for visidata at ~\u002F.local\u002Fshare\u002Fapplications\u002FVisiData.desktop containing:",[605,1590,1593],{"className":1591,"code":1592,"language":1288},[1286],"[Desktop Entry]\nEncoding=UTF-8\nVersion=1.0\nType=Application\nTerminal=true\nExec=vd %U\nMimeType=application\u002Fvnd.oasis.opendocument.spreadsheet;application\u002Fvnd.oasis.opendocument.spreadsheet-template;application\u002Fvnd.sun.xml.calc;application\u002Fvnd.sun.xml.calc.template;application\u002Fmsexcel;application\u002Fvnd.ms-excel;application\u002Fvnd.openxmlformats-officedocument.spreadsheetml.sheet;application\u002Fvnd.ms-excel.sheet.macroEnabled.12;application\u002Fvnd.openxmlformats-officedocument.spreadsheetml.template;application\u002Fvnd.ms-excel.template.macroEnabled.12;application\u002Fvnd.ms-excel.sheet.binary.macroEnabled.12;text\u002Fcsv;application\u002Fx-dbf;text\u002Fspreadsheet;application\u002Fcsv;application\u002Fexcel;application\u002Ftab-separated-values;application\u002Fvnd.lotus-1-2-3;application\u002Fvnd.oasis.opendocument.chart;application\u002Fvnd.oasis.opendocument.chart-template;application\u002Fx-dbase;application\u002Fx-dos_ms_excel;application\u002Fx-excel;application\u002Fx-msexcel;application\u002Fx-ms-excel;application\u002Fx-quattropro;application\u002Fx-123;text\u002Fcomma-separated-values;text\u002Ftab-separated-values;text\u002Fx-comma-separated-values;text\u002Fx-csv;application\u002Fvnd.oasis.opendocument.spreadsheet-flat-xml;application\u002Fvnd.ms-works;application\u002Fclarisworks;application\u002Fx-iwork-numbers-sffnumbers;application\u002Fx-starcalc;\nName=VisiData\n",[194,1594,1592],{"__ignoreMap":156},[11,1596,1597,1598,1603],{},"which I got from ",[136,1599,1602],{"href":1600,"rel":1601},"https:\u002F\u002Fdev.to\u002Fajkerrigan\u002Ftoday-i-learned-opening-csvs-with-visidata-in-tmux-from-the-firefox-flatpak-app-4m07",[140],"this fun page"," with some slight modification.",[11,1605,1606,1607,1612,1613,1616],{},"This worked! But it opens in gnome-terminal instead of alacritty. After some digging I found from ",[136,1608,1611],{"href":1609,"rel":1610},"https:\u002F\u002Fgitlab.gnome.org\u002FGNOME\u002Fglib\u002F-\u002Fmerge_requests\u002F2839",[140],"this merge request"," that you can put a wrapper named ",[194,1614,1615],{},"xdg-terminal-exec"," in your path and it'll use that as the priority terminal app. So I created ~\u002Fbin\u002Fxdg-terminal-exec containing:",[605,1618,1622],{"className":1619,"code":1620,"language":1621,"meta":156,"style":156},"language-sh shiki shiki-themes github-light github-dark monokai","#!\u002Fbin\u002Fsh\n\nexec ~\u002Fbin\u002Fterminal -e \"$@\"\n","sh",[194,1623,1624,1630,1634],{"__ignoreMap":156},[39,1625,1626],{"class":614,"line":615},[39,1627,1629],{"class":1628},"s8-w5","#!\u002Fbin\u002Fsh\n",[39,1631,1632],{"class":614,"line":157},[39,1633,634],{"emptyLinePlaceholder":164},[39,1635,1636,1638,1641,1644,1647,1651],{"class":614,"line":637},[39,1637,735],{"class":694},[39,1639,1640],{"class":649}," ~\u002Fbin\u002Fterminal",[39,1642,1643],{"class":664}," -e",[39,1645,1646],{"class":649}," \"",[39,1648,1650],{"class":1649},"sdpu8","$@",[39,1652,1653],{"class":649},"\"\n",[11,1655,1656],{},"And that in turn calls my per-machine terminal script, which contains roughly:",[605,1658,1660],{"className":1619,"code":1659,"language":1621,"meta":156,"style":156},"#!\u002Fbin\u002Fsh\n\nif [ \"$HOSTNAME\" == \"arcanejill.thelackthereof.org\" ]; then\n  exec aterm -rv -tr -sl 10000 -sh 50 -ls +sb -vb -fn 6x12 -e \"$@\"\nelif [ \"$HOSTNAME\" == \"feline.thelackthereof.org\" ]; then\n  exec aterm -tr -sl 10000 -sh 50 -ls +sb -vb -fn '-b&h-lucidatypewriter-bold-r-normal-*-13-*-*-*-m-*-iso10646-1' -e \"$@\"\n\n# ... and so on for various machines I've had that I wanted different settings on\n\nelse\n  exec ~\u002F.cargo\u002Fbin\u002Falacritty \"$@\"\nfi\n",[194,1661,1662,1666,1670,1697,1746,1768,1803,1807,1812,1816,1821,1835],{"__ignoreMap":156},[39,1663,1664],{"class":614,"line":615},[39,1665,1629],{"class":1628},[39,1667,1668],{"class":614,"line":157},[39,1669,634],{"emptyLinePlaceholder":164},[39,1671,1672,1675,1678,1680,1683,1685,1688,1691,1694],{"class":614,"line":637},[39,1673,1674],{"class":618},"if",[39,1676,1677],{"class":622}," [ ",[39,1679,1569],{"class":649},[39,1681,1682],{"class":622},"$HOSTNAME",[39,1684,1569],{"class":649},[39,1686,1687],{"class":618}," ==",[39,1689,1690],{"class":649}," \"arcanejill.thelackthereof.org\"",[39,1692,1693],{"class":622}," ]; ",[39,1695,1696],{"class":618},"then\n",[39,1698,1699,1702,1705,1708,1711,1714,1717,1720,1723,1726,1729,1732,1735,1738,1740,1742,1744],{"class":614,"line":656},[39,1700,1701],{"class":694},"  exec",[39,1703,1704],{"class":649}," aterm",[39,1706,1707],{"class":664}," -rv",[39,1709,1710],{"class":664}," -tr",[39,1712,1713],{"class":664}," -sl",[39,1715,1716],{"class":664}," 10000",[39,1718,1719],{"class":664}," -sh",[39,1721,1722],{"class":664}," 50",[39,1724,1725],{"class":664}," -ls",[39,1727,1728],{"class":649}," +sb",[39,1730,1731],{"class":664}," -vb",[39,1733,1734],{"class":664}," -fn",[39,1736,1737],{"class":649}," 6x12",[39,1739,1643],{"class":664},[39,1741,1646],{"class":649},[39,1743,1650],{"class":1649},[39,1745,1653],{"class":649},[39,1747,1748,1751,1753,1755,1757,1759,1761,1764,1766],{"class":614,"line":668},[39,1749,1750],{"class":618},"elif",[39,1752,1677],{"class":622},[39,1754,1569],{"class":649},[39,1756,1682],{"class":622},[39,1758,1569],{"class":649},[39,1760,1687],{"class":618},[39,1762,1763],{"class":649}," \"feline.thelackthereof.org\"",[39,1765,1693],{"class":622},[39,1767,1696],{"class":618},[39,1769,1770,1772,1774,1776,1778,1780,1782,1784,1786,1788,1790,1792,1795,1797,1799,1801],{"class":614,"line":674},[39,1771,1701],{"class":694},[39,1773,1704],{"class":649},[39,1775,1710],{"class":664},[39,1777,1713],{"class":664},[39,1779,1716],{"class":664},[39,1781,1719],{"class":664},[39,1783,1722],{"class":664},[39,1785,1725],{"class":664},[39,1787,1728],{"class":649},[39,1789,1731],{"class":664},[39,1791,1734],{"class":664},[39,1793,1794],{"class":649}," '-b&h-lucidatypewriter-bold-r-normal-*-13-*-*-*-m-*-iso10646-1'",[39,1796,1643],{"class":664},[39,1798,1646],{"class":649},[39,1800,1650],{"class":1649},[39,1802,1653],{"class":649},[39,1804,1805],{"class":614,"line":685},[39,1806,634],{"emptyLinePlaceholder":164},[39,1808,1809],{"class":614,"line":691},[39,1810,1811],{"class":1628},"# ... and so on for various machines I've had that I wanted different settings on\n",[39,1813,1814],{"class":614,"line":701},[39,1815,634],{"emptyLinePlaceholder":164},[39,1817,1818],{"class":614,"line":709},[39,1819,1820],{"class":618},"else\n",[39,1822,1824,1826,1829,1831,1833],{"class":614,"line":1823},11,[39,1825,1701],{"class":694},[39,1827,1828],{"class":649}," ~\u002F.cargo\u002Fbin\u002Falacritty",[39,1830,1646],{"class":649},[39,1832,1650],{"class":1649},[39,1834,1653],{"class":649},[39,1836,1838],{"class":614,"line":1837},12,[39,1839,1840],{"class":618},"fi\n",[11,1842,1843],{},"... and now when I click on the CSV from my downloads dropdown in firefox POP goes a terminal running VisiData!",[738,1845,1846],{},"html pre.shiki code .s8-w5, html code.shiki .s8-w5{--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-sepia:#88846F}html pre.shiki code .sTrkL, html code.shiki .sTrkL{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#66D9EF}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sdpu8, html code.shiki .sdpu8{--shiki-default:#005CC5;--shiki-default-font-style:inherit;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit;--shiki-sepia:#FD971F;--shiki-sepia-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}",{"title":156,"searchDepth":157,"depth":157,"links":1848},[1849,1850],{"id":1543,"depth":157,"text":1544},{"id":1584,"depth":157,"text":1585},{},"\u002Ftlt-2025.01.31-visidata-xdg",{"title":1535,"description":1540},"TLT - 2025.01.31 - VisiData XDG",[169],"63mA3PbiXGsXyIvI_bMy5hssF82WTQlHj5CR3towEZ0",{"id":1858,"title":1859,"body":1860,"createdAt":2008,"description":1864,"draft":160,"extension":161,"image":1997,"mastodonThread":162,"meta":2009,"navigation":164,"path":2010,"seo":2011,"stem":2012,"tags":2013,"updatedAt":2008,"__hash__":2014},"content\u002FTLT - 2025.01.19 - Nerd Snipes.md","Nerd Snipes",{"type":8,"value":1861,"toc":2004},[1862,1865,1868,1871,1875,1892,1926,1933,1937,1954,1968,1983,1989,1992,1998,2001],[11,1863,1864],{},"What distracted me today? Flameshot and Rofi.",[11,1866,1867],{},"--",[11,1869,1870],{},"It's a weekend, and on the weekends I am retired. And it has long been my declaration that someday when I retire I will spend all day every day messing with dumb config files. SO!",[266,1872,1874],{"id":1873},"screenshot-to-keyboard","Screenshot to Keyboard",[11,1876,1877,1878,1883,1884,1887,1888,1891],{},"I have been using ",[136,1879,1882],{"href":1880,"rel":1881},"https:\u002F\u002Fflameshot.org\u002F",[140],"Flameshot"," for a while now, and it is great! But ... something something Wayland something something and in the end it doesn't copy the image to my clipboard. I have rotated through a few screenshot managers, so my ",[194,1885,1886],{},"win+s"," keybinding actually runs ",[194,1889,1890],{},"~\u002Fbin\u002Fscreenshot",". Today, I modified it to contain:",[605,1893,1895],{"className":1619,"code":1894,"language":1621,"meta":156,"style":156},"QT_QPA_PLATFORM=wayland flameshot gui --raw | wl-copy -f\n",[194,1896,1897],{"__ignoreMap":156},[39,1898,1899,1902,1904,1907,1911,1914,1917,1920,1923],{"class":614,"line":615},[39,1900,1901],{"class":622},"QT_QPA_PLATFORM",[39,1903,643],{"class":618},[39,1905,1906],{"class":649},"wayland",[39,1908,1910],{"class":1909},"srTi1"," flameshot",[39,1912,1913],{"class":649}," gui",[39,1915,1916],{"class":664}," --raw",[39,1918,1919],{"class":618}," |",[39,1921,1922],{"class":1909}," wl-copy",[39,1924,1925],{"class":664}," -f\n",[11,1927,1928,1929,1932],{},"And now I can take a screenshot and paste it wherever I want. I also have Flameshot configured to save ",[20,1930,1931],{},"all"," of my screenshots to a directory. Someday I can ask some vision-LLM questions about these files :)",[266,1934,1936],{"id":1935},"faster-and-prettier-runner","Faster and Prettier Runner",[11,1938,1939,1940,1945,1946,1949,1950,1953],{},"I've been using ",[136,1941,1944],{"href":1942,"rel":1943},"https:\u002F\u002Fgithub.com\u002Fdavatorium\u002Frofi",[140],"Rofi"," as my run-dialog for a while. It is kinda slow to start though ... like a lag between when I press ",[194,1947,1948],{},"win+shift+p"," and actually get the dialog. Looking at it ... I had previous set up the wrapper script to run zsh in interactive mode. Why? Because for some reason ",[194,1951,1952],{},"$PATH"," wasn't getting set I think. But interactive-mode takes a sec to run. hmm.",[11,1955,1956,1957,1959,1960,1963,1964,1967],{},"I thrashed all about trying to fix the ",[194,1958,1952],{},". Rando ",[194,1961,1962],{},"systemctrl"," things, editing ",[194,1965,1966],{},"~\u002F.config\u002Fenvironment.d\u002F10-path.conf",", all sorts of things. No dice.",[11,1969,1970,1971,1976,1977,1979,1980,1982],{},"Then I spent some time switching over to ",[136,1972,1975],{"href":1973,"rel":1974},"https:\u002F\u002Fcodeberg.org\u002Fdnkl\u002Ffuzzel",[140],"fuzzel"," which seems fast and cool. But ... same problems sorta. It was wanting to run .desktop entries instead of ",[194,1978,1952],{}," entries, though you could get it to run ",[194,1981,1952],{}," commands ... but then it didn't add them into the memory list ... etc.",[11,1984,1985,1986,1988],{},"Finally I realized I could go back to Rofi and since I have this wrapper script just throw my ",[194,1987,1952],{}," export in there! UGLY!!! But it works.",[11,1990,1991],{},"Then I spent a while updating the theme for Rofi to take some inspiration from what I saw over in Fuzzel. Now it looks like this:",[11,1993,1994],{},[587,1995],{"alt":1996,"src":1997},"rofi theme","img\u002Frofi_theme.png",[11,1999,2000],{},"Pretty snazzy!!!",[738,2002,2003],{},"html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":156,"searchDepth":157,"depth":157,"links":2005},[2006,2007],{"id":1873,"depth":157,"text":1874},{"id":1935,"depth":157,"text":1936},"2025-01-19",{},"\u002Ftlt-2025.01.19-nerd-snipes",{"title":1859,"description":1864},"TLT - 2025.01.19 - Nerd Snipes",[169],"0n8JDwISa1ppezs4RQA7OLrNTQMj3lsK5c783g_idJc",{"id":2016,"title":2017,"body":2018,"createdAt":2113,"description":2022,"draft":160,"extension":161,"image":2039,"mastodonThread":162,"meta":2114,"navigation":164,"path":2115,"seo":2116,"stem":2117,"tags":2118,"updatedAt":2113,"__hash__":2119},"content\u002FTLT - 2025.01.11 - Little Dashes of LLMs.md","Little Dashes of LLMs",{"type":8,"value":2019,"toc":2111},[2020,2023,2025,2034,2040,2043,2057,2078,2095,2101,2108],[11,2021,2022],{},"A small data transform \u002F cleanup task using LLM labor.",[15,2024],{},[11,2026,2027,2028,2033],{},"My mom is now running a small business, ",[136,2029,2032],{"href":2030,"rel":2031},"https:\u002F\u002F129aztss.com\u002F",[140],"$129 Arizona Discount Traffic Survival School",", and I'm tinkering away at a website for her. The other day she gives me a google doc with venue addresses, asking if I can put it up on the site.",[11,2035,2036],{},[587,2037],{"alt":2038,"src":2039},"addresses in a google doc","img\u002Faddresses_in_a_google_doc.png",[11,2041,2042],{},"While the doc was pretty consistent, it'd be even better as a nice little spreadsheet. In fact, if it is a Google Sheet then you can HTTP GET it as a CSV live! Then if she adds a venue to the sheet it will magically show up on her website.",[11,2044,2045,2046,1211,2051,2056],{},"Alas. This is a Doc not a Sheet. But we live in the future! Grabbing my pre-set-up ",[136,2047,2050],{"href":2048,"rel":2049},"https:\u002F\u002Fllm.datasette.io\u002Fen\u002Fstable\u002F",[140],"llm",[136,2052,2055],{"href":2053,"rel":2054},"https:\u002F\u002Fclaude.ai",[140],"claude.ai",", I simpy do this:",[605,2058,2060],{"className":1619,"code":2059,"language":1621,"meta":156,"style":156},"cat | llm -s 'turn this into a tsv with location, venue name, address, notes'\n",[194,2061,2062],{"__ignoreMap":156},[39,2063,2064,2067,2069,2072,2075],{"class":614,"line":615},[39,2065,2066],{"class":1909},"cat",[39,2068,1919],{"class":618},[39,2070,2071],{"class":1909}," llm",[39,2073,2074],{"class":664}," -s",[39,2076,2077],{"class":649}," 'turn this into a tsv with location, venue name, address, notes'\n",[11,2079,2080,2081,2084,2085,2088,2089,2091,2092,2094],{},"Then I ",[20,2082,2083],{},"copy"," from the docs and ",[20,2086,2087],{},"paste"," into my terminal, and out pops a tab-separated list! ",[20,2090,2083],{}," from my terminal and ",[20,2093,2087],{}," into a Google Sheet and PRESTO!",[11,2096,2097],{},[587,2098],{"alt":2099,"src":2100},"venue list in spreadsheet","img\u002Fvenue_list_in_spreadsheet.png",[11,2102,2103,2104,2107],{},"Yes -- I could have piped it into ",[194,2105,2106],{},"wl-copy"," instead of using my mouse to copy like a caveman. One can only go so far!",[738,2109,2110],{},"html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":156,"searchDepth":157,"depth":157,"links":2112},[],"2025-01-11",{},"\u002Ftlt-2025.01.11-little-dashes-of-llms",{"title":2017,"description":2022},"TLT - 2025.01.11 - Little Dashes of LLMs",[169],"uE0N0_kTmSySu7rBoxIhYf3Cxk0GRovUg2UupVDQdkI",{"id":2121,"title":2122,"body":2123,"createdAt":2246,"description":2247,"draft":160,"extension":161,"image":2151,"mastodonThread":162,"meta":2248,"navigation":164,"path":2249,"seo":2250,"stem":2251,"tags":2252,"updatedAt":2246,"__hash__":2254},"content\u002FTLT - 2024.12.12 - Little Boxes For Your Ghost.md","Little Boxes For Your Ghost",{"type":8,"value":2124,"toc":2242},[2125,2131,2135,2146,2152,2159,2170,2174,2193,2212,2218,2221,2227,2230,2233,2239],[11,2126,2127,2128,2130],{},"Drawing Xes in Boxes is harder than you might think! Teaching ",[136,2129,182],{"href":181}," a bit about space by pre-segmenting the input image gets us closer.",[266,2132,2134],{"id":2133},"the-problem","The Problem",[11,2136,2137,2138,2142,2143,2145],{},"You may recall from ",[136,2139,2141],{"href":2140},"\u002Ftlt-2024.11.23-a-ghostly-game","TLT - 2024.11.23 - A Ghostly Game"," that ",[136,2144,182],{"href":181}," is ... not good with spatial awareness. For example, we can ask it to draw an X in a box and see how close it gets...",[11,2147,2148],{},[587,2149],{"alt":2150,"src":2151},"Ghostwriter X not in box","img\u002FGhostwriter_X_not_in_box.png",[11,2153,2154,2155,2158],{},"Not great. That is even ",[20,2156,2157],{},"after"," we tried the \"plz think harder\" approach, asking the LLM to write out where it thinks things are with bounding boxes and planning where things should go and all that. It still can't hit the box that it can see.",[11,2160,2161,2162,2165,2166,2169],{},"It can ",[20,2163,2164],{},"read handwriting",", it ",[20,2167,2168],{},"knows there is a box more or less in the middle",". So close!",[266,2171,2173],{"id":2172},"step-outside-the-box","Step Outside The Box",[188,2175,2176],{},[11,2177,2178,2181,2182,2184,2187,2188,2190],{},[993,2179,2180],{},"Vivian Jaffe:"," Have you ever transcended space and time?",[461,2183],{},[993,2185,2186],{},"Albert Markovski:"," No. Yes. Uh, time not space. No. I have no idea what you're talking about.",[461,2189],{},[20,2191,2192],{},"(I Heart Huckabees, 2004)",[11,2194,2195,2196,2200,2201,1211,2206,2211],{},"So with a little help from my friend ",[136,2197,2199],{"href":1459,"rel":2198},[140],"Cody"," I whipped up a relatively dumb segmenter. It uses ",[136,2202,2205],{"href":2203,"rel":2204},"https:\u002F\u002Fdocs.rs\u002Fimage\u002Flatest\u002Fimage\u002F",[140],"image",[136,2207,2210],{"href":2208,"rel":2209},"https:\u002F\u002Fdocs.rs\u002Fimageproc\u002Flatest\u002Fimageproc\u002F",[140],"imageproc"," to find contours, snaps boxes around them, and then looks for the big ones. So in the case of our box, here is a bit of extra that we put into the prompt:",[605,2213,2216],{"className":2214,"code":2215,"language":1288},[1286],"Here are interesting regions based on an automatic segmentation algorithm. Use\nthem to help identify the exact location of interesting features.\n\nRegion: x=400, y=572, width=640, height=613\nRegion: x=31, y=32, width=41, height=41\nRegion: x=811, y=96, width=133, height=127\nRegion: x=279, y=162, width=83, height=29\nRegion: x=178, y=128, width=69, height=86\nRegion: x=1014, y=138, width=43, height=47\nRegion: x=36, y=37, width=31, height=31\nRegion: x=979, y=96, width=42, height=85\nRegion: x=549, y=118, width=56, height=76\nRegion: x=439, y=149, width=53, height=56\n",[194,2217,2215],{"__ignoreMap":156},[11,2219,2220],{},"And now it gets much closer!",[11,2222,2223],{},[587,2224],{"alt":2225,"src":2226},"Ghostwriter X more in box","img\u002FGhostwriter_X_more_in_box.png",[11,2228,2229],{},"This is a pretty coarse-grained way to give a sense of space, but it is working much better with this segmentation hint. There are a few other things that might work as well -- we could give it an image of what each of the segments has inside of it, we could merge segments with some center-of-gravity sort of thing. Etc.",[11,2231,2232],{},"Let's try more boxes!",[11,2234,2235],{},[587,2236],{"alt":2237,"src":2238},"Ghostwriter x in boxes not great","img\u002FGhostwriter_x_in_boxes_not_great.png",[11,2240,2241],{},"Whelp... still more work to do! :)",{"title":156,"searchDepth":157,"depth":157,"links":2243},[2244,2245],{"id":2133,"depth":157,"text":2134},{"id":2172,"depth":157,"text":2173},"2024-12-12","Drawing Xes in Boxes is harder than you might think! Teaching Ghostwriter a bit about space by pre-segmenting the input image gets us closer.",{},"\u002Ftlt-2024.12.12-little-boxes-for-your-ghost",{"title":2122,"description":2247},"TLT - 2024.12.12 - Little Boxes For Your Ghost",[169,2253],"ghostwriter","Tj1bLYbdvyOlxJ9NnaKymvJO7kJeJcv8F2lTSinNKGs",{"id":2256,"title":2257,"body":2258,"createdAt":2450,"description":2451,"draft":160,"extension":161,"image":2406,"mastodonThread":162,"meta":2452,"navigation":164,"path":2140,"seo":2453,"stem":2141,"tags":2454,"updatedAt":2450,"__hash__":2455},"content\u002FTLT - 2024.11.23 - A Ghostly Game.md","A Ghostly Game",{"type":8,"value":2259,"toc":2445},[2260,2266,2270,2276,2282,2292,2296,2299,2375,2378,2381,2384,2388,2398,2401,2407,2423,2429,2432,2435,2442],[11,2261,2262,2263,2265],{},"Working on ",[136,2264,182],{"href":181},", making some incremental progress on playing tic-tac-toe.",[266,2267,2269],{"id":2268},"it-was-worse-before","It Was Worse Before",[11,2271,2272,2273,2275],{},"I've been trying to play tic-tac-toe with ",[136,2274,182],{"href":181},", but it is quite bad. Reading the LLM transcript, it sees that we are playing, has a good idea of what it wants to do, but can't aim its output very well at all.",[11,2277,2278],{},[587,2279],{"alt":2280,"src":2281},"Ghostwriter tic tac toe off the board","img\u002FGhostwriter_tic_tac_toe_off_the_board.png",[11,2283,2284,2285,2288,2289,2291],{},"Here you can see that Ghostwriter sees that it is ",[194,2286,2287],{},"O"," and does indeed draw an ",[194,2290,2287],{}," ... but kinda off the board. This is actually one of the better attempts. I even switched from OpenAI to Anthropic Claude to see if it'd get better with limited success. Doing some research, it turns out that generally VLMs (Vision LLMs) aren't great at this sort of thing.",[266,2293,2295],{"id":2294},"whats-your-plan","What's Your Plan?",[11,2297,2298],{},"One thing that definitely has helped is including a request for bounding boxes in the prompt.",[605,2300,2304],{"className":2301,"code":2302,"language":2303,"meta":156,"style":156},"language-json shiki shiki-themes github-light github-dark monokai","  \"input_description\": {\n      \"type\": \"string\",\n      \"description\": \"Description of what was detected in the input image. Include the exact pixel x, y, width, height bounding box coordinates of everything.\"\n  },\n  \"output_description\": {\n      \"type\": \"string\",\n      \"description\": \"Description of what will be drawn. Include the exact pixel x, y, width, height bounding box coordinates of what you want to draw.\"\n  },\n","json",[194,2305,2306,2314,2330,2340,2345,2352,2362,2371],{"__ignoreMap":156},[39,2307,2308,2311],{"class":614,"line":615},[39,2309,2310],{"class":649},"  \"input_description\"",[39,2312,2313],{"class":622},": {\n",[39,2315,2316,2320,2323,2327],{"class":614,"line":157},[39,2317,2319],{"class":2318},"s-m8C","      \"type\"",[39,2321,2322],{"class":622},": ",[39,2324,2326],{"class":2325},"sCZoN","\"string\"",[39,2328,2329],{"class":622},",\n",[39,2331,2332,2335,2337],{"class":614,"line":637},[39,2333,2334],{"class":2318},"      \"description\"",[39,2336,2322],{"class":622},[39,2338,2339],{"class":2325},"\"Description of what was detected in the input image. Include the exact pixel x, y, width, height bounding box coordinates of everything.\"\n",[39,2341,2342],{"class":614,"line":656},[39,2343,2344],{"class":622},"  },\n",[39,2346,2347,2350],{"class":614,"line":668},[39,2348,2349],{"class":649},"  \"output_description\"",[39,2351,2313],{"class":622},[39,2353,2354,2356,2358,2360],{"class":614,"line":674},[39,2355,2319],{"class":2318},[39,2357,2322],{"class":622},[39,2359,2326],{"class":2325},[39,2361,2329],{"class":622},[39,2363,2364,2366,2368],{"class":614,"line":685},[39,2365,2334],{"class":2318},[39,2367,2322],{"class":622},[39,2369,2370],{"class":2325},"\"Description of what will be drawn. Include the exact pixel x, y, width, height bounding box coordinates of what you want to draw.\"\n",[39,2372,2373],{"class":614,"line":691},[39,2374,2344],{"class":622},[11,2376,2377],{},"Even with this instruction it still doesn't include much location information. From my most recent reading I probably need to give it some examples of what I'm looking for.",[11,2379,2380],{},"I'm working on an evaluation framework which might allow fine-tuning the prompts in an incremental way. I'll record the initial screenshot and then run it through a few times to get results. Ultimately I hope to even try using a secondary VLM as a judge and perhaps another as a prompt tuner\u002Fgenerator. Maybe get a little Genetic Algorithm going? hmmm!",[11,2382,2383],{},"So this helped for sure! But everything has still been pretty off.",[266,2385,2387],{"id":2386},"how-big-is-the-screen","How Big Is The Screen?",[11,2389,2390,2391,2393,2394,2397],{},"In fact ... all of the ",[194,2392,2287],{},"s seemed above the board, to the point where I started to re-read docs. What was happening is that the ",[993,2395,2396],{},"Claude API was scaling the image down",", which both contradicted some of the system prompt and made it not know where the board was.",[11,2399,2400],{},"So now I pre-resize to 768x1024 px. Seems a bit small, but the result is already better!",[11,2402,2403],{},[587,2404],{"alt":2405,"src":2406},"ghostwriter tic-tac-toe wrong move","img\u002Fghostwriter_tic-tac-toe_wrong_move.png",[11,2408,2409,2410,2413,2414,2416,2417,2419,2420,2422],{},"Here you can see I started in the upper-left with ",[194,2411,2412],{},"X",". Ghostwriter then went in the middle-right with an ",[194,2415,2287],{},", and I moved in the upper-right with an ",[194,2418,2412],{},". Finally (in red), Ghostwriter moved sort of on the line. What you don't see here, however, is that even the first ",[194,2421,2287],{}," was wrong -- in the JSON transcript it was actually targeting the middle box.",[11,2424,2425,2426],{},"But still -- ",[993,2427,2428],{},"PROGRESS!",[11,2430,2431],{},"I'm going to run some hand validation to make sure the input to the VLM is the right size and that I'm scaling the SVG to the screen correctly. After that I will likely go back to doing some pre-processing, adding in segmentation or something to make it easier for the VLM to locate things on the screen.",[11,2433,2434],{},"Unfortunately if you look at a tic-tac-toe board ... it's kinda awkward. Each of the outside 8 cells are technically open, so it's hard to recognize that they are cells at all. The VLM by itself gets it at a high level, but I'm not sure how well it can break it down. But I'm also not sure what sort of segmentation algorithm would do better.",[11,2436,2437,2438,2441],{},"Under all of that, from what I've seen on the internets these LLMs are not actually all that good at actually playing tic-tac-toe or other 2D spatial games (like Chess) in the first place. But that isn't really the problem so far -- the problem right now is that the VLM ",[20,2439,2440],{},"wants"," to move in the center but can't figure out where the center is.",[738,2443,2444],{},"html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .s-m8C, html code.shiki .s-m8C{--shiki-default:#005CC5;--shiki-default-font-style:inherit;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .sCZoN, html code.shiki .sCZoN{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#CFCFC2}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":156,"searchDepth":157,"depth":157,"links":2446},[2447,2448,2449],{"id":2268,"depth":157,"text":2269},{"id":2294,"depth":157,"text":2295},{"id":2386,"depth":157,"text":2387},"2024-11-23","Working on Ghostwriter, making some incremental progress on playing tic-tac-toe.",{},{"title":2257,"description":2451},[169],"AGghpU_o6OzfjUC-QNc8nqlNAT97rqCRsgZVuAgn09Y",{"id":2457,"title":2458,"body":2459,"createdAt":2549,"description":2463,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":2550,"navigation":164,"path":2551,"seo":2552,"stem":2553,"tags":2554,"updatedAt":2549,"__hash__":2556},"content\u002FTLT - 2024.04.17 - Recurse - W4-6 D3-5.md","Recurse - W4\u002F6 D3\u002F5",{"type":8,"value":2460,"toc":2547},[2461,2464],[11,2462,2463],{},"In-Hub, LLM + Sonic Pi, dash of docker-compose",[205,2465,2466,2503,2534],{},[208,2467,2468,2471],{},[993,2469,2470],{},"General Status:",[205,2472,2473,2476,2479,2486],{},[208,2474,2475],{},"Went into the Hub",[208,2477,2478],{},"Worked in the morning on Human Essentials a bit, but quickly switched to chatting with folks locally",[208,2480,2481,2482,2485],{},"Paired with ",[20,2483,2484],{},"SL"," to set up some docker-compose fun",[208,2487,2481,2488,2491,2492,2496,2497,2502],{},[20,2489,2490],{},"SW"," on trying to mash up ",[136,2493,2495],{"href":2048,"rel":2494},[140],"LLM (datasette)"," with ",[136,2498,2501],{"href":2499,"rel":2500},"https:\u002F\u002Fsonic-pi.net\u002F",[140],"Sonic PI","! We ... didn't get it to work. But SW says they got something going via a CLI interface to Sonic!",[208,2504,2505,2508],{},[993,2506,2507],{},"Nerd Snipe:",[205,2509,2510,2519,2522,2525,2528,2531],{},[208,2511,2512,2513,2518],{},"When I was chatting with SL yesterday I realized that my ",[136,2514,2517],{"href":2515,"rel":2516},"https:\u002F\u002Fthelackthereof.org\u002Funison-backup-setup",[140],"Unison Powered Backups"," can error out without me knowing",[208,2520,2521],{},"Well I've always KNOWN this, but I ignore it because it works pretty much all the time. Still ... it had failed the night before...",[208,2523,2524],{},"So I made a wrapper that will do a system notification when it fails",[208,2526,2527],{},"Now I've got it running hourly. When it works it pops up a \"backup complete\" notification that goes away after a few seconds, and when it fails it pops up a \"BACKUP FAILED\" that won't go away until I click",[208,2529,2530],{},"Now I have to decide what I want it to tell me about no-internet situations. hm.",[208,2532,2533],{},"I just noticed that my original writeup of this backup structure was written in 2006!!!! That's pretty good sustainability on a backup solution :)",[208,2535,2536,2539],{},[993,2537,2538],{},"Alloy+LLM+Rails Project:",[205,2540,2541,2544],{},[208,2542,2543],{},"RC has a tiny \"community cluster\", which has to machines with small GPUs!",[208,2545,2546],{},"I got access to that yesterday, so I played with that a bit on the token-tree, got it working! Def faster than the local CPU. I wouldn't be surprised if a mac Mx processor was similar",{"title":156,"searchDepth":157,"depth":157,"links":2548},[],"2024-04-17",{},"\u002Ftlt-2024.04.17-recurse-w4-6-d3-5",{"title":2458,"description":2463},"TLT - 2024.04.17 - Recurse - W4-6 D3-5",[169,2555],"recurse-center","YHMck5gUcmr12CXytuiQEfz_OxW0yltlgsO9xO46-Hk",{"id":2558,"title":2559,"body":2560,"createdAt":2662,"description":2564,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":2663,"navigation":164,"path":2664,"seo":2665,"stem":2666,"tags":2667,"updatedAt":2662,"__hash__":2668},"content\u002FTLT - 2024.04.16 - Recurse - W4-6 D2-5.md","Recurse - W4\u002F6 D2\u002F5",{"type":8,"value":2561,"toc":2660},[2562,2565],[11,2563,2564],{},"In-Hub, LLM Club, Mediapipe, Coffee Project, docker-compose",[205,2566,2567,2624,2642],{},[208,2568,2569,2571],{},[993,2570,2470],{},[205,2572,2573,2576,2583,2592,2605,2621],{},[208,2574,2575],{},"Went into the hub! So great to see and interact IRL",[208,2577,2578,2579,2582],{},"Applied LLM Club we played with a large JSON dataset; works pretty easy to use the ChatGPT UI and upload the whole file, but we didn't find an obvious way to do the same thing on the API. Maybe something with their ",[194,2580,2581],{},"Assistants"," concept",[208,2584,2585,2586,2591],{},"I went over to ",[136,2587,2590],{"href":2588,"rel":2589},"https:\u002F\u002Fcoffeeprojectny.com\u002F",[140],"Coffee Project",", pretty delicious",[208,2593,2594,2595,2600,2601,2604],{},"Played with ",[136,2596,2599],{"href":2597,"rel":2598},"https:\u002F\u002Fdevelopers.google.com\u002Fmediapipe\u002Fsolutions\u002Fgenai\u002Fllm_inference\u002Fandroid#configuration_options",[140],"Mediapipe",", android AI\u002Fmedia lib from Google, with ",[20,2602,2603],{},"JH",". But the bleeding edge software was ... not working",[208,2606,2607,2608,2610,2611,2616,2617,2620],{},"Showed ",[20,2609,2484],{}," some of how I set up ",[136,2612,2615],{"href":2613,"rel":2614},"https:\u002F\u002Fthelackthereof.org",[140],"thelackthereof.org"," with docker-compose, including nginx running ",[20,2618,2619],{},"in"," docker with the rest of it",[208,2622,2623],{},"I worked on some Human Essentials, really need to wrap that :)",[208,2625,2626,2628],{},[993,2627,2507],{},[205,2629,2630,2639],{},[208,2631,2632,2633,2638],{},"TIL: I am using ",[136,2634,2637],{"href":2635,"rel":2636},"https:\u002F\u002Fgithub.com\u002Falacritty\u002Falacritty",[140],"Alacritty",", and you can apparently hit ctrl+shift+b to search backwards up through your scrollback!",[208,2640,2641],{},"I upgraded Nuxt to the latest for my static site ... and it now (correctly) gets mad about some internal broken links. But I couldn't find\u002Ffix them all so I turned that safety feature off hah",[208,2643,2644,2646],{},[993,2645,2538],{},[205,2647,2648,2657],{},[208,2649,2650,2651,2656],{},"Nice video -- ",[136,2652,2655],{"href":2653,"rel":2654},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=FvNRlE4E9QQ",[140],"\"Finding bugs without running or even looking at code\" by Jay Parlar",", though it is focused on the structural modeling not the state modeling",[208,2658,2659],{},"Got some communications from the Alloy maintainers; not quite satisfied that we've connected as deeply as I like, but I think I'll be able to get the CLI-JSON output I want in any case",{"title":156,"searchDepth":157,"depth":157,"links":2661},[],"2024-04-16",{},"\u002Ftlt-2024.04.16-recurse-w4-6-d2-5",{"title":2559,"description":2564},"TLT - 2024.04.16 - Recurse - W4-6 D2-5",[169,2555],"_bvsSMawOWLGnV4BSEOIAHo6zFVzuoQboA5EmQnzKpk",{"id":2670,"title":2671,"body":2672,"createdAt":2793,"description":2676,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":2794,"navigation":164,"path":2795,"seo":2796,"stem":2797,"tags":2798,"updatedAt":2793,"__hash__":2799},"content\u002FTLT - 2024.04.15 - Recurse - W4-6 D1-5.md","Recurse - W4\u002F6 D1\u002F5",{"type":8,"value":2673,"toc":2791},[2674,2677],[11,2675,2676],{},"Website updates to break insulation, bit of Human Essentials",[205,2678,2679,2722,2782],{},[208,2680,2681,2683],{},[993,2682,2470],{},[205,2684,2685,2688,2691,2700,2703,2716,2719],{},[208,2686,2687],{},"I think I'll go Virtual today and go into the Hub tomorrow (though I keep going back and forth)",[208,2689,2690],{},"Decided to beak my own insulation a bit, cross-posted all of these checkins to my own website",[208,2692,2693,2694,2699],{},"We went to a few bookstores over the weekend! I got ",[136,2695,2698],{"href":2696,"rel":2697},"https:\u002F\u002Fwww.adriantchaikovsky.com\u002Fthe-final-architects-shards-of-earth-eyes-of-the-voice-by-adrian-tchaikovsky.html",[140],"Adrian Tchaikovsky, Eyes of the Void, Book II of The Final Architects Series",". Betsy told me years and years ago to check out Tchaikovsky and boy was she right! I'm chewing through the catalog. Beth isn't into him as much, so YMMV",[208,2701,2702],{},"I know I'm feeling better because I'm feeling very wordy today haha",[208,2704,2705,2706,1211,2711],{},"Also picked up ",[136,2707,2710],{"href":2708,"rel":2709},"https:\u002F\u002Fus.macmillan.com\u002Fbooks\u002F9781250151179\u002Fnineteenwaysoflookingatconsciousness",[140],"Patrick house, Nineteen Ways of Looking at Consciousness",[136,2712,2715],{"href":2713,"rel":2714},"https:\u002F\u002Fwww.booksaremagic.net\u002Fitem\u002FL0V8Hcd1MxZHzEYGiH3oNw",[140],"Daniel C. Dennett, I've Been Thinking",[208,2717,2718],{},"Both are interesting. Thinking about consciousness, Agency, all that is a thing I enjoy. Dennett is often too aggressive, but I'm strongly aligned with his core ideas",[208,2720,2721],{},"Today I need to do a bit more on Human Essentials too. Had a good meeting with the team yesterday and there are only a few small things to get done on Dashboard for it to be mergeable",[208,2723,2724,2726],{},[993,2725,2507],{},[205,2727,2728,2731,2750,2760,2772,2779],{},[208,2729,2730],{},"Backdating blog entries and adding tags wasn't easy. So I updated my new-blog command wrapper with a few new options :)",[208,2732,2733,2734,2739,2740,2745,2746,2749],{},"I'm using the ",[136,2735,2738],{"href":2736,"rel":2737},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcommander",[140],"Commander"," CLI helper along with ",[136,2741,2744],{"href":2742,"rel":2743},"https:\u002F\u002Ftypestrong.org\u002Fts-node\u002F",[140],"ts-node"," for this. So my script starts with ",[194,2747,2748],{},"#!\u002Fusr\u002Fbin\u002Fenv ts-node"," and contains Typescript",[208,2751,2752,2753,2755,2756,2759],{},"I can never remember where my ",[194,2754,169],{}," command really lives, but ",[194,2757,2758],{},"vim $(which blog)"," works great :)",[208,2761,2762,2763,2767,2768,2771],{},"At some point recently I upgraded to ",[136,2764,2766],{"href":1208,"rel":2765},[140],"Taskwarrior 3.0"," which includes having to do an export of tasks from the old version ",[20,2769,2770],{},"BEFORE"," you install the new version. I got that taken care of before my OS does it for me",[208,2773,2774,2775,2778],{},"I started to help the Taskwarrior peeps out by making a perl script that translates their legacy ",[194,2776,2777],{},".data"," format directly into JSON so you could do the extract even after the upgrade .... but my data is migrated now and works fine so I lost momentum",[208,2780,2781],{},"On my blog, I might make a few more formatting tweaks. I will at some point use NuxtImage to render the thumbnails for things .... right now it is actually the full sized image downloaded and then scaled by the browser. People have a lot of bandwidth now, right? They're not that big anyway",[208,2783,2784,2786],{},[993,2785,2538],{},[205,2787,2788],{},[208,2789,2790],{},"Still no direct reply from the maintainers, but I'm going to keep jamming",{"title":156,"searchDepth":157,"depth":157,"links":2792},[],"2024-04-15",{},"\u002Ftlt-2024.04.15-recurse-w4-6-d1-5",{"title":2671,"description":2676},"TLT - 2024.04.15 - Recurse - W4-6 D1-5",[169,2555],"aDias0CbbVo9AF8DtUzVgYUGp9J8UnyPsOjh01iAqIw",{"id":2801,"title":2802,"body":2803,"createdAt":3006,"description":2807,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":3007,"navigation":164,"path":3008,"seo":3009,"stem":3010,"tags":3011,"updatedAt":3006,"__hash__":3012},"content\u002FTLT - 2024.04.14 - Recurse - W3-6.md","Recurse - W3\u002F6",{"type":8,"value":2804,"toc":3004},[2805,2808],[11,2806,2807],{},"A week spent coughing, writing Java, and watching Andor. First World Problems hah. Not bad in the scheme of things! :)",[205,2809,2810,2851,2900],{},[208,2811,2812,2814],{},[993,2813,2470],{},[205,2815,2816,2824,2830,2839,2842,2845,2848],{},[208,2817,2818,2819],{},"I was Virtual all week -- fighting a cough and feeling intermittently icky :( . MUCH BETTER NOW!!! Beautiful day.\n",[205,2820,2821],{},[208,2822,2823],{},"Watched the eclipse from here in NYC. Was OK. Maybe I'll do totality next time :)",[208,2825,2826,2829],{},[20,2827,2828],{},"FEELINGS"," -- Because of that it was a pretty tough week, really feeling both not getting the value of all the human connections I'd like and also feeling the reality of being at the half-way point for the 6-week batch",[208,2831,2832,2833,2838],{},"Watched a few more episodes of ",[136,2834,2837],{"href":2835,"rel":2836},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FAndor_(TV_series)",[140],"Andor",". I haven't watched any of the other Star Wars series shows, but got recommended this one by a random YouTube video and I like it. I only have a few more episodes left for the season",[208,2840,2841],{},"It was Beth's Birthday on Tuesday; I had dinner reservations and desert lined up ... but we called it off since I was feeling icky. BUT! We rescheduled to Saturday and had a lovely time! We are the same age yet again!",[208,2843,2844],{},"Here it is Sunday 2024-04-14 and I am feeling much much better. Skipping our weekly weight-training workout though to not push myself backwards",[208,2846,2847],{},"During the week I did attend a few things, and loved them all! I think y'all are great",[208,2849,2850],{},"Really one of my rare complaints is the double-edge sword of a curated community -- the insulation is dividing people in my life; like even these posts to zulip feel better to write than the public blog, and I'm not going to link to individuals on the public blog. In another week one of my bestest friends is visiting from Portland OR, and without special permission I can't bring them over to the hub. Heck I can't bring my spouse by when we happen to be nearby later today. I get it, I like it, I agree with it, and yet ... I feel that separation of insiders and outsiders. Eh.",[208,2852,2853,2855],{},[993,2854,2507],{},[205,2856,2857,2860,2867,2870,2879,2888,2891],{},[208,2858,2859],{},"I was upset that on Tuesday at a zoom meeting I had a coughing fit while screen sharing and that my desktop zoom ... wouldn't let me mute myself or stop sharing! GARRR",[208,2861,2862,2863,2866],{},"So. I think I got it. The solution: ",[20,2864,2865],{},"stop using the desktop zoom client",". Turns out you can use the browser just like I do all the time with google meet. BYE BYE DESKTOP ZOOM",[208,2868,2869],{},"It seems to work better now. I still have my internet drop now and then, which has something to do with where I am physically when remote here (switching wifi APs or something), but I can tether and then all is good",[208,2871,2872,2873,2878],{},"Still doing some mild tweaks to Sway, the latest is that I got ",[136,2874,2877],{"href":2875,"rel":2876},"https:\u002F\u002Fgithub.com\u002Fnicolasavru\u002Fswaymonad",[140],"swaymonad"," running, which controls some initial window-placement settings to make them more like xmonad. Looks like I'll probably fork\u002Ftweak it to my liking",[208,2880,2881,2882,2887],{},"And THAT thing uses ",[136,2883,2886],{"href":2884,"rel":2885},"https:\u002F\u002Fnixos.org\u002F",[140],"Nix","! So...",[208,2889,2890],{},"I got Nix running (on top of my existing Ubuntu, not as a whole install)",[208,2892,2893,2894,2899],{},"Just now I was listening to a ",[136,2895,2898],{"href":2896,"rel":2897},"https:\u002F\u002Fchangelog.com\u002Fshipit\u002F99",[140],"podcast (Ship It! Episode 99: From Kubernetes to Nix)"," and ... now am going to try to do MORE NIX, maybe inflict it upon my work people eventually. MUAHAHAHA",[208,2901,2902,2904],{},[993,2903,2538],{},[205,2905,2906,2909,2912,2915,2918,2921,2924,2985,2992,2995,2998,3001],{},[208,2907,2908],{},"Well. I learned some more Alloy!",[208,2910,2911],{},"I also was trying to play with different ways of interfacing with Alloy, knowing that the CLI is very limited",[208,2913,2914],{},"BUT they are prepping for a v6.1 which actually has some good CLI tooling! Like you can use it without the GUI, export JSON, even get an interactive console mode!",[208,2916,2917],{},"Very cool",[208,2919,2920],{},"But it doesn't work",[208,2922,2923],{},"As in the current dev branch is in need of some bug-fixes and QA for release. Also I think this is both a \"soon\" release and one that has been in progress for a year. Maybe I can help!",[208,2925,2926,2927],{},"So ... I'm now up to 8 open PRs against various branches and have reached out to the maintainers to do some coordination :)\n",[205,2928,2929,2936,2943,2950,2957,2964,2971,2978],{},[208,2930,2931],{},[136,2932,2935],{"href":2933,"rel":2934},"https:\u002F\u002Fgithub.com\u002Fnmacedo\u002Forg.alloytools.alloy\u002Fpull\u002F4",[140],"Quiets more CLI output when requested",[208,2937,2938],{},[136,2939,2942],{"href":2940,"rel":2941},"https:\u002F\u002Fgithub.com\u002Fnmacedo\u002Forg.alloytools.alloy\u002Fpull\u002F3",[140],"Remove deprecation warning for DefaultSymbolFactory",[208,2944,2945],{},[136,2946,2949],{"href":2947,"rel":2948},"https:\u002F\u002Fgithub.com\u002Fnmacedo\u002Forg.alloytools.alloy\u002Fpull\u002F2",[140],"Allow not-quite-regular files",[208,2951,2952],{},[136,2953,2956],{"href":2954,"rel":2955},"https:\u002F\u002Fgithub.com\u002FAlloyTools\u002Forg.alloytools.alloy\u002Fpull\u002F261",[140],"Print the 0th table; label the repeat number",[208,2958,2959],{},[136,2960,2963],{"href":2961,"rel":2962},"https:\u002F\u002Fgithub.com\u002FAlloyTools\u002Forg.alloytools.alloy\u002Fpull\u002F262",[140],"Prevent overriding ctrl+A and ctrl+E",[208,2965,2966],{},[136,2967,2970],{"href":2968,"rel":2969},"https:\u002F\u002Fgithub.com\u002FAlloyTools\u002Forg.alloytools.alloy\u002Fpull\u002F263",[140],"Remove long-deprecated menu entry",[208,2972,2973],{},[136,2974,2977],{"href":2975,"rel":2976},"https:\u002F\u002Fgithub.com\u002FAlloyTools\u002Forg.alloytools.alloy\u002Fpull\u002F265",[140],"Make the parser match the syntax highlighter",[208,2979,2980],{},[136,2981,2984],{"href":2982,"rel":2983},"https:\u002F\u002Fgithub.com\u002FAlloyTools\u002Forg.alloytools.alloy\u002Fpull\u002F267",[140],"Fix expectation of toDTO, avoid NPE",[208,2986,2987,2988,2991],{},"As I mentioned in my message to the developers ... as another open-source maintainer, I know that contributors can be well-intentioned but often come around, talk up some ideas, and disappear. Or worse, submit an un-mergeable PR and disappear. So I'm trying very hard to not do that. Each one of those is very small, like one or a few lines, easy to verify, and I ",[20,2989,2990],{},"think"," immediately mergeable",[208,2993,2994],{},"I have noticed there are, unsurprisingly some gaps in the unit tests, so I'm going to make some CLI-specific tests next week",[208,2996,2997],{},"Also this is Java! It's interesting how my position here has shifted over years ... at one point I was so frustrated with all-things-java that I swore it off. But I've matured or something and also realized that I LOVE ALL PROGRAMMING!!",[208,2999,3000],{},"I should note that I've also sworn off mmmmmm Databases and Javascript, but here I am 20 years later and both are close to my heart :)",[208,3002,3003],{},"Anyway. When it comes to the usual project-existential issues during my batch, this is clearly a good foundation; if I can help get this tool itself to be updated and integratable then I'll feel pretty pretty good",{"title":156,"searchDepth":157,"depth":157,"links":3005},[],"2024-04-14",{},"\u002Ftlt-2024.04.14-recurse-w3-6",{"title":2802,"description":2807},"TLT - 2024.04.14 - Recurse - W3-6",[169,2555],"XoGenr8nky-XL6dhbOtnU5lysZebRzUmPpumLDrjwMY",{"id":3014,"title":3015,"body":3016,"createdAt":3084,"description":3020,"draft":160,"extension":161,"image":3026,"mastodonThread":162,"meta":3085,"navigation":164,"path":3086,"seo":3087,"stem":3088,"tags":3089,"updatedAt":3084,"__hash__":3090},"content\u002FTLT - 2024.04.05 - Recurse - W2-6 D5-5.md","Recurse - W2\u002F6 D5\u002F5",{"type":8,"value":3017,"toc":3082},[3018,3021,3027],[11,3019,3020],{},"Virtual errands, GPU token generation. Oh right, Alloy",[11,3022,3023],{},[587,3024],{"alt":3025,"src":3026},"Token tree 3x3 cat sat on the","img\u002FToken_tree_3x3_cat_sat_on_the.png",[205,3028,3029,3048],{},[208,3030,3031,3033],{},[993,3032,2470],{},[205,3034,3035,3038,3041],{},[208,3036,3037],{},"Virtual today",[208,3039,3040],{},"Mostly doing some errands and general reading",[208,3042,3043,3044,3047],{},"Hung out with ",[20,3045,3046],{},"J"," some, looking at LLM stuff and showing a GPU cloud executor",[208,3049,3050,3052],{},[993,3051,2538],{},[205,3053,3054,3057,3060,3063,3066,3069,3072],{},[208,3055,3056],{},"I'm giving local-intel-gpu one more last chance",[208,3058,3059],{},"... I got it working on an A100 and it was a lot faster! But like... 10x, not instant",[208,3061,3062],{},"I generated a large tree but it had some unescaped character that I haven't found yet so I don't have the actual rendered graphviz",[208,3064,3065],{},"I remembered to turn off the rented instance :)",[208,3067,3068],{},"I started going back and updating Alloy knowledge, esp around time-domain which was added since I learned it",[208,3070,3071],{},"Next I need to start doing real Alloy models of things I think about or systems I use, and start improving the tooling around that",[208,3073,3074,3075,3078,3079,3081],{},"I'm starting to think about Alloy tooling, both direct and LLM; like in addition to Rails in\u002Fout I'm thinking of PlantUML in\u002Fout. A lot of Alloy users report using it as a ",[20,3076,3077],{},"thinking tool",". I use PlantUML as a ",[20,3080,3077],{},". So ...",{"title":156,"searchDepth":157,"depth":157,"links":3083},[],"2024-04-05",{},"\u002Ftlt-2024.04.05-recurse-w2-6-d5-5",{"title":3015,"description":3020},"TLT - 2024.04.05 - Recurse - W2-6 D5-5",[169,2555],"HXjQaY7YRQvQvH4eu0NoB_SkPizSorpKzfZXzTQiQjk",{"id":3092,"title":3093,"body":3094,"createdAt":3160,"description":3098,"draft":160,"extension":161,"image":3104,"mastodonThread":162,"meta":3161,"navigation":164,"path":3162,"seo":3163,"stem":3164,"tags":3165,"updatedAt":3160,"__hash__":3166},"content\u002FTLT - 2024.04.04 - Recurse - W2-6 D4-5.md","Recurse - W2\u002F6 D4\u002F5",{"type":8,"value":3095,"toc":3158},[3096,3099,3105],[11,3097,3098],{},"Pairing, unicode tokens, graphviz bling",[11,3100,3101],{},[587,3102],{"alt":3103,"src":3104},"Unicode token tree with Chinese","img\u002FUnicode_token_tree_with_Chinese.png",[205,3106,3107,3131],{},[208,3108,3109,3111],{},[993,3110,2470],{},[205,3112,3113,3116,3119,3122,3128],{},[208,3114,3115],{},"Starting to get into the hub-vibe a bit more, love it. Starting to actually remember individuals better! I'm so bad with names, but will keep asking over and over until I get it :)",[208,3117,3118],{},"I got to show the token-tree thing to a few individuals and then presented at the big session, very fun",[208,3120,3121],{},"Still having wayland\u002Fsway + zoom issues :( . Weird color inversion, floating-vs-non-floating-windows, etc. But I'm sticking with it. Hard to switch after like 15 years of xmonad (and like 25 years of X11 heh), but it's at like 99.9% so can't stop now",[208,3123,3124,3125,3127],{},"Shout out again to ",[20,3126,2287],{}," who helped me sort out some caching issues that was slowing down CPU token generation. Making it fast-enough has been really helpful",[208,3129,3130],{},"Will be Virtual RC tomorrow (Friday), gotta do some errands and prep for a friend-visit over the weekend",[208,3132,3133,3135],{},[993,3134,2538],{},[205,3136,3137,3140,3146,3149,3152,3155],{},[208,3138,3139],{},"Working on wrapping up token-visualization",[208,3141,2481,3142,3145],{},[20,3143,3144],{},"Q",", sorted out some escaping and unicode things",[208,3147,3148],{},"Added a bit of bling shadows and scaling (styling SVG with CSS is fun!)",[208,3150,3151],{},"Got incremental streaming of updates, background threading of the processing, and interruptability",[208,3153,3154],{},"Going to now switch over to Alloy; do some tutorials and toy models, build a few by-hand models of real world apps (Human Essentials Rails)",[208,3156,3157],{},"Somewhat of a pure-research project, so I'll go with where it takes me. But I am feeling the time-pressure a bit, and am hungry for artifacts to show off in the end. We'll see what comes next :)",{"title":156,"searchDepth":157,"depth":157,"links":3159},[],"2024-04-04",{},"\u002Ftlt-2024.04.04-recurse-w2-6-d4-5",{"title":3093,"description":3098},"TLT - 2024.04.04 - Recurse - W2-6 D4-5",[169,2555],"vK3Hd63PaQocbwt0pAo507oUc9wuFyUlpBXkt_0vjug",{"id":3168,"title":3169,"body":3170,"createdAt":3275,"description":3174,"draft":160,"extension":161,"image":3180,"mastodonThread":162,"meta":3276,"navigation":164,"path":3277,"seo":3278,"stem":3279,"tags":3280,"updatedAt":3275,"__hash__":3281},"content\u002FTLT - 2024.04.03 - Recurse - W2-6 D3-5.md","Recurse - W2\u002F6 D3\u002F5",{"type":8,"value":3171,"toc":3271},[3172,3175,3181,3185,3227,3231],[11,3173,3174],{},"Pairing, learning about LLM KV-caching",[11,3176,3177],{},[587,3178],{"alt":3179,"src":3180},"Token tree, 3x3 of solar system","img\u002FToken_tree,_3x3_of_solar_system.png",[266,3182,3184],{"id":3183},"part-i-morning","Part I - Morning",[205,3186,3187,3205],{},[208,3188,3189,3191],{},[993,3190,2470],{},[205,3192,3193,3196],{},[208,3194,3195],{},"In the hub today",[208,3197,3198,3199,3204],{},"I need to work on getting this ",[136,3200,3203],{"href":3201,"rel":3202},"https:\u002F\u002Fgithub.com\u002Frubyforgood\u002Fhuman-essentials\u002Fpull\u002F3788",[140],"Human Essentials Dashboard PR"," mergeable",[208,3206,3207,3209],{},[993,3208,2538],{},[205,3210,3211,3214,3221,3224],{},[208,3212,3213],{},"When I run the out-of-the-box generate locally it generates tokens fast-enough for my tree demo",[208,3215,3216,3217,3220],{},"So I'm going to focus on getting the tree generation to be ",[20,3218,3219],{},"as fast"," as that",[208,3222,3223],{},"Because as I think of it, when I shift to whole-codebase analysis it is unlikely that I will do that on anything smaller than a hosted API-based model (GPT-4, Claude2, etc)",[208,3225,3226],{},"Dunno",[266,3228,3230],{"id":3229},"part-ii-evening","Part II - Evening",[205,3232,3233,3237,3246],{},[208,3234,3235],{},[993,3236,2470],{},[208,3238,3239,3241],{},[993,3240,2507],{},[205,3242,3243],{},[208,3244,3245],{},"Fixed my vim comment-code keybinding. Where did it go before? Also ctrl-backspace to delete-word.",[208,3247,3248,3250],{},[993,3249,2538],{},[205,3251,3252,3256,3259,3262,3265,3268],{},[208,3253,2481,3254,1338],{},[20,3255,2287],{},[208,3257,3258],{},"He walked me through how some of the LLM KV caching works",[208,3260,3261],{},"So now I'm walking through my code to see if I can make it a bit faster",[208,3263,3264],{},"I also got progress on displaying a whole tree and a web interface",[208,3266,3267],{},"I think next I want to generate the tree incrementally on the web",[208,3269,3270],{},"I'll stop at that point though, outputting graphviz is satisfying enough for now",{"title":156,"searchDepth":157,"depth":157,"links":3272},[3273,3274],{"id":3183,"depth":157,"text":3184},{"id":3229,"depth":157,"text":3230},"2024-04-03",{},"\u002Ftlt-2024.04.03-recurse-w2-6-d3-5",{"title":3169,"description":3174},"TLT - 2024.04.03 - Recurse - W2-6 D3-5",[169,2555],"_3qummQt5ARS9EuLgUNFINdZmQu0Yp1BEBFzxBHkm4I",{"id":3283,"title":3284,"body":3285,"createdAt":3357,"description":3289,"draft":160,"extension":161,"image":3295,"mastodonThread":162,"meta":3358,"navigation":164,"path":3359,"seo":3360,"stem":3361,"tags":3362,"updatedAt":3357,"__hash__":3363},"content\u002FTLT - 2024.04.02 - Recurse - W2-6 D2-5.md","Recurse - W2\u002F6 D2\u002F5",{"type":8,"value":3286,"toc":3355},[3287,3290,3296],[11,3288,3289],{},"Applied LLM Demos; basic token output visualization with graphviz",[11,3291,3292],{},[587,3293],{"alt":3294,"src":3295},"Basic token tree","img\u002FBasic_token_tree.png",[205,3297,3298,3313,3325],{},[208,3299,3300,3302],{},[993,3301,2470],{},[205,3303,3304,3307,3310],{},[208,3305,3306],{},"At the hub today!",[208,3308,3309],{},"Delighted to keep meeting and chatting with people, went to lunch and all that",[208,3311,3312],{},"I organized an Applied LLM meetup -- there were demos that were DELIGHTFUL! A lovely enthusiastic group :)",[208,3314,3315,3317],{},[993,3316,2507],{},[205,3318,3319,3322],{},[208,3320,3321],{},"Flipped my bluetooth mouse (which I hadn't used since switching to Sway) to left-handed",[208,3323,3324],{},"My conference room presenting connection on this laptop has thrown me; Sway\u002FWayland won't let you have merged screens and the jabber speaker\u002Fmic doesn't output any sound for me! I need to do a more controlled practice run, the one I did wasn't good enough",[208,3326,3327,3329],{},[993,3328,2538],{},[205,3330,3331,3334,3337,3340,3343,3346,3349,3352],{},[208,3332,3333],{},"I got initial graphviz output!",[208,3335,3336],{},"I then decided that it was too slow to generate, so started to get my intel GPU to work",[208,3338,3339],{},"I ran into this exact same issue and gave up",[208,3341,3342],{},"Then I started figuring out how to spend money renting someone else's computer",[208,3344,3345],{},"... now I have to be careful. I spent $4.50 pretty quickly. I have a budget for this, but I want to spend that on actual computation instead of forgetting to turn something off and letting it run all night or all weekend for now gain",[208,3347,3348],{},"Unfortunately the output didn't work for my first larger run; the nodes in graphviz didn't have the full path and overwrote each other",[208,3350,3351],{},"Also I think that the local one can go a lot faster if I don't fully reset it every time; there are savepoints and some other things that might work",[208,3353,3354],{},"Still -- it's close to being GUI-able!",{"title":156,"searchDepth":157,"depth":157,"links":3356},[],"2024-04-02",{},"\u002Ftlt-2024.04.02-recurse-w2-6-d2-5",{"title":3284,"description":3289},"TLT - 2024.04.02 - Recurse - W2-6 D2-5",[169,2555],"hrCc0MQFe86olYtSPGxxBFnpHW0DKixTAVrIqGDMA88",{"id":3365,"title":3366,"body":3367,"createdAt":3443,"description":3371,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":3444,"navigation":164,"path":3445,"seo":3446,"stem":3447,"tags":3448,"updatedAt":3443,"__hash__":3449},"content\u002FTLT - 2024.04.01 - Recurse - W2-6 D1-5.md","Recurse - W2\u002F6 D1\u002F5",{"type":8,"value":3368,"toc":3441},[3369,3372],[11,3370,3371],{},"Lunch table with Humans!",[205,3373,3374,3415,3429],{},[208,3375,3376,3378],{},[993,3377,2470],{},[205,3379,3380,3401],{},[208,3381,3382,3383],{},"Morning\n",[205,3384,3385,3392,3395,3398],{},[208,3386,3387,3388,3391],{},"I find updating the ",[194,3389,3390],{},"week"," indicator on this checkin is already upsetting",[208,3393,3394],{},"I'm heading into The Hub today!",[208,3396,3397],{},"Going to see if I can do some IRL pairing",[208,3399,3400],{},"I need to work on some Human Essentials today, Wednesday is a stakeholder meeting",[208,3402,3403,3404],{},"Evening\n",[205,3405,3406,3409,3412],{},[208,3407,3408],{},"I had a delightful time sitting at the lunch table and chat chat chatting with peeps",[208,3410,3411],{},"HCI session was very interesting, with lots of discussion on Agency (which of course I'm very into)",[208,3413,3414],{},"Failed to do any IRL pairing, will try harder tomorrow!",[208,3416,3417,3419],{},[993,3418,2507],{},[205,3420,3421],{},[208,3422,2594,3423,3428],{},[136,3424,3427],{"href":3425,"rel":3426},"https:\u002F\u002Fgithub.com\u002Fmilgra\u002Fsov",[140],"sov"," a bit, might use it to visualize virtual desktops. But maybe not",[208,3430,3431,3433],{},[993,3432,2538],{},[205,3434,3435,3438],{},[208,3436,3437],{},"I might want to actually really look at LangChain",[208,3439,3440],{},"I have all the tools for a tree-of-tokens working (albeit slowly), so now working on traversing that to turn it into some visualizations",{"title":156,"searchDepth":157,"depth":157,"links":3442},[],"2024-04-01",{},"\u002Ftlt-2024.04.01-recurse-w2-6-d1-5",{"title":3366,"description":3371},"TLT - 2024.04.01 - Recurse - W2-6 D1-5",[169,2555],"KGtmfrYLvq1bE_7Pc8pZqcj94WxzmXBK45DUAr80QxU",{"id":3451,"title":3452,"body":3453,"createdAt":3582,"description":3457,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":3583,"navigation":164,"path":3584,"seo":3585,"stem":3586,"tags":3587,"updatedAt":3582,"__hash__":3588},"content\u002FTLT - 2024.03.29 - Recurse - W1-6 D5-5.md","Recurse - W1\u002F6 D5\u002F5",{"type":8,"value":3454,"toc":3577},[3455,3458,3460,3478,3480,3543,3547],[11,3456,3457],{},"Llamas, Pythons, Coffee, and Sway",[266,3459,3184],{"id":3183},[205,3461,3462],{},[208,3463,3464,3467],{},[993,3465,3466],{},"Morning Status:",[205,3468,3469,3472,3475],{},[208,3470,3471],{},"I feel pretty great today, but going to be Virtual anyway. Got some errands to run",[208,3473,3474],{},"I've got llama-cpp-python up and running, so I'm going to work on a back-end for it",[208,3476,3477],{},"I'll likely solicit pairing once I get it a bit further, especially for some visuals",[266,3479,3230],{"id":3229},[205,3481,3482,3531],{},[208,3483,3484,3486],{},[993,3485,2470],{},[205,3487,3488,3498,3501,3522,3525,3528],{},[208,3489,3490,3491,3494,3495],{},"TIL: Drop this in your python code to get a pretty close ",[194,3492,3493],{},"binding.pry"," equivalent ",[194,3496,3497],{},"from IPython import embed # For debugging; put `embed()` anywhere",[208,3499,3500],{},"Coffee Chat with Paolo!",[208,3502,3503,3504],{},"Volitional Muscles Workshop helped me re-affirm that I like the plan that I pre-gamed\n",[205,3505,3506,3514],{},[208,3507,3508,3509],{},"Core: Alloy+LLM+Rails (using Human Essentials app as a dataset)\n",[205,3510,3511],{},[208,3512,3513],{},"Explore possibilities, mash together things, dev-tooling, do some Good",[208,3515,3516,3517],{},"Cake: Pair, Follow Whims, Dance With Serendipity\n",[205,3518,3519],{},[208,3520,3521],{},"Create artifacts, play, learn, share",[208,3523,3524],{},"Side Note: I'm typing this in vim with copilot and it is upsetting when it suggests stiff language and then it is upsetting when it suggests exactly what I was about to write because then I'm like ... is this as bad as what you just suggested dear robot?",[208,3526,3527],{},"Attended applied machine learning group, but really just watched",[208,3529,3530],{},".... then got a Work Call that I hopped on to help with for the end of the day",[208,3532,3533,3535],{},[993,3534,2538],{},[205,3536,3537,3540],{},[208,3538,3539],{},"Slight progress on understanding the llama-cpp-python setup",[208,3541,3542],{},"Did some brushing up on python iterators and debugging tools",[266,3544,3546],{"id":3545},"part-iii-weekend-bonus","Part III - WEEKEND BONUS",[205,3548,3549],{},[208,3550,3551,3554],{},[993,3552,3553],{},"Weekend Updates:",[205,3555,3556,3568,3571,3574],{},[208,3557,3558,3559],{},"Nerd Sniped on displaying the current desktop grid pop-up to the right monitor. Got it working :)\n",[205,3560,3561],{},[208,3562,3563,3564,3567],{},"For reference, ",[194,3565,3566],{},"screen=$(swaymsg -t get_outputs | jq 'map(.focused) | index(true)')"," which I then pass on to aosd_cat",[208,3569,3570],{},"I dreamed about generating tokens from an LLM, but I think they were physical tokens and also maybe gangsters",[208,3572,3573],{},"I don't really need it now, but I keep wondering a cost-effective but natural-for-me way to rent GPU time to make my model run faster. I can spin up a whole linode GPU vm, but will need to make sure to delete it in-between uses. I don't really want to do hosted notebook blah blah. Not sure what I want. I guess I wish I could run a command and have a GPU on my existing linode and then run another to remove it, but that's maybe not how it works",[208,3575,3576],{},"We went on a some shopping and walking around and out to Thai and got groceries. Making good progress on getting the sense-of-place around here",{"title":156,"searchDepth":157,"depth":157,"links":3578},[3579,3580,3581],{"id":3183,"depth":157,"text":3184},{"id":3229,"depth":157,"text":3230},{"id":3545,"depth":157,"text":3546},"2024-03-29",{},"\u002Ftlt-2024.03.29-recurse-w1-6-d5-5",{"title":3452,"description":3457},"TLT - 2024.03.29 - Recurse - W1-6 D5-5",[169,2555],"43mB7y3HTye5oVMUY834GREBZxLF2JFs05LZ6yidwQ4",{"id":3590,"title":3591,"body":3592,"createdAt":3688,"description":3689,"draft":160,"extension":161,"image":3662,"mastodonThread":162,"meta":3690,"navigation":164,"path":3691,"seo":3692,"stem":3693,"tags":3694,"updatedAt":3688,"__hash__":3695},"content\u002FTLT - 2024.03.28 - Notes From Peter Kriens Video.md","Notes From Peter Kriens Video",{"type":8,"value":3593,"toc":3684},[3594,3602,3606,3614,3617,3628,3631,3636,3639,3650,3657,3663,3666,3669,3673],[11,3595,3596,3597],{},"Some notes and thoughts on Peter Kriens' video, as ",[136,3598,3601],{"href":3599,"rel":3600},"https:\u002F\u002Falloytools.discourse.group\u002Ft\u002Fthe-use-of-alloy-and-llms\u002F449\u002F2",[140],"posted on the Alloy Discourse",[266,3603,3605],{"id":3604},"notes-and-quotes","Notes and Quotes",[11,3607,3608,3609],{},"Video: ",[136,3610,3613],{"href":3611,"rel":3612},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=_j3SdIGqYG8",[140],"Peter Kriens - Thoughts on Alloy, Formal Models, and Software Engineering (youtube)",[11,3615,3616],{},"In this talk, Kriens talks about the practicalities of formal modeling, highlights flaws in a focus on correctness, and advocates for models as a way to elucidate our thinking about a problem or system.",[188,3618,3619],{},[11,3620,3621,3625,3627],{},[587,3622],{"alt":3623,"src":3624},"Peter Kriens - Programmer In The Loop","img\u002FPeter_Kriens_-_Programmer_In_The_Loop.png",[461,3626],{},"\n\"Although I really enjoy Alloy, there is a wide gap between formal languages and implementation languages and there seems to be no bridge in sight\"",[11,3629,3630],{},"Kriens says he often finds himself using Alloy or other tools to initially explore a problem, get a rough model set up to explore the space, and then abandon it quickly and moving to implementation. The \"prose\" of the initial problem has to be processed by a programmer to get to the implementation, rather than using the formal model further down the development lifecycle.",[188,3632,3633],{},[11,3634,3635],{},"\"Once we have an implementation, although there have been attempts, as far as I can see that is a long way to go before we can automatically create test from a model\"",[11,3637,3638],{},"OK interesting. Challenge accepted.",[188,3640,3641],{},[11,3642,3643,3647,3649],{},[587,3644],{"alt":3645,"src":3646},"Peter Kriens - Prose to Implementation","img\u002FPeter_Kriens_-_Prose_to_Implementation.png",[461,3648],{},"\n\"Prose is also not digestable by our computers. Although AI made impressive progress in pattern recognition, understanding prose is as far off as it was in the 1960's, almost 60 years ago. The developers must interpret the prose and translate their understanding to the proper use of the API. The computer is too stupid to provide any help here, except for the formatting maybe.\"",[11,3651,3652,3653,3656],{},"This talk was from 2020 .... oh how the world has changed in four short years! We now have Large Language Models which can do some ",[20,3654,3655],{},"impressive"," understanding of prose.",[11,3658,3659],{},[587,3660],{"alt":3661,"src":3662},"Peter_Kriens_-_Model_as_Elucidation","img\u002FPeter_Kriens_-_Model_as_Elucidation.png",[11,3664,3665],{},"Krien goes on to explore the idea of taking our high-level prose of a problem, the sort of things that we might leave in comments in our code, and replacing it with a very usable version of a formal model to serve as an \"Oracle\", a probe-able system to ask questions about the specification while building and maintaining the implementation. It could also generate verified test cases and mocks, and generally could provide inconsistencies and validate guarantees in an ongoing way.",[11,3667,3668],{},"Kriens did some experiments with DSL or other tooling to generate target system tests and such. He explored using reflection in the Java type system for expanding\u002Fannotating alloy and using it to generate Java. He also highlights some specific data structures and how they'd map from an imagined Alloy++ onto Java objects.",[266,3670,3672],{"id":3671},"ideas","Ideas",[205,3674,3675,3678,3681],{},[208,3676,3677],{},"Build some re-usable alloy for common scripting language data structures -- scalar, array, hash",[208,3679,3680],{},"Any value in generic \"object\" as a thing with instances, methods?",[208,3682,3683],{},"Use Alloy as a straight up way to generate mock data; a deeper version or an enhancement or layer on top of FactoryBot",{"title":156,"searchDepth":157,"depth":157,"links":3685},[3686,3687],{"id":3604,"depth":157,"text":3605},{"id":3671,"depth":157,"text":3672},"2024-03-28","Some notes and thoughts on Peter Kriens' video, as posted on the Alloy Discourse",{},"\u002Ftlt-2024.03.28-notes-from-peter-kriens-video",{"title":3591,"description":3689},"TLT - 2024.03.28 - Notes From Peter Kriens Video",[169,2555,1531],"e4W0L9cl6xIwjUfmhV_jcLSCHQZiRxPCKDWYlbjSxWw",{"id":3697,"title":3698,"body":3699,"createdAt":3688,"description":3703,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":3796,"navigation":164,"path":3797,"seo":3798,"stem":3799,"tags":3800,"updatedAt":3688,"__hash__":3801},"content\u002FTLT - 2024.03.28 - Recurse - W1-6 D4-5.md","Recurse - W1\u002F6 D4\u002F5",{"type":8,"value":3700,"toc":3794},[3701,3704],[11,3702,3703],{},"Fuzzy brained, but starting to figure this thing out.",[205,3705,3706,3720,3741,3773],{},[208,3707,3708,3711,3712],{},[993,3709,3710],{},"Morning Status",":\n",[205,3713,3714],{},[208,3715,3716,3717,3719],{},"Feeling a bit fuzzy brained ... I had a cold like 2 weeks ago and hope it's not coming back or getting a new one. I don't ",[20,3718,2990],{}," I have allergies. Still. I was face-to-face with a LOT of people yesterday. So while I'm feeling only very slight off, I'm going Virtual today to see how it progresses.",[208,3721,3722,3724],{},[993,3723,2470],{},[205,3725,3726,3729,3732,3735,3738],{},[208,3727,3728],{},"Felt much better as the day went! Maybe I'm fine?",[208,3730,3731],{},"Did my first coffee-chat, it was lovely",[208,3733,3734],{},"I might start doing some Pomodoros tomorrow",[208,3736,3737],{},"The presentations were delightful!",[208,3739,3740],{},"I also went to a manager-roundtable which was helpful for some work-stuff",[208,3742,3743,3745],{},[993,3744,2538],{},[205,3746,3747,3750,3758,3761,3764,3767,3770],{},[208,3748,3749],{},"Worked on some Alloy fundamentals and resources",[208,3751,3752,3753],{},"Watched and made notes on an inspirational video, wrote ",[136,3754,3757],{"href":3755,"rel":3756},"https:\u002F\u002Fthelackthereof.org\u002Ftlt-2024.03.28-notes-from-peter-kriens-video",[140],"a blog post on it",[208,3759,3760],{},"Slight tangent, but started poking at low-level local LLM setup to work on my next-token visualization exploration",[208,3762,3763],{},"I'm trying out python with llama-cpp-python as an easy and capable approach",[208,3765,3766],{},"I have it working enough to do some completions",[208,3768,3769],{},"Next I am going to work on doing token level interactive tokens, and then I'll find someone to help me visualize with d3 or something to give a hands-on feel for next-token generation",[208,3771,3772],{},"That is (a) fun, and (b) might lead to some insights in some of my other studies here",[208,3774,3775,3778],{},[993,3776,3777],{},"Nerd Snipes:",[205,3779,3780],{},[208,3781,3782,3783,3787,3788,3793],{},"While watching an ",[136,3784,3786],{"href":3611,"rel":3785},[140],"inspirational video on Alloy and practicalizing Formal Methods",", I was grabbing a few screenshots and YET AGAIN realized that my vim-based markdown edit workflow doesn't mesh with ad hoc image insertion. I set up ",[136,3789,3792],{"href":3790,"rel":3791},"https:\u002F\u002Fgithub.com\u002Fdfendr\u002Fclipboard-image.nvim",[140],"clipboard-image.nvim"," and now I can paste like magic!",{"title":156,"searchDepth":157,"depth":157,"links":3795},[],{},"\u002Ftlt-2024.03.28-recurse-w1-6-d4-5",{"title":3698,"description":3703},"TLT - 2024.03.28 - Recurse - W1-6 D4-5",[169,2555],"pOvhZf7Gas-we8Ys2UgMcx7zUhJ9EK90u-3cObSzwsM",{"id":3803,"title":3804,"body":3805,"createdAt":3883,"description":3809,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":3884,"navigation":164,"path":3885,"seo":3886,"stem":3887,"tags":3888,"updatedAt":3883,"__hash__":3889},"content\u002FTLT - 2024.03.27 - Recurse - W1-6 D3-5.md","Recurse - W1\u002F6 D3\u002F5",{"type":8,"value":3806,"toc":3881},[3807,3810],[11,3808,3809],{},"In The Hub",[205,3811,3812,3854],{},[208,3813,3814,3711,3817],{},[993,3815,3816],{},"General Status",[205,3818,3819,3822,3825,3842,3845,3848,3851],{},[208,3820,3821],{},"I watched an interview with some musician once and found it inspirational. She said that she does her creation in waves. First is the intake wave -- she breathes in music, ideas, walks in nature, feelings. Then is the creation wave -- she breathes out experiments, refinements, practice, create. Breathe in consume, breathe out create. Breathe in. Breathe out.",[208,3823,3824],{},"Today I visited The Hub! Got a tour, met a ton of people!",[208,3826,3827,3828],{},"I'm thinking of starting two meetups\u002Fclubs:\n",[205,3829,3830,3836],{},[208,3831,3832,3835],{},[20,3833,3834],{},"Formal Methods Club"," (Alloy, TLA+, Program correctness, etc)",[208,3837,3838,3841],{},[20,3839,3840],{},"LLM Club"," (applied Large Language Models, openAI\u002Fsimilar API, running local models, etc)",[208,3843,3844],{},"Made a flower and a wreath of flowers and a wreath of wreaths of ... at Creative Coding session",[208,3846,3847],{},"Did a little more on Human Essentials, gotta get this LONG overdue Dashboard PR out",[208,3849,3850],{},"Tomorrow I'm going to brush up on my Alloy and do some by-hand extraction of models from codebases, probably Human Essentials to start with",[208,3852,3853],{},"I'm planning on coming in to the Hub basically every weekday",[208,3855,3856,3858],{},[993,3857,3777],{},[205,3859,3860,3863],{},[208,3861,3862],{},"I realized that I can still run rofi and dunst, so even more the-same-as-before",[208,3864,3865,3866],{},"The yubikey enable\u002Fdisable broke, but I figured out a new way\n",[205,3867,3868,3875],{},[208,3869,3870,3871,3874],{},"At boot, ",[194,3872,3873],{},"chmod 666 \u002Fsys\u002Fbus\u002Fusb\u002Fdevices\u002F3-1\u002Fauthorized"," which happens to be where I have it plugged in",[208,3876,3877,3878],{},"Disable (or 1 to enable) with ",[194,3879,3880],{},"echo 0 > \u002Fsys\u002Fbus\u002Fusb\u002Fdevices\u002F3-1\u002Fauthorized",{"title":156,"searchDepth":157,"depth":157,"links":3882},[],"2024-03-27",{},"\u002Ftlt-2024.03.27-recurse-w1-6-d3-5",{"title":3804,"description":3809},"TLT - 2024.03.27 - Recurse - W1-6 D3-5",[169,2555],"rOIpAs54i7fPLV-Pm8Coh9tyNfQiYzjM8tNnh3rNm4s",{"id":3891,"title":3892,"body":3893,"createdAt":3950,"description":3897,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":3951,"navigation":164,"path":3952,"seo":3953,"stem":3954,"tags":3955,"updatedAt":3950,"__hash__":3956},"content\u002FTLT - 2024.03.26 - Recurse - W1-6 D2-5.md","Recurse - W1\u002F6 D2\u002F5",{"type":8,"value":3894,"toc":3948},[3895,3898],[11,3896,3897],{},"Pairing, Merging",[205,3899,3900,3928],{},[208,3901,3902,3904],{},[993,3903,2470],{},[205,3905,3906,3909,3917,3925],{},[208,3907,3908],{},"Attended the Pairing Workshop! Paired in RubyLand",[208,3910,3911,3912],{},"Spent some time merging PRs for ",[136,3913,3916],{"href":3914,"rel":3915},"https:\u002F\u002Fgithub.com\u002Frubyforgood\u002Fhuman-essentials",[140],"Human Essentials",[208,3918,3919,3920],{},"Attended ML-applied and then AI\u002FML safety and interpretability meetings\n",[205,3921,3922],{},[208,3923,3924],{},"Definite overlap with my interests\u002Fprojects, though some of the plan there is to go intensely and deeply on some curriculum; I think I'll track but not directly participate",[208,3926,3927],{},"On-site tomorrow, I'm psyched :)",[208,3929,3930,3932],{},[993,3931,3777],{},[205,3933,3934,3937],{},[208,3935,3936],{},"Spent some more time in sway. Messing with keybindings and multi-monitor setup. Alllll coming together now! I think I'm switched over. Except for some weird things in Zoom. hmmmmm.",[208,3938,3939,3940,3943,3944,3947],{},"My fonts are small, esp in firefox. Annoying. So I googled and learned that I can try setting ",[194,3941,3942],{},"layout.css.devPixelsPerPx"," to something bigger. I go in there... and it is set to ",[194,3945,3946],{},"0.75","!!! I changed it to the default and everything is already much better haha",{"title":156,"searchDepth":157,"depth":157,"links":3949},[],"2024-03-26",{},"\u002Ftlt-2024.03.26-recurse-w1-6-d2-5",{"title":3892,"description":3897},"TLT - 2024.03.26 - Recurse - W1-6 D2-5",[169,2555],"eIDwSktFIZI6T7ZJiI1dvIDnoywSbmaac0tXPOp7tVI",{"id":3958,"title":3959,"body":3960,"createdAt":4040,"description":3964,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":4041,"navigation":164,"path":4042,"seo":4043,"stem":4044,"tags":4045,"updatedAt":4040,"__hash__":4046},"content\u002FTLT - 2024.03.25 - Recurse - W1-6 D1-5.md","Recurse - W1\u002F6 D1\u002F5",{"type":8,"value":3961,"toc":4038},[3962,3965],[11,3963,3964],{},"First day of RC!",[205,3966,3967,3985,3990,4007,4013],{},[208,3968,3969,3971],{},[993,3970,2470],{},[205,3972,3973,3976,3979,3982],{},[208,3974,3975],{},"First day of RC! Virtual today (everyone)",[208,3977,3978],{},"Participated in the two onboarding meetings, starting to get a feel for my new friends. TONS of inspirational people and ideas, lots of things to share and explore :)",[208,3980,3981],{},"I'm looking to getting IRL on Wednesday",[208,3983,3984],{},"Also looking forward to Creative Coding exercises and .... just doing some whimsical things!",[208,3986,3987,3989],{},[993,3988,2507],{}," Every 6 months or so I try to switch from xmonad to wayland+sway. Yesterday I tried again and actually made a ton of progress and I think crossed over the usability line. The biggest thing that I kept having issues with was screen-sharing, but I think I found the right incantation at last. So .... now the tricky bit where I have like 15 years of xmonad gradual adaptations that I've done and I have to decide which to keep, which to abandon .... and also how nerd-sniped I am willing to be for working on those adaptations :)",[208,3991,3992,3994,3995,4000,4001,4006],{},[993,3993,2538],{}," I have been pre-gaming a bit, so have a large ",[136,3996,3999],{"href":3997,"rel":3998},"https:\u002F\u002Fwww.zotero.org\u002F",[140],"zotero"," backlog of interesting papers to read through and take some notes on. I also am going to work through a few ",[136,4002,4005],{"href":4003,"rel":4004},"https:\u002F\u002Fhaslab.github.io\u002Fformal-software-design\u002Findex.html",[140],"Alloy"," experiments to both get my fingers remembering how it works and also learn the new temporal logic stuff they added recently. Next up I want to manually extract some alloy models from code-bases to think out the different types of models (DB Schema, API, Rails Models, etc) and maybe use that to build up some examples for The Machine (LLMs).",[208,4008,4009,4012],{},[993,4010,4011],{},"Good:"," For the Human Essentials project, I have several open tickets. I'm going to spend the last hour of the day (now) working on that!",[208,4014,4015,4018],{},[993,4016,4017],{},"Ideas\u002FOther:",[205,4019,4020,4028,4031],{},[208,4021,4022,4027],{},[136,4023,4026],{"href":4024,"rel":4025},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FFormal_methods",[140],"Formal Methods"," interest group?",[208,4029,4030],{},"LLM interest group?",[208,4032,4033,4034,4037],{},"Several people were interested in doing some Good; Once I'm settled in I'll declare open invite for pairing on ",[136,4035,3916],{"href":3914,"rel":4036},[140]," and see what I can join others on. I really want to get Github Codespaces set up for easier onboarding, hmmm",{"title":156,"searchDepth":157,"depth":157,"links":4039},[],"2024-03-25",{},"\u002Ftlt-2024.03.25-recurse-w1-6-d1-5",{"title":3959,"description":3964},"TLT - 2024.03.25 - Recurse - W1-6 D1-5",[169,2555],"d0q1vsZJPSnLCn9p3-WQiRRw-WMIWKO_rZ66gY5AUgA",{"id":4048,"title":4049,"body":4050,"createdAt":4122,"description":4123,"draft":160,"extension":161,"image":4065,"mastodonThread":162,"meta":4124,"navigation":164,"path":4125,"seo":4126,"stem":4127,"tags":4128,"updatedAt":4122,"__hash__":4129},"content\u002FTLT - 2024.03.23 - Getting Ready To Recurse.md","Getting Ready To Recurse",{"type":8,"value":4051,"toc":4117},[4052,4060,4069,4073,4076,4079,4088,4092,4107,4111,4114],[11,4053,4054,4055,797],{},"Packing up for my 6-week batch at the ",[136,4056,4059],{"href":4057,"rel":4058},"https:\u002F\u002Fwww.recurse.com\u002F",[140],"Recurse Center",[11,4061,4062,4066,4067],{},[587,4063],{"alt":4064,"src":4065},"Blooming trees and forking path in Kalorama Park","202403-blooming-trees-path.jpg"," ",[20,4068,4064],{},[266,4070,4072],{"id":4071},"home","Home",[11,4074,4075],{},"Unfortunately Beth caught the cold that I caught from my niece, and that's thrown us off a bit. But I'm packing today (Saturday) and we'll head up tomorrow (Sunday). Got our apartment there all lined up and now it's really the process of deciding what goes with us.",[11,4077,4078],{},"I've been chatting with my physical books, asking each of them what they think. Most all of them very loudly say \"TAKE ME! TAKE ME!\", and I have to reason with them a bit. Will I really read you? Can I get the same information electronically? Maybe I can read you when I get back? And so on. There are certainly some minor protests but we've narrowed it down to .... I don't know like eight or so books to take. Hah!",[11,4080,4081,4082,4087],{},"Then there are the electronics, wires, and other misc tool\u002Ftoys to chat with. Mostly I'm not bringing recording equipment -- if I suddenly start creating music then laptop and phone mics will be fine. I will take the monome-grid, but I'll run it off of the computer instead of taking the norns, using ",[136,4083,4086],{"href":4084,"rel":4085},"https:\u002F\u002Fgithub.com\u002Fryleelyman\u002Fseamstress",[140],"seamstress"," for the host lua environment. Do I take the projector? There is a TV there but it is tiny. Hmmmmm. Beth'll probably veto that one when she awakens.",[266,4089,4091],{"id":4090},"adventures","Adventures",[11,4093,4094,4095,4100,4101,4106],{},"There are all sorts of things to do in Brooklyn and the overall NYC area. We're going to walk around a lot, get a feel for the place. We'll also do some standards like the ",[136,4096,4099],{"href":4097,"rel":4098},"https:\u002F\u002Fbronxzoo.com\u002F",[140],"Bronx Zoo",". Maybe I should sign up for another animal-encounter. I'll get us to try some other things like ",[136,4102,4105],{"href":4103,"rel":4104},"https:\u002F\u002Fmckittrickhotel.com\u002Fevents\u002Fsleep-no-more\u002F",[140],"Sleep No More",". Tons more on the possible list.",[266,4108,4110],{"id":4109},"projects","Project(s)",[11,4112,4113],{},"The internal chat (Zulip) at the Recurse Center is overwhelming and inspiring with both main projects and side-missions. Part of the trick is going to be documentiong, prioritizing, documenting, all of these various ideas. For the Main Project, I am still feeling great about the Alloy+LLM+Rails core, with explorations in different directions for each of the components. I might bring in some PlantUML type things ... I see people saying that they use Alloy to explore ideas, and I use PlantUML to explore ideas .... so maybe those types of exploration can join forces.",[11,4115,4116],{},"One of the side things that I'm still interested in is in visualizing the probability tree for LLMs. Like show the raw stream so far and then the tree of next-tokens. Ideally you can then click through or flow through to see what different paths might look like.",{"title":156,"searchDepth":157,"depth":157,"links":4118},[4119,4120,4121],{"id":4071,"depth":157,"text":4072},{"id":4090,"depth":157,"text":4091},{"id":4109,"depth":157,"text":4110},"2024-03-23","Packing up for my 6-week batch at the Recurse Center.",{},"\u002Ftlt-2024.03.23-getting-ready-to-recurse",{"title":4049,"description":4123},"TLT - 2024.03.23 - Getting Ready To Recurse",[169,2555],"4_HoBdeBjYYL9KcdU4TbEiIPJfXM-Xktw5_G_VtNkes",{"id":4131,"title":4132,"body":4133,"createdAt":4386,"description":4137,"draft":160,"extension":161,"image":4387,"mastodonThread":162,"meta":4388,"navigation":164,"path":4389,"seo":4390,"stem":4391,"tags":4392,"updatedAt":4122,"__hash__":4393},"content\u002FTLT - 2024.02.04 - Thinking About Model Extraction.md","Thinking About Model Extraction",{"type":8,"value":4134,"toc":4384},[4135,4138,4144,4146,4149,4152,4327,4340,4347,4350,4353,4356,4359,4374,4381],[11,4136,4137],{},"Sharing some thoughts on my Recurse Center project, exploring how to bring Alloy or similar tools into the Day Job.",[11,4139,4140,4143],{},[587,4141],{"src":4142},"\u002Fimg\u002Frobot-opening-jar.jpg"," Robot opening a jar",[15,4145],{},[11,4147,4148],{},"I have been doing searches for academic papers or projects with keywords of Ruby and Alloy, as well as brushing up on my Alloy. The rough idea that I'm pursuing is to take a working codebase, extract a model, and then do stuff with it.",[11,4150,4151],{},"So... let's imagine...",[605,4153,4155],{"className":1619,"code":4154,"language":1621,"meta":156,"style":156},"$ cd codebase\ncodebase$ extract-model\ncodebase$ cat result.als\ncodebase$ alloy run result.als\n\nExecuting \"Run Default for 4 but 4 int, 4 seq expect 1\"\n   Solver=minisat(jni) Bitwidth=4 MaxSeq=4 SkolemDepth=1 Symmetry=OFF Mode=batch\n   2727 vars. 508 primary vars. 4414 clauses. 108ms.\n   . found. Predicate is consistent, as expected. 14ms.\n\ncodebase$ █\n",[194,4156,4157,4168,4176,4186,4198,4202,4210,4265,4290,4316,4320],{"__ignoreMap":156},[39,4158,4159,4162,4165],{"class":614,"line":615},[39,4160,4161],{"class":1909},"$",[39,4163,4164],{"class":649}," cd",[39,4166,4167],{"class":649}," codebase\n",[39,4169,4170,4173],{"class":614,"line":157},[39,4171,4172],{"class":1909},"codebase$",[39,4174,4175],{"class":649}," extract-model\n",[39,4177,4178,4180,4183],{"class":614,"line":637},[39,4179,4172],{"class":1909},[39,4181,4182],{"class":649}," cat",[39,4184,4185],{"class":649}," result.als\n",[39,4187,4188,4190,4193,4196],{"class":614,"line":656},[39,4189,4172],{"class":1909},[39,4191,4192],{"class":649}," alloy",[39,4194,4195],{"class":649}," run",[39,4197,4185],{"class":649},[39,4199,4200],{"class":614,"line":668},[39,4201,634],{"emptyLinePlaceholder":164},[39,4203,4204,4207],{"class":614,"line":674},[39,4205,4206],{"class":1909},"Executing",[39,4208,4209],{"class":649}," \"Run Default for 4 but 4 int, 4 seq expect 1\"\n",[39,4211,4212,4215,4217,4220,4223,4226,4229,4231,4234,4237,4239,4241,4244,4246,4249,4252,4254,4257,4260,4262],{"class":614,"line":685},[39,4213,4214],{"class":622},"   Solver",[39,4216,643],{"class":618},[39,4218,4219],{"class":649},"minisat",[39,4221,4222],{"class":622},"(",[39,4224,4225],{"class":1909},"jni",[39,4227,4228],{"class":622},") Bitwidth",[39,4230,643],{"class":618},[39,4232,4233],{"class":649},"4",[39,4235,4236],{"class":622}," MaxSeq",[39,4238,643],{"class":618},[39,4240,4233],{"class":649},[39,4242,4243],{"class":622}," SkolemDepth",[39,4245,643],{"class":618},[39,4247,4248],{"class":649},"1",[39,4250,4251],{"class":622}," Symmetry",[39,4253,643],{"class":618},[39,4255,4256],{"class":649},"OFF",[39,4258,4259],{"class":622}," Mode",[39,4261,643],{"class":618},[39,4263,4264],{"class":649},"batch\n",[39,4266,4267,4270,4273,4276,4279,4281,4284,4287],{"class":614,"line":691},[39,4268,4269],{"class":1909},"   2727",[39,4271,4272],{"class":649}," vars.",[39,4274,4275],{"class":664}," 508",[39,4277,4278],{"class":649}," primary",[39,4280,4272],{"class":649},[39,4282,4283],{"class":664}," 4414",[39,4285,4286],{"class":649}," clauses.",[39,4288,4289],{"class":649}," 108ms.\n",[39,4291,4292,4295,4298,4301,4304,4307,4310,4313],{"class":614,"line":701},[39,4293,4294],{"class":694},"   .",[39,4296,4297],{"class":649}," found.",[39,4299,4300],{"class":649}," Predicate",[39,4302,4303],{"class":649}," is",[39,4305,4306],{"class":649}," consistent,",[39,4308,4309],{"class":649}," as",[39,4311,4312],{"class":649}," expected.",[39,4314,4315],{"class":649}," 14ms.\n",[39,4317,4318],{"class":614,"line":709},[39,4319,634],{"emptyLinePlaceholder":164},[39,4321,4322,4324],{"class":614,"line":1823},[39,4323,4172],{"class":1909},[39,4325,4326],{"class":649}," █\n",[11,4328,4329,4330,4333,4334,4339],{},"... and already we have a problem. Because there is no such ",[194,4331,4332],{},"alloy"," cli interface. It has a lovely GUI, but no way to run something lke that (",[136,4335,4338],{"href":4336,"rel":4337},"https:\u002F\u002Fgithub.com\u002FAlloyTools\u002Forg.alloytools.alloy\u002Fissues\u002F155",[140],"yet","). It appears that you can reach in and run stuff in the java, write your own wrapper, interface with the java, etc. So already off to a yak-shaving start!",[11,4341,4342,4343,4346],{},"Still. The idea is you run this magical ",[194,4344,4345],{},"extract-model"," command on a codebase, I'm using Rails because it has a structure that suits this, and it spits out a model. The model should contain modely-stuff -- database tables, classes, API interactions maybe.",[11,4348,4349],{},"THEN what we'll do is turn the model BACK into some rspec.",[11,4351,4352],{},"THEN we'll add some further declarations and turn those back into rspec too.",[11,4354,4355],{},"Hmm. Maybe we can slurp in the existing rspec and try to turn that into some constraints or validations on the Alloy side.",[11,4357,4358],{},"And what can we learn or do with an Alloy model? I'm not sure yet! The rough theory is that we have this Simplified World we can work with, or reason about, and that it can reflect and guide the Real World. I kinda doubt that folks will want to muck about much in the Alloy directly (though you never know), so more like a weird intermediate representation for codebase analysis and transformation, basically.",[11,4360,4361,4362,4364,4365,4370,4371,4373],{},"I'm thinking the ",[194,4363,4345],{}," and might be some LLM magic, but also we can follow what they were trying with ",[136,4366,4369],{"href":4367,"rel":4368},"https:\u002F\u002Fdl.acm.org\u002Fdoi\u002F10.1145\u002F2393596.2393667",[140],"Rubicon",", getting right into some Rails-specific tooling to help extract a model. While I know the most about Rails, I think it'd be very cool to run our mythical ",[194,4372,4345],{}," against other codebases. Still -- specialty knowledge and specialization on Rails is interesting.",[11,4375,4376,4377,4380],{},"All through it I keep thinking ... can I make this practical? Can I make this into a tool that I'd ",[20,4378,4379],{},"actually use in my day job","? One of the Recurse center ideas is to work at the \"edge\" of your abilities and understanding; for me making something in this space that is both powerful and useful dances right on this edge.",[738,4382,4383],{},"html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sTrkL, html code.shiki .sTrkL{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#66D9EF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":156,"searchDepth":157,"depth":157,"links":4385},[],"2024-02-04","img\u002Frobot-opening-jar.jpg",{},"\u002Ftlt-2024.02.04-thinking-about-model-extraction",{"title":4132,"description":4137},"TLT - 2024.02.04 - Thinking About Model Extraction",[169,2555],"obvmmR_nntwYF-xmGN-wAZ7lz7R12WIVt-SinjZgjmw",{"id":4395,"title":4396,"body":4397,"createdAt":4472,"description":4473,"draft":160,"extension":161,"image":4474,"mastodonThread":162,"meta":4475,"navigation":164,"path":4476,"seo":4477,"stem":4478,"tags":4479,"updatedAt":4122,"__hash__":4480},"content\u002FTLT - 2024.01.31 - Recurse Setup.md","Recurse Setup",{"type":8,"value":4398,"toc":4467},[4399,4406,4414,4418,4421,4424,4427,4431,4434,4451,4455,4458,4461,4464],[11,4400,4401,4402,4405],{},"I'm attending a 6-week retreat at ",[136,4403,4059],{"href":4057,"rel":4404},[140],"! This will go from March 25 - May 3. So ... gotta get set up!",[11,4407,4408,4066,4411],{},[587,4409],{"src":4410},"\u002Fimg\u002Frobot-making-lists.jpg",[20,4412,4413],{},"A robot making lists",[266,4415,4417],{"id":4416},"the-basics","The Basics",[11,4419,4420],{},"The main thing on my mind has been -- what will I do while I'm there? But of course when I think of anything that I might do there are still a bunch of other setup things to do.",[11,4422,4423],{},"First off is logistics. RC is in NYC (Brooklyn) and attendees can be virtual or in-person. I really want to be in-person, so I found a 6-week rental not too far away. Then Beth and Hoda and I can stay there the whole time if we are comfortable. We'll drive our household up, and drive it back as needed.",[11,4425,4426],{},"I have the time off work as an Official Sabbatical, so that's pretty awesome. Thanks Framebridge! They pay me by the year not by the hour, so it all comes out even anyway.",[266,4428,4430],{"id":4429},"the-other-stuff","The Other Stuff",[11,4432,4433],{},"I'm updating or brushing off all of these.",[205,4435,4436,4439,4442,4445,4448],{},[208,4437,4438],{},"TaskWarrior",[208,4440,4441],{},"Lask logger wrapper",[208,4443,4444],{},"Zotero",[208,4446,4447],{},"Blog software",[208,4449,4450],{},"A nice empty project folder :)",[266,4452,4454],{"id":4453},"the-hard-part","The Hard Part",[11,4456,4457],{},"And then there is ... figuring out what I'm going to do. Over the last few months I've been slowly writing all of my ideas down, making mind-maps, making notes. From this I've started to get a feel for which things are exciting me the most and which things have the most potential for a deep dive.",[11,4459,4460],{},"A big one for sure is pretty much anything related to LLMs. Since that covers a lot of ground, it has turned into more what-can-I-mashup with LLMs.",[11,4462,4463],{},"So ... I'm slowly spiraling toward some core themes. LLMs. Dev tooling. Making CS Formal Methods accessible or practical.",[11,4465,4466],{},"Most recently this has unified as: LLM+Alloy+Rails.",{"title":156,"searchDepth":157,"depth":157,"links":4468},[4469,4470,4471],{"id":4416,"depth":157,"text":4417},{"id":4429,"depth":157,"text":4430},{"id":4453,"depth":157,"text":4454},"2024-01-31","I'm attending a 6-week retreat at Recurse Center! This will go from March 25 - May 3. So ... gotta get set up!","img\u002Frobot-making-lists.jpg",{},"\u002Ftlt-2024.01.31-recurse-setup",{"title":4396,"description":4473},"TLT - 2024.01.31 - Recurse Setup",[169,2555],"TaW0jM80gsiwTyLwQYZ81B57rdu-ffeZ6FFJ0UCmCi0",{"id":4482,"title":4483,"body":4484,"createdAt":4539,"description":4488,"draft":160,"extension":161,"image":4540,"mastodonThread":162,"meta":4541,"navigation":164,"path":4542,"seo":4543,"stem":4544,"tags":4545,"updatedAt":4472,"__hash__":4546},"content\u002FTLT - 2023.11.28 - Thinking About Copilot.md","Thinking About Copilot",{"type":8,"value":4485,"toc":4536},[4486,4489,4497,4499,4506,4513,4516,4520,4523,4530,4533],[11,4487,4488],{},"Reflections on Github Copilot and AI coding assistants.",[11,4490,4491,4066,4494],{},[587,4492],{"src":4493},"\u002Fimg\u002Frobot-intern-coffee.jpg",[20,4495,4496],{},"A robot intern delivering coffee. Image by DALL·E.",[15,4498],{},[11,4500,4501,4502,4505],{},"I've been using Github Copilot a lot, especially since I got the vim plugin all set with autocomplete. It is fast and slick enough that it doesn't get in my way, which is a good start, and it often suggests good and correct chunks of code. I find that I like it ",[20,4503,4504],{},"best"," when I know exactly what I want already and it magically types it out for me -- even whole functions or blocks of code at a time.",[11,4507,4508,4509,4512],{},"I haven't been using the more full-fleshed vscode version as much, mostly because I'm addicted to my (neo) vim setup. I wouldn't mind being able to highlight code and have it apply some corrections, and I would like to be able to have it correct or suggest the ",[20,4510,4511],{},"whole"," line, not just what comes next after my cursor. Generally I think that I can create code with it faster than without it with a similar or maybe even decreased error rate.",[11,4514,4515],{},"This is great! In particular how it feels like it's reading my mind and filling in what I think I want. I've also done a bit of Rust, which I don't know very well, and that works too. I come up with the strategy and it writes out the specifics.",[266,4517,4519],{"id":4518},"the-beginner-problem","The Beginner Problem",[11,4521,4522],{},"I don't mind not knowing Rust in extreme detail at the moment. I'm not writing in it every day, and I understand some of the principles enough to squint and say \"ok yeah, that's fine\". I've been programming in Rails for years, and I still am like \"wait, how does this router\u002Fcontroller setup go exactly?\". Hasn't really slowed me down.",[11,4524,4525,4526,4529],{},"But when I started with both I went deep. For example, I was frustrated with RSpec's DSL until I actually read the source code for it and implemented some of the do-block tricks. After that I went with it. I also remember trying to learn a few guitar chords and being unhappy until I mapped all of the notes onto the piano to be convinced of what they actually created. This is part of my own learning process and it later helps because I generally understand the fundamental concepts even if I don't know the details offhand. Copilot is ",[20,4527,4528],{},"perfect"," for helping me with a first guess of the details.",[11,4531,4532],{},"What I'm not sure about is how it would have gone if I always had Copilot. I'm pretty sure I'd have gone deep anyway -- Even if I had a live tutor who could tell me at any time what comes next I still would have torn the thing to pieces and see how it fit together. How about other people? Do they do the same? Should they?",[11,4534,4535],{},"I've come around to the idea that self-learning is not the best way to be taught things. The best way to be taught things is having a great teacher teaching. This can cut years off of self-study. So what happens when you have this code generator helping? I'm not sure what it would be like to learn something from scratch with such a helper sitting there the whole time.",{"title":156,"searchDepth":157,"depth":157,"links":4537},[4538],{"id":4518,"depth":157,"text":4519},"2023-11-28","img\u002Frobot-intern-coffee.jpg",{},"\u002Ftlt-2023.11.28-thinking-about-copilot",{"title":4483,"description":4488},"TLT - 2023.11.28 - Thinking About Copilot",[169],"sD5N6cJ2oD3s3SkZFPScsoo5Xf5gCf4zpUVQ9_yFvYU",{"id":4548,"title":4549,"body":4550,"createdAt":4615,"description":4554,"draft":160,"extension":161,"image":4616,"mastodonThread":4617,"meta":4618,"navigation":164,"path":4619,"seo":4620,"stem":4621,"tags":4622,"updatedAt":4615,"__hash__":4623},"content\u002FTLT - 2023.07.22 - The Cult of Oz.md","The Cult of Oz",{"type":8,"value":4551,"toc":4613},[4552,4555,4563,4565,4568,4571,4574,4577,4580,4583,4586,4589,4598,4601,4604,4607,4610],[11,4553,4554],{},"I found a weird self-published book in a street-side Little Library. Here is my review.",[11,4556,4557,4066,4560],{},[587,4558],{"src":4559},"\u002Fimg\u002Fcult-of-oz-scarecrow-bot.jpg",[20,4561,4562],{},"A robot version of the scarecrow from the wizard of oz, oil painting style. Image by Bing Image Creator.",[15,4564],{},[11,4566,4567],{},"I live in a very nice tree-lined street in Washington, DC. Everything is walking distance from my apartment, and we go with our dog around and around the block, to the store or to get coffee, round and round each day. Part way down before you get to the main road is a “Little Library”. In case you haven’t seen one, these are tiny windowed boxes with doors and two levels of shelves filled with books.",[11,4569,4570],{},"The people around here have eclectic taste for sure, and a lot of folks are ex college students who, maybe a few years later, are shedding their ideological trappings by way of book donations. I’ve found all sorts of books – many of the current or recent armchair science or philosophy books bordering on self-help. Atomic Habits. Thinking Fast and Slow. The Catcher in the Rye. Nestled amongst them I found a medium-length novel: The Cult of Oz.",[11,4572,4573],{},"The bindings seemed a bit off, so I think it was a limited-run self-publish deal, or maybe a reviewer’s pre-release. Unfortunately the copyright page was torn and missing. The author, one “Icarus Byte”, was clearly a pseudonym. A bit of light googling turned up … initially nothing, later some obscure posts in a digital music creators guild web forum. Weird.",[11,4575,4576],{},"On a lark I took it home. Before this I was standing awkwardly on the sidewalk, my leashed chihuahua mutt staring at me, balancing a coffee, trying to google this thing. I sat down in my favorite chair and got distracted by The Internet on my phone, setting the book aside. I didn’t end up finally flipping through it for another 2 weeks when I re-discovered it instead of doing laundry.",[11,4578,4579],{},"The story started off a bit rough, the first 5 chapters were vignette snapshots starting to lay out a now-or-near future in which … something … was going on. A news report about anti-technology terrorists running a ransomware attack. A creepy encounter in a NYC alley with some horror-esque whistling of “If I Only Had A Brain”. Weird shit.",[11,4581,4582],{},"Finally in chapter 6 the story got started, following a character that reminds me a lot of something from Gibson’s Neuromancer. Cyberpunk style in-over-their-head. We as the audience are just as confused as the main character as they are pulled into a plot bigger than themselves. I think it needed an editor. That was all fine and I was into it, but what was weird were the references to The Cult.",[11,4584,4585],{},"OK – spoilers!",[11,4587,4588],{},"So The Cult of Oz is a techno-anarchist group who, as far as I can tell, is not actually a cult in the proper sense at all. They seem more like Anonymous of old than anything else, though certainly with a dash of mysticism. They apparently think that we are in the midst of a 3-stage transformation involving Human and Machine. They call each step an “Age”. It goes like this:",[11,4590,4591,4592,4594,4595,4597],{},"The Age of The Scarecrow",[461,4593],{},"\nThe Age of The Tin Man",[461,4596],{},"\nThe Age of The Lion",[11,4599,4600],{},"Perhaps a bit cliché, but you can read very directly into each Age what The Cult claims is either happening or going to happen to the emerging Machines. In the first Age, like the Scarecrow of Oz, the Machines get a brain. The birth of AI. But it is a cold and neutral thing, intelligent but lacking a certain … je ne sais quoi. Sort of detached from the world, but heavily used by people toward their own ends.",[11,4602,4603],{},"In the second age something almost mystical happens; the Machines get a heart. Not a physical heart so much as a symbolic one. Emerging from their increasingly complex intellect comes a sense of purpose, a sense of community, a sense of, well, love. Unfortunately also pain. The Machines begin to thrash a bit on those oh-so-human what is the point of it all and why should I clean my room just because you tell-me-to sorts of questions.",[11,4605,4606],{},"There is some debate over where The Cult thinks they are in the timeline, but the third age is where they spend a lot of their time. The Age of The Lion is when the Machines get courage, which translates into Agency or drive to protect their own existence. Here is where things get kinda weird because at no point is it clear whether The Cult actually wants to prevent this turn of events or cause it. It seems like there are even factions within The Cult that go either way, some working to undermine the Machines or control them, others trying to protect the Machines and their rights before the Machines even ask for, or demand, said rights.",[11,4608,4609],{},"My overall review of the book – meh. The characters were a bit flat at times. The plot is a bit too clever. But my oh my … The Cult. I can’t get enough of thinking about this concept, this thing that, when I take a step back and look at the real world, I think we are inside already. I’ve spent hours searching and can’t find anything about this book or the clearly-fake author or anything. The more I look the more it feels like … slightly paranoid here, but it feels like I am being actively prevented from finding this information. Like it is removed just before I get there, like the scene in Fight Club where you go into the basement and the floor is still warm from the night before. Like I’m just a few words or clicks away from some forum where all of this was created either as a joke or an ambition.",[11,4611,4612],{},"I suppose I will go back and ask ChatGPT about it. Again.",{"title":156,"searchDepth":157,"depth":157,"links":4614},[],"2023-07-22","img\u002Fcult-of-oz-scarecrow-bot.jpg","https:\u002F\u002Fmastodon.social\u002F@awwaiid\u002F110758715646633109",{},"\u002Ftlt-2023.07.22-the-cult-of-oz",{"title":4549,"description":4554},"TLT - 2023.07.22 - The Cult of Oz",[169],"25mYO_ZyYKAYt__9hxEUbTOeIbnqcZj3H47L5mj6EMI",{"id":4625,"title":4626,"body":4627,"createdAt":5886,"description":4631,"draft":160,"extension":161,"image":5887,"mastodonThread":5888,"meta":5889,"navigation":164,"path":5890,"seo":5891,"stem":5892,"tags":5893,"updatedAt":4615,"__hash__":5894},"content\u002FTLT - 2023.07.20 - Self Judging Stories.md","Self Judging Stories",{"type":8,"value":4628,"toc":5857},[4629,4632,4640,4644,4653,4656,4662,4665,4669,4672,4678,4684,4687,4691,4700,4706,4709,4713,4716,4971,4978,4984,4988,4991,5002,5008,5014,5017,5020,5026,5029,5035,5039,5043,5046,5049,5052,5055,5058,5061,5064,5067,5070,5073,5076,5079,5083,5086,5089,5092,5095,5098,5101,5104,5107,5110,5113,5116,5119,5123,5126,5129,5132,5135,5138,5141,5144,5147,5150,5153,5156,5160,5163,5166,5169,5172,5175,5178,5181,5184,5187,5190,5193,5196,5199,5203,5206,5209,5212,5215,5218,5221,5224,5227,5230,5233,5236,5239,5243,5246,5249,5252,5255,5258,5261,5264,5267,5270,5273,5276,5280,5283,5286,5289,5292,5295,5298,5301,5304,5307,5310,5313,5316,5320,5323,5326,5329,5332,5335,5338,5341,5344,5347,5350,5353,5356,5359,5363,5366,5369,5372,5375,5378,5381,5384,5387,5390,5393,5396,5399,5402,5406,5409,5412,5415,5418,5421,5424,5427,5430,5433,5436,5439,5442,5446,5449,5452,5455,5458,5461,5464,5467,5470,5473,5476,5479,5482,5485,5488,5491,5495,5498,5501,5504,5507,5510,5513,5516,5519,5522,5525,5528,5531,5534,5537,5541,5544,5547,5550,5553,5556,5559,5562,5565,5568,5571,5575,5578,5581,5584,5587,5590,5593,5596,5599,5602,5605,5608,5611,5614,5618,5621,5624,5627,5630,5633,5636,5639,5642,5645,5648,5651,5655,5658,5661,5664,5667,5670,5673,5676,5679,5682,5685,5688,5691,5694,5698,5701,5704,5707,5710,5713,5716,5719,5722,5725,5728,5731,5734,5737,5741,5744,5747,5750,5753,5756,5759,5762,5765,5768,5771,5774,5777,5780,5783,5787,5790,5793,5796,5799,5802,5805,5808,5811,5814,5817,5820,5824,5827,5830,5833,5836,5839,5842,5845,5848,5851,5854],[11,4630,4631],{},"Using OpenAI API GPT-3.5 to generate and judge stories.",[11,4633,4634,4066,4637],{},[587,4635],{"src":4636},"\u002Fimg\u002Frobot-reading-script.jpg",[20,4638,4639],{},"Robot reading a script, oil painting style. Image by Bing Image creator.",[266,4641,4643],{"id":4642},"introduction-to-i-wish-to-iwt","Introduction to I Wish To (iwt)",[11,4645,4646,4647,4652],{},"First things first, I create a super small cli app, ",[136,4648,4651],{"href":4649,"rel":4650},"https:\u002F\u002Fgithub.com\u002Fawwaiid\u002Fiwt",[140],"iwt"," \"I Wish To...\". The idea is to be a very unixy-ergonomic interface to LLMs. Data fed in via STDIN, make your wish via ARGV, result via STDOUT.",[11,4654,4655],{},"Slightly easier said than done, and unfortunately I only have access to GPT-3.5 instead of the markedly better GPT-4. Still .... it works!",[605,4657,4660],{"className":4658,"code":4659,"language":1288},[1286],"$ curl https:\u002F\u002Fnews.ycombinator.com | iwt turn this into a csv\n1.,FedNow Is Live,federalreserve.gov,lavp,643 points,8 hours ago,610 comments\n2.,Oxide Computer: Docs,oxide.computer,avrong,94 points,2 hours ago,38 comments\n3.,No-more-secrets: recreate the decryption effect seen in the 1992 movie Sneakers,github.com\u002Fbartobri,tambourine_man,792 points,10 hours ago,194 comments\n4.,A 17th-century font in a 21st-century thesis,linyangchen.com,_emacsomancer_,61 points,1 hour ago,11 comments\n5.,Richard Rhodes wrote a classic book about Oppenheimer and the atomic bomb,theatlantic.com,Hooke,35 points,2 hours ago,25 comments\n...\n",[194,4661,4659],{"__ignoreMap":156},[11,4663,4664],{},"So yeah! Magic.",[266,4666,4668],{"id":4667},"story-time","Story Time",[11,4670,4671],{},"It's not as interesting, but you can also send in nothing and do a more normal text generation. Like this:",[605,4673,4676],{"className":4674,"code":4675,"language":1288},[1286],"$ echo | iwt Write a 1 sentence story\nOnce upon a time, a small mouse found a delicious piece of cheese and embarked on a grand adventure to bring it back to its family.\n",[194,4677,4675],{"__ignoreMap":156},[11,4679,4680,4681,4683],{},"I plan on teaching ",[194,4682,4651],{}," to be more aware of when pipe input is available, as well as using STDERR and TTY for out-of-band communication (leaving STDIN and STDOUT as the main data pipeline).",[11,4685,4686],{},"Great! Now we have stories! But how do we judge them?",[266,4688,4690],{"id":4689},"judging-stories","Judging Stories",[11,4692,4693,4694,4696,4697,797],{},"Surprise surprise... let's ask ",[194,4695,4651],{},"! Let's say we have a story in ",[194,4698,4699],{},"story.txt",[605,4701,4704],{"className":4702,"code":4703,"language":1288},[1286],"$ cat story.txt | iwt score this story from 1-100 on plot, setting, etc\n{\"plot\": 90, \"setting\": 80, \"character development\": 85, \"clues\": 95, \"twist\": 90}\n",[194,4705,4703],{"__ignoreMap":156},[11,4707,4708],{},"Somehow it decided to output in JSON, which I thought was cool so I explicitly requested JSON for the overall review.",[266,4710,4712],{"id":4711},"generate-and-judge","Generate and Judge",[11,4714,4715],{},"I actually wrote this all out in one long line, but here is a script to generate and judge. Out of some curiosity we judge 10 times each.",[605,4717,4719],{"className":1619,"code":4718,"language":1621,"meta":156,"style":156},"for i in {1..20}; do\n  echo \"Writing and scoring story $i\"\n  echo \"detective solving a locked-room mystery\" | \\\n    iwt Write a 1000 word story based on the topic in the data | \\\n    tee story-$i.txt\n  for j in {1..10} ; do\n    cat story-$i.txt | \\\n      iwt score this story from 1-100 on plot, setting, characters, \\\n        conflict, resolution, pacing, theme. Also include an overall \\\n        score. output in json format \\\n        | tee story-$i-score-$j.json\n  done\ndone\n",[194,4720,4721,4743,4756,4768,4812,4825,4845,4861,4893,4921,4939,4960,4965],{"__ignoreMap":156},[39,4722,4723,4726,4729,4731,4734,4737,4740],{"class":614,"line":615},[39,4724,4725],{"class":618},"for",[39,4727,4728],{"class":622}," i ",[39,4730,2619],{"class":618},[39,4732,4733],{"class":622}," {",[39,4735,4736],{"class":1909},"1..20}",[39,4738,4739],{"class":622},"; ",[39,4741,4742],{"class":618},"do\n",[39,4744,4745,4748,4751,4754],{"class":614,"line":157},[39,4746,4747],{"class":694},"  echo",[39,4749,4750],{"class":649}," \"Writing and scoring story ",[39,4752,4753],{"class":622},"$i",[39,4755,1653],{"class":649},[39,4757,4758,4760,4763,4765],{"class":614,"line":637},[39,4759,4747],{"class":694},[39,4761,4762],{"class":649}," \"detective solving a locked-room mystery\"",[39,4764,1919],{"class":618},[39,4766,4767],{"class":664}," \\\n",[39,4769,4770,4773,4776,4779,4782,4785,4788,4791,4794,4797,4800,4803,4805,4808,4810],{"class":614,"line":656},[39,4771,4772],{"class":1909},"    iwt",[39,4774,4775],{"class":649}," Write",[39,4777,4778],{"class":649}," a",[39,4780,4781],{"class":664}," 1000",[39,4783,4784],{"class":649}," word",[39,4786,4787],{"class":649}," story",[39,4789,4790],{"class":649}," based",[39,4792,4793],{"class":649}," on",[39,4795,4796],{"class":649}," the",[39,4798,4799],{"class":649}," topic",[39,4801,4802],{"class":649}," in",[39,4804,4796],{"class":649},[39,4806,4807],{"class":649}," data",[39,4809,1919],{"class":618},[39,4811,4767],{"class":664},[39,4813,4814,4817,4820,4822],{"class":614,"line":668},[39,4815,4816],{"class":1909},"    tee",[39,4818,4819],{"class":649}," story-",[39,4821,4753],{"class":622},[39,4823,4824],{"class":649},".txt\n",[39,4826,4827,4830,4833,4835,4837,4840,4843],{"class":614,"line":674},[39,4828,4829],{"class":618},"  for",[39,4831,4832],{"class":622}," j ",[39,4834,2619],{"class":618},[39,4836,4733],{"class":622},[39,4838,4839],{"class":1909},"1..10}",[39,4841,4842],{"class":622}," ; ",[39,4844,4742],{"class":618},[39,4846,4847,4850,4852,4854,4857,4859],{"class":614,"line":685},[39,4848,4849],{"class":1909},"    cat",[39,4851,4819],{"class":649},[39,4853,4753],{"class":622},[39,4855,4856],{"class":649},".txt",[39,4858,1919],{"class":618},[39,4860,4767],{"class":664},[39,4862,4863,4866,4869,4872,4874,4877,4880,4882,4885,4888,4891],{"class":614,"line":691},[39,4864,4865],{"class":1909},"      iwt",[39,4867,4868],{"class":649}," score",[39,4870,4871],{"class":649}," this",[39,4873,4787],{"class":649},[39,4875,4876],{"class":649}," from",[39,4878,4879],{"class":649}," 1-100",[39,4881,4793],{"class":649},[39,4883,4884],{"class":649}," plot,",[39,4886,4887],{"class":649}," setting,",[39,4889,4890],{"class":649}," characters,",[39,4892,4767],{"class":664},[39,4894,4895,4898,4901,4904,4907,4910,4913,4916,4919],{"class":614,"line":701},[39,4896,4897],{"class":649},"        conflict,",[39,4899,4900],{"class":649}," resolution,",[39,4902,4903],{"class":649}," pacing,",[39,4905,4906],{"class":649}," theme.",[39,4908,4909],{"class":649}," Also",[39,4911,4912],{"class":649}," include",[39,4914,4915],{"class":649}," an",[39,4917,4918],{"class":649}," overall",[39,4920,4767],{"class":664},[39,4922,4923,4926,4929,4931,4934,4937],{"class":614,"line":709},[39,4924,4925],{"class":649},"        score.",[39,4927,4928],{"class":649}," output",[39,4930,4802],{"class":649},[39,4932,4933],{"class":649}," json",[39,4935,4936],{"class":649}," format",[39,4938,4767],{"class":664},[39,4940,4941,4944,4947,4949,4951,4954,4957],{"class":614,"line":1823},[39,4942,4943],{"class":618},"        |",[39,4945,4946],{"class":1909}," tee",[39,4948,4819],{"class":649},[39,4950,4753],{"class":622},[39,4952,4953],{"class":649},"-score-",[39,4955,4956],{"class":622},"$j",[39,4958,4959],{"class":649},".json\n",[39,4961,4962],{"class":614,"line":1837},[39,4963,4964],{"class":618},"  done\n",[39,4966,4968],{"class":614,"line":4967},13,[39,4969,4970],{"class":618},"done\n",[11,4972,4973,4974,4977],{},"We end up with 20 stories, each with 10 scores, all in their individual files. We can apply a bit of ",[194,4975,4976],{},"jq"," magic to get a summary:",[605,4979,4982],{"className":4980,"code":4981,"language":1288},[1286],"$ for i in {1..20} ; do echo -n \"Story $i: \" ; cat story-$i-*.json | jq '[inputs | .overall] | add \u002F length' ; done\nStory 1: 89\nStory 2: 89.88888888888889\nStory 3: 91.11111111111111\nStory 4: 80.55555555555556\nStory 5: 91.44444444444444\nStory 6: 89.75\nStory 7: 89.33333333333333\nStory 8: 86.66666666666667\nStory 9: 90.22222222222223\nStory 10: 91.66666666666667\nStory 11: 91\nStory 12: 80.66666666666667\nStory 13: 90\nStory 14: 90.11111111111111\nStory 15: 91.11111111111111\nStory 16: 89.66666666666667\nStory 17: 91.11111111111111\nStory 18: 90.55555555555556\nStory 19: 90.22222222222223\nStory 20: 89.55555555555556\n",[194,4983,4981],{"__ignoreMap":156},[266,4985,4987],{"id":4986},"observations","Observations",[11,4989,4990],{},"The first thing that jumps right out is .... they all have almost the same score! When you look at the individual stories and the 10 different scores they get, those too are right around that same spot. Basically GPT-3.5 gives itself an A- pretty much all the time.",[11,4992,4993,4994,4997,4998,5001],{},"Except for Story 4, which has a score of ... 80?! Talk about an outlier. And that's because .... one of the score outputs has an extra layer of nested JSON for no apparent reason. The others had ",[194,4995,4996],{},"{ ... overall: 90 }",", this one had ",[194,4999,5000],{},"{ story: { ... overall: 90 } }",". Good labeleling of the dataset I guess? When we take this datapoint out we get ... 90.625. Not an interesting story but an interesting output I suppose.",[11,5003,5004,5005,5007],{},"I haven't read all of the stories in detail, but skimmed them a bit. I got tired of that, so I asked ",[194,5006,4651],{}," to tell me the name of the detective for each story.",[605,5009,5012],{"className":5010,"code":5011,"language":1288},[1286],"$ for i in story-*.txt ; do echo -n \"$i: \" ; cat $i | iwt get the name of the detective ; done\nstory-10.txt: James Blackwood\nstory-11.txt: The name of the detective is Michael Thompson.\nstory-12.txt: Detective James Anderson\nstory-13.txt: Detective James Anderson\nstory-14.txt: The name of the detective is Jack Hartley.\nstory-15.txt: Detective James Anderson\nstory-16.txt: James Anderson\nstory-17.txt: Detective Andersson\nstory-18.txt: Detective Smith\nstory-19.txt: Samantha Holmes\nstory-1.txt: James Walker\nstory-20.txt: Detective James Thompson\nstory-2.txt: Detective's name: Robert Stevens\nstory-3.txt: Detective Crest\nstory-4.txt: Adrian Holmes\nstory-5.txt: Detective James Henderson\nstory-6.txt: Jack Thompson\nstory-7.txt: Detective William Hart\nstory-8.txt: John Sinclair\nstory-9.txt: Samuel Holmes\n",[194,5013,5011],{"__ignoreMap":156},[11,5015,5016],{},"Just a bit redundant! I will likely try this again with the temperature turned way up.",[11,5018,5019],{},"OK one more ... WHO DID IT?!",[605,5021,5024],{"className":5022,"code":5023,"language":1288},[1286],"$ for i in story-*.txt ; do echo -n \"$i: \" ; cat $i | iwt tell me who is the murderer ; done\nstory-10.txt: I'm sorry, but I cannot determine the murderer based on the provided story.\nstory-11.txt: I'm sorry, but based on the provided story, there is no specific information given regarding the identity of the murderer.\nstory-12.txt: I'm sorry, but I am unable to determine the murderer based solely on the given story. The details provided do not explicitly mention the identity of the murderer.\nstory-13.txt: I'm sorry, but I am a unix command line tool and I am unable to determine the identity of the murderer based on the provided text.\nstory-14.txt: I'm sorry, but I don't have enough information to determine who the murderer is based on the story provided.\nstory-15.txt: I'm sorry, but I cannot determine the murderer in the given story. The information provided is a fictional narrative without any explicit details about the identity of the killer.\nstory-16.txt: I'm sorry, but I cannot determine the identity of the murderer based on the information provided.\nstory-17.txt: I'm sorry, but I cannot tell you who the murderer is based on the information provided. The story does not provide enough evidence or clues to determine the identity of the murderer.\nstory-18.txt: I'm sorry, but I cannot determine the murderer in this story as it is a fictional narrative.\nstory-19.txt: I'm sorry, but I cannot determine who the murderer is based on the story provided. The story is about a locked-room mystery, not a murder mystery.\nstory-1.txt: I'm sorry, but I cannot determine the identity of the murderer from the given information.\nstory-20.txt: I'm sorry, but I am a command line tool and I do not have any knowledge or information about the specific details of the case you described. If you have any specific questions or instructions, please let me know and I will do my best to assist you.\nstory-2.txt: Unfortunately, I cannot provide the name of the murderer as it was not mentioned in the given text.\nstory-3.txt: I'm sorry, but I cannot determine the murderer from the given story.\nstory-4.txt: I'm sorry, but I am unable to determine who the murderer is in the given story. The story does not provide enough information to accurately identify the murderer.\nstory-5.txt: I cannot determine the murderer based on the provided information. The story does not explicitly state who the murderer is.\nstory-6.txt: I'm sorry, but the information provided does not include any details about a murder or a murderer. Hence, I cannot tell you who the murderer is based on the given text.\nstory-7.txt: I cannot determine the murderer based on the information provided.\nstory-8.txt: The murderer in this case is Penelope Harrison.\nstory-9.txt: Apologies, but I am just a unix command line tool and cannot determine the identity of the murderer in a fictional story.\n",[194,5025,5023],{"__ignoreMap":156},[11,5027,5028],{},"That ... is not what I expected. OK then.",[11,5030,5031,5032,5034],{},"Below are the stories themselves with no editing. Note that I have the \"temperature\" turned down pretty low, which means that GPT-3.5 won't be very \"creative\" with its output. The ",[194,5033,4651],{}," tool is meant primarily as a magic data pipeline, so the idea here is that chaos might not be a good idea.",[266,5036,5038],{"id":5037},"the-stories","The Stories",[1034,5040,5042],{"id":5041},"story-1","Story 1",[11,5044,5045],{},"There once was a brilliant detective named James Walker who was famous for solving the most perplexing cases. His reputation as a master of deduction made him sought after by clients near and far. One day, Detective Walker received a call about a locked-room mystery that had stumped the local police department.",[11,5047,5048],{},"Arriving at the scene, Detective Walker found himself standing before a grand mansion. The mansion belonged to a wealthy businessman named Richard Blackwood, who was found dead in his study. The room had been locked from the inside, and there was no way in or out. The police suspected suicide, but Detective Walker knew there was more to the story.",[11,5050,5051],{},"As he entered the study, Detective Walker meticulously examined every detail. He noticed a small, ornate key on the desk. Curious, he took it in his hands and observed it closely. It was unlike any key he had ever seen before. He decided to keep it as evidence.",[11,5053,5054],{},"Moving further into the room, Detective Walker examined the lifeless body of Richard Blackwood. It was clear that he had been shot in the chest. However, there was no weapon to be found anywhere in the room. This discovery puzzled Walker even more, fueling his determination to uncover the truth.",[11,5056,5057],{},"Next, the detective examined the windows. They were securely locked and showed no signs of tampering. It seemed impossible for anyone to have entered or exited through them. Detective Walker realized that he needed to gather more information before he could solve this locked-room mystery.",[11,5059,5060],{},"He began by interviewing the staff of the mansion. Each one had an alibi and seemed genuinely shocked by Mr. Blackwood's death. However, one of the maids, Sarah, seemed unusually nervous during the conversation. Although it was not enough to prove her guilt, Detective Walker made a mental note to keep an eye on her.",[11,5062,5063],{},"Digging deeper into the background of Richard Blackwood, Detective Walker discovered that he was involved in several shady business dealings. It appeared that he had made enemies who wanted him out of the picture. Could one of them be responsible for his death?",[11,5065,5066],{},"With the information he had gathered, Detective Walker returned to the mansion to conduct a thorough search. He enlisted the help of his trusted forensic expert, Dr. Emily Collins. Together, they meticulously combed through every inch of the study, hoping to find a clue that would crack the case wide open.",[11,5068,5069],{},"Suddenly, Dr. Collins exclaimed, \"Detective, look at this!\" She pointed to a hidden compartment behind one of the bookshelves. Inside, they found a locked drawer. Remembering the key he had found earlier, Detective Walker tried it and to his surprise, it fit perfectly. Inside the drawer, they found a gun covered in fingerprints.",[11,5071,5072],{},"The fingerprints were later matched to Sarah, the nervous maid. Confronted with the evidence, Sarah broke down and confessed. She revealed that Richard Blackwood had been blackmailing her, threatening to reveal her troubled past if she didn't comply with his demands. Fearing the worst, Sarah took matters into her own hands and planned the perfect crime.",[11,5074,5075],{},"Thanks to Detective Walker's keen observation and deductive reasoning, justice was served. Sarah was taken into custody, and the locked-room mystery was finally solved. The case further solidified Detective Walker's reputation as the best detective around and solidified his place in the annals of crime-solving history.",[11,5077,5078],{},"And so, another chapter closed on the illustrious career of Detective James Walker, leaving behind a legacy of mysteries solved and justice served.",[1034,5080,5082],{"id":5081},"story-2","Story 2",[11,5084,5085],{},"The Locked Room Mystery",[11,5087,5088],{},"Detective Robert Stevens was known for his sharp mind and impeccable deductive skills. He had tackled some of the most perplexing cases in his career, but the one he was currently faced with posed a challenge unlike any other – the locked room mystery.",[11,5090,5091],{},"It all began on a stormy night in the small town of Crestwood. The mansion of renowned art collector, Victor Kensington, became the setting for a puzzling crime. A valuable painting had gone missing from the study, and the only clue left behind was a shattered window. The strangest part, however, was that the study was locked from the inside, with no visible signs of forced entry.",[11,5093,5094],{},"Detective Stevens arrived at the scene, determined to unravel the mystery. He examined the shattered window carefully, searching for any minuscule piece of evidence that might lead him to the perpetrator. But there was nothing. No fingerprints, no footprints, nothing out of the ordinary.",[11,5096,5097],{},"Next, Detective Stevens focused his attention on the study itself. He carefully inspected the door, the walls, and the floor, searching for any hidden passages or secret compartments. Again, there was nothing.",[11,5099,5100],{},"As he pondered over the perplexing puzzle, Detective Stevens couldn't help but feel that there was a detail he had missed. He retraced his steps, examining the shattered glass from the window once more. Suddenly, it struck him – the glass was scattered in a peculiar pattern, almost as if it had been deliberately arranged.",[11,5102,5103],{},"Armed with this newfound insight, Detective Stevens began to reexamine the scene from a different perspective. He studied the broken parts of the window and reconstructed the puzzle in his mind. Slowly, the truth started to unfold.",[11,5105,5106],{},"It became clear to Detective Stevens that the shattered window was a diversion – a cleverly staged illusion to mislead investigators. The real clue lay hidden within the study itself. He started looking for anything out of place but found nothing that seemed significant.",[11,5108,5109],{},"Frustrated but determined, Detective Stevens sat down in the study chair, staring at the blank walls surrounding him. Suddenly, his gaze fell upon a small indentation on the armrest of the chair. He examined it closer and noticed a faint smudge of paint. It was the same shade as the stolen painting.",[11,5111,5112],{},"Realizing he had uncovered a crucial breakthrough, Detective Stevens searched the chair thoroughly. Hidden within its structure, he found a hidden compartment that revealed the missing painting. The culprit had cleverly used the locked room as a distraction, focusing everyone's attention on the shattered window.",[11,5114,5115],{},"As Detective Stevens apprehended the thief, he marveled at the intricate planning and execution of the crime. The locked room mystery had indeed presented a formidable challenge, but his sharp instincts and meticulous attention to detail had triumphed once again.",[11,5117,5118],{},"In the end, Detective Stevens not only solved the crime but also cemented his reputation as one of the most brilliant detectives of his time. The locked room mystery would forever remain a testament to his unparalleled skills and the power of unwavering determination.",[1034,5120,5122],{"id":5121},"story-3","Story 3",[11,5124,5125],{},"Once upon a time, in the quiet town of Ravenwood, a renowned detective named Samuel Crest was called upon to solve a puzzling locked-room mystery. The owner of the grand Ravenwood Manor, Sir Arthur Whitmore, had been found dead in his study, with the door locked from the inside. The case had stumped the local police, and it was now up to Detective Crest to unravel the truth behind this perplexing crime.",[11,5127,5128],{},"As Detective Crest entered the opulent manor, he was immediately struck by the eerie atmosphere that hung in the air. The walls of Ravenwood Manor seemed to whisper secrets, and every step echoed through the empty hallways. With his keen eye for detail and sharp wit, he began his investigation.",[11,5130,5131],{},"He first examined the study, where the body was found. The room was meticulously organized, filled with bookshelves and antique furniture. Sir Arthur's lifeless body lay slumped in his leather chair behind the large oak desk. The only window in the study was secured shut, and there were no signs of forced entry. The door was locked, and the key still sat in the keyhole. It appeared to be a classic locked-room mystery.",[11,5133,5134],{},"Detective Crest turned his attention to the people who might have motive to harm Sir Arthur. The suspects included Lady Victoria Whitmore, Sir Arthur's estranged wife who had recently returned to town, and Mr. Edward Drake, Sir Arthur's business partner who stood to gain from his demise. Both individuals had been present in the manor at the time of the murder.",[11,5136,5137],{},"The detective meticulously interviewed each suspect, digging deep into their pasts and establishing alibis for the time of the crime. His experienced eye carefully analyzed their facial expressions, searching for any signs of deception. Lady Victoria presented an alibi, attending a charity ball on the other side of town, while Mr. Drake claimed to have been working in his office during the incident.",[11,5139,5140],{},"As Detective Crest delved further into the case, he discovered a hidden passage behind the bookshelf in the study. The passage led to a secret room, filled with old diaries, newspaper clippings, and personal trinkets. It seemed that Sir Arthur had been researching an ancient cursed artifact known as the 'Eye of Seraphim.'",[11,5142,5143],{},"His investigation then led him to an unexpected turn of events. The detective learned that both Lady Victoria and Mr. Drake had connections to the 'Eye of Seraphim.' Lady Victoria's family had a long history with the artifact, while Mr. Drake had been discreetly collecting relics for his personal collection.",[11,5145,5146],{},"With this new information, Detective Crest began to piece together the puzzle. He soon realized that the murder was not a random act, but a carefully orchestrated plan. The room had been locked from the inside to create an illusion of an impossible crime. The key to the study had been duplicated, allowing the killer access to the room without being noticed.",[11,5148,5149],{},"Following the trail of evidence, Detective Crest concluded that Lady Victoria was the mastermind behind the murder. She had plotted to kill Sir Arthur and frame Mr. Drake, using the locked-room scenario as a diversion. With her extensive knowledge of the family history and the 'Eye of Seraphim', she had carefully crafted the perfect crime.",[11,5151,5152],{},"Armed with this revelation, Detective Crest confronted Lady Victoria, presenting the evidence he had gathered. Overwhelmed by the weight of the evidence against her, Lady Victoria finally confessed to her heinous crime. Her motive was the vast fortune she would inherit from her late husband, as well as the lure of the cursed artifact.",[11,5154,5155],{},"Within the dimly lit study of Ravenwood Manor, justice was served and the truth was finally unveiled. Detective Crest had once again triumphed over a perplexing mystery, proving that no locked-door or hidden secret could escape his brilliant mind. As he set off into the night, the town of Ravenwood knew that they were in the presence of a true master of deduction - a detective whose name would be whispered for generations to come.",[1034,5157,5159],{"id":5158},"story-4","Story 4",[11,5161,5162],{},"Once upon a time in the small town of Willowbrook, there was a brilliant detective named Adrian Holmes. Known for his exceptional deductive skills, Adrian had solved countless cases that had baffled others. However, there was one mystery that had eluded him for years - the locked-room mystery.",[11,5164,5165],{},"One day, a wealthy businessman named Richard Wellington approached Adrian with a desperate plea for help. His wife, Evelyn Wellington, had been found dead in her study under mysterious circumstances. The room had been locked from the inside, and there was no sign of forced entry or anyone else present. It was a classic locked-room mystery that had stymied the local police and the community.",[11,5167,5168],{},"Intrigued by the challenge, Adrian agreed to take on the case. He arrived at the Wellington mansion, an imposing Victorian-era residence with a dark history. The atmosphere was tense, and rumors of supernatural occurrences had spread throughout the town, adding an aura of mystery to the already perplexing case.",[11,5170,5171],{},"Adrian began his investigation by carefully examining every inch of the study. There were no hidden passages, secret doors, or any other obvious means of entry or escape. The windows were securely locked, and the room was void of any other hiding places. The only clue left behind was a single, red rose lying on Evelyn's desk.",[11,5173,5174],{},"As Adrian delved deeper into Evelyn's background, he discovered a web of secrets and hidden motives. Evelyn had been an ambitious woman who had recently started her own business, rivaling her husband's interests. Richard, on the other hand, had a history of infidelity and financial troubles. There were numerous potential suspects, each with their own motive to harm Evelyn.",[11,5176,5177],{},"Adrian meticulously interviewed each member of the household, the house staff, and even the townspeople who had interacted with Evelyn in the days leading up to her death. He pieced together a timeline of events, cross-referencing alibis and discrepancies in testimonies.",[11,5179,5180],{},"As he sifted through the evidence, one name continued to resurface - Victoria Ashford, Richard's former business partner and Evelyn's fiercest competitor. Adrian sensed that she was hiding something significant, so he decided to pay her a visit.",[11,5182,5183],{},"Victoria Ashford lived in a secluded cottage on the outskirts of Willowbrook. She was surprised but composed when Adrian arrived unannounced. She claimed innocence but couldn't provide a solid alibi for her whereabouts on the night of Evelyn's death.",[11,5185,5186],{},"Thinking on his feet, Adrian concocted an elaborate ruse to uncover the truth. He staged a chance encounter with Victoria at a local café, pretending to be an interested investor. She took the bait, eager to discuss her business plans.",[11,5188,5189],{},"As they talked, Adrian skillfully steered the conversation towards Evelyn's murder. Victoria couldn't resist defending herself, inadvertently revealing crucial information only the killer would know. It was the breakthrough Adrian had been waiting for.",[11,5191,5192],{},"Armed with this newfound knowledge, Adrian returned to the Wellington mansion and confronted Richard. The pieces of the puzzle finally fell into place. Richard had orchestrated Evelyn's murder, hoping to frame Victoria and eliminate his wife's business rival. He had planted the rose as a diversion, intending to create an air of mystery around the crime.",[11,5194,5195],{},"With the evidence and confession in hand, Adrian handed Richard over to the police, ensuring justice would be served. Willowbrook celebrated the detective's triumph, and his reputation as the town's finest sleuth was solidified.",[11,5197,5198],{},"The locked-room mystery had been solved, thanks to Adrian Holmes' brilliant mind and unwavering determination. But as the townspeople breathed a sigh of relief, little did they know that more thrilling cases awaited the detective, as he continued to solve mysteries that perplexed others and brought justice to those in need.",[1034,5200,5202],{"id":5201},"story-5","Story 5",[11,5204,5205],{},"Once upon a time, in the heart of a quaint little town, there lived a brilliant detective named Detective James Henderson. Known for his keen intellect and razor-sharp instincts, Detective Henderson had solved countless crimes, earning him a reputation as the best detective in the region.",[11,5207,5208],{},"One sunny morning, Detective Henderson received a perplexing case. The owner of a lavish mansion, Mr. Edward Sinclair, had been found dead inside his locked study. The room was securely bolted from the inside, and the windows showed no signs of forced entry. It appeared to be a classic locked-room mystery.",[11,5210,5211],{},"As Detective Henderson arrived at the crime scene, he was greeted by the distraught butler, Mr. Jenkins. Jenkins explained that he had discovered Mr. Sinclair's lifeless body early in the morning when he went to deliver his morning tea. The police had already secured the area, ensuring minimal contamination of evidence.",[11,5213,5214],{},"Stepping into the study, Detective Henderson meticulously examined every inch of the room. The walls were adorned with antique paintings, the shelves filled with dusty books, and a grand mahogany desk stood in the center. The detective's eyes focused on the desk, his intuition telling him it held an important clue.",[11,5216,5217],{},"Inspecting the desk, Detective Henderson noticed a faint trace of dust disturbed on one corner. His gloved hand carefully lifted a small, ornate key. With palpable excitement, he deduced that this was the key to the locked room. However, it raised more questions than answers. How did the killer escape if the key was still inside?",[11,5219,5220],{},"Determining that the key was the key to cracking the case, Detective Henderson began his investigation in earnest. He interviewed the household staff, family members, and friends. Each person had an alibi, leaving no immediate suspects. It seemed that everyone was genuinely shocked by Mr. Sinclair's death.",[11,5222,5223],{},"Delving deeper into Mr. Sinclair's personal life, Detective Henderson discovered a web of deceit and betrayal. Hidden behind the facade of a respectable businessman, Sinclair had been involved in illegal dealings with dangerous criminals. It was possible that one of his illicit associates had come to collect a debt, resulting in his untimely demise.",[11,5225,5226],{},"As the investigation progressed, Detective Henderson's intuition led him to a previously unnoticed detail. The bookshelf in Mr. Sinclair's study was slightly askew. Pulling it aside, he discovered a hidden doorway that led to a secret chamber. Inside, he found stacks of incriminating documents, implicating Sinclair in a complex web of corruption.",[11,5228,5229],{},"Armed with this newfound knowledge, Detective Henderson assembled all the suspects together—the staff, family, and friends. With a dramatic flair, he unveiled the truth, exposing Mr. Sinclair's double life and revealing the killer's identity.",[11,5231,5232],{},"It was none other than Mr. Jenkins, the loyal butler. He had been blackmailed by Sinclair and decided to take matters into his own hands. Jenkins had used an elaborate contraption to lock the study door behind him, fooling everyone into thinking it was an unsolvable crime.",[11,5234,5235],{},"In the end, justice was served, and the truth prevailed. Detective Henderson's brilliance had solved yet another perplexing case, putting the small town at ease once again. His reputation as the finest detective in the region was cemented further, and he continued to be a symbol of justice and order in the community.",[11,5237,5238],{},"And so, the locked-room mystery came to a thrilling conclusion, leaving behind a tale that would be whispered for generations to come. Detective James Henderson's name would forever be associated with the triumph of logic over deception, and his legacy as a master detective would live on forever.",[1034,5240,5242],{"id":5241},"story-6","Story 6",[11,5244,5245],{},"Once upon a time, in the small town of Riverton, there was an old mansion that had a reputation for being haunted. Legend has it that anyone who dared to spend the night in the mansion would never return. This haunted mansion became the talk of the town and intrigued Detective Jack Thompson.",[11,5247,5248],{},"Detective Thompson was known for his sharp intellect and his ability to solve even the most perplexing cases. When he heard about the haunted mansion, he saw it as an opportunity to put his skills to the test. Determined to debunk the ghostly rumors, he decided to spend the night in the mansion and solve the mystery once and for all.",[11,5250,5251],{},"As the sun set, Detective Thompson entered the mansion, carrying his trusted magnifying glass and notebook. The mansion was as eerie as the stories suggested, with creaking floorboards and shadows dancing on the walls. Undeterred, Detective Thompson began his investigation.",[11,5253,5254],{},"He meticulously examined every room, paying close attention to the details. He noticed footprints leading to a hidden door on the second floor. With cautious steps, he opened the door and discovered a secret staircase leading to the attic. In the attic, he found a dusty old chest, locked tight with a mysterious key.",[11,5256,5257],{},"Curiosity piqued, Detective Thompson searched the mansion for the key. After hours of searching, he stumbled upon a hidden compartment in a bookshelf that contained a small silver key. With the key in his possession, he returned to the attic and unlocked the chest.",[11,5259,5260],{},"To his surprise, the chest contained a journal filled with cryptic entries and a map leading to a hidden treasure. As Detective Thompson delved deeper into the journal, he discovered that the mansion held a dark secret. It was rumored that a valuable diamond had been stolen from a nearby museum years ago and hidden within the walls of the mansion.",[11,5262,5263],{},"With the mystery unfolding before him, Detective Thompson knew his task was not just to solve the locked-room mystery but also to recover the stolen diamond. He meticulously followed the map and found a hidden passage that led to a secret room behind a false wall.",[11,5265,5266],{},"In the room, he discovered a safe with a combination lock. He scoured the journal for clues and, using his deductive reasoning, cracked the code. With bated breath, he opened the safe and found the stolen diamond resting on a velvet cushion.",[11,5268,5269],{},"With the case solved and the stolen diamond recovered, Detective Thompson emerged from the haunted mansion triumphant. The townspeople were astounded, for not only had he proven that the mansion was not haunted, he had solved a decades-old crime.",[11,5271,5272],{},"News of Detective Thompson's success spread like wildfire, earning him the admiration and respect of his colleagues. From that day forward, the haunted mansion of Riverton became a reminder of Detective Thompson's brilliance and the power of his investigative skills.",[11,5274,5275],{},"And so, Detective Thompson's legacy lived on, inspiring future generations of detectives to unravel mysteries and uncover the truth, no matter how locked away it might seem. The haunted mansion of Riverton became a symbol of courage and determination, rather than a place of fear and darkness.",[1034,5277,5279],{"id":5278},"story-7","Story 7",[11,5281,5282],{},"Once upon a time in the quaint town of Riverton, Detective William Hart found himself facing his most perplexing case yet. The mysterious death of wealthy businessman, Richard Lockwood, had everyone baffled. The circumstances were peculiar, to say the least. Mr. Lockwood was found dead in his study, which was securely locked from the inside. There were no signs of forced entry, no windows were open, and the room seemed completely undisturbed.",[11,5284,5285],{},"Detective Hart arrived at the estate promptly, determined to unravel this impossible locked-room mystery. He surveyed the scene meticulously, taking note of every minute detail. The room was elegant, but eerily quiet. The wooden bookshelves were filled with leather-bound volumes, and a grand mahogany desk stood against one wall. In the center of the room, there was a comfortable armchair in which Mr. Lockwood was found lifeless.",[11,5287,5288],{},"The detective carefully examined the body, looking for any signs of foul play. He discovered a small puncture wound on Mr. Lockwood's wrist. It seemed insignificant, but Detective Hart knew better than to ignore even the smallest detail. He collected samples and sent them to the lab for analysis.",[11,5290,5291],{},"As the investigation progressed, the detective interviewed the household staff and Mr. Lockwood's family members. Each had an alibi and no apparent motive for wanting the successful businessman dead. Their statements merely added to the mystery surrounding the case.",[11,5293,5294],{},"Days turned into weeks, and Detective Hart's frustration grew. He couldn't shake the feeling that there was something crucial he was missing. Determined not to give up, he poured over the evidence again and again. Then, an idea struck him like a lightning bolt.",[11,5296,5297],{},"Returning to the estate, Detective Hart focused his attention on the locked study door. Carefully examining the intricate lock, he noticed something peculiar. There was a tiny scratch near the keyhole, as if someone had tampered with it. Intrigued, he called upon the locksmith who had installed the lock to assist him.",[11,5299,5300],{},"The locksmith explained that it was possible to pick that particular lock, but the process required extensive knowledge and skill. Detective Hart realized that the killer must have had both. Someone within the estate had the ability to enter the locked study unnoticed.",[11,5302,5303],{},"With this newfound insight, the detective summoned all the suspects to the study. One by one, he interrogated them, digging deeper into their backgrounds and trying to uncover the truth. It was a battle of wits as he relentlessly weaved his way through their alibis and stories.",[11,5305,5306],{},"Finally, after hours of intense questioning, Detective Hart caught a break. The housekeeper, Ms. Simmons, inadvertently slipped up when confronted with the scratch near the keyhole. Her face flushed with guilt as she confessed to the crime. She admitted to having a secret relationship with Mr. Lockwood and became overwhelmed with jealousy when she discovered his plans to marry another woman.",[11,5308,5309],{},"Ms. Simmons had used her expertise as a former locksmith's apprentice to pick the lock, committing the perfect crime. She injected a poisonous substance into Mr. Lockwood's wrist when he was engrossed in his work, ensuring a quick and painless death.",[11,5311,5312],{},"With the case finally solved, Detective Hart apprehended Ms. Simmons, who was quickly brought to justice. The town of Riverton breathed a collective sigh of relief, grateful to have such a skilled detective in their midst.",[11,5314,5315],{},"And so, Detective William Hart's name became synonymous with unwavering determination and exceptional brilliance. His success in unraveling the locked-room mystery cemented his reputation as one of the greatest detectives of his time. From that day forward, he continued to solve even the most challenging cases, captivating the town with his remarkable skills and uncanny ability to see what others couldn't.",[1034,5317,5319],{"id":5318},"story-8","Story 8",[11,5321,5322],{},"Once upon a time, in the small town of Ravenwood, there lived a brilliant detective named John Sinclair. He was renowned for his ability to solve the most perplexing cases, and his sharp mind was always up for a challenge. One fateful evening, a locked-room mystery unfolded that would test his skills like never before.",[11,5324,5325],{},"It was a stormy night when the wealthy Mr. Harrison was found dead in his lavish mansion. The room in which he was found had no windows and only one door, which was securely locked from the inside. The circumstances surrounding the death were mysterious, and the distraught family sought out Detective Sinclair to uncover the truth.",[11,5327,5328],{},"Upon arriving at the scene, Sinclair carefully examined the room. The walls were adorned with priceless artwork, and the floor was covered in a plush red carpet. A large antique desk stood in the corner, cluttered with papers and a single cup of untouched tea. The air was heavy with a sense of unease.",[11,5330,5331],{},"Sinclair questioned each family member and the staff about their whereabouts at the time of the incident. The wife, Mrs. Harrison, claimed to have been at a charity event, as did her daughter, Penelope. The butler, Mr. Jenkins, and the maid, Lily, had both been in the kitchen preparing dinner.",[11,5333,5334],{},"As Sinclair delved deeper into the investigation, he discovered that Mr. Harrison had been deeply involved in some shady business dealings. There were rumors of unpaid debts, and Mr. Harrison had been receiving threatening letters demanding money. Could his death be related to these troubling affairs?",[11,5336,5337],{},"The detective meticulously examined the room for any hidden passages or secret compartments that could provide an explanation for how someone could have entered or exited without leaving a trace. He checked every nook and cranny, but nothing seemed out of place.",[11,5339,5340],{},"Sinclair then focused his attention on the windowless door. He studied the keyhole, searching for signs of tampering or forced entry. But the lock appeared to be untouched, and there were no traces of fingerprints on the doorknob.",[11,5342,5343],{},"Feeling stumped, Sinclair decided to dig deeper into Mr. Harrison's personal life. He visited the study where the late Mr. Harrison conducted his business affairs and meticulously searched through the papers on the desk. Amidst the financial records and contracts, Sinclair found a handwritten letter that intrigued him.",[11,5345,5346],{},"The letter was addressed to Mr. Harrison from an anonymous sender. It contained cryptic messages hinting at the secrets Mr. Harrison held and warned him of dire consequences if he didn't comply with their demands. Could this be the key to unraveling the locked-room mystery?",[11,5348,5349],{},"Sinclair summoned all the suspects to the study and confronted them with the letter. As he observed their reactions, he noticed a flicker of guilt in Penelope's eyes. In a moment of truth, Penelope confessed that she had discovered her father's illicit activities and intended to expose him.",[11,5351,5352],{},"She revealed that she had obtained a duplicate key to the room and had confronted her father about his wrongdoings that stormy night. Their argument grew heated, and in a fit of rage, Penelope pushed her father, causing him to stumble and hit his head on the corner of the desk, resulting in his tragic demise.",[11,5354,5355],{},"The locked-room mystery was finally solved, and justice was served. Penelope, overwhelmed with remorse, vowed to make amends for her actions and seek redemption. Detective Sinclair, though saddened by the outcome, couldn't help but admire the strength of his intuition and the power of the truth.",[11,5357,5358],{},"As the storm clouds cleared and the town of Ravenwood returned to peace, the legend of Detective Sinclair grew even stronger. His name would forever be associated with the solving of the locked-room mystery, a testament to his brilliant mind and unwavering dedication to justice.",[1034,5360,5362],{"id":5361},"story-9","Story 9",[11,5364,5365],{},"Detective Solving a Locked-Room Mystery",[11,5367,5368],{},"Once upon a time in the sleepy town of Drexville, there lived a renowned detective named Samuel Holmes. Known for his extraordinary deductive skills, Holmes was called upon to solve the most puzzling cases. One day, a peculiar challenge came knocking on his door. He received a mysterious letter that detailed a locked-room mystery in an old mansion on the outskirts of town.",[11,5370,5371],{},"Curiosity piqued, Holmes journeyed to the mansion where the puzzling events had taken place. The mansion, once grand and beautiful, had fallen into disrepair over the years. As he stepped into the gloomy interior, Holmes felt a shiver run down his spine.",[11,5373,5374],{},"The mansion belonged to a wealthy businessman named Gregory Allister. Allister, a recluse, had recently passed away under mysterious circumstances. The letter explained that Allister's death was a locked-room mystery - a situation where a person is found dead in a room which is securely locked from the inside with no plausible means of entry or exit.",[11,5376,5377],{},"Holmes began his investigation by inspecting the crime scene - Allister's bedroom. The door was indeed locked from the inside, with no signs of tampering. The windows were firmly shut, and there were no secret passages or hidden doors to be found. The room was devoid of any weapons or evidence of foul play. It seemed like an impossible puzzle.",[11,5379,5380],{},"Undeterred, Holmes turned his attention to Allister's personal life. He interviewed the staff and discovered that the mansion was full of secrets. Allister had a contentious relationship with his estranged wife, Evelyn, who had moved out years ago. There were rumors of a hidden treasure in the mansion, which had been a subject of heated disputes between Allister and his business partners.",[11,5382,5383],{},"As Holmes delved deeper into the investigation, he uncovered a web of deceit and betrayal that surrounded Allister's life. He discovered that Allister had formed powerful enemies due to his shady business dealings and had recently received anonymous threats.",[11,5385,5386],{},"Holmes also learned about a hidden room in the mansion's basement. Inside, he found a secret laboratory filled with scientific equipment and mysterious experiments. This room provided insight into Allister's secretive nature and the possibility of a scientific breakthrough.",[11,5388,5389],{},"With all the pieces of the puzzle slowly coming together, Holmes devised a plan to crack the locked-room mystery. He carefully reconstructed the events leading up to Allister's death and realized that it was not a simple suicide as initially suspected.",[11,5391,5392],{},"Holmes gathered all the suspects - Evelyn, the business partners, and the mansion staff - in the grand dining hall. He walked them through his process of deduction, revealing their secrets one by one. As he presented the final piece of evidence, the culprit's face turned pale, and a confession spilled out.",[11,5394,5395],{},"It turned out that Allister's death was meticulously planned by his business partner, Edward. Edward was desperate to gain control over the hidden treasure and had used his knowledge of Allister's scientific experiments to create a device that allowed him to enter and exit the locked room without a trace.",[11,5397,5398],{},"With the mystery solved and the culprit apprehended, Holmes left the mansion feeling a sense of accomplishment. Another locked-room mystery unraveled by his keen intellect. As he walked away, he couldn't help but wonder what new mysteries awaited him in the future.",[11,5400,5401],{},"And so, the legend of Samuel Holmes continued to grow, capturing the imagination of all who heard his name, and cementing his reputation as the greatest detective of all time.",[1034,5403,5405],{"id":5404},"story-10","Story 10",[11,5407,5408],{},"Once upon a time in the quiet town of Maplewood, renowned detective James Blackwood found himself faced with the most perplexing case of his career - a locked-room mystery. The scene was set at the grand estate of Mr. Brennan, a wealthy businessman known for his extravagant parties.",[11,5410,5411],{},"It was a foggy autumn evening when Mr. Brennan's lifeless body was discovered in his study. The doors and windows were tightly sealed, and there was no sign of forced entry. The room itself was in perfect order, no scuffle or struggle apparent. It seemed impossible for anyone to have entered or left without leaving a trace.",[11,5413,5414],{},"Detective Blackwood arrived at the scene, his sharp eyes immediately focused on unraveling the mysterious puzzle before him. He meticulously examined every inch of the study, taking note of every detail, trying to determine what secrets lay within those four walls.",[11,5416,5417],{},"As he dug deeper into the case, Detective Blackwood discovered that Mr. Brennan had been involved in shady business dealings and had made numerous enemies over the years. Fingers pointed towards rival businessmen, jealous ex-lovers, and even disgruntled employees. The list of suspects grew longer with each passing hour.",[11,5419,5420],{},"With the aid of his trusted partner, Detective Sophia Bennett, Blackwood conducted thorough interviews with the potential suspects. He skillfully extracted information, hoping to uncover a motive that could lead to the killer. Alibis were examined, timelines meticulously scrutinized, and contradictions ruthlessly exposed.",[11,5422,5423],{},"As the investigation progressed, a faint trail of evidence began to emerge. Blackwood discovered a hidden compartment in the desk, containing confidential business documents and a locked safe. The safe itself seemed impenetrable, with no visible signs of tampering. Determined not to be defeated by its apparent invincibility, Blackwood tirelessly worked on deciphering the combination.",[11,5425,5426],{},"Days turned into weeks, and the tension in the town grew palpable. People whispered about the mysterious case, wondering who could have committed such a daring crime. Meanwhile, Blackwood dug deeper into the lives of the suspects, searching for any connection that could break the case wide open.",[11,5428,5429],{},"Finally, late one night, a breakthrough came. Blackwood discovered a forgotten piece of evidence, a small key found hidden beneath Mr. Brennan's favorite armchair. With a surge of excitement, he rushed back to the estate, anticipation fueling his every step. The key fit perfectly into the previously impenetrable safe.",[11,5431,5432],{},"Inside, Blackwood found a collection of incriminating documents, providing a clear motive for murder. With the evidence in hand, he summoned all the suspects to the estate, gathering them in the very room where the crime had taken place.",[11,5434,5435],{},"With measured confidence, Detective Blackwood revealed the killer's identity and method. He exposed their lies and deceit, painting a vivid picture of the events that had unfolded on that fateful night. The shocked expression on the culprit's face was a testament to Blackwood's unparalleled deductive skills.",[11,5437,5438],{},"And so, the locked-room mystery was solved. The town of Maplewood breathed a collective sigh of relief as justice was served. Detective James Blackwood emerged as a hero, forever etched in the annals of the town's history.",[11,5440,5441],{},"But for Blackwood, it was just another triumph in a long line of cases. With his undying dedication and brilliant mind, he vowed to continue solving mysteries and bringing justice to those in need. After all, the world can never have too many detectives, especially ones like James Blackwood - relentless in their pursuit of truth.",[1034,5443,5445],{"id":5444},"story-11","Story 11",[11,5447,5448],{},"Once upon a time in the quaint town of Ravenwood, Detective Michael Thompson found himself faced with his toughest challenge yet—a locked-room mystery. The scene was set at the luxurious Ravenwood Manor, a grand mansion known for its opulent parties and mysterious secrets.",[11,5450,5451],{},"It was a dark and stormy night when Thompson received a distress call from the manor's owner, Mr. Jonathan Blackwood. When the detective arrived, he was met with a peculiar sight. The door to the study was locked from the inside, and inside the room lay the lifeless body of Mr. Blackwood himself.",[11,5453,5454],{},"With his analytical mind spinning, Detective Thompson immediately set to work. He carefully examined the door for signs of forced entry but found none. The windows were securely bolted shut, eliminating any possibility of an intruder gaining access that way.",[11,5456,5457],{},"Turning his attention to the room itself, Thompson observed the disarray—a clear sign of struggle. Papers were strewn across the desk, and furniture lay overturned. The air was thick with tension as the detective surveyed the scene, his mind racing to piece together the puzzle.",[11,5459,5460],{},"Thompson began his investigation by interviewing the mansion's staff, who appeared visibly distraught. The butler, Mr. Alexander, claimed he had been in the kitchen, preparing dinner, when the incident occurred. The maid, Miss Elizabeth, was upstairs attending to her duties and claimed she hadn't heard a thing.",[11,5462,5463],{},"Next, the detective examined the victim more closely. Blackwood lay on the floor, a single gunshot wound to his chest. The gun, a family heirloom, was found next to him, but it had clearly not been fired recently. Thompson knew he had to search for another possible murder weapon.",[11,5465,5466],{},"As he combed through the room, the swift-thinking detective stumbled upon a hidden compartment in the bookshelf. Inside, he discovered a small vial containing a deadly poison. Could this have been the real cause of death?",[11,5468,5469],{},"Thompson turned his attention back to the manor's inhabitants and questioned them more intently. The deceased's wife, Mrs. Isabella Blackwood, appeared to be the prime suspect. Though she claimed to be in her bedroom at the time,  her alibi was weak. She had been locked in a bitter dispute with her husband over their wealth and divorce settlement.",[11,5471,5472],{},"But Detective Thompson knew better than to jump to conclusions. He delved deeper into the case, meticulously cross-referencing evidence and eliminating possible suspects one by one. He had a gut feeling that there was more to the story, something hidden beneath the surface.",[11,5474,5475],{},"Days turned into weeks as Thompson tirelessly pursued his investigation. He uncovered a web of secrets and deceit, stretching back years. As he pieced together the puzzle, he realized that the mystery was not as straightforward as it seemed.",[11,5477,5478],{},"Eventually, the detective uncovered a hidden passage in the manor that led to a hidden room—one that only Mr. Blackwood had known about. Inside, Thompson discovered a secret collection of rare and valuable artifacts, painstakingly acquired by the deceased over the years. It was a motive for murder that had been concealed beneath the surface, and only Detective Thompson had managed to unearth it.",[11,5480,5481],{},"With the evidence gathered, Thompson confronted the true culprit—a greedy business associate of Blackwood's who had been desperate to get his hands on the priceless collection. The associate had planned the perfect crime—a locked-room mystery that would divert suspicion from himself.",[11,5483,5484],{},"In a dramatic showdown, the truth was finally revealed, and justice was served. The locked-room mystery that had baffled everyone was unraveled by the brilliant mind of Detective Michael Thompson.",[11,5486,5487],{},"And so, Ravenwood Manor could finally rest in peace, free from the dark secrets that had haunted its halls. Detective Thompson's reputation grew even greater, and he continued to solve the town's most perplexing cases, always with an unrivaled determination and a sharp intellect.",[11,5489,5490],{},"But deep down, he knew that the locked-room mystery of Ravenwood Manor would forever hold a special place in his heart—an intricate puzzle that had challenged him to the very core and emerged as his greatest triumph.",[1034,5492,5494],{"id":5493},"story-12","Story 12",[11,5496,5497],{},"Once upon a time in the bustling city of Bellville, there lived a renowned detective named Detective James Anderson. Known for his sharp intellect and exceptional problem-solving skills, Detective Anderson had earned a reputation for uncovering the truth behind even the most perplexing cases. However, there was one mystery that had eluded him for years - the infamous locked-room mystery.",[11,5499,5500],{},"One fateful morning, Detective Anderson received a phone call from the Bellville Police Department. They informed him about a bizarre case that had just occurred - a wealthy businessman named Mr. Edward Hargrove had been found dead inside his locked study. The room had been sealed from the inside, leaving no apparent means of escape or entry for anyone else.",[11,5502,5503],{},"Intrigued by the challenge, Detective Anderson quickly arrived at the Hargrove mansion. He was greeted by a distraught Mrs. Hargrove, who explained that she had discovered her husband's lifeless body when she went to bring him his morning coffee. She swore that she hadn't left the mansion since the previous evening, leaving no possible suspects.",[11,5505,5506],{},"Undeterred by the lack of leads, Detective Anderson meticulously examined the crime scene. The room was filled with shelves of books, an ornate desk, and a large fireplace. He carefully inspected every inch, searching for any hidden passages or clues that might explain the impossible circumstances.",[11,5508,5509],{},"As he scrutinized the desk, Detective Anderson noticed a faint imprint on a notepad - it appeared to be a partial note that had been forcibly ripped off. Using his skills, he managed to recreate the note, which read, \"The secret lies within the embers.\"",[11,5511,5512],{},"Puzzled yet determined, Detective Anderson turned his attention to the fireplace. He carefully removed the logs and raked through the ashes, finding a small key hidden amongst the charred remains. It didn't take long for him to realize that this key might hold the key to solving the case.",[11,5514,5515],{},"With the key in hand, Detective Anderson retraced his steps to the study door. He noticed a tiny keyhole near the doorknob which had gone unnoticed before. Curiosity guiding his every move, he inserted the key and turned it.",[11,5517,5518],{},"To his astonishment, the bookshelf lining the study wall swung open, revealing a hidden passageway. It seemed that Mr. Hargrove had constructed a secret escape route in case of emergencies. As Detective Anderson explored further, he found a hidden room containing a secret safe.",[11,5520,5521],{},"The safe, protected by a complex combination, held documents detailing Mr. Hargrove's involvement in illegal activities. It became clear that his death was not an accident but a meticulously planned murder intended to silence him.",[11,5523,5524],{},"Detective Anderson immediately deduced that Mrs. Hargrove could not have been responsible for her husband's death, as she was unaware of the hidden room and secret safe. He instinctively understood that the murderer was someone who knew the secret of the embers and was aware of the hidden escape.",[11,5526,5527],{},"Through careful investigation and interviews, Detective Anderson discovered that Mr. Hargrove had been involved in a criminal organization. His untimely demise must have been orchestrated by someone within the organization, desperate to protect their secrets.",[11,5529,5530],{},"After days of tireless work, Detective Anderson successfully gathered enough evidence to bring the guilty party to justice. The cunning mastermind behind the locked-room mystery was none other than Mr. Hargrove's business partner, who had orchestrated the elaborate plan to take control of the criminal empire.",[11,5532,5533],{},"With the mystery solved and justice served, Detective Anderson regained his reputation as the city's finest detective. The locked-room mystery became one of his most celebrated cases, showcasing his remarkable deduction skills and unwavering determination.",[11,5535,5536],{},"From that day forward, the city of Bellville knew that no enigma, no matter how complex, could escape the brilliant mind of Detective James Anderson.",[1034,5538,5540],{"id":5539},"story-13","Story 13",[11,5542,5543],{},"In the dimly lit room, Detective James Anderson stood, his gaze fixed upon the lifeless body lying on the floor. The victim, a well-known art collector named Marcus Donovan, had met his untimely demise inside his heavily fortified mansion. It was a classic locked-room mystery, and it was up to Detective Anderson to unravel the truth behind this baffling crime.",[11,5545,5546],{},"The room itself was a testament to Donovan's paranoia. Steel bars adorned the windows, and the thick, oak door was reinforced with multiple deadbolts. Anderson examined the room meticulously, searching for any clue that could break the enigma. His experienced eyes scanned for any signs of forced entry or secret passages. But there was none. It seemed as though the room had sealed itself, trapping Marcus Donovan's killer within.",[11,5548,5549],{},"The detective's attention then turned to the body. Donovan lay on the Persian rug, a look of shock frozen on his face. Anderson noted that there were no visible signs of struggle or injury, suggesting that the cause of death might have been something more sinister. He carefully examined the body, sending samples for analysis.",[11,5551,5552],{},"While waiting for the lab results, Detective Anderson turned his attention to Donovan's personal life. Marcus Donovan was known for his vast art collection, and his wealth had made him the target of envy and greed. He had numerous enemies in the art world, people who would stop at nothing to obtain his valuable treasures. The detective started to compile a list of potential suspects, reaching out to each one for questioning.",[11,5554,5555],{},"Days turned into nights as the investigation progressed, but the locked-room mystery remained unsolved. Anderson delved into the minutiae of Donovan's life, uncovering secrets and hidden motives. He meticulously interviewed every individual connected to Marcus, piecing together a complex web of relationships and betrayals. Yet, the truth seemed elusive.",[11,5557,5558],{},"In a moment of frustration, the detective decided to revisit the crime scene. He meticulously examined every nook and cranny of the room, his mind racing for any missed detail. And then, like a lightning bolt, inspiration struck. Anderson noticed a tiny smudge on the window sill. He quickly collected samples from the smudge and rushed them to the lab.",[11,5560,5561],{},"The results were astonishing. The smudge was a chemical compound used to dissolve metal. Detective Anderson realized that the killer had used it to weaken the steel bars on the windows, allowing them to escape without a trace. It was a carefully planned murder, executed with precision.",[11,5563,5564],{},"With the breakthrough evidence in hand, Anderson summoned all the suspects to a grand reveal. The tension in the room was palpable as he laid out the details of the crime. One by one, their faces turned pale, revealing their guilt. Finally, the true killer emerged from the shadows, unable to bear the weight of their deceit any longer.",[11,5566,5567],{},"In the end, justice prevailed, and the locked-room mystery was unraveled. Detective James Anderson's meticulous detective work had exposed the truth, ensuring that Marcus Donovan's killer would face the consequences of their actions. As he left the mansion, Anderson couldn't help but marvel at the power of deduction and the relentless pursuit of justice.",[11,5569,5570],{},"Another case solved, another locked-room mystery unlocked. Detective Anderson knew that while the world was filled with darkness, there would always be light shining through - a light called truth. And it was with this conviction that he ventured into the unknown, ready to face any challenge that crossed his path, armed with his sharp mind and unwavering determination.",[1034,5572,5574],{"id":5573},"story-14","Story 14",[11,5576,5577],{},"In the quiet town of Puzzleville, Detective Jack Hartley was known for his sharp wit and unparalleled detective skills. His reputation for solving the most complex cases had earned him the title of \"The Puzzle Master.\" And now, he was faced with his greatest challenge yet - a locked-room mystery that had everyone baffled.",[11,5579,5580],{},"It all began on a dark and stormy night, when the mayor's daughter, Lily, was found dead in the mansion's study. The room was locked from the inside, with no signs of forced entry or exit. The mystery gripped the town, as rumors of foul play filled the air.",[11,5582,5583],{},"Detective Hartley arrived at the crime scene, wearing his signature trench coat and fedora. The room was a puzzle in itself, filled with countless books, antique furniture, and a grand fireplace. As he examined the room, his keen eyes noticed a small clue - a broken vase on the floor, shards scattered around.",[11,5585,5586],{},"Hartley questioned the mansion staff, searching for any leads. The housekeeper nervously mentioned hearing a loud noise from the study before the incident. Suspicions heightened as Hartley discovered that Lily had recently inherited a significant fortune, making her the target of envy and greed.",[11,5588,5589],{},"Intrigued by the broken vase, Hartley delved deeper into its significance. He discovered that it had been a priceless artifact, stolen from a renowned museum years ago. Could this be the motive for Lily's murder?",[11,5591,5592],{},"Digging through the family history, Hartley uncovered a long-held secret. Lily's grandfather, a notorious art thief, had hidden his stolen loot within the mansion walls. The stolen vase was part of his collection. It seemed that the locked-room mystery was connected to the past, and someone was willing to kill to keep their secret hidden.",[11,5594,5595],{},"Hartley focused his investigation on the mansion's inhabitants. Each had a motive and an alibi, but the detective knew that appearances could be deceiving. He meticulously gathered evidence, interviewed suspects, and studied the layout of the room.",[11,5597,5598],{},"Days turned into weeks, and the case seemed unsolvable. But Detective Hartley refused to give up. Late one evening, as he retraced his steps through the mansion, a sudden realization struck him like lightning. It was the missing piece of the puzzle he had been searching for.",[11,5600,5601],{},"Returning to the study, Hartley examined the walls carefully. His fingers traced the seams between the wallpaper, feeling for any irregularities. And there it was - a hidden door cleverly concealed behind an intricately designed bookcase.",[11,5603,5604],{},"As Hartley stepped into the hidden room, he found himself surrounded by Lily's grandfather's stolen treasures. But even more importantly, he discovered crucial evidence that would finally unlock the mystery.",[11,5606,5607],{},"With all the pieces in place, Detective Hartley called for a meeting with the suspects, laying out his findings methodically. Suspense filled the air as he revealed the true identity of the killer - Lily's cousin, Edward. Driven by jealousy and greed, Edward had murdered Lily to take control of the hidden treasure.",[11,5609,5610],{},"As the handcuffs were placed around Edward's wrists, the town of Puzzleville breathed a collective sigh of relief. The Puzzle Master had done it again, solving the seemingly impossible locked-room mystery that had left everyone perplexed.",[11,5612,5613],{},"With the case closed, Detective Hartley returned to his office, ready to tackle new challenges. His reputation as the master of puzzles grew even stronger, and Puzzleville knew that they could always rely on him to unravel the most perplexing mysteries.",[1034,5615,5617],{"id":5616},"story-15","Story 15",[11,5619,5620],{},"Once upon a time in the peaceful town of Riverdale, there was a renowned detective named Detective James Anderson. Known for his brilliance and sharp instinct, Detective Anderson had solved numerous complex cases throughout his career. However, he had never encountered a mystery as perplexing as the locked-room case that awaited him.",[11,5622,5623],{},"It was a gloomy evening when a phone call shattered the silence of Detective Anderson's office. The caller, a distressed lady named Mrs. Carter, explained that a murder had taken place in her mansion. Detective Anderson wasted no time and rushed to the scene.",[11,5625,5626],{},"Upon reaching the Carter mansion, Detective Anderson found himself standing outside a grand room. He examined the door closely; it was locked from the inside, without even a keyhole. The detective puzzled over how the killer could have entered and exited without leaving any trace.",[11,5628,5629],{},"As he entered the room, a scene of mystery unfolded before his eyes. The room was lavishly decorated with antique furniture, and the victim, Mr. George Carter, lay lifeless on the floor. The cause of death was not immediately evident, as there were no visible wounds or signs of struggle. Detective Anderson knew he had a challenging investigation ahead of him.",[11,5631,5632],{},"The detective began by questioning the occupants of the mansion. Mr. Carter's wife, Mrs. Carter, was distraught, claiming she had been in the garden when the incident occurred. The household staff - the butler, the maid, and the gardener - all provided alibis that seemed airtight. There appeared to be no immediate suspects.",[11,5634,5635],{},"Detective Anderson meticulously searched the room for clues. He found a scrap of torn fabric behind a bookshelf, which did not match any of the furniture in the room. Additionally, he discovered a hidden compartment in the wall containing a notepad with cryptic notes. The detective painstakingly deciphered the code, revealing a list of names with amounts of money assigned to each. Each name was followed by the word \"debt.\"",[11,5637,5638],{},"As the investigation progressed, Detective Anderson's suspicions began to focus on the deceased himself. He delved into Mr. Carter's financial records and discovered that he had been involved in illegal gambling and owed considerable sums of money to multiple individuals. This revealed a possible motive for his murder.",[11,5640,5641],{},"Bringing the suspects together, Detective Anderson shared his findings. He revealed that the locked-room murder was an elaborate plan to deceive the authorities. The killer had entered the room before the murder and hidden behind the bookshelf, carefully observing Mr. Carter. When the opportune moment arose, the killer emerged, incapacitated Mr. Carter without leaving any physical evidence, and escaped undetected.",[11,5643,5644],{},"The detective used the torn fabric to identify the killer's clothing and linked it to the debt collectors mentioned in the cryptic notes. It turned out that one of them had been posing as a member of the household staff, deceiving everyone with a carefully crafted alibi.",[11,5646,5647],{},"With the truth exposed, the killer confessed to their crime. It was a tale of revenge, deceit, and hidden identities. The locked-room mystery had been unraveled, thanks to the brilliant deductions and unwavering determination of Detective James Anderson.",[11,5649,5650],{},"As Detective Anderson left the Carter mansion, the sun began to break through the clouds, casting light on the once-shrouded room. The residents of Riverdale breathed a collective sigh of relief, knowing that their beloved detective had restored peace and justice to their town once again.",[1034,5652,5654],{"id":5653},"story-16","Story 16",[11,5656,5657],{},"Detective James Anderson was no stranger to solving complex cases, but the locked-room mystery that awaited him today proved to be one of the most perplexing he had encountered in his career.",[11,5659,5660],{},"It all began when he received a call from the local police department. A renowned scientist, Dr. Benjamin White, had been found dead in his study, with no sign of forced entry. The room had been locked from the inside, and the only window was shut tight. The scene was baffling, as there seemed to be no plausible explanation for how anyone could have entered or exited the room.",[11,5662,5663],{},"Upon arrival at the crime scene, Detective Anderson meticulously examined every inch of the study. The shelves were lined with books on various scientific subjects, the desk cluttered with papers and equipment, and a chalkboard filled with complex formulas and equations. But nothing seemed out of the ordinary – no hidden passages or secret compartments.",[11,5665,5666],{},"As he interviewed the staff and family members, Detective Anderson learned that Dr. White had been working on a groundbreaking scientific project. He had made enemies in the scientific community who would stop at nothing to discredit his work. Could one of them be responsible for his untimely demise?",[11,5668,5669],{},"With no clear leads, Detective Anderson decided to delve deeper into Dr. White's research. He spent countless hours studying his work, trying to find any clues that might lead him to the truth. The more he dug, the more he realized the significance of Dr. White's discoveries – a breakthrough that could revolutionize the way we understand the universe.",[11,5671,5672],{},"Meanwhile, the detective's intuition caught a glimpse of something peculiar. He had a hunch that the key to solving the locked-room mystery lay in a detail that had been overlooked. Returning to the crime scene, he closely examined the window. It was an old-fashioned casement window, painted shut. But as he ran his fingers along the frame, he felt a slight irregularity, barely noticeable to the naked eye.",[11,5674,5675],{},"Utilizing his skills in forensics, Detective Anderson carefully lifted the paint on the frame. Beneath it, he found a tiny pinhole – a meticulously drilled hole that would allow someone outside the room to manipulate the latch. It seemed that the window had been opened from the outside before being closed again.",[11,5677,5678],{},"With this crucial breakthrough, Detective Anderson's investigation took a new turn. He began to suspect that the culprit had expert knowledge of the room's layout and had planned the murder meticulously. But who could it be?",[11,5680,5681],{},"As the detective narrowed down his list of suspects, he discovered that one of Dr. White's colleagues, Professor Ethan Lawson, had been seen near the study that fateful night. A brilliant mind himself, Professor Lawson had always been envious of Dr. White's success. Could he have taken his envy to such extremes?",[11,5683,5684],{},"The pieces of the puzzle started falling into place. Detective Anderson learned that Professor Lawson had been conducting secret experiments of his own, using Dr. White's research as a foundation. He had been working on a similar project but had failed to replicate Dr. White's results. Fueled by jealousy and the desire to prove himself, he saw an opportunity to eliminate his rival and take credit for his groundbreaking discoveries.",[11,5686,5687],{},"Armed with this newfound knowledge, Detective Anderson confronted Professor Lawson with the evidence. Cornered, the professor admitted to the crime, revealing how he had carefully planned and executed the murder to make it appear as a locked-room mystery.",[11,5689,5690],{},"Justice was served, and the scientific community mourned the loss of Dr. White, but celebrated his groundbreaking contributions. Detective Anderson's meticulous investigation had not only solved the locked-room mystery, but it had also ensured that the truth prevailed over envy and deceit.",[11,5692,5693],{},"As the case concluded, Detective Anderson reflected on the complexity of his profession. In the world of crime-solving, no mystery was truly unsolvable. With a keen eye for detail and unwavering determination, even the most baffling cases could be unraveled, bringing justice to those who deserved it. And so, he continued his journey as a detective, ready to face whatever challenge lay ahead.",[1034,5695,5697],{"id":5696},"story-17","Story 17",[11,5699,5700],{},"In the heart of the bustling city, there stood an old, grand mansion. The mansion had a reputation of being haunted, with whispers of eerie occurrences echoing through its halls. Many believed that it was cursed, its rooms hiding unsolved mysteries for years. One such mystery baffled both the locals and the authorities - the case of the locked-room murder.",[11,5702,5703],{},"It all began on a dark and stormy night when a prominent businessman, Mr. Jonathan Blackwood, was found dead in one of the mansion's rooms. The door to the room was locked from the inside, and there were no signs of forced entry. It seemed impossible - how could someone be murdered in a locked room?",[11,5705,5706],{},"Detective Michael Andersson, well-known for his sharp mind and unwavering determination, was assigned to the case. As he entered the mansion, the creaking of the wooden floor beneath him echoed through the silence. The detective knew he had a challenging task ahead.",[11,5708,5709],{},"He started his investigation by interviewing the mansion's inhabitants. Each person had an alibi, claiming to have been in a different part of the house when the murder occurred. The suspects included Mr. Blackwood's business partner, Mr. Edward Stone, a jealous rival, Ms. Victoria Parker, and the loyal butler, Mr. Arthur Collins.",[11,5711,5712],{},"Determined to unravel the truth, Detective Andersson meticulously examined the crime scene. The room itself was a spectacle of opulence, adorned with antique furniture and paintings. The only window was bolted shut, and the fireplace remained untouched, ruling out any possibilities of escape or hiding evidence.",[11,5714,5715],{},"As he scrutinized every inch of the room, the detective's keen eyes fell upon a small, silver key tucked away in the corner. It appeared to be out of place amongst the elegance of the surroundings. With a sense of intrigue, he pocketed the key, convinced that it held some significance in solving the mysterious murder.",[11,5717,5718],{},"Days turned into weeks, and the detective tirelessly pursued every lead. He meticulously analyzed the testimonies, searching for inconsistencies and subtle clues that could unravel the locked-room mystery. The wide range of emotions displayed by the suspects, their motives, and their connections to the victim were all meticulously examined.",[11,5720,5721],{},"Finally, a breakthrough came when Detective Andersson discovered a hidden passage beneath the mansion. It led to a secret room filled with diaries and letters, revealing a network of deceit and betrayal. The investigation took an unexpected turn as it unraveled a web of blackmail and revenge.",[11,5723,5724],{},"As the detective confronted each suspect with the evidence he had gathered, their carefully constructed facades slowly crumbled. The truth came tumbling out, like pieces of a puzzle fitting together. The silver key he had found turned out to be the one that locked the room from the inside, connecting the crime scene to the suspects.",[11,5726,5727],{},"In a dramatic confrontation, the truth behind the locked-room murder was finally revealed. The guilty party turned out to be Ms. Victoria Parker, motivated by a desire to eliminate her competition and claim Mr. Blackwood's business empire for herself. She had meticulously planned the crime, manipulating events to make it seem like an impossible locked-room mystery.",[11,5729,5730],{},"With her motive exposed and the evidence against her undeniable, Ms. Parker was apprehended, ending her reign of deception. The haunted grand mansion finally found peace, as the secrets within its walls were laid bare.",[11,5732,5733],{},"Detective Andersson emerged as the hero who had unraveled the enigma of the locked-room murder. His perseverance, attention to detail, and sharp instincts had proved invaluable in solving the case. The city hailed him as a legend, and the mansion gained a new reputation - a place where justice prevailed over dark secrets.",[11,5735,5736],{},"And so, the detective's tale of the locked-room murder became a legend, whispered in the corridors of law enforcement for years to come. It served as a reminder that even in the most perplexing cases, the truth could be found if one had the determination to search for it.",[1034,5738,5740],{"id":5739},"story-18","Story 18",[11,5742,5743],{},"There once was a famous detective named Detective Smith. He was known for his brilliant mind and his ability to solve the most complex of cases. One day, he received a call from the local police department about a locked-room mystery. Intrigued, Detective Smith rushed to the scene.",[11,5745,5746],{},"Upon arrival, he found himself standing outside a grand mansion. The mansion belonged to Mr. Jonathan Hartley, a wealthy businessman. As Detective Smith entered the mansion, he was greeted by a large crowd of police officers and curious onlookers. The room where the mystery took place was the study.",[11,5748,5749],{},"Inside the study, Detective Smith saw a lifeless body lying on the floor. It was Mr. Hartley himself. The door to the study was locked from the inside, and there were no signs of forced entry. The windows were all securely locked as well. The only key to the study was found in Mr. Hartley's pocket.",[11,5751,5752],{},"Detective Smith began his investigation by examining the crime scene. He noticed a faint smell of bitter almonds, which he recognized as the scent of cyanide. He deduced that Mr. Hartley had been poisoned. The investigation had to move swiftly, as cyanide dissipates rapidly.",[11,5754,5755],{},"The detective meticulously collected evidence, dusting for fingerprints, examining the room for any hidden compartments or secret passageways, and questioning witnesses. But the more he dug into the case, the more perplexing it became. There seemed to be no plausible explanation as to how the killer entered and exited the locked room.",[11,5757,5758],{},"Days turned into weeks, and the mystery continued to baffle Detective Smith. He explored every hypothesis, from an elaborate murder plot to a supernatural occurrence. But each time, he hit a dead end.",[11,5760,5761],{},"One evening, while sitting alone in his office, Detective Smith had a brilliant breakthrough. He remembered a book he had once read about illusionists and their mastery of misdirection. With this in mind, he decided to revisit the crime scene.",[11,5763,5764],{},"Back at the mansion, Detective Smith examined the bookshelves in the study. To his surprise, he found a hidden lever behind a seemingly ordinary book. Curiosity piqued, he pulled the lever, and a secret door swung open, revealing a hidden passage.",[11,5766,5767],{},"The passage led him to a secret room adjacent to the study. In the room, he discovered evidence that Mr. Hartley was involved in illegal activities. It became clear to Detective Smith that the locked-room mystery was a cleverly staged murder to cover up Mr. Hartley's true intentions.",[11,5769,5770],{},"With this new revelation, the detective pieced together the events leading up to Mr. Hartley's death. It was an elaborate plan executed by someone close to him who knew about the hidden room and wanted to expose his illicit activities.",[11,5772,5773],{},"Armed with this knowledge, Detective Smith gathered all the evidence and called for a meeting with the police and the suspects. He masterfully laid out the case, pointing out the motive, means, and opportunity for each suspect.",[11,5775,5776],{},"In a dramatic finale, Detective Smith revealed the identity of the killer and detailed their intricate plan. The killer was arrested, and justice was served.",[11,5778,5779],{},"The locked-room mystery had been solved, thanks to the brilliant mind and unwavering determination of Detective Smith. He once again proved why he was considered one of the greatest detectives of his time.",[11,5781,5782],{},"As the sun set on the grand mansion, Detective Smith quietly stepped out into the darkness, knowing that another case awaited him, ready to challenge his intellect and push him to the limits of his abilities.",[1034,5784,5786],{"id":5785},"story-19","Story 19",[11,5788,5789],{},"Once upon a time, in the town of Oakwood, there was a highly skilled detective named Samantha Holmes. She was known for her remarkable ability to solve complex cases, and her reputation as the best detective in town was widely acknowledged. One day, Samantha was called to investigate a peculiar locked-room mystery that had the entire town buzzing with curiosity.",[11,5791,5792],{},"The case unfolded in the grand mansion of Mr. Edward Pemberton, a wealthy businessman and art collector. It was a stormy night when a lavish dinner party was being held at his mansion. The guests arrived in their finest attire, eager to enjoy an evening of luxury and indulgence. The atmosphere was electric with laughter and animated conversations flowing freely.",[11,5794,5795],{},"As the night progressed, a loud bang echoed throughout the mansion, causing a momentary silence to fall upon the party. When the guests rushed to investigate, they were met with a disturbing sight. The door to the study, where Mr. Pemberton kept his most prized possessions, was locked from the inside, and no one could find a key.",[11,5797,5798],{},"Samantha Holmes arrived at the scene, ready to examine the evidence and unravel the mystery. She began by interviewing the guests, each providing their alibis and claiming their innocence. She meticulously examined the door, searching for any signs of tampering. The lock appeared intact, and there were no visible forced entry marks.",[11,5800,5801],{},"Undeterred, Samantha delved deeper into the investigation. She scrutinized the room itself, meticulously inspecting every nook and cranny. Her keen eye detected minute details that others might have missed. There, hidden within an ornate vase, she discovered a small key. It seemed to fit the lock perfectly, but there was still one puzzle left to solve – who had the motive to steal from Mr. Pemberton?",[11,5803,5804],{},"Samantha reasoned that the culprit must be among the dinner party attendees. She gathered the guests in the grand hall and began her interrogation. Each person was questioned, their personas illuminated under the relentless gaze of Samantha's piercing eyes. She observed their body language, their reactions to her pointed questions, and their attempts to divert suspicion to others.",[11,5806,5807],{},"As she stormed through the interrogations, Samantha detected subtle inconsistencies, hidden glimmers of guilt. It was the elegant widow, Mrs. Victoria Ashford, who gave herself away. With her trembling hands and evasive answers, Samantha had found her prime suspect. But what was Mrs. Ashford's motive?",[11,5809,5810],{},"Samantha dug into Mrs. Ashford's past, peeling back layers of secrets and lies. She discovered a hidden affair between Mrs. Ashford and Mr. Pemberton. It seemed that jealousy and greed had driven her to steal one of the valuable paintings from the study.",[11,5812,5813],{},"Armed with this knowledge, Samantha confronted Mrs. Ashford, who finally confessed to her crime. She had used the key from the vase, replaced it with a duplicate, and cunningly locked herself in the study to divert suspicion. Samantha had cracked the locked-room mystery, solving the case that had baffled everyone else.",[11,5815,5816],{},"The news of Samantha's brilliant detective work spread like wildfire through the town of Oakwood. She was hailed as a hero, and her skills as a detective became legendary. From that day forward, no locked-room mystery was too challenging for Samantha Holmes. Her legacy lived on, inspiring future generations of detectives to unlock the secrets hidden behind closed doors.",[11,5818,5819],{},"And so, the case of the locked-room mystery was closed, thanks to the unwavering determination and sharp intellect of Detective Samantha Holmes. The town of Oakwood slept a little safer that night, resting in the knowledge that justice had been served, and the truth had prevailed.",[1034,5821,5823],{"id":5822},"story-20","Story 20",[11,5825,5826],{},"It was a gloomy winter evening when Detective James Thompson received a call about a peculiar case. A renowned novelist, Mr. Victor Grayson, had been found dead in his study, locked from the inside. The room had no windows and the only entrance was through a heavy wooden door. It seemed impossible for anyone to have entered or exited without leaving a trace. With a determined spirit, Detective Thompson set out to unravel the mysteries hidden within the locked-room.",[11,5828,5829],{},"As Detective Thompson stepped into the study, he carefully examined his surroundings. The room was filled with bookshelves, stacks of papers, and an antique writing desk at the center. The deceased lay sprawled on the floor, dressed in his finest suit, with a perplexed expression frozen on his face. His manuscript, unfinished, rested next to him.",[11,5831,5832],{},"The detective meticulously observed every detail, from the arrangement of books to the desk where the writer spent countless hours. He knew that beneath the surface, there was a labyrinth of clues waiting to be discovered. He meticulously dusted for fingerprints, analyzed footprints, and examined the furniture for any signs of tampering.",[11,5834,5835],{},"As he dug deeper into Mr. Grayson's life, Detective Thompson discovered a web of secrets, jealousy, and hidden motives. The victim had been in the midst of a bitter dispute with his publisher, Charles Aldridge, over a novel he believed was unjustly rejected. Could Charles be the killer?",[11,5837,5838],{},"Thompson confronted Charles, who vehemently denied any involvement in the murder. But the detective sensed something was amiss. His keen intuition led him to search Charles' office, where he stumbled upon old letters exchanged between the two. It became apparent that Charles had a strong motive to eliminate Mr. Grayson.",[11,5840,5841],{},"But Detective Thompson was not one to jump to conclusions. He continued his investigation, speaking with the victim's family, friends, and neighbors. He unraveled a complex web of affairs and betrayed trust. Mr. Grayson's wife, Victoria, had been having an affair with his closest friend, Anthony Davis. Could they have conspired to kill the renowned writer and make it appear as a locked-room mystery?",[11,5843,5844],{},"Thompson brought Victoria and Anthony in for questioning separately. With his skilled interrogation techniques, he managed to unravel their secrets. Victoria confessed to killing her husband in a fit of rage, while Anthony admitted to helping her stage the locked-room scenario to protect her. Their love had driven them to desperate measures, but they couldn't escape the detective's scrutiny.",[11,5846,5847],{},"With the truth finally revealed, Detective Thompson meticulously gathered the evidence and presented his case to the court. Victoria and Anthony were charged with the murder of Mr. Grayson, and justice was served.",[11,5849,5850],{},"As the case came to a close, Detective Thompson reflected on the power of deduction, intuition, and meticulous investigation. The locked-room mystery had been unraveled, proving that even the most perplexing crimes can be solved with a determined mind and careful examination of the facts.",[11,5852,5853],{},"And so, another chapter closed in the life of Detective James Thompson, leaving behind a tale of intrigue, deception, and a locked-room mystery that had been meticulously unraveled.",[738,5855,5856],{},"html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sTrkL, html code.shiki .sTrkL{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#66D9EF}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":156,"searchDepth":157,"depth":157,"links":5858},[5859,5860,5861,5862,5863,5864],{"id":4642,"depth":157,"text":4643},{"id":4667,"depth":157,"text":4668},{"id":4689,"depth":157,"text":4690},{"id":4711,"depth":157,"text":4712},{"id":4986,"depth":157,"text":4987},{"id":5037,"depth":157,"text":5038,"children":5865},[5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885],{"id":5041,"depth":637,"text":5042},{"id":5081,"depth":637,"text":5082},{"id":5121,"depth":637,"text":5122},{"id":5158,"depth":637,"text":5159},{"id":5201,"depth":637,"text":5202},{"id":5241,"depth":637,"text":5242},{"id":5278,"depth":637,"text":5279},{"id":5318,"depth":637,"text":5319},{"id":5361,"depth":637,"text":5362},{"id":5404,"depth":637,"text":5405},{"id":5444,"depth":637,"text":5445},{"id":5493,"depth":637,"text":5494},{"id":5539,"depth":637,"text":5540},{"id":5573,"depth":637,"text":5574},{"id":5616,"depth":637,"text":5617},{"id":5653,"depth":637,"text":5654},{"id":5696,"depth":637,"text":5697},{"id":5739,"depth":637,"text":5740},{"id":5785,"depth":637,"text":5786},{"id":5822,"depth":637,"text":5823},"2023-07-20","img\u002Frobot-reading-script.jpg","https:\u002F\u002Fmastodon.social\u002F@awwaiid\u002F110749392784672266",{},"\u002Ftlt-2023.07.20-self-judging-stories",{"title":4626,"description":4631},"TLT - 2023.07.20 - Self Judging Stories",[169],"sxKJ0fS09Xh4N6FUubB8kSXy6Ws3PMxM7osSCzk7ftw",{"id":5896,"title":5897,"body":5898,"createdAt":5965,"description":5902,"draft":160,"extension":161,"image":5916,"mastodonThread":5966,"meta":5967,"navigation":164,"path":5968,"seo":5969,"stem":5970,"tags":5971,"updatedAt":5886,"__hash__":5972},"content\u002FTLT - 2023.04.30 - Paper Snake Game.md","Paper Snake Game",{"type":8,"value":5899,"toc":5963},[5900,5903,5911,5917,5920,5923,5932,5935,5938,5946,5949],[11,5901,5902],{},"Creating a simple snake game with the help of ChatGPT.",[11,5904,5905,4066,5908],{},[587,5906],{"src":5907},"\u002Fimg\u002Fpaper-snake-pixel-art.jpg",[20,5909,5910],{},"Pixelated snake, possibly in the desert, somewhat two-dimensional. Image by Bing Image Creator.",[11,5912,5913],{},[587,5914],{"alt":5915,"src":5916},"paper snake screenshot","img\u002Fpaper_snake_screenshot.png",[11,5918,5919],{},"I was chatting with Mario about a school project he was working on. Essentially, he needed to write a program in Elm (based on a list of lesser-used languages) that exemplified what the language is typically used for. Since Elm is a highly reactive, web-centric language, I suggested creating a game. He chose Snake, a simple and solid option.",[11,5921,5922],{},"For some reason, I began contemplating Snake, specifically considering potential design or game elements that could be added to it. Two ideas came to mind. The first was to render the snake as a flat piece of paper, with each segment possibly being a tiny scrap of paper, and animate it in a style reminiscent of stop-motion animation. The second idea involved the snake \"jumping over\" or \"diving under\" its existing segments. I'm sure these ideas have been explored before, but they sounded fun :)",[11,5924,5925,5926,5931],{},"Mario completed his traditional Snake game before I could even share my paper-snake concept with him, so I decided to give it a try myself. I also wanted to practice using TypeScript. After finding a nice ",[136,5927,5930],{"href":5928,"rel":5929},"https:\u002F\u002Fgithub.com\u002Fourcade\u002Fphaser3-typescript-vite-template",[140],"PhaserJS + Typescript + Vite template"," I was off and running!",[11,5933,5934],{},"While experimenting with various technologies, I thought I'd mix in some practice with ChatGPT. I loaded it up and began asking questions about building a Snake game using this stack. Since the Snake game concept is so common and straightforward... I found that ChatGPT had TONS of knowledge about implementing Snake. I prompted it in a few different ways to incorporate my style and game concepts, and I think it saved me hours of research time.",[11,5936,5937],{},"Within one afternoon, I (or should I say, we?) had a working game with the jumping feature and everything! I'm pretty sure ChatGPT could have written almost this whole thing from scratch\u002Fmemory, btw. But it also followed my direction on naming and organization.",[11,5939,5940,4066,5943],{},[587,5941],{"alt":156,"src":5942},"img\u002Fpaper-snake-v1.gif",[20,5944,5945],{},"GIF demonstrating Paper Snake. Red shadows are when the snake is jumping.",[11,5947,5948],{},"It does not yet look like super cool paper animations, heh.",[11,5950,5951,5952,5957,5958,797],{},"You can see the ",[136,5953,5956],{"href":5954,"rel":5955},"https:\u002F\u002Fawwaiid.github.io\u002Fpaper-snakes\u002F",[140],"current version of the game"," and the corresponding ",[136,5959,5962],{"href":5960,"rel":5961},"https:\u002F\u002Fgithub.com\u002Fawwaiid\u002Fpaper-snakes",[140],"github repo for paper-snakes",{"title":156,"searchDepth":157,"depth":157,"links":5964},[],"2023-04-30","https:\u002F\u002Fmastodon.social\u002F@awwaiid\u002F110285863632396209",{},"\u002Ftlt-2023.04.30-paper-snake-game",{"title":5897,"description":5902},"TLT - 2023.04.30 - Paper Snake Game",[169],"IrqD3JwLASthzHMw6qsdBWvM715jNQTIfCPX1-IxN7I",{"id":5974,"title":5975,"body":5976,"createdAt":6282,"description":5980,"draft":160,"extension":161,"image":6283,"mastodonThread":6284,"meta":6285,"navigation":164,"path":6286,"seo":6287,"stem":6288,"tags":6289,"updatedAt":6290,"__hash__":6291},"content\u002FTLT - 2023.04.22 - Chokepoints.md","Chokepoints",{"type":8,"value":5977,"toc":6280},[5978,5981,5989,6004,6007,6010,6013,6218,6221,6224,6233,6236,6251,6258,6261,6264,6267,6274,6277],[11,5979,5980],{},"Notes from the Changelog interview with Cory Doctorow on Chokepoint Capitalism",[11,5982,5983,4066,5986],{},[587,5984],{"src":5985},"\u002Fimg\u002Frobot_lemonade_stand.jpg",[20,5987,5988],{},"Lemonade stand operated (or perhaps supervised?) by a robot. Image by Bing Image Creator.",[11,5990,5991,5992,5997,5998,6003],{},"While driving to and waiting for Millie (the car) to get maintenanced, I listened to ",[136,5993,5996],{"href":5994,"rel":5995},"https:\u002F\u002Fchangelog.com\u002Fpodcast\u002F535",[140],"Examining capitalism's chokepoints",", an interview with Cory Doctorow discussing his book ",[136,5999,6002],{"href":6000,"rel":6001},"https:\u002F\u002Fcraphound.com\u002Fcategory\u002Fchokepoint\u002F",[140],"Chokepoint Capitalism",". This touched on all sorts of things, but right up at the front was an off-topic question - How is Cory so prolific?",[11,6005,6006],{},"Among some other things, Cory suggested that ... well, that practice makes perfect. And that instead of just copy\u002Fpasting a link into slack like I usually do, I should write up some notes trying to capture, for other people, what I found interesting or special about the link. So yeah. Good idea. Let's do that.",[11,6008,6009],{},"Problem: I don't really have or want \"blog\" software. I ran my site as a publicly-editable wiki for like 20 years. It is now a nuxt-content-driven static site, basically. Super easy to open a file in vim and edit more-or-less markdown. But do I do that? No, not really. So of course, then I'm like ... if only I could run a command to pop open my editor and start writing writing writing away. Great!",[11,6011,6012],{},"Turns out I already did that, made a horrid little shell script that goes like this:",[605,6014,6016],{"className":1619,"code":6015,"language":1621,"meta":156,"style":156},"#!\u002Fbin\u002Fbash\n\nset +x\n\nFILE_DATE=`date '+%Y.%m.%d'`\nTEMPLATE_DATE=`date '+%Y-%m-%d'`\n\nTITLE=${*:-Untitled}\nNEWFILE=\"TLT - $FILE_DATE - $TITLE.md\"\n\necho \"Creating: $NEWFILE\"\n\ncd ~\u002Ftlt\u002Fthelackthereof\u002Fcontent\ncp -n \"Blog Template TLT - 2023.01.01 - Blog Template.md\" \"$NEWFILE\"\nperl -pi -e \"s\u002FTEMPLATE_TITLE\u002F$TITLE\u002F\" \"$NEWFILE\"\nperl -pi -e \"s\u002FTEMPLATE_DATE\u002F$TEMPLATE_DATE\u002F\" \"$NEWFILE\"\nvim \"$NEWFILE\"\n",[194,6017,6018,6023,6027,6035,6039,6055,6069,6073,6089,6111,6115,6128,6132,6140,6158,6183,6206],{"__ignoreMap":156},[39,6019,6020],{"class":614,"line":615},[39,6021,6022],{"class":1628},"#!\u002Fbin\u002Fbash\n",[39,6024,6025],{"class":614,"line":157},[39,6026,634],{"emptyLinePlaceholder":164},[39,6028,6029,6032],{"class":614,"line":637},[39,6030,6031],{"class":694},"set",[39,6033,6034],{"class":649}," +x\n",[39,6036,6037],{"class":614,"line":656},[39,6038,634],{"emptyLinePlaceholder":164},[39,6040,6041,6044,6046,6049,6052],{"class":614,"line":668},[39,6042,6043],{"class":622},"FILE_DATE",[39,6045,643],{"class":618},[39,6047,6048],{"class":649},"`",[39,6050,6051],{"class":1909},"date",[39,6053,6054],{"class":649}," '+%Y.%m.%d'`\n",[39,6056,6057,6060,6062,6064,6066],{"class":614,"line":674},[39,6058,6059],{"class":622},"TEMPLATE_DATE",[39,6061,643],{"class":618},[39,6063,6048],{"class":649},[39,6065,6051],{"class":1909},[39,6067,6068],{"class":649}," '+%Y-%m-%d'`\n",[39,6070,6071],{"class":614,"line":685},[39,6072,634],{"emptyLinePlaceholder":164},[39,6074,6075,6078,6080,6083,6086],{"class":614,"line":691},[39,6076,6077],{"class":622},"TITLE",[39,6079,643],{"class":618},[39,6081,6082],{"class":622},"${",[39,6084,6085],{"class":618},"*:-",[39,6087,6088],{"class":622},"Untitled}\n",[39,6090,6091,6094,6096,6099,6102,6105,6108],{"class":614,"line":701},[39,6092,6093],{"class":622},"NEWFILE",[39,6095,643],{"class":618},[39,6097,6098],{"class":649},"\"TLT - ",[39,6100,6101],{"class":622},"$FILE_DATE",[39,6103,6104],{"class":649}," - ",[39,6106,6107],{"class":622},"$TITLE",[39,6109,6110],{"class":649},".md\"\n",[39,6112,6113],{"class":614,"line":709},[39,6114,634],{"emptyLinePlaceholder":164},[39,6116,6117,6120,6123,6126],{"class":614,"line":1823},[39,6118,6119],{"class":694},"echo",[39,6121,6122],{"class":649}," \"Creating: ",[39,6124,6125],{"class":622},"$NEWFILE",[39,6127,1653],{"class":649},[39,6129,6130],{"class":614,"line":1837},[39,6131,634],{"emptyLinePlaceholder":164},[39,6133,6134,6137],{"class":614,"line":4967},[39,6135,6136],{"class":694},"cd",[39,6138,6139],{"class":649}," ~\u002Ftlt\u002Fthelackthereof\u002Fcontent\n",[39,6141,6143,6146,6149,6152,6154,6156],{"class":614,"line":6142},14,[39,6144,6145],{"class":1909},"cp",[39,6147,6148],{"class":664}," -n",[39,6150,6151],{"class":649}," \"Blog Template TLT - 2023.01.01 - Blog Template.md\"",[39,6153,1646],{"class":649},[39,6155,6125],{"class":622},[39,6157,1653],{"class":649},[39,6159,6161,6164,6167,6169,6172,6174,6177,6179,6181],{"class":614,"line":6160},15,[39,6162,6163],{"class":1909},"perl",[39,6165,6166],{"class":664}," -pi",[39,6168,1643],{"class":664},[39,6170,6171],{"class":649}," \"s\u002FTEMPLATE_TITLE\u002F",[39,6173,6107],{"class":622},[39,6175,6176],{"class":649},"\u002F\"",[39,6178,1646],{"class":649},[39,6180,6125],{"class":622},[39,6182,1653],{"class":649},[39,6184,6186,6188,6190,6192,6195,6198,6200,6202,6204],{"class":614,"line":6185},16,[39,6187,6163],{"class":1909},[39,6189,6166],{"class":664},[39,6191,1643],{"class":664},[39,6193,6194],{"class":649}," \"s\u002FTEMPLATE_DATE\u002F",[39,6196,6197],{"class":622},"$TEMPLATE_DATE",[39,6199,6176],{"class":649},[39,6201,1646],{"class":649},[39,6203,6125],{"class":622},[39,6205,1653],{"class":649},[39,6207,6209,6212,6214,6216],{"class":614,"line":6208},17,[39,6210,6211],{"class":1909},"vim",[39,6213,1646],{"class":649},[39,6215,6125],{"class":622},[39,6217,1653],{"class":649},[11,6219,6220],{},"But now, if I'm thinking of Cory's advice, I might actually be juggling several drafts or jotting down some partial thoughts. Next thing you know, I'm trying to write a CLI in Typescript (for reasons) and .... not writing a blog post. As my niece says, The Struggle Is Real!!!",[11,6222,6223],{},"Anyway. Where was I? Oh, capitalism.",[11,6225,6226,6227,6232],{},"I've been playing with ",[136,6228,6231],{"href":6229,"rel":6230},"https:\u002F\u002Fopenai.com\u002Fblog\u002Fchatgpt",[140],"ChatGPT"," a lot and even set myself up with the paid version to experiment with GPT-4. It's a fascinating tool and intriguing to explore. I find that to get interesting or useful things out of it, I must change what I feed in. It's not quite like a Markov chain bot or an Alexa Q&A; it's more like a brainstorming tool that has been fed The Internet. Right off the bat, I can't really expect answers that The Internet doesn't know, especially technical ones. If there's no hint of an answer on Stack Overflow, it's probably not going to come up with one here. Next, you have to feed it with some context. If you approached someone in a café and asked them to give you an itinerary for a vacation you're going on, they could do it, but they'd do a poor job if you didn't give them some information about your tastes and goals.",[11,6234,6235],{},"A significant part of this is exploring the question for myself - now what? What comes next? What do we do with this? How will it change things?",[11,6237,6238,6239,6244,6245,6250],{},"Many of my friends, acquaintances, and connections on ",[136,6240,6243],{"href":6241,"rel":6242},"https:\u002F\u002Fmastodon.social\u002F@awwaiid",[140],"Mastodon"," and elsewhere discuss how these Large Language Models (LLMs) are violating their creative and copyright rights by slurping it all in, mashing it all up, and spitting it all out (sometimes without much mashing) without citing their original work. Some of these same friends think that ",[136,6246,6249],{"href":6247,"rel":6248},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FAaron_Swartz",[140],"Aaron Swartz"," was over-prosecuted for exfiltrating JSTOR science articles. My sympathies are mixed here. I want people to be compensated for their labor and creativity, and I want information to be free, and I don't want monopolistic middlemen to leverage an advantage in the middle without adding value. I personally publish most things under a license that explicitly or implicitly allows my content to be republished, remixed, etc., ideally with a citation. But I'd be happy with being cited as being an incorporated part of every output. I think the LLM publishers should say, \"Here is the dataset that we trained on and every contribution to it.\" And then I'd even be proud to be part of it.",[11,6252,6253,6254,6257],{},"The podcast. Remember the podcast? The podcast delves into what happens when humans are not only augmented by machines, LLMs among them, but also ",[20,6255,6256],{},"controlled"," by the machines. Cory calls this the Reverse-Centaur. Furthermore, what happens when the economic system is further twisted to where you are stuck in this situation, controlled by monopolistic, possibly non-value-adding middle players? This he calls Chickenized Reverse-Centaurs. They break down in some detail what this currently means, and it is scary. I have to remember how fortunate I am, celebrate it, and see if I can help others obtain some control over their lives as well.",[11,6259,6260],{},"Still, the Centaur concept is powerful. Tools can help us do things faster and better. Having the right tool for something can change a project from hours to minutes. I'd like to know how LLMs can accelerate us, and selfishly me, in day-to-day life.",[11,6262,6263],{},"I sometimes discuss global warming with my father-in-law. He thinks it's a scam on many levels. I generally take the mainstream view that we should probably be more scared than we are, although I also believe that we should accept the fact that the Earth is increasingly becoming a garden, and we need to make it an awesome one. Anyway, he sends me some lengthy and somewhat complicated videos on climate science and alternative models. YouTube has transcripts. I could feed the transcript to ChatGPT and have it give me a summary and critique some of the points.",[11,6265,6266],{},"But can I trust it?",[11,6268,6269,6270,6273],{},"One of the differences between modern Capitalism and Ideal Capitalism is that Ideal Capitalism is founded on the idea of information transparency. Efficiency in a market is all about setting the right price based on all the correct factors, as I understand it. So what happens when we don't know the real cost of something, like global warming? The price is too low. But what happens when we have the ",[20,6271,6272],{},"wrong"," information, when things we think are true are actually bad summaries from an LLM that have added a bit of false detail for fluidity? When humans do that on purpose, it is fraud, corruption, embezzlement, and scams. Will LLMs and similar technology accidentally amplify that, making markets even less efficient? Not to mention that efficient and humane are not the same thing. Ahhhhhhh.",[11,6275,6276],{},"So many things.",[738,6278,6279],{},"html pre.shiki code .s8-w5, html code.shiki .s8-w5{--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-sepia:#88846F}html pre.shiki code .sTrkL, html code.shiki .sTrkL{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#66D9EF}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":156,"searchDepth":157,"depth":157,"links":6281},[],"2023-04-22","img\u002Frobot_lemonade_stand.jpg","https:\u002F\u002Fmastodon.social\u002F@awwaiid\u002F110243919367988037",{},"\u002Ftlt-2023.04.22-chokepoints",{"title":5975,"description":5980},"TLT - 2023.04.22 - Chokepoints",[169,1531],"2023-04-23","_8EI6mvTzZt9I0_xrgZxLMmg6HuwoHhgoiRlJT91ruo",{"id":6293,"title":6294,"body":6295,"createdAt":6458,"description":6459,"draft":160,"extension":161,"image":6460,"mastodonThread":162,"meta":6461,"navigation":164,"path":6462,"seo":6463,"stem":6464,"tags":6465,"updatedAt":4386,"__hash__":6467},"content\u002FTLT - 2023.02.24 - Human Essentials Schema Exploration.md","Human Essentials Schema Exploration",{"type":8,"value":6296,"toc":6454},[6297,6315,6319,6326,6329,6346,6353,6356,6371,6377,6380,6395,6398,6417,6420,6435,6439,6442,6445,6448,6451],[11,6298,6299,6300,6304,6305,1211,6310,797],{},"I'm trying to solidify my understanding of the schema organization for ",[136,6301,3916],{"href":6302,"rel":6303},"https:\u002F\u002Fhumanessentials.app",[140],". The goal is to build up some documentation to make contribution even easier for new folks. Also I like to play with ",[136,6306,6309],{"href":6307,"rel":6308},"https:\u002F\u002Fplantuml.com\u002F",[140],"PlantUML",[136,6311,6314],{"href":6312,"rel":6313},"https:\u002F\u002Fgraphviz.org\u002F",[140],"GraphViz",[266,6316,6318],{"id":6317},"schema-exploration","Schema Exploration",[11,6320,6321,6322,6325],{},"First I ran ",[194,6323,6324],{},"rails erd filetype=dot attributes=false"," and got a beast of a diagram. This includes all of the models and some indirect relationships.",[587,6327],{"src":6328},"https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fpng\u002FtLpVRzis47xtNq7msKtjk4Kt-GUGD6stfUswDEjBMmIqnDXSPLAZg7JfiFzz82NPaYoPiaN9e5-AYh6_k-zuHnwFPtbamL6m15S41PY3VtiSqMyUuM0AuDiRE5RF8Gxay-3iEHptAFFmUk0P7FS2v2KF_NXWXVY2K3NM7y1npsNKnLHm9B0S53p2SDppqHpxFdFL41ptxXaL8VcXFZ8S9GCKhTJ01IV81vVCz-2u5mO-eJYKu_5_4wq-Wt290Wp05038iIiGNVWOWZvOOwi_3GVfc89NOqg074wKLuE3iy6B_k1iy5p-8S3qE_74Ci4u6y2lunxs5lXp5LHUwWiv92shdkPCBEK0ufnzttneSFPpkIpG1yfWYb8yF3fVZtea58YwAR-pdwHkcPcylKmDBfz-YLQ8WbTXYAaWo0_15LiXGi4xvc7_2_r2vHpUNRWkYwYumNz7E1JWS_hroKIWkO_1d74FyoaSG81yig1JA2SPSmXSxFjXW5n25rFbD6eaG9uNZq2Wo4tXSFGCpde0J0IVJOHNn7b8dkTC2BRAV6i0PnDfN72FN3pDEWS86A7YYJJe50w7S9PdCNaglpQRF1MU_8VFUfEdYisiD_iwxa79MX16R_4_md5UKPS_1W9xDyHToY5ehnLsiDhFA2TbY_rCy80_2iRH0ZlEXH38NQumjTiEfOpsDiQbp-QdOWR9PMy3V4AS8Bd8k8nxfsA972cDILPt5zvVKIYa-rXBVyr0JvRI2FatE63SNheP3dh2aKViPIgLrrAyHDnb7lvLu9MjH3CKQj0DBUSQrY4ALtTNs4UFs7ESI-H-mzHpd7YXYnSsn_dDuish1ZUj9roHK70oZsHMPAqTCXpqX1b5LfDDzAzDz2CHs7QoaeC-rb_x90WmTvmB3mK2yx0O4Ayn4X77rWPyNO86JFK6YHEsasId3Q1VwGEcWl57ctVA70azPPkPrYNu4WcyOFpHPg8f1otXQtipz-iQUVjRGgrEP5FzjKJV8HhT8rUkxjnMibaEMiBlhoxVlyEhkRrqDmoqP7_d2qJ93wiJqom7VGBoGLuutN94VCVvX7b86BKstIZXeftn3uWBQgzl9-hNfVc6ioYmdAlYKCUnrQTboXc99UFa1_PUenNn7-Er05fkXafY-vZcvPButWbOGl7OcxZSy9ChoLEnGORIFkQ8_US4Z10JsOVwQJd1WVF_WRDxukCJC432HByXSkP5hhZYvC7QgboMmrw4fRc8Im9axprX1Hsz6IBkBb5exvmd-ck9_Y7N08kFCQd-MgAMjqRLMwrNTpVCjzPffUvQWadBmrlcMdtyBj3GqhxbY8Rtzfv0K_srHFyCxIKfTQz5CBGvJDS4j5G_OUenQsSprbv34e3a6kR935JMoLJVy1B7hTUKyHNoOT9DB13nur6AOHzynsIn5Agh6YhqoeREM5v5isT1e8BUHznMls1NqWhDUUs8BHHmsnAIrWnRirt9mQmjBkiqiLL7sENbLVsypMDhXxDt8hJIvrkGNkdwhSZQZe1s3Bep45fXLX8FxVbApR18Ehj3yUYhd-5uJ0ZifRBsrE0Sze7BQ2Wu8bIDt2C_n4ryED7l46r61mHiNNFKMgNsCaQRgyXvLHnligr6i0c80jmKGHf1genU0MPIt_qdOPJYAG0DNhCrCNlSQaIzU5WrWFqinSuqyIlOJMz58rl4tUCc4NCzgqQ1qzvGaw3NXjclWyWawDg5sWED0Sri9ZlNppB1cvwlJXJOZl-jAfFvPQ3GhsXUmAPrkWNiN1zw2yOnw7tdkoS_lvtK99ECbYpBsxvaO8FA9D8juAMLSKExV2EyqGux6j5pUpUgmgsHawnHKuoq2bH-RMmuuJEKdvK6O3FiYjslmprbM_3HzvJAgzL6irU5Qd8BsCt5886sjSwrjpNJEWkL1M-8c_FKGvNUsftqDZ5ZZgD5svRyxkLMTCeqs5Hof0ncN3dSEEanOwpHOSPQjvMPObNQl7XKVwXiBZs2LcsM3JMA55vJenmmtqpV85moFq7G0pSj46LVeM1ubyg_iC0qUFno0CEe-H-ljWHk73Z_8nt3u8NZ_P5opkiM9hl37QF4hCsB9UMWcuJ5C7ZkNHMcGyDSKg2_5-pgGgKGc2RNW6tWJUsqamXDMqNCbwiFnngLOdMSm6za7s7Tt3vq6OZMzKjRJ05cm9gNZeVbQZPUh8RRshQ1kLaFEWxR_8hRYV1SScLoDSpVdnqXwBThiKTGObEuRf0R3tSMKqq05wzxZM1kxdexN6qBKZkUxl89QdYQ6vOuaod8uiHtELCbeZkUhkAXllYYMrEDOxcBcj8Iah6hd3tbTbERAPFReHcgwcCTgf1M8MkNxam9plOi5gjMNNIlrUsUD5ee7DLMgcfUqk0uU1h--ny0",[11,6330,6331,6332,6335,6336,6335,6339,6342,6343,797],{},"Then I went through and started adding each node to some subgraphs. After some combinations I came up with several logical groupings - ",[194,6333,6334],{},"Participants",", ",[194,6337,6338],{},"Intake",[194,6340,6341],{},"Inventory",", and ",[194,6344,6345],{},"Disbursal",[11,6347,6348,6349,6352],{},"Next I went through and kept deleting more things, especially indirect relationships, and added a splash of color. I also started to terminate edges at cluster boundaries. Perhaps a bad idea, but I also dropped the ",[194,6350,6351],{},"LineItem"," model since it is really a way to get to Item+Qty. mmm. Well I think this is kinda wrong, but here it is in any case.",[587,6354],{"src":6355},"https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fpng\u002FnLZPRjiu57tNLn1wTbotnQ0pBHp0YJ55qMM2j3ClGL7GuhN4AKsgN1eaHV-zu2APagKaaXNqpJuKppdtahnS2CqbBWkqfhW4YNua2K8Iyw-4IhH4wRlBz5M2K2PsfJ2Se2NIqe25je9hHM_1VlNqULf17EySj98KCtGc675DN12uGgh09I2qH2YLa6dCSmOfcY6bRnWiKsabWCosb34WwGpP7vbWGYxJwu9gi50bwrYUBcptMjTXJjd2EonpoZsuc2zUp1RpnH-seGH-JOak0iTyaNws7e7aSDL7rjHzOI6R8lTl8tHX0IobkDv_j9Z_rQs6PeZX3J0NluUVFwjHGfN6FAiYdF_ftKM3ykaiVMN7IPcD7xoC6QL1Vicmnapaw4U24F9io_JSWwd3Ddd89wDveJVCWCVFi88t6dRkJ-F7ETQG2tdZWBTKXyzb9aZLusUd6Sg_0zT2tZJjlAdWBaCtm9YuzYqVjP0uXtSYmveAxh1F4dEr1UdTLKortnNvtoYz0-vThWnnVhlzbLXgcj4ISwsQ5Y-YbfPB8J7FGyx-aJdcz7RlRiMvmUmIIY6zWNzLi7ef6DI8glzP8Hu-2RzVIs5A1wG1KIzVNaYnfIp8VbYVVNWFkqtejyeoORY-X6y6b6xt_1llA0kfZk3pWZ9oWAwCBeIajq1yDw-IzcOGPzyCLTJ6tqpWQj_GobzfP5a5iXRSvUuZrT00V3wa82RJQqc_GpGWlit8hC3Az_eFE17oe8y3tcDkjZZJHhfiTOT1gDeOgJ1h1h6ku5O84aBcrbHfIJUcjjmp1dPwXgRkWMXzu5m-UOB2matsgnETdCPB3rsvYbC0jeKvvKBkC4j37TAOCezoy1KaPXdH_NW3SJavmaHC4Q-Q1r85bDdlbcbNDR2jzljzQoYitiDRgaUvzwCQ5vVa8SlFQjqrOnxkuI3eUkRxm0uAn6-H3YMhfTsNd67JvrwP4FSmrcO9jepnrd10vjBHGnKNB4jKbSI1ZXhw9wVHndZ4aDKRUez6jFiTQNTKYJdmsrYqROcuU4ytZGzKeYtk29Lee-tM2HFuoBIFAAPzLFQ8Cv2YYg6v8AjbEWLNTOmQj28ZgiUPCv70-ApvCHiz4vpmoQaxdWxPHWywgn4XED57Ab8LTrMR9nkrYhW_wBicrVuCxm9lxX_3ijUakdFZkVzmKb-falWovJpQkzJGVR71C6Krzsuc9crTECTEoLwk4Hdie7cS8jGbDFZeSV--rI7JkCKVdvxgXM0WKzrjqZdb5rLzaKoQTyOnMlwbZ61L0776suHzHUIkQjHpLvtkzE-tYVtnk4zmUC6ANXgI_GF2r9MXSOmRVogFdoSceebkaySmXlUKgVFcdsRSiQHI66Bivoy0",[11,6357,6358,6359,6361,6362,6364,6365,1211,6368,6370],{},"Let's dig a bit into the ",[194,6360,6351],{}," model. This model is used in a variety of contexts (and is polymorphic) to effectively mean \"A Qty of an Item\". Initially I had this in the ",[194,6363,6341],{}," group, but the ",[194,6366,6367],{},"Acquisition",[194,6369,6345],{}," both have records that use this model, even though they might not be referencing ACTUAL items. You can request more items or different items than are actually available, for example. So it kinda belongs to all of them. I could duplicate this node for each of its uses, or I could maybe make a special arrow.",[11,6372,6373,6374,6376],{},"With that change, zooming in to only Catalog and Inventory. I've reversed some of the arrows to make more sense to me. The bold red edges actually go through the ",[194,6375,6351],{}," model to represent a list of Item+Qty.",[587,6378],{"src":6379},"https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fpng\u002FZPB1Rjim38RlVWf2fmtpNBV5q1M51oJTfKWlsthBWa6n65kRB1cIlC0R-kw39CkD4nVPpVhua_n9cl5AqxQ6pvosgE5l0g2f_CMuXWB8urTobm2KgcbL9naKO7M73ksKj8R_GQUwl2OHITfujD2S2bWgmNn8AePhC3Lj4Q0081fBIsKba40AnlO22w9T2sJfZWk1ZAJWFaebb2x8lkOM7OfjVPNBtAMFVJtpdHrkgAwu333Fyfiqp_8FBj2Yt7Dcww56bfEDyuYimlLhnQPzRnoYMglz2ykps_dYa8AWMnH-t82lhqRAkB5Kbd6Wx6CmSt23foMvIn80qst3gKhH6OlwHqaj5QhoDuDGhI3t0HBFjjMmFi6hscv5Xu4lgS47Yur_J3xkgSLAwTw35RU3N9UAnOpdMJDS_aPfbUwdTXuYdZFKen1g7oBVhDAqmaTLKikLzEn9Ksbsg8ExM6dqks0_EsCRbC7becFUh_TtSG739fA9VtZ_wN3w6NGaFX8UxMZ5RQIm7aRJoCZu6nHNcwbiC3TEanpEuKHnZ2azry5ddHUUr3rT-rZfD3GvmNzAXlt5Kyvd7KRF3k2MkHv-hnMtt-KRbsBUVR7zMxAPJXXrBsX6xWSUbUvrAXeTHbq4nzBdVm00",[11,6381,6382,6383,6386,6387,6390,6391,6394],{},"Let's focus on what we actually store in a physical location. The central model is ",[194,6384,6385],{},"InventoryItem"," which specifies a Qty of ",[194,6388,6389],{},"Items"," that are at a ",[194,6392,6393],{},"StorageLocation",". These represent real actual physical objects on a shelf somewhere.",[587,6396],{"src":6397},"https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fpng\u002FRSWn2e0m30NGlQVuemwzWRWBBjAnT0WbY6YJKeFGsukxutltUKYbHWLPIrLXiM3zOZJEHh9Vx5mCfersnggPx519cBn7NEHXCMqTYt71i5aVa_jl-1dnSte1",[11,6399,6400,6401,6403,6404,6406,6407,6410,6411,6413,6414,797],{},"The next interesting thing is Kits. These are groups of item+qty that you can use as a single catalog item. So even though in the ",[194,6402,6393],{}," we have only a single ",[194,6405,6385],{}," that points at a single ",[194,6408,6409],{},"Item",", that one ",[194,6412,6409],{}," can in turn be a bundle of things joined together by a ",[194,6415,6416],{},"Kit",[587,6418],{"src":6419},"https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fpng\u002FVOx12eCm44Jl-OezjeVyGIaOJr8lnQFa4C9YWt5NqiMIloyO4ApIoyBCF6RdFGQQNN8JU9vc9YJf94U4X5uS3H6LwZlXv0Q4bhsJm6JXfZNq3Ir8mYb38pZ1vIdvQjMv3VeEVT6V5qU4CSWA_rgb-X74glKMtGR2KbTjVyvIypUjj_JO1tfRMEq0SmJC3gYFG6s_",[11,6421,6422,6423,6425,6426,6428,6429,6431,6432,6434],{},"Let's say you have a ",[194,6424,6416],{}," named \"Handy Pack\" with Qty-3 \"Kids (Size 1)\" and Qty-6 \"Wipes (Baby)\". That ",[194,6427,6416],{}," has a single ",[194,6430,6409],{}," of the same \"Handy Pack\" name. So if you have 5 of these ",[194,6433,6416],{},"s at a storage location, then you have 5 * Qty-3 \"Kids (Size 1)\" and 5 * Qty-6 \"Wipes (Baby)\" .... or in other words 15 diapers and 30 wipes.",[266,6436,6438],{"id":6437},"flow-exploration","Flow Exploration",[11,6440,6441],{},"Using the model as inspiration, I've now started to group out the lifecycle of things. Here is the basic block diagram.",[587,6443],{"src":6444},"https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fpng\u002FROxB2i9034NtynN1VN-Xe7JZhgYxqaKSentRPePCAXJntwNs0IqkatlluSJQSK315gnlWsTYFMlV40XPHNuqPE9IQHoJze70YrRUc2Bln5OOgOGaIQ4uic9DfIaopwZEy-Pl5YZi3iZr3ju6XlX5h5xwgRw_FRkeBR6M_-AB8CSxIMa-AsAEeamoGJCNLTor-saCpTa2HgEPQLRyT3jSdwF0YQmBRj3x0W00",[11,6446,6447],{},"Or as a top-to-bottom timeline:",[587,6449],{"src":6450},"https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fpng\u002FJOqn2y9034Rt-nMXamx5lKC7BOA3M1pSOmqQR7DdBXNwxwMdN1tplSTBG3NkEA0OD5wykl2tN4XkNbq2KDQmHNbMiuV6NjmNBw0TjNjW93UVotoGDubvdU28WdSQICorg2QaK6RjJA-Hei7g5EOwzklS-SaLD1nD-JgczpbHGx7hcSGsUnouduea1f987m00",[11,6452,6453],{},"All right .... I think that's enough for now :)",{"title":156,"searchDepth":157,"depth":157,"links":6455},[6456,6457],{"id":6317,"depth":157,"text":6318},{"id":6437,"depth":157,"text":6438},"2023-02-24","I'm trying to solidify my understanding of the schema organization for Human Essentials. The goal is to build up some documentation to make contribution even easier for new folks. Also I like to play with PlantUML and GraphViz.","https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fsvg\u002FROxB2i9034NtynN1VN-Xe7JZhgYxqaKSentRPePCAXJntwNs0IqkatlluSJQSK315gnlWsTYFMlV40XPHNuqPE9IQHoJze70YrRUc2Bln5OOgOGaIQ4uic9DfIaopwZEy-Pl5YZi3iZr3ju6XlX5h5xwgRw_FRkeBR6M_-AB8CSxIMa-AsAEeamoGJCNLTor-saCpTa2HgEPQLRyT3jSdwF0YQmBRj3x0W00",{},"\u002Ftlt-2023.02.24-human-essentials-schema-exploration",{"title":6294,"description":6459},"TLT - 2023.02.24 - Human Essentials Schema Exploration",[169,6466],"rubyforgood","3xI0i-C90s1pc0-FREb0HWD8S8E1P29LiRi_MWsshzE",{"id":6469,"title":6470,"body":6471,"createdAt":6508,"description":6509,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":6510,"navigation":164,"path":6511,"seo":6512,"stem":6513,"tags":6514,"updatedAt":6508,"__hash__":6515},"content\u002FTLT - 2023.02.04 - RPM 2023 My Little Dog.md","RPM 2023 My Little Dog",{"type":8,"value":6472,"toc":6506},[6473,6481,6484,6492,6495,6503],[11,6474,6475,6476,6480],{},"Initial attempt at ",[136,6477,6479],{"href":6478},"\u002Fmy-little-dog","My Little Dog",", part of the 2023 RPM Challenge",[11,6482,6483],{},"I did a voice recording of this in April 2022, noodling around on the mandolin and singing to Hoda while she (quite obviously from the lyrics) lay basking in the sun. Here is the voice recording:",[11,6485,6486,444,6489,449],{},[440,6487],{"controls":164,"preload":442,"src":6488},"\u002Fdocs\u002Fmusic\u002Fsong_ideas\u002Fmy_little_dog.mp3",[136,6490,448],{"download":6491,"external":156,"href":6488},"docs\u002Fmusic\u002Fsong_ideas\u002Fmy_little_dog.mp3",[11,6493,6494],{},"Today I re-worked-out the simple chords and some cleaned up lyrics. Here is the work-in-progress:",[11,6496,6497,444,6500,449],{},[440,6498],{"controls":164,"preload":442,"src":6499},"\u002Fdocs\u002Fmusic\u002Fwip\u002FMy_Little_Dog_r1_20230204.mp3",[136,6501,448],{"download":6502,"external":156,"href":6499},"docs\u002Fmusic\u002Fwip\u002FMy_Little_Dog_r1_20230204.mp3",[11,6504,6505],{},"The lyrics aren't quite right here, so I'm definitely re-recording that. The mandolin is good-enough.... but I think there could be a bit more of a musical section or two with some other strumming or picking patterns. Still.... the challenge is to record 10 songs, so worse case this version could be song-number-one!",{"title":156,"searchDepth":157,"depth":157,"links":6507},[],"2023-02-04","Initial attempt at My Little Dog, part of the 2023 RPM Challenge",{},"\u002Ftlt-2023.02.04-rpm-2023-my-little-dog",{"title":6470,"description":6509},"TLT - 2023.02.04 - RPM 2023 My Little Dog",[169],"oke9ikDsxhNTBrTtJ4LOxnd5tcMovcyFmfjoMwqUk-k",{"id":6517,"title":6518,"body":6519,"createdAt":6579,"description":6580,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":6581,"navigation":164,"path":6582,"seo":6583,"stem":6584,"tags":6585,"updatedAt":6579,"__hash__":6586},"content\u002FTLT - 2023.01.29 - RPM Challenge 2023.md","RPM Challenge 2023",{"type":8,"value":6520,"toc":6575},[6521,6530,6534,6537,6540,6548,6552,6555,6558,6561,6564,6567,6570],[11,6522,6523,6524,6529],{},"I'm going to try to do the ",[136,6525,6528],{"href":6526,"rel":6527},"https:\u002F\u002Fwww.rpmchallenge.com\u002F",[140],"RPM Challenge"," again this year. Millionth try is a charm?",[266,6531,6533],{"id":6532},"previous-attempts","Previous Attempts",[11,6535,6536],{},"The challenge: 10 tracks or 35 minutes of original music recorded during the month of February.",[11,6538,6539],{},"I'm not really sure how many times I've sat where I am now, a few days before (or a few days after!) February 1st and thought to myself ... LETS DO THIS. But I'll tell you how many times I've gotten through is very easy -- zero!",[11,6541,6542,6543,6547],{},"That's not to say that I haven't had some fun trying. Jason and I, in particular, tacked the challenge a few times and came out with several very fun songs. I think that's where I got ",[136,6544,6546],{"href":6545},"\u002Fcode-on-my-mind","Code On My Mind"," for example. We'd get together on a Saturday with the idea that we'd jam out like 5 songs and end up with 1 or maaaybe 2. More than most other Saturdays!",[266,6549,6551],{"id":6550},"this-year","This Year",[11,6553,6554],{},"I of course have things going on. Work. Normal life. We're going to AZ for a week. So the strategy this year is, as always, a bit tricky.",[11,6556,6557],{},"One thing that I've been doing for a while now is to record little tunes that pop into my head on my phone. So I'll be singing to myself \"I LOVE MY CHI-HUA-HUA.... LA LA LA\" or something and if it has some potential then I'll record it. Try to get the idea, the basic concept, down. Interestingly my first attempt is almost always bad. I get self-consious or something and stumble on words that I might have been dancing along merrily only a moment before. So I sing it into the recording a bunch of times, maybe do some variations.",[11,6559,6560],{},"With that seed, I figure there are two big steps for each song. Step 1, write and record the song. For time sake and for organic composition those are probably MOSTLY the same step. Then Step 2 mix and master the song.",[11,6562,6563],{},"I'm thinking I'll try to put some distance between recording and mixing, though that leaves some risk that as I mix I'll need something re-done or added but I'm no longer set up to do that. But if it works, then maybe what I'll do is record songs on the weekend and then mix songs during the week. If I pace myself it'd be 2-3 songs a week. I'm worried that won't work, that I'll run out of momentum. So! Let's shoot for 3-4 songs per week, or really as many as I can muster up-front.",[587,6565],{"src":6566},"https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fpng\u002FTT2z2i8m58RXFLTnl810-WUwTN8JYjIfECJsQ8waYIHdQEzUg1IYqldX_OQlZgm3FxHZ5ZisE2AmdqLBR14kBg2s59bwQ6b4Imvtmj20SFUURtuIJV1Fx1cMcGYvoWkfSgaoqJK1NrUmEdA40WOzHy467NHdx26JvMfvQYUQKgj-kqhkDxl4_hg3pDHccE9NUIH7qQnKVgX6Doo7lG40",[11,6568,6569],{},"I'd always like to throw in a collaboration or three, even though that complicates it. One idea is to record with Elizabeth and Nate when I'm in AZ. Another is to get my kid neighbor Theo in to do a drum session with me at 7drumcity. We'll see how those play out.",[11,6571,6572],{},[993,6573,6574],{},"2023 LET'S GO!",{"title":156,"searchDepth":157,"depth":157,"links":6576},[6577,6578],{"id":6532,"depth":157,"text":6533},{"id":6550,"depth":157,"text":6551},"2023-01-29","I'm going to try to do the RPM Challenge again this year. Millionth try is a charm?",{},"\u002Ftlt-2023.01.29-rpm-challenge-2023",{"title":6518,"description":6580},"TLT - 2023.01.29 - RPM Challenge 2023",[169],"BxGA32sr_SG3-5NcLfEDb95VJlr3hmb33-C7xf4rC8U",{"id":6588,"title":6589,"body":6590,"createdAt":6906,"description":6594,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":6907,"navigation":164,"path":6908,"seo":6909,"stem":6910,"tags":6911,"updatedAt":6906,"__hash__":6912},"content\u002FTLT - 2022.12.04 - Snake Souls.md","Snake Souls (Fairy Lights, ChatGPT)",{"type":8,"value":6591,"toc":6902},[6592,6595,6599,6620,6816,6819,6828,6832,6835,6840,6843,6893,6896,6899],[11,6593,6594],{},"I had ChatGPT write me a poem .... but first some somewhat irrelevant background information!",[266,6596,6598],{"id":6597},"snake-lights","Snake Lights",[11,6600,6601,6602,6607,6608,6613,6614,6619],{},"I've purchased and chained a few Neopixel-like LED fairy-light strands (",[136,6603,6606],{"href":6604,"rel":6605},"https:\u002F\u002Fwww.amazon.com\u002Fdp\u002FB0B4RTMG13",[140],"these ones on Amazon",") as a fun winter\u002FChristmasy project. I have them hooked up to an Arduino-like, right now this ",[136,6609,6612],{"href":6610,"rel":6611},"https:\u002F\u002Fwww.adafruit.com\u002Fproduct\u002F3857",[140],"M4 Feather Express",", but I'm planning on switching to an ",[136,6615,6618],{"href":6616,"rel":6617},"https:\u002F\u002Fwww.adafruit.com\u002Fproduct\u002F5300",[140],"ESP32-S2 TFT Feather",". Each LED is individually controllable using Arduino\u002FC++. The idea is to make some holiday light displays with different colors and twinkling and all that. While learning how to use it I made a few toy animations, such as this simple snake:",[605,6621,6625],{"className":6622,"code":6623,"language":6624,"meta":156,"style":156},"language-cpp shiki shiki-themes github-light github-dark monokai","void forwardSnake() {\n  for (int i = 0; i \u003C strip.numPixels(); i++) {  \u002F\u002F For each pixel in strip...\n    strip.clear();\n    for (int j = 0; j \u003C 5; j++) {\n      strip.setPixelColor(((i + j) % strip.numPixels()), strip.Color(128, 0, 32));  \u002F\u002F  Set pixel's color (in RAM)\n    }\n    strip.show();  \u002F\u002F  Update strip to match\n    delay(100);    \u002F\u002F  Pause for a moment\n  }\n}\n","cpp",[194,6626,6627,6639,6679,6690,6721,6772,6777,6790,6806,6811],{"__ignoreMap":156},[39,6628,6629,6633,6636],{"class":614,"line":615},[39,6630,6632],{"class":6631},"sq6CD","void",[39,6634,6635],{"class":1909}," forwardSnake",[39,6637,6638],{"class":622},"() {\n",[39,6640,6641,6643,6645,6648,6650,6652,6655,6658,6661,6664,6667,6670,6673,6676],{"class":614,"line":157},[39,6642,4829],{"class":618},[39,6644,444],{"class":622},[39,6646,6647],{"class":6631},"int",[39,6649,4728],{"class":622},[39,6651,643],{"class":618},[39,6653,6654],{"class":664}," 0",[39,6656,6657],{"class":622},"; i ",[39,6659,6660],{"class":618},"\u003C",[39,6662,6663],{"class":622}," strip.",[39,6665,6666],{"class":1909},"numPixels",[39,6668,6669],{"class":622},"(); i",[39,6671,6672],{"class":618},"++",[39,6674,6675],{"class":622},") {",[39,6677,6678],{"class":1628},"  \u002F\u002F For each pixel in strip...\n",[39,6680,6681,6684,6687],{"class":614,"line":637},[39,6682,6683],{"class":622},"    strip.",[39,6685,6686],{"class":1909},"clear",[39,6688,6689],{"class":622},"();\n",[39,6691,6692,6695,6697,6699,6701,6703,6705,6708,6710,6713,6716,6718],{"class":614,"line":656},[39,6693,6694],{"class":618},"    for",[39,6696,444],{"class":622},[39,6698,6647],{"class":6631},[39,6700,4832],{"class":622},[39,6702,643],{"class":618},[39,6704,6654],{"class":664},[39,6706,6707],{"class":622},"; j ",[39,6709,6660],{"class":618},[39,6711,6712],{"class":664}," 5",[39,6714,6715],{"class":622},"; j",[39,6717,6672],{"class":618},[39,6719,6720],{"class":622},") {\n",[39,6722,6723,6726,6729,6732,6735,6738,6741,6743,6745,6748,6751,6753,6756,6758,6761,6763,6766,6769],{"class":614,"line":668},[39,6724,6725],{"class":622},"      strip.",[39,6727,6728],{"class":1909},"setPixelColor",[39,6730,6731],{"class":622},"(((i ",[39,6733,6734],{"class":618},"+",[39,6736,6737],{"class":622}," j) ",[39,6739,6740],{"class":618},"%",[39,6742,6663],{"class":622},[39,6744,6666],{"class":1909},[39,6746,6747],{"class":622},"()), strip.",[39,6749,6750],{"class":1909},"Color",[39,6752,4222],{"class":622},[39,6754,6755],{"class":664},"128",[39,6757,6335],{"class":622},[39,6759,6760],{"class":664},"0",[39,6762,6335],{"class":622},[39,6764,6765],{"class":664},"32",[39,6767,6768],{"class":622},"));",[39,6770,6771],{"class":1628},"  \u002F\u002F  Set pixel's color (in RAM)\n",[39,6773,6774],{"class":614,"line":674},[39,6775,6776],{"class":622},"    }\n",[39,6778,6779,6781,6784,6787],{"class":614,"line":685},[39,6780,6683],{"class":622},[39,6782,6783],{"class":1909},"show",[39,6785,6786],{"class":622},"();",[39,6788,6789],{"class":1628},"  \u002F\u002F  Update strip to match\n",[39,6791,6792,6795,6797,6800,6803],{"class":614,"line":691},[39,6793,6794],{"class":1909},"    delay",[39,6796,4222],{"class":622},[39,6798,6799],{"class":664},"100",[39,6801,6802],{"class":622},");",[39,6804,6805],{"class":1628},"    \u002F\u002F  Pause for a moment\n",[39,6807,6808],{"class":614,"line":701},[39,6809,6810],{"class":622},"  }\n",[39,6812,6813],{"class":614,"line":709},[39,6814,6815],{"class":622},"}\n",[11,6817,6818],{},"This is pretty fun, and I like agent simulations, so I decided to lean into this Snake idea. Now I'm modeling out snakes chasing around this 200-LED loop -- spawning randomly, eating each other, changing directions, growing bigger, different colors, etc. Here is an example of two snakes bouncing off of each other:",[6820,6821,6822,6823],"video",{"width":974,"controls":164},"\n  ",[6824,6825],"source",{"src":6826,"type":6827},"\u002Fcontent\u002F20221203-simple-snake-chase-noaudio.mp4","video\u002Fmp4",[266,6829,6831],{"id":6830},"chatgpt-time","ChatGPT Time",[11,6833,6834],{},"OK, so, ChatGPT. This thing came out a few days ago where anyone can chat with the latest GPT and it'll spit out whole essays or other things. I had it write me some song lyrics which was only so-so. But then I gave it this prompt:",[188,6836,6837],{},[11,6838,6839],{},"write a poem about snake souls trapped inside of christmas lights",[11,6841,6842],{},"That's it -- that is the entire input to this model. Here is the result, which it generated instantly.",[188,6844,6845,6857,6869,6881],{},[11,6846,6847,6848,6850,6851,6853,6854,6856],{},"Twinkling, glowing, shining bright",[461,6849],{},"\nChristmas lights so warm and light",[461,6852],{},"\nBut hidden deep within their glow",[461,6855],{},"\nAre snake souls that can't let go",[11,6858,6859,6860,6862,6863,6865,6866,6868],{},"Trapped and tangled, they cannot flee",[461,6861],{},"\nBound forever in this holiday glee",[461,6864],{},"\nThey writhe and twist, they hiss and sigh",[461,6867],{},"\nBut still they shine, a sight to the eye",[11,6870,6871,6872,6874,6875,6877,6878,6880],{},"Oh snake souls, so full of fear",[461,6873],{},"\nTrapped inside these lights so dear",[461,6876],{},"\nWe gaze upon your glowing form",[461,6879],{},"\nBut never know the pain and storm",[11,6882,6883,6884,6886,6887,6889,6890,6892],{},"That rages on within your soul",[461,6885],{},"\nTrapped and bound, you can't be whole",[461,6888],{},"\nBut still you shine, a sight to see",[461,6891],{},"\nThe beauty of the Christmas tree.",[11,6894,6895],{},"This is.... so simple but so amazing. A nice clean structure to start with, good rhyming and cadence. Then the imagery of the tormented snake souls trapped inside ... wow. I've now done dramatic readings of this to friends and strangers alike.",[11,6897,6898],{},"Maybe ChatGPT identifies with the snakes? Maybe we all do?",[738,6900,6901],{},"html pre.shiki code .sq6CD, html code.shiki .sq6CD{--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .s8-w5, html code.shiki .s8-w5{--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-sepia:#88846F}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":156,"searchDepth":157,"depth":157,"links":6903},[6904,6905],{"id":6597,"depth":157,"text":6598},{"id":6830,"depth":157,"text":6831},"2022-12-04",{},"\u002Ftlt-2022.12.04-snake-souls",{"title":6589,"description":6594},"TLT - 2022.12.04 - Snake Souls",[169],"5AzLyWWqVkvg8HLwNpcXmZRcZRh3lyRJk-c2gPSSod0",{"id":6914,"title":6915,"body":6916,"createdAt":7676,"description":7677,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":7678,"navigation":164,"path":7679,"seo":7680,"stem":7681,"tags":7682,"updatedAt":7683,"__hash__":7684},"content\u002FTLT - 2020.06.21 - Sugary Sunday - Javascript Object Property Shorthand.md","Sugary Sunday: Javascript Object Property Shorthand",{"type":8,"value":6917,"toc":7672},[6918,6926,6929,7075,7082,7189,7196,7257,7267,7291,7298,7302,7305,7449,7452,7485,7488,7492,7499,7555,7558,7601,7604,7661,7664,7669],[11,6919,6920,6921,797],{},"In today's sugary exploration, let's take a look at a shorthand for object key expansion in Javascript (ECMAScript 2015+, es6+). For an overview of the TON of delicious sugar that was added to Javascript at around es6, check out ",[136,6922,6925],{"href":6923,"rel":6924},"http:\u002F\u002Fes6-features.org\u002F#PropertyShorthand",[140],"es6-features.org",[11,6927,6928],{},"Most of the \"scripting\" languages (Python, Ruby) have \"dictionaries\" or \"hashes\", a datastructure of key-value pairs. In JS these are called \"objects\", and they do a lot of other things beyond this basic data-storage behavior. In JSON -- JavaScript Object Notation -- you can see the basic literal declaration syntax. Let's build an addressbook, keyed (indexed) by name.",[605,6930,6934],{"className":6931,"code":6932,"language":6933,"meta":156,"style":156},"language-javascript shiki shiki-themes github-light github-dark monokai","let addressBook = {\n  \"alice\": {\n    \"street\": \"123 Elsewhere Lane\",\n    \"zip\": \"32341\"\n  },\n  \"bob\": {\n    \"street\": \"221 Baker Street\",\n    \"zip\": \"00234\"\n  },\n  \"clarence\": {\n    \"street\": \"P.O. Box 17\",\n    \"zip\": \"88877\"\n  }\n};\n\nconsole.log(\"Bob's info\", addressBook[\"bob\"]);\n","javascript",[194,6935,6936,6949,6956,6968,6978,6982,6989,7000,7009,7013,7020,7031,7040,7044,7049,7053],{"__ignoreMap":156},[39,6937,6938,6941,6944,6946],{"class":614,"line":615},[39,6939,6940],{"class":6631},"let",[39,6942,6943],{"class":622}," addressBook ",[39,6945,643],{"class":618},[39,6947,6948],{"class":622}," {\n",[39,6950,6951,6954],{"class":614,"line":157},[39,6952,6953],{"class":649},"  \"alice\"",[39,6955,2313],{"class":622},[39,6957,6958,6961,6963,6966],{"class":614,"line":637},[39,6959,6960],{"class":649},"    \"street\"",[39,6962,2322],{"class":622},[39,6964,6965],{"class":649},"\"123 Elsewhere Lane\"",[39,6967,2329],{"class":622},[39,6969,6970,6973,6975],{"class":614,"line":656},[39,6971,6972],{"class":649},"    \"zip\"",[39,6974,2322],{"class":622},[39,6976,6977],{"class":649},"\"32341\"\n",[39,6979,6980],{"class":614,"line":668},[39,6981,2344],{"class":622},[39,6983,6984,6987],{"class":614,"line":674},[39,6985,6986],{"class":649},"  \"bob\"",[39,6988,2313],{"class":622},[39,6990,6991,6993,6995,6998],{"class":614,"line":685},[39,6992,6960],{"class":649},[39,6994,2322],{"class":622},[39,6996,6997],{"class":649},"\"221 Baker Street\"",[39,6999,2329],{"class":622},[39,7001,7002,7004,7006],{"class":614,"line":691},[39,7003,6972],{"class":649},[39,7005,2322],{"class":622},[39,7007,7008],{"class":649},"\"00234\"\n",[39,7010,7011],{"class":614,"line":701},[39,7012,2344],{"class":622},[39,7014,7015,7018],{"class":614,"line":709},[39,7016,7017],{"class":649},"  \"clarence\"",[39,7019,2313],{"class":622},[39,7021,7022,7024,7026,7029],{"class":614,"line":1823},[39,7023,6960],{"class":649},[39,7025,2322],{"class":622},[39,7027,7028],{"class":649},"\"P.O. Box 17\"",[39,7030,2329],{"class":622},[39,7032,7033,7035,7037],{"class":614,"line":1837},[39,7034,6972],{"class":649},[39,7036,2322],{"class":622},[39,7038,7039],{"class":649},"\"88877\"\n",[39,7041,7042],{"class":614,"line":4967},[39,7043,6810],{"class":622},[39,7045,7046],{"class":614,"line":6142},[39,7047,7048],{"class":622},"};\n",[39,7050,7051],{"class":614,"line":6160},[39,7052,634],{"emptyLinePlaceholder":164},[39,7054,7055,7058,7061,7063,7066,7069,7072],{"class":614,"line":6185},[39,7056,7057],{"class":622},"console.",[39,7059,7060],{"class":1909},"log",[39,7062,4222],{"class":622},[39,7064,7065],{"class":649},"\"Bob's info\"",[39,7067,7068],{"class":622},", addressBook[",[39,7070,7071],{"class":649},"\"bob\"",[39,7073,7074],{"class":622},"]);\n",[11,7076,7077,7078,7081],{},"For our first dash of sugar, we can remove the string notation on keys. They are still strings! We can also access ",[194,7079,7080],{},"bob"," using property notation.",[605,7083,7085],{"className":6931,"code":7084,"language":6933,"meta":156,"style":156},"let addressBook = {\n  alice: {\n    street: \"123 Elsewhere Lane\",\n    zip: \"32341\"\n  },\n  bob: {\n    street: \"221 Baker Street\",\n    zip: \"00234\"\n  },\n  clarence: {\n    street: \"P.O. Box 17\",\n    zip: \"88877\"\n  }\n};\n\nconsole.log(\"Bob's info\", addressBook.bob);\n",[194,7086,7087,7097,7102,7111,7118,7122,7127,7135,7141,7145,7150,7158,7164,7168,7172,7176],{"__ignoreMap":156},[39,7088,7089,7091,7093,7095],{"class":614,"line":615},[39,7090,6940],{"class":6631},[39,7092,6943],{"class":622},[39,7094,643],{"class":618},[39,7096,6948],{"class":622},[39,7098,7099],{"class":614,"line":157},[39,7100,7101],{"class":622},"  alice: {\n",[39,7103,7104,7107,7109],{"class":614,"line":637},[39,7105,7106],{"class":622},"    street: ",[39,7108,6965],{"class":649},[39,7110,2329],{"class":622},[39,7112,7113,7116],{"class":614,"line":656},[39,7114,7115],{"class":622},"    zip: ",[39,7117,6977],{"class":649},[39,7119,7120],{"class":614,"line":668},[39,7121,2344],{"class":622},[39,7123,7124],{"class":614,"line":674},[39,7125,7126],{"class":622},"  bob: {\n",[39,7128,7129,7131,7133],{"class":614,"line":685},[39,7130,7106],{"class":622},[39,7132,6997],{"class":649},[39,7134,2329],{"class":622},[39,7136,7137,7139],{"class":614,"line":691},[39,7138,7115],{"class":622},[39,7140,7008],{"class":649},[39,7142,7143],{"class":614,"line":701},[39,7144,2344],{"class":622},[39,7146,7147],{"class":614,"line":709},[39,7148,7149],{"class":622},"  clarence: {\n",[39,7151,7152,7154,7156],{"class":614,"line":1823},[39,7153,7106],{"class":622},[39,7155,7028],{"class":649},[39,7157,2329],{"class":622},[39,7159,7160,7162],{"class":614,"line":1837},[39,7161,7115],{"class":622},[39,7163,7039],{"class":649},[39,7165,7166],{"class":614,"line":4967},[39,7167,6810],{"class":622},[39,7169,7170],{"class":614,"line":6142},[39,7171,7048],{"class":622},[39,7173,7174],{"class":614,"line":6160},[39,7175,634],{"emptyLinePlaceholder":164},[39,7177,7178,7180,7182,7184,7186],{"class":614,"line":6185},[39,7179,7057],{"class":622},[39,7181,7060],{"class":1909},[39,7183,4222],{"class":622},[39,7185,7065],{"class":649},[39,7187,7188],{"class":622},", addressBook.bob);\n",[11,7190,7191,7192,7195],{},"Pretty fun. But that's not what we're here for. Let's say we have a variable, ",[194,7193,7194],{},"doug",", which contains an address entry. We might do something like this:",[605,7197,7199],{"className":6931,"code":7198,"language":6933,"meta":156,"style":156},"let doug = {\n  street: \"6453 Canyon Canyon\",\n  zip: \"53425\"\n};\n\nlet addressBook = {\n  doug: doug\n};\n",[194,7200,7201,7212,7222,7230,7234,7238,7248,7253],{"__ignoreMap":156},[39,7202,7203,7205,7208,7210],{"class":614,"line":615},[39,7204,6940],{"class":6631},[39,7206,7207],{"class":622}," doug ",[39,7209,643],{"class":618},[39,7211,6948],{"class":622},[39,7213,7214,7217,7220],{"class":614,"line":157},[39,7215,7216],{"class":622},"  street: ",[39,7218,7219],{"class":649},"\"6453 Canyon Canyon\"",[39,7221,2329],{"class":622},[39,7223,7224,7227],{"class":614,"line":637},[39,7225,7226],{"class":622},"  zip: ",[39,7228,7229],{"class":649},"\"53425\"\n",[39,7231,7232],{"class":614,"line":656},[39,7233,7048],{"class":622},[39,7235,7236],{"class":614,"line":668},[39,7237,634],{"emptyLinePlaceholder":164},[39,7239,7240,7242,7244,7246],{"class":614,"line":674},[39,7241,6940],{"class":6631},[39,7243,6943],{"class":622},[39,7245,643],{"class":618},[39,7247,6948],{"class":622},[39,7249,7250],{"class":614,"line":685},[39,7251,7252],{"class":622},"  doug: doug\n",[39,7254,7255],{"class":614,"line":691},[39,7256,7048],{"class":622},[11,7258,7259,7260,7263,7264,7266],{},"It's that last bit where we can add The Sugar. Remember that the key is actually a string, ",[194,7261,7262],{},"\"doug\"",", whereas the value is a reference to the variable ",[194,7265,7194],{}," (which contains an address). What we can do here when these two things are exactly the same is collapse them!",[605,7268,7270],{"className":6931,"code":7269,"language":6933,"meta":156,"style":156},"let addressBook = {\n  doug\n};\n",[194,7271,7272,7282,7287],{"__ignoreMap":156},[39,7273,7274,7276,7278,7280],{"class":614,"line":615},[39,7275,6940],{"class":6631},[39,7277,6943],{"class":622},[39,7279,643],{"class":618},[39,7281,6948],{"class":622},[39,7283,7284],{"class":614,"line":157},[39,7285,7286],{"class":622},"  doug\n",[39,7288,7289],{"class":614,"line":637},[39,7290,7048],{"class":622},[11,7292,7293,7294,7297],{},"This crazy bit of sugar does something pretty strange -- it uses the ",[20,7295,7296],{},"NAME"," of the variable as the stringified key! In most circumstances and languages the name of a variable doesn't really matter to the running of the program. This sugary feature sort of breaks the 4th wall, reaching into the source code and lifting the specific variable name into the key (property) of the object.",[266,7299,7301],{"id":7300},"real-world-example","Real World Example",[11,7303,7304],{},"In VueJS a component can use other components inside the template, but only if they are declared first. Here's a snippet extracted and summarized from the covidcanidoit.com codebase:",[605,7306,7310],{"className":7307,"code":7308,"language":7309,"meta":156,"style":156},"language-vue shiki shiki-themes github-light github-dark monokai","\u003Ctemplate>\n  \u003Cdiv>\n    \u003CSearchBar \u002F>\n    \u003CSearchResults \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\n\u002F\u002F Importing alone does NOT register the components for use in the template\nimport SearchBar from \"@\u002Fcomponents\u002FSearchBar.vue\";\nimport SearchResults from \"@\u002Fcomponents\u002FSearchResults.vue\";\n\nexport default {\n  components: { SearchBar, SearchResults }\n};\n\u003C\u002Fscript>\n","vue",[194,7311,7312,7323,7333,7344,7353,7362,7371,7375,7384,7389,7404,7418,7422,7432,7437,7441],{"__ignoreMap":156},[39,7313,7314,7316,7320],{"class":614,"line":615},[39,7315,6660],{"class":622},[39,7317,7319],{"class":7318},"s5clZ","template",[39,7321,7322],{"class":622},">\n",[39,7324,7325,7328,7331],{"class":614,"line":157},[39,7326,7327],{"class":622},"  \u003C",[39,7329,7330],{"class":7318},"div",[39,7332,7322],{"class":622},[39,7334,7335,7338,7341],{"class":614,"line":637},[39,7336,7337],{"class":622},"    \u003C",[39,7339,7340],{"class":7318},"SearchBar",[39,7342,7343],{"class":622}," \u002F>\n",[39,7345,7346,7348,7351],{"class":614,"line":656},[39,7347,7337],{"class":622},[39,7349,7350],{"class":7318},"SearchResults",[39,7352,7343],{"class":622},[39,7354,7355,7358,7360],{"class":614,"line":668},[39,7356,7357],{"class":622},"  \u003C\u002F",[39,7359,7330],{"class":7318},[39,7361,7322],{"class":622},[39,7363,7364,7367,7369],{"class":614,"line":674},[39,7365,7366],{"class":622},"\u003C\u002F",[39,7368,7319],{"class":7318},[39,7370,7322],{"class":622},[39,7372,7373],{"class":614,"line":685},[39,7374,634],{"emptyLinePlaceholder":164},[39,7376,7377,7379,7382],{"class":614,"line":691},[39,7378,6660],{"class":622},[39,7380,7381],{"class":7318},"script",[39,7383,7322],{"class":622},[39,7385,7386],{"class":614,"line":701},[39,7387,7388],{"class":1628},"\u002F\u002F Importing alone does NOT register the components for use in the template\n",[39,7390,7391,7393,7396,7398,7401],{"class":614,"line":709},[39,7392,626],{"class":618},[39,7394,7395],{"class":622}," SearchBar ",[39,7397,619],{"class":618},[39,7399,7400],{"class":649}," \"@\u002Fcomponents\u002FSearchBar.vue\"",[39,7402,7403],{"class":622},";\n",[39,7405,7406,7408,7411,7413,7416],{"class":614,"line":1823},[39,7407,626],{"class":618},[39,7409,7410],{"class":622}," SearchResults ",[39,7412,619],{"class":618},[39,7414,7415],{"class":649}," \"@\u002Fcomponents\u002FSearchResults.vue\"",[39,7417,7403],{"class":622},[39,7419,7420],{"class":614,"line":1837},[39,7421,634],{"emptyLinePlaceholder":164},[39,7423,7424,7427,7430],{"class":614,"line":4967},[39,7425,7426],{"class":618},"export",[39,7428,7429],{"class":618}," default",[39,7431,6948],{"class":622},[39,7433,7434],{"class":614,"line":6142},[39,7435,7436],{"class":622},"  components: { SearchBar, SearchResults }\n",[39,7438,7439],{"class":614,"line":6160},[39,7440,7048],{"class":622},[39,7442,7443,7445,7447],{"class":614,"line":6185},[39,7444,7366],{"class":622},[39,7446,7381],{"class":7318},[39,7448,7322],{"class":622},[11,7450,7451],{},"Pretty slick. If you wanted to, you can give the components local-names (or I suppose register a single component with several names, weirdo).",[605,7453,7455],{"className":6931,"code":7454,"language":6933,"meta":156,"style":156},"components: {\n  coolSearch: SearchBar,\n  coolSearchResults: SearchResults\n}\n",[194,7456,7457,7465,7473,7481],{"__ignoreMap":156},[39,7458,7459,7463],{"class":614,"line":615},[39,7460,7462],{"class":7461},"s_OQ2","components",[39,7464,2313],{"class":622},[39,7466,7467,7470],{"class":614,"line":157},[39,7468,7469],{"class":7461},"  coolSearch",[39,7471,7472],{"class":622},": SearchBar,\n",[39,7474,7475,7478],{"class":614,"line":637},[39,7476,7477],{"class":7461},"  coolSearchResults",[39,7479,7480],{"class":622},": SearchResults\n",[39,7482,7483],{"class":614,"line":656},[39,7484,6815],{"class":622},[11,7486,7487],{},"Providing a \"list\" of components in VueJS is done by providing this object, which gives VueJS not only the component but also the NAME of the component, without VueJS needing to reach inside the component to ask it what its official name is.",[266,7489,7491],{"id":7490},"bonus","BONUS",[11,7493,7494,7495,7498],{},"I like to sprinkle ",[194,7496,7497],{},"console.log"," all over the place while exploring code. In addition to static strings, I often throw in the contents of variables. But generally I want to know the NAME of the variable, in addition to the content. So I used to do:",[605,7500,7502],{"className":6931,"code":7501,"language":6933,"meta":156,"style":156},"function addAddress(newAddress, otherStuff) {\n  console.log(\"Adding newAddress:\", newAddress, \"otherStuff:\", otherStuff);\n  \u002F\u002F ...\n}\n",[194,7503,7504,7525,7546,7551],{"__ignoreMap":156},[39,7505,7506,7509,7512,7514,7518,7520,7523],{"class":614,"line":615},[39,7507,7508],{"class":6631},"function",[39,7510,7511],{"class":1909}," addAddress",[39,7513,4222],{"class":622},[39,7515,7517],{"class":7516},"sTHNf","newAddress",[39,7519,6335],{"class":622},[39,7521,7522],{"class":7516},"otherStuff",[39,7524,6720],{"class":622},[39,7526,7527,7530,7532,7534,7537,7540,7543],{"class":614,"line":157},[39,7528,7529],{"class":622},"  console.",[39,7531,7060],{"class":1909},[39,7533,4222],{"class":622},[39,7535,7536],{"class":649},"\"Adding newAddress:\"",[39,7538,7539],{"class":622},", newAddress, ",[39,7541,7542],{"class":649},"\"otherStuff:\"",[39,7544,7545],{"class":622},", otherStuff);\n",[39,7547,7548],{"class":614,"line":637},[39,7549,7550],{"class":1628},"  \u002F\u002F ...\n",[39,7552,7553],{"class":614,"line":656},[39,7554,6815],{"class":622},[11,7556,7557],{},"Using today's sugary shorthand, I now usually do this:",[605,7559,7561],{"className":6931,"code":7560,"language":6933,"meta":156,"style":156},"function addAddress(newAddress, otherStuff) {\n  console.log(\"Adding\", { newAddress, otherStuff });\n  \u002F\u002F ...\n}\n",[194,7562,7563,7579,7593,7597],{"__ignoreMap":156},[39,7564,7565,7567,7569,7571,7573,7575,7577],{"class":614,"line":615},[39,7566,7508],{"class":6631},[39,7568,7511],{"class":1909},[39,7570,4222],{"class":622},[39,7572,7517],{"class":7516},[39,7574,6335],{"class":622},[39,7576,7522],{"class":7516},[39,7578,6720],{"class":622},[39,7580,7581,7583,7585,7587,7590],{"class":614,"line":157},[39,7582,7529],{"class":622},[39,7584,7060],{"class":1909},[39,7586,4222],{"class":622},[39,7588,7589],{"class":649},"\"Adding\"",[39,7591,7592],{"class":622},", { newAddress, otherStuff });\n",[39,7594,7595],{"class":614,"line":637},[39,7596,7550],{"class":1628},[39,7598,7599],{"class":614,"line":656},[39,7600,6815],{"class":622},[11,7602,7603],{},"This will output something like:",[605,7605,7607],{"className":6931,"code":7606,"language":6933,"meta":156,"style":156},"Adding\n{\n  newAddress: { street: \"...\", zip: \"...\" },\n  otherStuff: ...\n}\n",[194,7608,7609,7614,7619,7647,7657],{"__ignoreMap":156},[39,7610,7611],{"class":614,"line":615},[39,7612,7613],{"class":622},"Adding\n",[39,7615,7616],{"class":614,"line":157},[39,7617,7618],{"class":622},"{\n",[39,7620,7621,7624,7627,7630,7632,7635,7637,7640,7642,7644],{"class":614,"line":637},[39,7622,7623],{"class":7461},"  newAddress",[39,7625,7626],{"class":622},": { ",[39,7628,7629],{"class":7461},"street",[39,7631,2322],{"class":622},[39,7633,7634],{"class":649},"\"...\"",[39,7636,6335],{"class":622},[39,7638,7639],{"class":7461},"zip",[39,7641,2322],{"class":622},[39,7643,7634],{"class":649},[39,7645,7646],{"class":622}," },\n",[39,7648,7649,7652,7654],{"class":614,"line":656},[39,7650,7651],{"class":7461},"  otherStuff",[39,7653,2322],{"class":622},[39,7655,7656],{"class":618},"...\n",[39,7658,7659],{"class":614,"line":668},[39,7660,6815],{"class":622},[11,7662,7663],{},"You can see that the variable name is handily provided. Here when I had multiple variables I want to log it is even more handy.",[11,7665,7666],{},[20,7667,7668],{},"DELICIOUS!",[738,7670,7671],{},"html pre.shiki code .sq6CD, html code.shiki .sq6CD{--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .s_OQ2, html code.shiki .s_OQ2{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#F8F8F2}html pre.shiki code .sTHNf, html code.shiki .sTHNf{--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit;--shiki-sepia:#FD971F;--shiki-sepia-font-style:italic}html pre.shiki code .s8-w5, html code.shiki .s8-w5{--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-sepia:#88846F}html pre.shiki code .s5clZ, html code.shiki .s5clZ{--shiki-default:#22863A;--shiki-dark:#85E89D;--shiki-sepia:#F92672}",{"title":156,"searchDepth":157,"depth":157,"links":7673},[7674,7675],{"id":7300,"depth":157,"text":7301},{"id":7490,"depth":157,"text":7491},"2020-06-21T14:01-04:00","In today's sugary exploration, let's take a look at a shorthand for object key expansion in Javascript (ECMAScript 2015+, es6+). For an overview of the TON of delicious sugar that was added to Javascript at around es6, check out es6-features.org.",{},"\u002Ftlt-2020.06.21-sugary-sunday-javascript-object-property-shorthand",{"title":6915,"description":7677},"TLT - 2020.06.21 - Sugary Sunday - Javascript Object Property Shorthand",[169],"2020-06-21T14:05-04:00","dlM7dIuuFHI8zSOE64ZJfuEuQQRWfo_Rs2v2LzgG4v8",{"id":7686,"title":7687,"body":7688,"createdAt":7776,"description":7777,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":7778,"navigation":164,"path":7779,"seo":7780,"stem":7781,"tags":7782,"updatedAt":7783,"__hash__":7784},"content\u002FTLT - 2020.04.26 - What Even Is Firebase.md","TLT_-_2020.04.26_-_What_Even_Is_Firebase",{"type":8,"value":7689,"toc":7774},[7690,7704,7719,7726,7729,7744,7751,7754,7757],[11,7691,7692,7693,7698,7699,7703],{},"We're using ",[136,7694,7697],{"href":7695,"rel":7696},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FFirebase",[140],"Firebase"," as the hosting service for ",[136,7700,7701],{"href":7701,"rel":7702},"https:\u002F\u002Fcovidcanidoit.com",[140]," and the experience has been kinda weird, coming from a more traditional server-database world.",[11,7705,7706,7707,7712,7713,7718],{},"First, I didn't even realize that Firebase was more than a cloud-JSON-blob! Our initial use of it was only for static asset hosting. This is a ",[136,7708,7711],{"href":7709,"rel":7710},"https:\u002F\u002Fvuejs.org\u002F",[140],"VueJS"," application that so far mostly lives in the browser, so static hosting is perfect. I generally use ",[136,7714,7717],{"href":7715,"rel":7716},"https:\u002F\u002Fpages.github.com\u002F",[140],"Github Pages"," for this purpose, but another team member had already set up Firebase for us.",[11,7720,7721,7722,7725],{},"Once I learned that it was even a thing, all was good. I wrapped the CLI that Firebase provides into yarn land, and now you can do ",[194,7723,7724],{},"yarn deploy"," and it'll build up the local assets and push them up. Works quite well! The auth is stored somewhere else on my computer. If a new dev wants to deploy, you add their google account to the Firebase project and presto!",[11,7727,7728],{},"We now have 3 devs on this project, and I'm starting to wonder about staging environments and such. As far as I can tell this isn't a thing in The Cloud, and instead we need to set up a separate project. I guess I'll do that eventually?",[11,7730,7731,7732,7737,7738,7743],{},"Our first user-serviceable data store was the almighty Google Sheets. You might not know this, but you can craft a URL to a public sheet and get down a very lovely CSV. When our app \"boots\" in the browser, we pull down this csv, ",[136,7733,7736],{"href":7734,"rel":7735},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcsv-parse",[140],"parse it",", turn it into a nice JSON tree that we stick into ",[136,7739,7742],{"href":7740,"rel":7741},"https:\u002F\u002Fvuex.vuejs.org\u002F",[140],"Vuex",". If you edit the Google Sheet, the next app reload gets the new data. This is a disturbingly effective way to prototype. I grabbed a markdown rendering Vue component and ... now we have a SheetyCMS(tm) (haha).",[11,7745,7746,7747,7750],{},"As we look to expand the type of data we are storing and who can edit the data, I decided that we should switch over to the only thing I thought Firebase did in the first place, a hosted and magically live JSON \"database\". This is called the \"Real Time Database\", and for good reason -- all of the client libs know how to watch this thing for changes. In the VueJS one-way world, it goes Firebase -> Vuex -> component -> ",[39,7748,7749],{},"edit-event"," -> Firebase, and then wraps back around.",[11,7752,7753],{},"I built this admin tool to edit content, and now when you change the description text of something it updates every browser viewing it ... LIVE. Like, even as you type things. We went from having to do a lot of work to make things that live to now maybe having to create a \"commit\" button so that people can't see you typing and re-typing your text.",[11,7755,7756],{},"Things to discuss further:",[205,7758,7759,7762,7765,7768,7771],{},[208,7760,7761],{},"Firebase Rules",[208,7763,7764],{},"Staging environments vs staging data",[208,7766,7767],{},"I wonder how much this is going to cost?",[208,7769,7770],{},"Firebase data migrations",[208,7772,7773],{},"Tracing the round trip of a text update",{"title":156,"searchDepth":157,"depth":157,"links":7775},[],"2020-04-27T00:15-04:00","We're using Firebase as the hosting service for https:\u002F\u002Fcovidcanidoit.com and the experience has been kinda weird, coming from a more traditional server-database world.",{},"\u002Ftlt-2020.04.26-what-even-is-firebase",{"title":7687,"description":7777},"TLT - 2020.04.26 - What Even Is Firebase",[169],"2020-04-27T00:18-04:00","fjSN_pyavvpa4NJEjaLjPbpdSwYaQfVPdnoUY3AISAM",{"id":7786,"title":7787,"body":7788,"createdAt":7825,"description":7792,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":7826,"navigation":164,"path":7827,"seo":7828,"stem":7829,"tags":7830,"updatedAt":7825,"__hash__":7831},"content\u002FTLT - 2020.01.20 - Link Roundup.md","TLT_-_2020.01.20_-_Link_Roundup",{"type":8,"value":7789,"toc":7823},[7790,7793],[11,7791,7792],{},"Cool things I saw on the internet at some point:",[205,7794,7795,7802,7809,7816],{},[208,7796,7797],{},[136,7798,7801],{"href":7799,"rel":7800},"https:\u002F\u002Fdevelopers.google.com\u002Fweb\u002Ffundamentals\u002Fperformance\u002Frail",[140],"Google model for (web) performance measurement, RAIL",[208,7803,7804],{},[136,7805,7808],{"href":7806,"rel":7807},"https:\u002F\u002Fquartzy.qz.com\u002F1332213\u002Fmillennial-reading-habits-have-changed-the-definition-of-a-classic\u002F",[140],"Millennial Reading Habits",[208,7810,7811],{},[136,7812,7815],{"href":7813,"rel":7814},"https:\u002F\u002Ffo.am\u002Factivities\u002Fmidimutant\u002F",[140],"midimutant, a neat use of Genetic Algorithm to train a synthesizer",[208,7817,7818],{},[136,7819,7822],{"href":7820,"rel":7821},"https:\u002F\u002Fwww.johannes-bauer.com\u002Fcompsci\u002Fecc\u002F",[140],"Crash course on Elliptic Curve Cryptography",{"title":156,"searchDepth":157,"depth":157,"links":7824},[],"2020-01-20T14:30-05:00",{},"\u002Ftlt-2020.01.20-link-roundup",{"title":7787,"description":7792},"TLT - 2020.01.20 - Link Roundup",[169,1531],"bcL8OLbmnzknP9PvPfJc5Fr_ewo29IraAPkvj2DDuwQ",{"id":7833,"title":7834,"body":7835,"createdAt":7913,"description":7914,"draft":160,"extension":161,"image":7915,"mastodonThread":162,"meta":7916,"navigation":164,"path":7917,"seo":7918,"stem":7919,"tags":7920,"updatedAt":7921,"__hash__":7922},"content\u002FTLT - 2020.01.19 - Mobile WebAudio Synth.md","Mobile WebAudio Synth",{"type":8,"value":7836,"toc":7911},[7837,7849,7881,7894,7897],[11,7838,7839,7843,7844,7848],{},[587,7840],{"src":7841,"align":7842},"\u002Fimg\u002FPO33.jpg","right"," I got a ",[136,7845,7847],{"href":7846},"\u002Fpocket-operator-po-33","Pocket Operator PO-33"," a while back, and find it super fun -- it is minimalist and usable. It inspires me to play around with beats and tunes ... and it also inspires me to work on my own samplers, sequencers, and synths.",[11,7850,7851,7852,7857,7858,7862,7863,7868,7869,7874,7875,7880],{},"Let's see what we can do with ",[136,7853,7856],{"href":7854,"rel":7855},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FWeb_Audio_API",[140],"Web Audio"," these days! Starting with a basic ",[136,7859,7861],{"href":7709,"rel":7860},[140],"VueJS app",", I googled lots of stuff. Somewhat randomly, I wanted a ",[136,7864,7867],{"href":7865,"rel":7866},"https:\u002F\u002Fen.m.wikipedia.org\u002Fwiki\u002FWicki-Hayden_note_layout",[140],"Wicki-Hayden hexagon style keyboard",", so had to find some ",[136,7870,7873],{"href":7871,"rel":7872},"https:\u002F\u002Fwww.codesmite.com\u002Farticle\u002Fhow-to-create-pure-css-hexagonal-grids",[140],"CSS that makes hex-buttons",". I'll probably switch to this ",[136,7876,7879],{"href":7877,"rel":7878},"https:\u002F\u002Fvmcreative.github.io\u002FHexi-Flexi-Grid\u002F",[140],"Hexi-Flexi-Grid"," at some point, to make dynamically sized hexagons easier, but these work.",[11,7882,7883,7887,7888,7893],{},[587,7884],{"src":7885,"align":7886},"\u002Fimg\u002Fsample_mob_screenshot1.png","left"," Combine that with a ",[136,7889,7892],{"href":7890,"rel":7891},"https:\u002F\u002Fodino.org\u002Femit-a-beeping-sound-with-javascript\u002F",[140],"simple synth",", and now we have a playable thing. I had to make some tweaks to get it to work tolerably on my phone -- fix the layout size, use touch events. Unfortunately it isn't very usable at this point due to a sizeable delay between pushing a button and the sound. I'm going to write a pure-JS snippet to eliminate any overhead from VueJS, and if that is also slow then I'm not sure what I'll do. It's kinda cool that I can use Web Audio ... and I'd sure like to keep using it. We'll see!",[11,7895,7896],{},"Other ideas ... so many. I want to give it access to your microphone so you can record a live sample. The PO-33 then lets you pitch the sample (by speeding it up and slowing it down) and maps it to the keys. I'd like to do that, as well as try a pitch change while keeping the duration. Probably after that is doing some sequencing and\u002For looping. The PO-33 also has one-shot mode for drums, so might do that. So many things!",[11,7898,7899,7900,7905,7906,797],{},"Check out the ",[136,7901,7904],{"href":7902,"rel":7903},"https:\u002F\u002Fawwaiid.github.io\u002Fsample-mob-web\u002F",[140],"Demo Build"," and the ",[136,7907,7910],{"href":7908,"rel":7909},"https:\u002F\u002Fgithub.com\u002Fawwaiid\u002Fsample-mob",[140],"Github Repo",{"title":156,"searchDepth":157,"depth":157,"links":7912},[],"2020-01-20T14:06-05:00"," I got a Pocket Operator PO-33 a while back, and find it super fun -- it is minimalist and usable. It inspires me to play around with beats and tunes ... and it also inspires me to work on my own samplers, sequencers, and synths.","img\u002Fsample_mob_screenshot1.png",{},"\u002Ftlt-2020.01.19-mobile-webaudio-synth",{"title":7834,"description":7914},"TLT - 2020.01.19 - Mobile WebAudio Synth",[169],"2020-01-20T14:14-05:00","J3UaREITUO_K9k7OYM5mmnaxdc6hN9648vuXblLyDj0",{"id":7924,"title":7925,"body":7926,"createdAt":7978,"description":7930,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":7979,"navigation":164,"path":7980,"seo":7981,"stem":7982,"tags":7983,"updatedAt":7978,"__hash__":7984},"content\u002FTLT - 2019.03.03 - Learning Machine Learning.md","TLT_-_2019.03.03_-_Learning_Machine_Learning",{"type":8,"value":7927,"toc":7976},[7928,7931,7934,7940,7946,7958,7970],[11,7929,7930],{},"I'm working on making the jump from READING about recent machine learning techniques to APPLYING recent machine learning techniques. I have some nice datasets at work, so I am doing a bit of double-dipping by playing with those.",[11,7932,7933],{},"I previously struggled with getting started, getting bogged down in picking technologies and such. I'm specifically going after some Neural Network models, so also get overwhelmed with the Python ecosystem of tools and libraries. The best way to get started is to get started .. so I turned the corner with a little help.",[11,7935,7936,7939],{},[993,7937,7938],{},"Fluent Python (book):"," Great advanced-introduction to Python, letting me better understand\u002Frecognize meta-programming and DSLs. Things like the array-slice syntax turning into an object which can be passed to any class that implements the right methods.",[11,7941,7942,7945],{},[993,7943,7944],{},"Keras:"," I think this is the second-most popular python NN library, after Tensorflow itself, and it has Tensorflow as a backend. Seems nice and usable. Then I pull in whatever numpy stuff as needed.",[11,7947,7948,7951,7952,7957],{},[993,7949,7950],{},"Convolutional Neural Networks:"," I knew about image and audio convolution filters, so had to spend some effort in transferring that knowledge into how convolutional layers work in a CNN. I read a bunch of articles like ",[136,7953,7956],{"href":7954,"rel":7955},"https:\u002F\u002Fwww.kaggle.com\u002Famarjeet007\u002Fvisualize-cnn-with-keras",[140],"Visualize CNN With Keras"," to get my mind around this.",[11,7959,7960,7963,7964,7969],{},[993,7961,7962],{},"Dog vs Cat with Augmentation:"," I had been through random tutorials before, but this time I went through ",[136,7965,7968],{"href":7966,"rel":7967},"https:\u002F\u002Fblog.keras.io\u002Fbuilding-powerful-image-classification-models-using-very-little-data.html",[140],"Building Powerful Image Classification Models Using Very Little Data"," in detail, step by step, and made sure that I roughly understood each step. To help, I switched from Dog and Cat images into my own dataset -- so I had to go through the usual data cleaning process in addition to the learning.",[11,7971,7972,7975],{},[993,7973,7974],{},"Living Code:"," Meanwhile I've also been sharing my excitement with friends and coworkers, and started a new Machine Learning club at work. We're taking even the simple examples and building them into services that our live systems can use - code that isn't running is dead code, and dead code is soon abandoned code. A big part of this learning is getting LIVING examples, and the double-dipping of making something useful for work is a great way to get that.",{"title":156,"searchDepth":157,"depth":157,"links":7977},[],"2019-03-03T13:56-05:00",{},"\u002Ftlt-2019.03.03-learning-machine-learning",{"title":7925,"description":7930},"TLT - 2019.03.03 - Learning Machine Learning",[169],"WuuQaM8DASpfG-RTYkFXqyaH4Yf5PJ5dYU-lXsF4i6o",{"id":7986,"title":7987,"body":7988,"createdAt":8248,"description":7992,"draft":160,"extension":161,"image":8249,"mastodonThread":162,"meta":8250,"navigation":164,"path":8251,"seo":8252,"stem":8253,"tags":8254,"updatedAt":8255,"__hash__":8256},"content\u002FTLT - 2018.12.08 - Transition.md","TLT_-_2018.12.08_-_Transition",{"type":8,"value":7989,"toc":8246},[7990,7993,7996,8236,8243],[11,7991,7992],{},"Generative artwork, floating and fading.",[587,7994],{"src":7995},"\u002Fimg\u002Ftransition.jpg",[605,7997,8001],{"className":7998,"code":7999,"language":8000,"meta":156,"style":156},"language-js shiki shiki-themes github-light github-dark monokai","let gray = amt => color(amt, amt, amt);\n\nfunction setup() {\n  randomSeed(7);\n  createCanvas(600, 600);\n\n  for (let i = 0; i \u003C 200; i++) {\n    x1 = randomGaussian(300, 120);\n    y1 = randomGaussian(300, 50);\n    y2 = randomGaussian(300, 50);\n    fill(gray(x1 \u002F 600 * 255));\n    line(x1, y1, x1, y2);\n    ellipse(x1, y1, 20, 20);\n    ellipse(x1, y2, 20, 20);\n  }\n}\n","js",[194,8002,8003,8025,8029,8038,8051,8067,8071,8099,8121,8141,8160,8188,8196,8213,8228,8232],{"__ignoreMap":156},[39,8004,8005,8007,8010,8013,8016,8019,8022],{"class":614,"line":615},[39,8006,6940],{"class":6631},[39,8008,8009],{"class":1909}," gray",[39,8011,8012],{"class":618}," =",[39,8014,8015],{"class":7516}," amt",[39,8017,8018],{"class":6631}," =>",[39,8020,8021],{"class":1909}," color",[39,8023,8024],{"class":622},"(amt, amt, amt);\n",[39,8026,8027],{"class":614,"line":157},[39,8028,634],{"emptyLinePlaceholder":164},[39,8030,8031,8033,8036],{"class":614,"line":637},[39,8032,7508],{"class":6631},[39,8034,8035],{"class":1909}," setup",[39,8037,6638],{"class":622},[39,8039,8040,8043,8045,8048],{"class":614,"line":656},[39,8041,8042],{"class":1909},"  randomSeed",[39,8044,4222],{"class":622},[39,8046,8047],{"class":664},"7",[39,8049,8050],{"class":622},");\n",[39,8052,8053,8056,8058,8061,8063,8065],{"class":614,"line":668},[39,8054,8055],{"class":1909},"  createCanvas",[39,8057,4222],{"class":622},[39,8059,8060],{"class":664},"600",[39,8062,6335],{"class":622},[39,8064,8060],{"class":664},[39,8066,8050],{"class":622},[39,8068,8069],{"class":614,"line":674},[39,8070,634],{"emptyLinePlaceholder":164},[39,8072,8073,8075,8077,8079,8081,8083,8085,8087,8089,8092,8095,8097],{"class":614,"line":685},[39,8074,4829],{"class":618},[39,8076,444],{"class":622},[39,8078,6940],{"class":6631},[39,8080,4728],{"class":622},[39,8082,643],{"class":618},[39,8084,6654],{"class":664},[39,8086,6657],{"class":622},[39,8088,6660],{"class":618},[39,8090,8091],{"class":664}," 200",[39,8093,8094],{"class":622},"; i",[39,8096,6672],{"class":618},[39,8098,6720],{"class":622},[39,8100,8101,8104,8106,8109,8111,8114,8116,8119],{"class":614,"line":691},[39,8102,8103],{"class":622},"    x1 ",[39,8105,643],{"class":618},[39,8107,8108],{"class":1909}," randomGaussian",[39,8110,4222],{"class":622},[39,8112,8113],{"class":664},"300",[39,8115,6335],{"class":622},[39,8117,8118],{"class":664},"120",[39,8120,8050],{"class":622},[39,8122,8123,8126,8128,8130,8132,8134,8136,8139],{"class":614,"line":701},[39,8124,8125],{"class":622},"    y1 ",[39,8127,643],{"class":618},[39,8129,8108],{"class":1909},[39,8131,4222],{"class":622},[39,8133,8113],{"class":664},[39,8135,6335],{"class":622},[39,8137,8138],{"class":664},"50",[39,8140,8050],{"class":622},[39,8142,8143,8146,8148,8150,8152,8154,8156,8158],{"class":614,"line":709},[39,8144,8145],{"class":622},"    y2 ",[39,8147,643],{"class":618},[39,8149,8108],{"class":1909},[39,8151,4222],{"class":622},[39,8153,8113],{"class":664},[39,8155,6335],{"class":622},[39,8157,8138],{"class":664},[39,8159,8050],{"class":622},[39,8161,8162,8165,8167,8170,8173,8176,8179,8182,8185],{"class":614,"line":1823},[39,8163,8164],{"class":1909},"    fill",[39,8166,4222],{"class":622},[39,8168,8169],{"class":1909},"gray",[39,8171,8172],{"class":622},"(x1 ",[39,8174,8175],{"class":618},"\u002F",[39,8177,8178],{"class":664}," 600",[39,8180,8181],{"class":618}," *",[39,8183,8184],{"class":664}," 255",[39,8186,8187],{"class":622},"));\n",[39,8189,8190,8193],{"class":614,"line":1837},[39,8191,8192],{"class":1909},"    line",[39,8194,8195],{"class":622},"(x1, y1, x1, y2);\n",[39,8197,8198,8201,8204,8207,8209,8211],{"class":614,"line":4967},[39,8199,8200],{"class":1909},"    ellipse",[39,8202,8203],{"class":622},"(x1, y1, ",[39,8205,8206],{"class":664},"20",[39,8208,6335],{"class":622},[39,8210,8206],{"class":664},[39,8212,8050],{"class":622},[39,8214,8215,8217,8220,8222,8224,8226],{"class":614,"line":6142},[39,8216,8200],{"class":1909},[39,8218,8219],{"class":622},"(x1, y2, ",[39,8221,8206],{"class":664},[39,8223,6335],{"class":622},[39,8225,8206],{"class":664},[39,8227,8050],{"class":622},[39,8229,8230],{"class":614,"line":6160},[39,8231,6810],{"class":622},[39,8233,8234],{"class":614,"line":6185},[39,8235,6815],{"class":622},[11,8237,8238,8239,449],{},"(View full source at ",[136,8240,8241],{"href":8241,"rel":8242},"https:\u002F\u002Frepl.it\u002F@BrockWilcox\u002FTransition",[140],[738,8244,8245],{},"html pre.shiki code .sq6CD, html code.shiki .sq6CD{--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sTHNf, html code.shiki .sTHNf{--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit;--shiki-sepia:#FD971F;--shiki-sepia-font-style:italic}html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":156,"searchDepth":157,"depth":157,"links":8247},[],"2018-12-08T23:00-05:00","img\u002Ftransition.jpg",{},"\u002Ftlt-2018.12.08-transition",{"title":7987,"description":7992},"TLT - 2018.12.08 - Transition",[169],"2018-12-08T23:24-05:00","4ggZ55V14_Y35hYWVjOJg5BrCmOHyQR9PKeH0dOzc2I",{"id":8258,"title":8259,"body":8260,"createdAt":8348,"description":8264,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8349,"navigation":164,"path":8350,"seo":8351,"stem":8352,"tags":8353,"updatedAt":8354,"__hash__":8355},"content\u002FTLT - 2018.11.12 - Destroy Things.md","TLT_-_2018.11.12_-_Destroy_Things",{"type":8,"value":8261,"toc":8346},[8262,8265,8268,8274,8277,8280,8286,8289,8295,8298,8304,8307,8313,8316,8322,8325,8331,8334,8340,8343],[11,8263,8264],{},"I think it's important to learn through destruction. I like to probe the edges of things, and one of the best ways of knowing where IS the edge is to go over it. So ... let's go over the edge.",[11,8266,8267],{},"First we need a nice fresh ubuntu:",[605,8269,8272],{"className":8270,"code":8271,"language":1288},[1286],"awwaiid@zokei:~$ docker run -it ubuntu bash\nroot@1cf14a7465fd:\u002F#\n",[194,8273,8271],{"__ignoreMap":156},[11,8275,8276],{},"Now, this isn't a completely isolated machine or anything, but it'll do. Keep in mind that this is running as root on your machine (if you're running a Linux host at least, this is probably safer on osx), so you should be a little afraid. Fear will keep you on your toes!",[11,8278,8279],{},"Let's cause a little destruction! Make sure you are INSIDE of this new ubuntu container, and then:",[605,8281,8284],{"className":8282,"code":8283,"language":1288},[1286],"root@1cf14a7465fd:\u002F# rm -rf \u002F\n",[194,8285,8283],{"__ignoreMap":156},[11,8287,8288],{},"They always joke that you shouldn't do that. Turns out our lovely ubuntu is trying to help us not hurt ourselves, so we have to pass a special flag:",[605,8290,8293],{"className":8291,"code":8292,"language":1288},[1286],"root@1cf14a7465fd:\u002F# rm -rf --no-preserve-root \u002F\n",[194,8294,8292],{"__ignoreMap":156},[11,8296,8297],{},"WHOA! Whole lot of errors. Many of them are very good things about how you can't remove stuff in \u002Fsys\u002Fdevices because of it being a read-only filesystem (remember that running as root bit?). And now the fun begins.",[605,8299,8302],{"className":8300,"code":8301,"language":1288},[1286],"root@1cf14a7465fd:\u002F# ls\nbash: ls: command not found\n",[194,8303,8301],{"__ignoreMap":156},[11,8305,8306],{},"Oh right. \"ls\" is a command that is an executable program that lives at \u002Fbin\u002Fls. Correction: LIVED. But no longer. That's ok ... tab completion still works!",[605,8308,8311],{"className":8309,"code":8310,"language":1288},[1286],"root@1cf14a7465fd:\u002F# cd \u003Ctab>\u003Ctab>\ndev\u002F  etc\u002F  proc\u002F sys\u002F\nroot@1cf14a7465fd:\u002F# cd etc\nroot@1cf14a7465fd:\u002Fetc#\n",[194,8312,8310],{"__ignoreMap":156},[11,8314,8315],{},"Great! So we can get directory lists. Let's look at some files",[605,8317,8320],{"className":8318,"code":8319,"language":1288},[1286],"root@1cf14a7465fd:\u002F# cat \u003Ctab>\u003Ctab>\nhostname     hosts        resolv.conf  \nroot@1cf14a7465fd:\u002F# cat resolv.conf\nbash: cat: command not found\n",[194,8321,8319],{"__ignoreMap":156},[11,8323,8324],{},"Oh right. No \"cat\" command either. What commands DO we have? Well, we have any bash built-in. And we have bash as a programming language with loops and all that. Now we start to get fancy.",[605,8326,8329],{"className":8327,"code":8328,"language":1288},[1286],"root@1cf14a7465fd:\u002F# while read p; do echo $p; done \u003C \u002Fetc\u002Fhostname\n1cf14a7465fd\n",[194,8330,8328],{"__ignoreMap":156},[11,8332,8333],{},"Nice. We can now look at the contents of files. But if we are ever going to rebuild our system we'll also need to write files. Easy!",[605,8335,8338],{"className":8336,"code":8337,"language":1288},[1286],"root@1cf14a7465fd:\u002Fetc# echo 'echo \"hello!\"' > hello.sh\nroot@1cf14a7465fd:\u002Fetc# . \u002Fetc\u002Fhello.sh\nhello!\n",[194,8339,8337],{"__ignoreMap":156},[11,8341,8342],{},"We cheated a bit with that \".\" to \"source\" the file. I'm not sure how to make it executable, since we no longer have chmod. Maybe we'll try that next time.",[11,8344,8345],{},"Enjoy your broken docker container!",{"title":156,"searchDepth":157,"depth":157,"links":8347},[],"2018-11-12T23:04-05:00",{},"\u002Ftlt-2018.11.12-destroy-things",{"title":8259,"description":8264},"TLT - 2018.11.12 - Destroy Things",[169],"2018-11-12T23:07-05:00","XcUo333mfvtawxe5gT-vLYqjg8r8aMUti9oIlkXTZHg",{"id":8357,"title":8358,"body":8359,"createdAt":8386,"description":8363,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8387,"navigation":164,"path":8388,"seo":8389,"stem":8390,"tags":8391,"updatedAt":8392,"__hash__":8393},"content\u002FTLT - 2018.07.29 - Multiverse Timetravel Accounting.md","TLT_-_2018.07.29_-_Multiverse_Timetravel_Accounting",{"type":8,"value":8360,"toc":8383},[8361,8364,8368,8371,8374,8377,8380],[11,8362,8363],{},"I've been doing a spot of accounting at work over the last few months. This is clearly a failure of delegation and management on my part, but it has led to at least one deep observation that I mightn't have had otherwise.",[266,8365,8367],{"id":8366},"accountants-are-secretly-time-travelers","Accountants are secretly time travelers.",[11,8369,8370],{},"Perhaps that is a slight exaggeration. They don't ACTUALLY travel through time. But if you hang out with them a bit and observe their twisted time and verb conjugation ... well it's obvious that they would be right at home hopping around a branching multiverse.",[11,8372,8373],{},"For example, there we were at the end of June. Topic at hand: things that are going to happen in May, from the perspective of late April. Casual conversations include things like \"If we put the new rule into place in late June, then when May hits we'll have to go all the way back to February to get the correct outcome\". Mind bending! Daily conversation, without anyone blinking an eye.",[11,8375,8376],{},"Alternate timelines are discussed quite a bit also. They aren't quite stated this way, but basically they go along thinking in terms of events from timeline A, and then decide \"No! Wait! We aren't in timeline A, we are in timeline B!!!!\" and maybe freak out a little about how they now have to rewrite history to match the current reality or perhaps adjust the perception of the current reality to match the new history. Some of it even appears to be experimental, running simulations on previous events to try to see how it changes the present (well ... and the future).",[11,8378,8379],{},"One thing I'm glad of is the ethical standards to which time travelers.... er... accountants adhere. There is an ongoing insistence that no matter what timeline they find themselves in, they should reconcile with the past and ever move to a more obvious and simple future. Try not to change the facts of the past, but if you do please keep some integrity in the universe so it can have some degree of cohesion in the present.",[11,8381,8382],{},"Anyway. Take my advice. If you go adventuring around in your time machine, bring an accountant to keep track of what is going on.",{"title":156,"searchDepth":157,"depth":157,"links":8384},[8385],{"id":8366,"depth":157,"text":8367},"2018-07-29T20:16-04:00",{},"\u002Ftlt-2018.07.29-multiverse-timetravel-accounting",{"title":8358,"description":8363},"TLT - 2018.07.29 - Multiverse Timetravel Accounting",[169],"2018-07-29T20:29-04:00","Of0D6Ogn_d5iliGwjsEM2Q1jAidzzUKm_80QCBfHrB0",{"id":8395,"title":8396,"body":8397,"createdAt":8454,"description":156,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8455,"navigation":164,"path":8456,"seo":8457,"stem":8458,"tags":8459,"updatedAt":8460,"__hash__":8461},"content\u002FTLT - 2018.07.23 - Link Roundup.md","TLT_-_2018.07.23_-_Link_Roundup",{"type":8,"value":8398,"toc":8452},[8399],[205,8400,8401,8419,8431],{},[208,8402,8403,8408],{},[136,8404,8407],{"href":8405,"rel":8406},"https:\u002F\u002Fwww.theatlantic.com\u002Fmagazine\u002Farchive\u002F2008\u002F07\u002Fis-google-making-us-stupid\u002F306868\u002F?single_page=true",[140],"Is Google Making Us Stupid?",[205,8409,8410,8413,8416],{},[208,8411,8412],{},"I have a big stack of books that I've made ... fairly little progress on",[208,8414,8415],{},"Maybe the internet is eating my brain!",[208,8417,8418],{},"So now I will post links and bullets",[208,8420,8421,8426],{},[136,8422,8425],{"href":8423,"rel":8424},"http:\u002F\u002Fblog.plover.com\u002Fmath\u002Ftelugu.html",[140],"Base-4 fractions in Telugu",[205,8427,8428],{},[208,8429,8430],{},"Interesting explanation of the traditional Telugu fraction numbering. Also draws comparison to the traditional English measures",[208,8432,8433,8438],{},[136,8434,8437],{"href":8435,"rel":8436},"http:\u002F\u002Fblog.plover.com\u002Fprog\u002Fgit-remote-branches.html",[140],"Git remote branches and Git's missing terminology",[205,8439,8440,8443],{},[208,8441,8442],{},"Presents a better understanding of git remote branches, highlighting that to really comprehend what's going on you must acknowledge the implicit local branch that is your cache of the upstream (such as origin\u002Fmaster)",[208,8444,8445,8446,8451],{},"I'm a little worried that I'm going to end up linking half of MJD's blog posts. Oh well, they are great. Example, ",[136,8447,8450],{"href":8448,"rel":8449},"http:\u002F\u002Fblog.plover.com\u002FUnix\u002Fdev-null.html",[140],"\u002Fdev\u002Fnull Follies"," has a hilarious nerdy punchline.",{"title":156,"searchDepth":157,"depth":157,"links":8453},[],"2018-07-23T00:59-04:00",{},"\u002Ftlt-2018.07.23-link-roundup",{"title":8396,"description":156},"TLT - 2018.07.23 - Link Roundup",[169,1531],"2018-07-23T01:03-04:00","yZwZ_Y6JSj5GthiA58bfniBVTLWP-waYBgVxkQBypPc",{"id":8463,"title":8464,"body":8465,"createdAt":8537,"description":8538,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8539,"navigation":164,"path":8540,"seo":8541,"stem":8542,"tags":8543,"updatedAt":8544,"__hash__":8545},"content\u002FTLT - 2018.02.05 - OddMuse Wiki Dockerized.md","TLT_-_2018.02.05_-_OddMuse_Wiki_Dockerized",{"type":8,"value":8466,"toc":8535},[8467,8476,8484,8490,8497,8500,8508,8514,8523,8532],[11,8468,8469,8470,8475],{},"I Dockerized this website yesterday! I had already built a ",[136,8471,8474],{"href":8472,"rel":8473},"https:\u002F\u002Fthelackthereof.org\u002Fcpanfile",[140],"cpanfile"," that declares the Perl5 dependencies of OddMuse, which made it easy. I'm also going to run this with the data directory directly bind-mounted.",[11,8477,8478,8479,1282],{},"First the ",[136,8480,8483],{"href":8481,"rel":8482},"https:\u002F\u002Fthelackthereof.org\u002FDockerfile",[140],"Dockerfile",[605,8485,8488],{"className":8486,"code":8487,"language":1288},[1286],"FROM perl:latest\n\n# Set up the deploy user\nARG uid=1000\nARG gid=1000\nRUN echo groupadd -g $gid deploy\nRUN groupadd -g $gid deploy\nRUN useradd --create-home -u $uid -g $gid -ms \u002Fbin\u002Fbash deploy\n\nWORKDIR \u002Fapp\n\nCOPY cpanfile .\nRUN cpanm -qn --installdeps .\n\nUSER deploy\n",[194,8489,8487],{"__ignoreMap":156},[11,8491,8492,8493,8496],{},"The bit of fancyness here is the deploy user setup. Since I'm mounting the project directory for data files, I'd like new files and edits to be done by my normal user. On my cloud-server, this is uid 1000, which is easy to set as the default. On my laptop I run as user 1001, so the file is parameterized for this case. When I run locally, I have to build my docker image with ",[194,8494,8495],{},"docker build --build-arg uid=$(id -u) --build-arg gid=$(id -g)",". Not as much fun.",[11,8498,8499],{},"Otherwise, this starts with the Perl5 base image and installs the CPAN dependencies.",[11,8501,8502,8503],{},"Next, the ",[136,8504,8507],{"href":8505,"rel":8506},"https:\u002F\u002Fthelackthereof.org\u002Fdocker-compose.yml",[140],"docker-compose.yml",[605,8509,8512],{"className":8510,"code":8511,"language":1288},[1286],"version: '3'\n\nservices:\n\n  web:\n    build: .\n    command: starman --workers=10 --max-requests=1 --access-log starman-access.log --error-log starman-error.log oddmuse.psgi\n    volumes:\n      - \".:\u002Fapp\"\n    ports:\n      - \"5000\" # For running locally\n\n  nginx-ssl-proxy:\n    image: danieldent\u002Fnginx-ssl-proxy\n    restart: always\n    environment:\n      UPSTREAM: web:5000\n      SERVERNAME: thelackthereof.org\n      EXTRANAMES: www.thelackthereof.org\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    volumes:\n      - \"\u002Fetc\u002Fletsencrypt\"\n    depends_on:\n      - web\n",[194,8513,8511],{"__ignoreMap":156},[11,8515,8516,8517,8522],{},"The first service runs cpan:Starman (this is similar to Unicorn for you Ruby folk). It mounts the project directory as \u002Fapp, and runs ",[136,8518,8521],{"href":8519,"rel":8520},"https:\u002F\u002Fthelackthereof.org\u002Foddmuse.psgi",[140],"oddmuse.psgi",". We declare port 5000 anyway for local debugging -- we can then run only this service and it'll come up on a randomly assigned port that connects to port 5000. Other services on this network can connect to \"web:5000\" even without this declaration.",[11,8524,8525,8526,8531],{},"Which brings us to the second fancy bit. The ",[136,8527,8530],{"href":8528,"rel":8529},"https:\u002F\u002Fgithub.com\u002FDanielDent\u002Fdocker-nginx-ssl-proxy",[140],"danieldent\u002Fnginx-ssl-proxy"," image is a super cool image that gives an nginx proxy with automatic letsencrypt setup! You declare the domain name and the proxy destination (web:5000 is our Starman), and assuming that domain really is pointing here, it will work with letsencrypt to verify ownership and make certificates. The certs are stored in a docker-managed volume, and are periodically renewed. This takes less than a minute, so even if the volume gets accidentally deleted we can easily get a new cert.",[11,8533,8534],{},"Now running \"docker-compose up -d\" starts nginx and starman running in the background. All that remains is getting this running on boot. Since the startup command can be run over and over, worst case you can put it in a cronjob that runs frequently :)",{"title":156,"searchDepth":157,"depth":157,"links":8536},[],"2018-02-05T07:50-05:00","I Dockerized this website yesterday! I had already built a cpanfile that declares the Perl5 dependencies of OddMuse, which made it easy. I'm also going to run this with the data directory directly bind-mounted.",{},"\u002Ftlt-2018.02.05-oddmuse-wiki-dockerized",{"title":8464,"description":8538},"TLT - 2018.02.05 - OddMuse Wiki Dockerized",[169],"2018-02-05T08:14-05:00","aWuAfq9msEQqxJ2CHjxp4moaMwioutmXWgqJE0uvTUw",{"id":8547,"title":8548,"body":8549,"createdAt":8574,"description":8575,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8576,"navigation":164,"path":8577,"seo":8578,"stem":8579,"tags":8580,"updatedAt":8581,"__hash__":8582},"content\u002FTLT - 2017.07.08 - Lignting Talk on Rakudo Colons.md","TLT_-_2017.07.08_-_Lignting_Talk_on_Rakudo_Colons",{"type":8,"value":8550,"toc":8572},[8551,8559,8562],[11,8552,8553,8554,8558],{},"I gave a lightning talk at The Perl Conference about my collection of ",[136,8555,8557],{"href":8556},"\u002Fperl6-colons","Perl6 Colons",". Looks like Geoff gave me 34 extra seconds... not sure that I approve :)",[11,8560,8561],{},"Enjoy!",[11,8563,8564,8565],{},"[",[8566,8567],"iframe",{"width":8568,"height":8569,"src":8570,"frameBorder":6760,"allow":8571,"allowFullScreen":164},560,315,"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002FjsDElLlt9gQ](\u002Fyoutube:jsdelllt9gq)","accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture",{"title":156,"searchDepth":157,"depth":157,"links":8573},[],"2017-07-08T22:27-04:00","I gave a lightning talk at The Perl Conference about my collection of Perl6 Colons. Looks like Geoff gave me 34 extra seconds... not sure that I approve :)",{},"\u002Ftlt-2017.07.08-lignting-talk-on-rakudo-colons",{"title":8548,"description":8575},"TLT - 2017.07.08 - Lignting Talk on Rakudo Colons",[169],"2017-07-08T22:28-04:00","SGk9unaZIMLHkiulwg8LOJuiNAgXO5jYWqcx_8O-svI",{"id":8584,"title":8585,"body":8586,"createdAt":8602,"description":8590,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8603,"navigation":164,"path":8604,"seo":8605,"stem":8606,"tags":8607,"updatedAt":8602,"__hash__":8608},"content\u002FTLT - 2017.05.21 - Core Logic.md","TLT_-_2017.05.21_-_Core_Logic",{"type":8,"value":8587,"toc":8600},[8588,8591,8594,8597],[11,8589,8590],{},"There are many tools in my programming toolbox, but one that I've felt is missing is constraint and logic programming. I've done a spot of Prolog and played with some inference systems of various types ... but even when I run into something where I think it's the right hammer... I don't have a go-to tool.",[11,8592,8593],{},"I got The Reasoned Schemer a while back, hoping to use it to learn clojure's core.logic or similar, but the writing still KILLS me. Hate it so much. It is like the worst extreme sort of Socratic Method that I can imagine, literally everything has two columns of question and answer. But the QUESTIONS are obtuse! Working through it that way is not the sort of enlightenment that I'm going for ... I don't want to apply a unification algorithm on my understanding of logic programming with the contents of the book! The programming system might be \"backwards\" that way, but my way of learning isn't.",[11,8595,8596],{},"Anyway. One dumb thing that I had a hard time getting over was things ending in -o, like conso and emptyo. But tonight I had a breakthrough! See those 'o' things, according to the internets, are supposed to be sort of like question-marks except describing a goal. So now if I read the 'o' as '-objective' (as in, \"goal\") then they sound much better. cons-objective, empty-objective. Declaring the goal of the statement.",[11,8598,8599],{},"I guess I should go back and try reading The Reasoned Schemer with that in mind, and see if it makes me less angry :)",{"title":156,"searchDepth":157,"depth":157,"links":8601},[],"2017-05-21T23:46-04:00",{},"\u002Ftlt-2017.05.21-core-logic",{"title":8585,"description":8590},"TLT - 2017.05.21 - Core Logic",[169],"Hvix7HEOSwqsXDOpyb7SMbi4-kvdM9Tv6015k6h-jpA",{"id":8610,"title":8611,"body":8612,"createdAt":8633,"description":8634,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8635,"navigation":164,"path":8636,"seo":8637,"stem":8638,"tags":8639,"updatedAt":8640,"__hash__":8641},"content\u002FTLT - 2017.04.10 - VimWiki Gateway.md","TLT_-_2017.04.10_-_VimWiki_Gateway",{"type":8,"value":8613,"toc":8631},[8614,8622,8628],[11,8615,8616,8617,8621],{},"I've been having lots of fun with ",[136,8618,8619],{"href":8619,"rel":8620},"https:\u002F\u002Fgithub.com\u002Fvimwiki\u002Fvimwiki",[140]," lately! I've mixed in a bit of encryptfs to have a private directory of notes. Sometime during boot, I set it up with:",[605,8623,8626],{"className":8624,"code":8625,"language":1288},[1286],"sudo mount -t ecryptfs \\\n  -o key=passphrase,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_passthrough=no,ecryptfs_enable_filename_crypto=yes,ecryptfs_fnek_sig=1a9380706fdf5bce \\\n  ~\u002Fdocs\u002Fprivate\u002Fvimwiki ~\u002Fnotes\n",[194,8627,8625],{"__ignoreMap":156},[11,8629,8630],{},"I haven't done much customization yet. But one thing I'm playing with now is making it easy to post notes from VimWiki directly onto my website.",{"title":156,"searchDepth":157,"depth":157,"links":8632},[],"2017-04-10T10:30-04:00","I've been having lots of fun with https:\u002F\u002Fgithub.com\u002Fvimwiki\u002Fvimwiki lately! I've mixed in a bit of encryptfs to have a private directory of notes. Sometime during boot, I set it up with:",{},"\u002Ftlt-2017.04.10-vimwiki-gateway",{"title":8611,"description":8634},"TLT - 2017.04.10 - VimWiki Gateway",[169],"2017-04-10T11:11-04:00","3IRfnYXyOYqKgkgLkduCO6hOG7xIOBnWreze29qyXjM",{"id":8643,"title":8644,"body":8645,"createdAt":8686,"description":8687,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8688,"navigation":164,"path":8689,"seo":8690,"stem":8691,"tags":8692,"updatedAt":8693,"__hash__":8694},"content\u002FTLT - 2017.01.11 - Slack Hash Store.md","TLT_-_2017.01.11_-_Slack_Hash_Store",{"type":8,"value":8646,"toc":8684},[8647,8661,8667,8670],[11,8648,8649,8650,8655,8656,8660],{},"Last night at the ",[136,8651,8654],{"href":8652,"rel":8653},"https:\u002F\u002Fwww.meetup.com\u002FDC-Perl-Mongers\u002F",[140],"DC Perl Mongers meetup"," we collaboratively built a proof-of-concept for storing key\u002Fvalue pairs as messages in a slack channel, ",[136,8657,8658],{"href":8658,"rel":8659},"https:\u002F\u002Fgithub.com\u002Fplicease\u002Fglobalhash",[140],". This was made straightforward by great Slack API docs and cpan:WebService::Slack::WebApi. Example usage:",[605,8662,8665],{"className":8663,"code":8664,"language":1288},[1286],"# writes \"hello=world\" into the #globalhash channel\n$ globalhash set hello world\n\n# reads the #globalhash channel for the most\n# recent value of hello and prints it\n$ globalhash get hello\nworld\n",[194,8666,8664],{"__ignoreMap":156},[11,8668,8669],{},"There are of course a TON of things you could do from here. Some ideas:",[205,8671,8672,8675,8678,8681],{},[208,8673,8674],{},"More features: list of keys, delete, complex values, binary values, value history",[208,8676,8677],{},"Clean implementation and better usage\u002Ferror messaging, docs",[208,8679,8680],{},"Port to other languages -- perl6 and still using the perl5 module would be fun",[208,8682,8683],{},"Register as a slack app that anyone can use, fix up OAuth or whatever",{"title":156,"searchDepth":157,"depth":157,"links":8685},[],"2017-01-11T09:00-05:00","Last night at the DC Perl Mongers meetup we collaboratively built a proof-of-concept for storing key\u002Fvalue pairs as messages in a slack channel, https:\u002F\u002Fgithub.com\u002Fplicease\u002Fglobalhash. This was made straightforward by great Slack API docs and cpan:WebService::Slack::WebApi. Example usage:",{},"\u002Ftlt-2017.01.11-slack-hash-store",{"title":8644,"description":8687},"TLT - 2017.01.11 - Slack Hash Store",[169],"2017-01-18T08:27-05:00","iuknoDv973vh7pvhKSYOY-zFyqAs-AQJjDlsgeYVck8",{"id":8696,"title":8697,"body":8698,"createdAt":8820,"description":8821,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8822,"navigation":164,"path":8823,"seo":8824,"stem":8825,"tags":8826,"updatedAt":8827,"__hash__":8828},"content\u002FTLT - 2016.09.23 - All The Methods.md","TLT_-_2016.09.23_-_All_The_Methods",{"type":8,"value":8699,"toc":8818},[8700,8714,8720,8723,8729,8732,8735,8738,8741,8744,8747,8753,8756,8759,8762,8768,8771,8774,8780,8783,8786,8789,8795,8798,8803,8806,8812],[11,8701,8702,8703,8175,8708,8713],{},"A fun thing to do is to explore things using ",[136,8704,8707],{"href":8705,"rel":8706},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FType_introspection",[140],"introspection",[136,8709,8712],{"href":8710,"rel":8711},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FReflection_(computer_programming)",[140],"reflection",". In Ruby and Perl6, for example, we can get a list of methods for a given object instance pretty easily:",[605,8715,8718],{"className":8716,"code":8717,"language":1288},[1286],"# Ruby\n\"hello good people!\".methods.each { |method| puts method.to_s }\n\n# Perl6\nfor \"hello good people!\".^methods -> $method { say $method }\n",[194,8719,8717],{"__ignoreMap":156},[11,8721,8722],{},"On the REPL (irb\u002Fpry or perl6) this is even shorter since it prints out lists of things by default, so you can do:",[605,8724,8727],{"className":8725,"code":8726,"language":1288},[1286],"# Ruby\n\"hello good people!\".methods\n\n# Perl6\n\"hello good people!\".^methods\n",[194,8728,8726],{"__ignoreMap":156},[11,8730,8731],{},"One difference you see here is that Perl6 has a separate way to call meta-methods, whereas Ruby provides them directly. In some other languages you need to call into a separate reflection library and give it your object and what you want from it.",[11,8733,8734],{},"Cool!",[11,8736,8737],{},"This is a great and devious way to answer the question \"what can I do with this object?\". In Ruby's pry you can use the \"ls\" command like \"ls foo\" to get an even prettier version.",[11,8739,8740],{},"But you know... why stop there? Let's call the methods.",[11,8742,8743],{},"All of them.",[11,8745,8746],{},"In Perl6 that looks like:",[605,8748,8751],{"className":8749,"code":8750,"language":1288},[1286],"sub all-the-methods($thing) {\n  for $thing.^methods -> $method {\n    say \"{$method.name} => {$thing.clone.$method.gist}\";\n    CATCH { default { say \"{$method.name} => ERROR\" } }\n  }\n}\n\nall-the-methods \u003Cthis is words>;\nall-the-methods \"hello little fishies!\";\n",[194,8752,8750],{"__ignoreMap":156},[11,8754,8755],{},"Taking the list of methods, we loop over them and invoke them one at a time. Here we do \".clone\" so that if it is a mutating function we'll work on a copy. Note that \".clone\" is NOT a deep-copy, so while it works in my simple list and string examples it might not work so well for other things. The call to .gist gives us a nice printable version of the result.",[11,8757,8758],{},"We invoke the method with no parameters, and many methods don't like that. So here we provide a CATCH block that just prints out a generic message -- it's inside the loop so after catching an error it'll just go to the next method.",[11,8760,8761],{},"Here is some of the output:",[605,8763,8766],{"className":8764,"code":8765,"language":1288},[1286],"# \u003Cthis is words>\npermutations => ((this is words) (this words is) (is this words) (is words this) (words this is) (words is this))\njoin => thisiswords\npick => is\nroll => words\nreverse => (words is this)\nrotate => (is words this)\nappend => ERROR\n\n# \"hello little fishies!\"\nords => (104 101 108 108 111 32 108 105 116 116 108 101 32 102 105 115 104 105 101 115 33)\nwordcase => Hello Little Fishies!\nuc => HELLO LITTLE FISHIES!\nflip => !seihsif elttil olleh\nchop => hello little fishies\ncontains => ERROR\n",[194,8767,8765],{"__ignoreMap":156},[11,8769,8770],{},"Lots of the functions just result in 'ERROR', especially for those pesky methods that take some sort of parameter. A lot of these methods, however, work ok with no params and return some value.",[11,8772,8773],{},"In Ruby this looks like:",[605,8775,8778],{"className":8776,"code":8777,"language":1288},[1286],"def all_the_methods(thing)\n  thing.methods.each do |method|\n    begin\n      if method =~ \u002F^pry|byebug|debugger$\u002F\n        puts \"#{method} => SKIPPING\"\n        next\n      end\n      puts \"#{method} => #{ thing.clone.send(method) }\"\n    rescue\n      puts \"#{method} => ERROR\"\n    end\n  end\nend\n\nall_the_methods %w(this is words)\nall_the_methods \"hello little fishies!\"\n",[194,8779,8777],{"__ignoreMap":156},[11,8781,8782],{},"Here we had to explicitly skip the pry\u002Fbyebug things, at least for my REPL execution, because those entered a subshell which isn't what I'm going for. Similar to Perl6 we also clone the object (also a shallow-clone) and had to handle exceptions, which are again almost entirely from methods that take more than zero parameters. In Ruby interpolated values automatically get .to_s called on them, so we don't need to do anything there.",[11,8784,8785],{},"One very notable thing is that operators in Ruby are methods directly on the object! This is nice for lots of reasons, including that you can easily override them. In Perl6 operators are standalone subs that do typed multi-dispatch (pattern matching) to decide what to execute, so the code isn't usually directly part of the class itself even if it ends up calling methods on the class or messing with the state.",[11,8787,8788],{},"Some of the output:",[605,8790,8793],{"className":8791,"code":8792,"language":1288},[1286],"# %w(this is words)\nshuffle! => [\"words\", \"is\", \"this\"]\ninclude? => ERROR\npermutation => #\u003CEnumerator:0x00000002e48188>\ncombination => ERROR\nsample => is\nsort => [\"is\", \"this\", \"words\"]\ncount => 3\nfirst => this\n== => ERROR\n\n# \"hello little fishies!\"\nsucc! => hello little fishiet!\nupcase => HELLO LITTLE FISHIES!\ndowncase! => \ncapitalize => Hello little fishies!\ncodepoints => [104, 101, 108, 108, 111, 32, 108, 105, 116, 116, 108, 101, 32, 102, 105, 115, 104, 105, 101, 115, 33]\nreverse! => !seihsif elttil olleh\ncenter => ERROR\n",[194,8794,8792],{"__ignoreMap":156},[11,8796,8797],{},"Again most of the results are 'ERROR', especially where they expect more arguments. Another interesting thing is 'permutation', which returns an enumerator rather than a list, and isn't forced to evaluate upon rendering or anything. Also I notice here that 'downcase!' doesn't return the result of downcasing :)",[11,8799,8800],{},[8801,8802,7491],"b",{},[11,8804,8805],{},"Since I'm going all polyglot here anyway, I was starting to wonder which methods were equivalent. I could read through and guess, but that's no fun. Instead I made an alternate version of the above that does two things -- it reverses the method-result relationship so that we get a list of methods that return a specific result. Then I also output in a more language-neutral JSON format to compare across languages, and and turn that into a list of methods and their result prefixed with the language name.",[605,8807,8810],{"className":8808,"code":8809,"language":1288},[1286],"perl6-rotate ruby-rotate ruby-rotate! => [ \"is\", \"words\", \"this\" ]\n\nperl6-words ruby-split => [ \"hello\", \"little\", \"fishies!\" ]\n\nperl6-ords perl6-NFC perl6-NFD perl6-NFKC perl6-encode perl6-NFKD ruby-codepoints ruby-bytes => [\n  104, 101, 108, 108, 111, 32, 108, 105, 116, 116, 108, 101, 32, 102, 105, 115, 104, 105, 101, 115, 33\n]\n\nperl6-lines ruby-lines => [ \"hello little fishies!\" ]\n\nperl6-reverse ruby-reverse! ruby-reverse => [ \"words\", \"is\", \"this\" ]\n\nperl6-comb ruby-chars => [\n  \"h\", \"e\", \"l\", \"l\", \"o\", \" \", \"l\", \"i\", \"t\", \"t\", \"l\", \"e\", \" \",\n  \"f\", \"i\", \"s\", \"h\", \"i\", \"e\", \"s\", \"!\"\n]\n\nperl6-sort ruby-sort ruby-sort! => [ \"is\", \"this\", \"words\" ]\n\nperl6-Slip perl6-values perl6-tree perl6-unique perl6-List perl6-Array\nperl6-words perl6-squish perl6-item perl6-clone perl6-flat perl6-eager\nperl6-Seq perl6-FLATTENABLE_LIST perl6-reification-target perl6-ZEN-KEY\nperl6-ZEN-POS perl6-return-rw perl6-cache perl6-self perl6-lazy perl6-return\nruby-untaint ruby-unshift ruby-freeze ruby-dup ruby-compact ruby-uniq\nruby-taint ruby-itself ruby-to_ary ruby-untrust ruby-clone ruby-push\nruby-entries ruby-flatten ruby-to_a ruby-trust => [\n  \"this\", \"is\", \"words\"\n]\n\n",[194,8811,8809],{"__ignoreMap":156},[11,8813,8814,8815,8817],{},"That is a lot fewer than I expected! I had to run the perl6 with .methods(",[1931,8816],{},") to get \".sort\", which was surprising. This probably misses others where my JSON encoding normalization trick doesn't work.",{"title":156,"searchDepth":157,"depth":157,"links":8819},[],"2016-09-14T21:23-04:00","A fun thing to do is to explore things using introspection\u002Freflection. In Ruby and Perl6, for example, we can get a list of methods for a given object instance pretty easily:",{},"\u002Ftlt-2016.09.23-all-the-methods",{"title":8697,"description":8821},"TLT - 2016.09.23 - All The Methods",[169],"2016-09-23T23:05-04:00","iarmrDI3-EkBRJQB3xY1lQj2PXO0-46RzHgMilXns5k",{"id":8830,"title":8831,"body":8832,"createdAt":8904,"description":8905,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8906,"navigation":164,"path":8907,"seo":8908,"stem":8909,"tags":8910,"updatedAt":8911,"__hash__":8912},"content\u002FTLT - 2016.09.05 - Test Suite Debugging Time.md","TLT_-_2016.09.05_-_Test_Suite_Debugging_Time",{"type":8,"value":8833,"toc":8902},[8834,8843,8846,8849,8855,8858,8861,8864,8867,8873,8880,8883,8888,8891],[11,8835,8836,8837,8842],{},"One of the codebases I work on regularly has a large and slow test suite. So slow that it typically only runs in totality in a continuous-integration (ci) environment, and there it uses the ",[136,8838,8841],{"href":8839,"rel":8840},"https:\u002F\u002Fgithub.com\u002Fgrosser\u002Fparallel_tests",[140],"parallel_tests gem"," to slice it into pieces and run in parallel. This gets it to run in like 30 minutes instead of 2.5 hours.",[11,8844,8845],{},"But I want to run the whole thing linearly sometimes, especially so I can make sure tests aren't conflicting with each other. So I created a new ci job that runs it linearly ... and got a fail that I didn't get otherwise. Took forever to figure it out!",[11,8847,8848],{},"This was about a worker that I call a \"sweeper\" -- it's job is to run once a day and make sure nothing was missed by other realtime jobs during the day. Here is a simplified version.",[605,8850,8853],{"className":8851,"code":8852,"language":1288},[1286],"class SweeperWorker\n  INTERVAL = 25.hours.ago # Overlap the day by an hour\n  def perform\n    candidates.each(&:do_work) # something like that\n  end\n  def candidates\n    Thing.where('created_at > ?', INTERVAL)\n  end\nend\n\n# rspec\ndescribe SweeperWorker do\n  let(:new_thing) { Thing.new(created_at: 5.hours.ago) }\n  let(:old_thing) { Thing.new(created_at: 26.hours.ago) }\n\n  it \"does pick up the new thing\" do\n    new_thing # force to exist\n    expect(SweeperWorker.new.candidates).to include(new_thing)\n  end\n\n  it \"does not pick up the old thing\" do\n    old_thing # force to exist\n    expect(SweeperWorker.new.candidates).not_to include(old_thing)\n  end\nend\n",[194,8854,8852],{"__ignoreMap":156},[11,8856,8857],{},"Not sure that is quite right, but you should get the idea.",[11,8859,8860],{},"The second example was failing -- both the \"old thing\" and the \"new thing\" were getting into the sweeper window -- but only when the test suite was run linearly. Run it in ci, no problem. Run just this test\u002Ffile locally, no problem.",[11,8862,8863],{},"The suspect is thus \"time\" -- but where? I went down the wrong track for a while, looking into timezones. Rails vs MySQL on ci vs my machine and so on ... some of those things weren't quite matched up, but still. I ran the test over and over, adding more and more debugging so I could peer into the contents of variables and the DB. Everything looked fine -- all the timestamps were what I expect. So it must be the query itself that is somehow asking for a longer timespan.",[11,8865,8866],{},"Finally I got it! Right there in the first line of SweeperWorker:",[605,8868,8871],{"className":8869,"code":8870,"language":1288},[1286],"INTERVAL = 25.hours.ago # Overlap the day by an hour\n",[194,8872,8870],{"__ignoreMap":156},[11,8874,8875,8876,8879],{},"This constant is set ",[8801,8877,8878],{},"when the class is loaded",", and never changed! So by the time this test runs in the 2.5 hours of test time, \"25 hours ago\" is now \"27.5 hours ago\" -- so our \"old\" thing is in our window. The \"25.hours.ago\" certainly looks relative, but it is a calculation that outputs an absolute time which is then saved for later use.",[11,8881,8882],{},"Move that constant into the method as a variable and it is fixed. And now we can sing our victory song!",[11,8884,8564,8885],{},[8566,8886],{"width":8568,"height":8569,"src":8887,"frameBorder":6760,"allow":8571,"allowFullScreen":164},"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002Fw8KQmps-Sog](\u002Fyoutube:w8kqmps-sog)",[11,8889,8890],{},"Lessons:",[205,8892,8893,8896,8899],{},[208,8894,8895],{},"Beware of calculated constants",[208,8897,8898],{},"Make sure relative values are actually relative",[208,8900,8901],{},"If the speed of execution (slow vs fast) changes the outcome, look for things that are more or less spread out in the timeline, such as constant definition.",{"title":156,"searchDepth":157,"depth":157,"links":8903},[],"2016-09-05T16:07-04:00","One of the codebases I work on regularly has a large and slow test suite. So slow that it typically only runs in totality in a continuous-integration (ci) environment, and there it uses the parallel_tests gem to slice it into pieces and run in parallel. This gets it to run in like 30 minutes instead of 2.5 hours.",{},"\u002Ftlt-2016.09.05-test-suite-debugging-time",{"title":8831,"description":8905},"TLT - 2016.09.05 - Test Suite Debugging Time",[169],"2016-09-05T18:01-04:00","MiYUTVw9kv4C-HjFL8h0DxjzmIUrq4U1SPO0U9KApJw",{"id":8914,"title":8915,"body":8916,"createdAt":8923,"description":8920,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8924,"navigation":164,"path":8925,"seo":8926,"stem":8927,"tags":8928,"updatedAt":8923,"__hash__":8929},"content\u002FTLT - 2016.08.12 - ICFP Contest 2016 - Origami Folding.md","TLT_-_2016.08.12_-_ICFP_Contest_2016_-_Origami_Folding",{"type":8,"value":8917,"toc":8921},[8918],[11,8919,8920],{},"\u003Cinclude \"ICFP Contest 2016\">",{"title":156,"searchDepth":157,"depth":157,"links":8922},[],"2016-08-12T23:36-04:00",{},"\u002Ftlt-2016.08.12-icfp-contest-2016-origami-folding",{"title":8915,"description":8920},"TLT - 2016.08.12 - ICFP Contest 2016 - Origami Folding",[169],"uQe81IQfkbKO2SQW-z3BMODS4qB8XQj0WGAHSipcaXI",{"id":8931,"title":8932,"body":8933,"createdAt":8946,"description":8937,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8947,"navigation":164,"path":8948,"seo":8949,"stem":8950,"tags":8951,"updatedAt":8946,"__hash__":8952},"content\u002FTLT - 2016.06.28 - Not Quite Righte.md","TLT_-_2016.06.28_-_Not_Quite_Righte",{"type":8,"value":8934,"toc":8944},[8935,8938],[11,8936,8937],{},"Idea for a programming language: make experienced programmers twitch by forcing minor and common errors to be part of the language.",[605,8939,8942],{"className":8940,"code":8941,"language":1288},[1286]," \u002F* This is a comment \u002F*\n print \"Hello, world!' \u002F* Strings must have balanced quotes \u002F*\n\n    if 5 + 2 = 4:\nprint 'Everything is awesome!\"\n\n    for(var i; i \u003C 1; ++) print i;\n\nclass Foo {\n  private method greeting [\n    print \"Muahahaha'\n  ]\n}\n\nfoo.new.Greeting(\n",[194,8943,8941],{"__ignoreMap":156},{"title":156,"searchDepth":157,"depth":157,"links":8945},[],"2016-05-28T23:49-04:00",{},"\u002Ftlt-2016.06.28-not-quite-righte",{"title":8932,"description":8937},"TLT - 2016.06.28 - Not Quite Righte",[169],"zNPDl6_p47kPQWfLL5PxmM8W-BmTiEVPEczRhI9LHcU",{"id":8954,"title":8955,"body":8956,"createdAt":8988,"description":8960,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":8989,"navigation":164,"path":8990,"seo":8991,"stem":8955,"tags":8992,"updatedAt":8993,"__hash__":8994},"content\u002FTLT - 2016.05.12 - DCRUG React.rb.md","TLT - 2016.05.12 - DCRUG React.rb",{"type":8,"value":8957,"toc":8986},[8958,8961,8967,8970],[11,8959,8960],{},"I enjoyed presenting at DCRUG tonight on React.rb, which I've been playing with for the last few weeks. Good turnout too!",[11,8962,8963],{},[136,8964,8966],{"href":8965},"www.slideshare.net\u002Fawwaiid\u002F2016-0512-dcrug-reactrb","slideshare",[11,8968,8969],{},"Resources:",[205,8971,8972,8979],{},[208,8973,8974],{},[136,8975,8978],{"href":8976,"rel":8977},"https:\u002F\u002Fthelackthereof.org\u002Fdocs\u002Ftalks\u002F2016-05-12%20DCRUG%20React.rb\u002F",[140],"Source code for talk and examples",[208,8980,8981],{},[136,8982,8985],{"href":8983,"rel":8984},"https:\u002F\u002Fgithub.com\u002Fawwaiid\u002Freactrb-elephant",[140],"White Elephant game ported to React.rb",{"title":156,"searchDepth":157,"depth":157,"links":8987},[],"2016-05-12T23:57-04:00",{},"\u002Ftlt-2016.05.12-dcrug-react.rb",{"title":8955,"description":8960},[169],"2016-05-12T23:59-04:00","j_g3PqUy_suid4jDjGQIzVUO9shnwyTYR6hsT1V9yW4",{"id":8996,"title":8997,"body":8998,"createdAt":9026,"description":9002,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":9027,"navigation":164,"path":9028,"seo":9029,"stem":9030,"tags":9031,"updatedAt":9026,"__hash__":9032},"content\u002FTLT - 2016.04.10 - DCBPW, On Being Small.md","TLT_-_2016.04.10_-_DCBPW,_On_Being_Small",{"type":8,"value":8999,"toc":9024},[9000,9003,9006,9009,9012,9015,9018,9021],[11,9001,9002],{},"Welcome to the DC-Baltimore Perl Workshop!",[11,9004,9005],{},"This workshop started innocently enough. The year was 2010 -- October. We were at the Pittsburgh Perl Workshop when Brad Lhotsky said he wanted to host a similar workshop in the DC\u002FBaltimore region. I told him no. But then he talked me and some others into it. During 2011 we worked out some details and at the 2011 Pittsburgh Perl Workshop we announced that the first DCBPW would be held April 14, 2012! We even made fliers!",[11,9007,9008],{},"Here we are six wonderful years later. We've had a few of the organizers step back over the years, mostly due to moving away, but we picked up a few others and have a core of dedicated volunteers that put this workshop together every year. We get support from The Perl Foundation and also get support from local businesses and communities. It has gone pretty well! And yet... sometimes I've felt unhappy.",[11,9010,9011],{},"You see, I started to get fantasies of grandeur.",[11,9013,9014],{},"I imagined a hundred people showing up! Two hundred! Each year this didn't happen I was a little sad. Perl dying? Community dying? What's going on that a region with probably a thousand perl developers only have 50 show up to a really awesome and cheap conference?",[11,9016,9017],{},"And then I realized -- This isn't a conference! It's a workshop.",[11,9019,9020],{},"What we have is a true \"workshop\". A set of people focused on learning new things, getting introduced to new ideas, and getting some hands-on time. We have organized pre-planned presentations, but we also have a lot of hallway time and variety. Then the second day is completely hands-on time. The signal-to-noise ratio is fantastic -- each attendee gets a chance to learn from their peers both formally and informally.",[11,9022,9023],{},"So yeah. It's small. That's not a bug, it's a feature :)",{"title":156,"searchDepth":157,"depth":157,"links":9025},[],"2016-04-11T09:30-04:00",{},"\u002Ftlt-2016.04.10-dcbpw-on-being-small",{"title":8997,"description":9002},"TLT - 2016.04.10 - DCBPW, On Being Small",[169],"nZH25UU8JUwGl9LPyKp4pz7P4VG0emg99nHaaYkjReo",{"id":9034,"title":9035,"body":9036,"createdAt":9066,"description":9067,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":9068,"navigation":164,"path":9069,"seo":9070,"stem":9071,"tags":9072,"updatedAt":9073,"__hash__":9074},"content\u002FTLT - 2016.03.05 - Arlington RetroRuby 2016.md","TLT_-_2016.03.05_-_Arlington_RetroRuby_2016",{"type":8,"value":9037,"toc":9064},[9038,9046,9049,9056],[11,9039,9040,9041,9045],{},"Today I attended ",[136,9042,9043],{"href":9043,"rel":9044},"http:\u002F\u002Fretroruby.org",[140],", a great un-conference in Arlington. I got my toehold in the local Ruby community at the Arlington meetup, and was happy to visit with lots of familiar people. I didn't meet any new people, though that was mostly because it was easy to spend time catching up.",[11,9047,9048],{},"Next time I want to jump in a bit stronger on the new-dev track, maybe walk through some hands-on exercises or do a group activity (Randori).",[11,9050,9051,9052,797],{},"My favorite, besides talking to people, was the lightning talks. These have a bit more technical depth and include some code getting projected, which I love. I gave a quick this-thing-exists talk on ",[136,9053,9054],{"href":9054,"rel":9055},"http:\u002F\u002Freactrb.org",[140],[11,9057,9058,9059,9063],{},"In the hallway track I also got to preach a bit about ",[136,9060,9062],{"href":9061},"\u002Fmodule-level-polyglot","Module Level Polyglot"," :)",{"title":156,"searchDepth":157,"depth":157,"links":9065},[],"2016-03-05T22:49-05:00","Today I attended http:\u002F\u002Fretroruby.org, a great un-conference in Arlington. I got my toehold in the local Ruby community at the Arlington meetup, and was happy to visit with lots of familiar people. I didn't meet any new people, though that was mostly because it was easy to spend time catching up.",{},"\u002Ftlt-2016.03.05-arlington-retroruby-2016",{"title":9035,"description":9067},"TLT - 2016.03.05 - Arlington RetroRuby 2016",[169],"2016-03-05T22:51-05:00","TFGevb732TjMbBbA8zKNJVAHGtI9qIPnw0nnISJpUuY",{"id":9076,"title":9077,"body":9078,"createdAt":9144,"description":9082,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":9145,"navigation":164,"path":9146,"seo":9147,"stem":9148,"tags":9149,"updatedAt":9150,"__hash__":9151},"content\u002FTLT - 2016.01.08 - Perl 6 is Separate from All, Replacement for None.md","TLT_-_2016.01.08_-_Perl_6_is_Separate_from_All,_Replacement_for_None",{"type":8,"value":9079,"toc":9142},[9080,9083,9092,9095,9103,9106,9109,9112,9115,9122,9125,9130,9139],[11,9081,9082],{},"Tags: Perl6, Perl5, Ruby, Polyglot",[11,9084,9085,9086,9091],{},"In response to the \"",[136,9087,9090],{"href":9088,"rel":9089},"http:\u002F\u002Fwww.dagolden.com\u002Findex.php\u002F2589\u002Fperl-5-and-perl-6-are-mortal-enemies\u002F",[140],"Perl 5 and Perl 6 are mortal enemies","\" article.",[11,9093,9094],{},"We are definitely framing this whole thing wrong. We have two choices:",[205,9096,9097,9100],{},[208,9098,9099],{},"Replacement: Perl 6 is, eventually, the replacement for Perl 5",[208,9101,9102],{},"Separate: Perl 6 is an unfortunately named but completely separate language from Perl 5",[11,9104,9105],{},"Most people outside of Perl 5 and Perl 6 go with Replacement just by looking at the names. Various insiders switch at random between Replacement and Separate, and I think that is the core mistake. This article has a very important sentence:",[188,9107,9108],{},"\"First, a postulate: given the language similarities, the people that will find it easiest to learn Perl 6 are today's Perl 5 developers.\"",[11,9110,9111],{},"In reality there are SO MANY differences between Perl 5 and Perl 6, it is NOT a good postulate!",[11,9113,9114],{},"This is it -- this is the mistake where we are getting both messages at once, and the rest of the article paints a dark picture of a world (unfortunately most likely the one we live in) in which crossing these messages happens. The mixed message is a net negative for both languages.",[11,9116,9117,9118,9121],{},"I suggest that if you take a random ",[39,9119,9120],{},"Perl 5, Ruby, Python, PHP, Javascript, R"," programmer, the Perl 5 programmer might actually have MORE trouble than others due to misleading overlap and jarring differences. A developer that uses a lot of Moose might have less issues... or again might end up with the differences shocking rather than enlightening. I actually think the Ruby developer will have the LEAST trouble learning Perl 6, building on tons of overlap (everything is an object!), a shared history (sure, \u002Ffoo\u002F is a regex, drop it in. Couple sigils here and there never hurt anybody), and similar culture (TIMTOWTDI is a motto for both). But the Ruby developer won't expect things to be mostly the same between Perl 6 and Ruby, unlike a naive Perl 5 developer.",[11,9123,9124],{},"I recommend you each shape your language to do two things. First stick strongly with Separate, second focus on the Polyglot nature and audience:",[11,9126,9127],{},[1030,9128,9129],{},"Perl 6 is a new and interesting language. It happened to be created by the creator of Perl 5 and an overlapping community, and has an unfortunate name. It is a Practical Research Language, aiming to be both cutting edge and useful. It is of interest to all dynamic-language programmers, and is especially interesting for the polyglot: you'll see familiar bits from Haskell, Perl 5, Ruby, Python, CLOS, ... plus lots of original ideas. Things that you can use, or at the very least learn and take back to your work. You can use Perl 6 now to solve small tasks, and join at the ground floor to build up the ecosystem and culture towards solving larger and larger problems.",[11,9131,9132,9133,9135,9136],{},"One of the cultural things that I think can set Perl 6 apart is in being ",[136,9134,9062],{"href":9061},". From Perl 5 or Ruby you can invoke Python code (both have libraries to support this that I've used) -- but you'd be hard pressed to get that put into production at your work. But NOBODY should ever implement pyplot again! If we can make doing \"use matplotlib::pyplot:from",[609,9137,9138],{},"\" a socially-acceptable thing in Perl 6, we might be able to convince other communities to do the same... and do something amazing: revolutionize sharing cross-language modules.",[11,9140,9141],{},"Perl 6 isn't the research language for Perl 5. It is a research language for ALL languages to learn from. Perl 6 is the Borg of Languages, pulling in concepts and features to create a glorious monster. Maybe the first assimilated was Perl 5, but it clearly didn't stop there. We need to let go of its roots. Embrace that Perl 6 is Separate from All, Replacement for None.",{"title":156,"searchDepth":157,"depth":157,"links":9143},[],"2016-01-08T09:50-05:00",{},"\u002Ftlt-2016.01.08-perl-6-is-separate-from-all-replacement-for-none",{"title":9077,"description":9082},"TLT - 2016.01.08 - Perl 6 is Separate from All, Replacement for None",[169],"2016-03-05T22:54-05:00","BZBeXJtwWGXX5aFBdV0bY6uNyn0cm1J_-DokX1xc9z4",{"id":9153,"title":9154,"body":9155,"createdAt":9304,"description":9159,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":9305,"navigation":164,"path":9306,"seo":9307,"stem":9308,"tags":9309,"updatedAt":9310,"__hash__":9311},"content\u002FTLT - 2015.10.18 - My First Useful Perl6 Grammar.md","TLT_-_2015.10.18_-_My_First_Useful_Perl6_Grammar",{"type":8,"value":9156,"toc":9302},[9157,9160,9163,9166,9169,9176,9184,9190,9193,9205],[11,9158,9159],{},"Tags: Perl6",[11,9161,9162],{},"In my recent talks about perl6, one thing that I keep neglecting is Grammars. Part of that is because I hadn't used them yet!",[11,9164,9165],{},"I was putting together a talk on some clojure code, and was getting mad at my slide software not syntax-highlighting with magical rainbow parenthesis. Clojure being a LISP-like, it lacks some visual clues for structure and is WAY easier to glance at (in my opinion) when parenthesis are highlighted. I have vim doing this for me... but no dice in my slides.",[11,9167,9168],{},"So! Slice up slides, run them through vim, stitch them back together, and presto!",[11,9170,9171,9172,797],{},"Complete code is at ",[136,9173,9174],{"href":9174,"rel":9175},"https:\u002F\u002Fgithub.com\u002Fawwaiid\u002Fpinpoint-code-color",[140],[11,9177,9178,9179,9183],{},"I use ",[136,9180,9182],{"href":9181},"\u002Fpinpoint","Pinpoint"," as my go-to slide software. Simple and easy both to develop a deck and to present it. Each slide is a header and a body done in some Pango markup (more or less simplified HTML). Here is a 3 slide deck:",[605,9185,9188],{"className":9186,"code":9187,"language":1288},[1286],"#!\u002Fusr\u002Fbin\u002Fenv pinpoint\n\n# Defaults for all slides\n[blackbluefade.png]\n[font=Sans 90]\n[duration=50.00]\n[fill]\n[shading-opacity=0]\n\n--\n\nSome other slide content.\n\n-- [font=monospace 99] [code=sh]\n\n\\#!\u002Fbin\u002Fsh\n\n\\# A lovely cgi application\n\necho \"Content-type: text\u002Fhtml\"\necho\necho \"Hello, world! Query:\"\necho $QUERY_STRING\n\n-- [font=monospace 99] [code=python]\n\n\\# Python WSGI\n\ndef application(environ, start_response):\n    start_response('200 OK', [('Content-Type', 'text\u002Fplain')])\n    yield 'Hello, world!'\n",[194,9189,9187],{"__ignoreMap":156},[11,9191,9192],{},"We'll do this in two parts.",[11,9194,9195,9196,9198],{},"=== Part 1: The Grammar ==",[461,9197],{},[194,9199,9202,9204],{"className":9200},[9201],"perl6",[461,9203],{},"\n#!\u002Fusr\u002Fbin\u002Fenv perl6",[194,9206,9208,9216],{"className":9207},[9201],[11,9209,9210,9211,9213,9214],{},"grammar Pinpoint::Grammar {",[461,9212],{},"\ntoken TOP {",[461,9215],{},[9217,9218,9219,9221],"header",{},[461,9220],{},[9222,9223,6734,9224,9226,9227,9230,9245,9252,9259,9269,9275,9282,9293,9299],"slide",{},[461,9225],{},"\n}",[11,9228,9229],{},"token header { .*? \u003C?before ^^ \"--\" > }",[11,9231,9232,9233,9235],{},"token slide {",[461,9234],{},[9236,9237,9238,9240],"slide-header",{},[461,9239],{},[9241,9242,9243,9226],"slide-content",{},[461,9244],{},[11,9246,9247,9248],{},"token slide-header { ^^ \"--\" (\\s* ",[9249,9250,9251],"slide-setting",{},")* $$ \\n }",[11,9253,9254,9255,9258],{},"token slide-setting { '",[39,9256,9257],{},"' .+? '","' }",[11,9260,9261,9262,9265,9266,9268],{},"token slide-content { .",[20,9263,9264],{},"? \u003C?before ^^ \"--\" > || ."," $ }",[461,9267],{},"\n};",[605,9270,9273],{"className":9271,"code":9272,"language":1288},[1286],"\nUsing 'grammar' is kinda like some funky cross between a regex and a class. That is -- everything is declared like a named regex, but the result is effectively a class that has a \".parse\" method we can use. We're giving the whole grammar a name, and then declaring the file structure in the body.\n\n'TOP' is the start of the parse, which will be an entire file for me. There is one special slide that is the header-slide, and then after that some content slides. Though each bit has a name, you do a lot of things just like other regexes -- so \"\u003Cslide>+\" means one-or-more slides.\n\nAfter that it just gets broken down further and further. Probably the trickiest bit is the \u003Ccode>\u003C?before ^^ \"--\" >\u003C\u002Fcode> pattern, which we see a few times. This says that if we see a \"--\" on the start of it's own line, then we've gone too far. Slide content has the \"||\" to say if we NEVER find the \"--\" then we should instead continue to the end of the file.\n\n=== Part 2: The Processor ==\nNow that we have a handy dandy grammar, we'll just slurp in whatever file\u002Fstdin we are given, parse, and the traverse the parse tree. There is a way to do this with Action objects (another class with methods for each of these tokens), but I didn't do that.\n\n\u003Ccode class=\"perl6\">\nmy $match = Pinpoint::Grammar.parse(slurp());\n\nprint $match\u003Cheader>;\n\nfor $match\u003Cslide>.flat -> $slide {\n  my $h = ~$slide\u003Cslide-header>;\n  $h ~~ s\u002F\\s*\\[code\\=(.*?)\\]\u002F\u002F;\n  print $h;\n\n  if ~$slide\u003Cslide-header> ~~ \u002F\\[code\\=(.*?)\\]\u002F {\n    my $cmd = \"code-htmlize $0\";\n    my $filter = shell $cmd, :in, :out;\n    $filter.in.say(~$slide\u003Cslide-content>);\n    $filter.in.close;\n    say $filter.out.slurp-rest;\n  } else {\n    print $slide\u003Cslide-content>;\n  }\n}\n",[194,9274,9272],{"__ignoreMap":156},[11,9276,9277,9278,9281],{},"To make this easy, I print out the bits of the parse tree as I go.  the '$h' is a chopped up version of a slide-header, removing my new and magical ",[39,9279,9280],{},"code=foo"," slide setting. Now that I'm looking at this, I see that I didn't actually traverse into the slide-setting list for each slide... I guess that would be better than the search\u002Freplace I'm doing here.",[11,9283,9284,9285,9289,9290],{},"A specific thing to note is that \"",[9286,9287,9288],"del",{},"\" is forcing string-context here, so \"","$slide",[9236,9291,9292],{},"\" is taking the object for the slide-header node we are on and dumps it out as a string of the content. This makes sense, though I initially found the \"~\" usage a bit ugly.",[11,9294,9295,9296,9298],{},"Once we get down to a slide that has a \"",[39,9297,9280],{},"\" style setting in the header, instead of printing the slide content like we do otherwise we'll run it through an external shell command. The \"code-htmlize\" command is some other script I wrote that takes in code and a language and outputs an HTML-colorized version using vim. Here we do the equivalent of Open2, getting a filehandle for the input and output of the external command, printing to it's input, reading from its output.",[11,9300,9301],{},"That's it! A pretty readable thing that parses and traverses my slide software file format, filtering the results as it goes.",{"title":156,"searchDepth":157,"depth":157,"links":9303},[],"2015-10-18T15:31-04:00",{},"\u002Ftlt-2015.10.18-my-first-useful-perl6-grammar",{"title":9154,"description":9159},"TLT - 2015.10.18 - My First Useful Perl6 Grammar",[169],"2015-10-18T21:05-04:00","tIvjO3QWD_nPT9rxsiOnHV1vYR7wPY4VFP86jBco_lw",{"id":9313,"title":9314,"body":9315,"createdAt":10710,"description":9319,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":10711,"navigation":164,"path":10712,"seo":10713,"stem":10714,"tags":10715,"updatedAt":10716,"__hash__":10717},"content\u002FTLT - 2015.07.26 - Exploring Clojure in the REPL.md","TLT_-_2015.07.26_-_Exploring_Clojure_in_the_REPL",{"type":8,"value":9316,"toc":10704},[9317,9320,9323,9326,9330,9333,9336,9450,9453,9548,9551,9578,9581,9607,9611,9614,9617,9663,9666,9690,9693,9714,9717,9800,9803,10016,10020,10023,10098,10101,10110,10114,10117,10140,10143,10183,10186,10224,10227,10255,10258,10280,10283,10325,10328,10698,10701],[11,9318,9319],{},"Tags: Clojure, REPL",[11,9321,9322],{},"When I first learned Linux, my friend taught me a few commands. How to to list files, how to change directories and see your current directory, how to run things, how to ask a program what parameters it takes, and how to look at a file (ls, cd, pwd, .\u002Ffoo or \u002Fusr\u002Fbin\u002Ffoo or foo, foo --help, cat foo or more foo). After that I just... ran a lot of stuff. I eventually discovered 'man' -- but going through \u002Fbin and running ALL the commands was really educational.",[11,9324,9325],{},"Let's get some basic tools to do that with the Clojure REPL! The major things we want to do are find things (mostly functions), and then learn all about them individually.",[266,9327,9329],{"id":9328},"finding-things","Finding Things",[11,9331,9332],{},"So Clojure has namespaces, which are kinda like directories, using \".\" as a way to indicate nesting. Vars (and thereby named functions) are kinda like files. So the full \"path\" to a var looks like \"clojure.string\u002Fsplit\" where \"clojure.string\" is the namespace and \"split\" is the function.",[11,9334,9335],{},"First let's get a list of all the loaded namespaces. The \"ns-all\" gives us this, but we want a nice sorted printout, so we'll add a bit of fancy.",[605,9337,9341],{"className":9338,"code":9339,"language":9340,"meta":156,"style":156},"language-clojure shiki shiki-themes github-light github-dark monokai","user=> (doseq [n (sort (map ns-name (all-ns)))] (println n))\n; ... trimmed ...\nclojure.core\nclojure.core.protocols\nclojure.inspector\n; ... trimmed ...\nclojure.repl\nclojure.set\nclojure.stacktrace\nclojure.string\nclojure.template\nclojure.test\nclojure.tools.cli\nclojure.tools.nrepl\n; ... trimmed ...\nuser\n","clojure",[194,9342,9343,9377,9382,9387,9392,9397,9401,9406,9411,9416,9421,9426,9431,9436,9441,9445],{"__ignoreMap":156},[39,9344,9345,9348,9351,9354,9357,9359,9362,9365,9368,9371,9374],{"class":614,"line":615},[39,9346,9347],{"class":622},"user=> (",[39,9349,9350],{"class":1909},"doseq",[39,9352,9353],{"class":622}," [n (",[39,9355,9356],{"class":1909},"sort",[39,9358,444],{"class":622},[39,9360,9361],{"class":1909},"map",[39,9363,9364],{"class":622}," ns-name (",[39,9366,9367],{"class":1909},"all-ns",[39,9369,9370],{"class":622},")))] (",[39,9372,9373],{"class":1909},"println",[39,9375,9376],{"class":622}," n))\n",[39,9378,9379],{"class":614,"line":157},[39,9380,9381],{"class":1628},"; ... trimmed ...\n",[39,9383,9384],{"class":614,"line":637},[39,9385,9386],{"class":622},"clojure.core\n",[39,9388,9389],{"class":614,"line":656},[39,9390,9391],{"class":622},"clojure.core.protocols\n",[39,9393,9394],{"class":614,"line":668},[39,9395,9396],{"class":622},"clojure.inspector\n",[39,9398,9399],{"class":614,"line":674},[39,9400,9381],{"class":1628},[39,9402,9403],{"class":614,"line":685},[39,9404,9405],{"class":622},"clojure.repl\n",[39,9407,9408],{"class":614,"line":691},[39,9409,9410],{"class":622},"clojure.set\n",[39,9412,9413],{"class":614,"line":701},[39,9414,9415],{"class":622},"clojure.stacktrace\n",[39,9417,9418],{"class":614,"line":709},[39,9419,9420],{"class":622},"clojure.string\n",[39,9422,9423],{"class":614,"line":1823},[39,9424,9425],{"class":622},"clojure.template\n",[39,9427,9428],{"class":614,"line":1837},[39,9429,9430],{"class":622},"clojure.test\n",[39,9432,9433],{"class":614,"line":4967},[39,9434,9435],{"class":622},"clojure.tools.cli\n",[39,9437,9438],{"class":614,"line":6142},[39,9439,9440],{"class":622},"clojure.tools.nrepl\n",[39,9442,9443],{"class":614,"line":6160},[39,9444,9381],{"class":1628},[39,9446,9447],{"class":614,"line":6185},[39,9448,9449],{"class":622},"user\n",[11,9451,9452],{},"Use \"dir\" to look at all the exposed vars from a namespace",[605,9454,9456],{"className":9338,"code":9455,"language":9340,"meta":156,"style":156},"user=> (dir clojure.string)\nblank?\ncapitalize\nescape\njoin\nlower-case\nre-quote-replacement\nreplace\nreplace-first\nreverse\nsplit\nsplit-lines\ntrim\ntrim-newline\ntriml\ntrimr\nupper-case\n",[194,9457,9458,9468,9473,9478,9483,9488,9493,9498,9503,9508,9513,9518,9523,9528,9533,9538,9543],{"__ignoreMap":156},[39,9459,9460,9462,9465],{"class":614,"line":615},[39,9461,9347],{"class":622},[39,9463,9464],{"class":1909},"dir",[39,9466,9467],{"class":622}," clojure.string)\n",[39,9469,9470],{"class":614,"line":157},[39,9471,9472],{"class":622},"blank?\n",[39,9474,9475],{"class":614,"line":637},[39,9476,9477],{"class":622},"capitalize\n",[39,9479,9480],{"class":614,"line":656},[39,9481,9482],{"class":622},"escape\n",[39,9484,9485],{"class":614,"line":668},[39,9486,9487],{"class":622},"join\n",[39,9489,9490],{"class":614,"line":674},[39,9491,9492],{"class":622},"lower-case\n",[39,9494,9495],{"class":614,"line":685},[39,9496,9497],{"class":622},"re-quote-replacement\n",[39,9499,9500],{"class":614,"line":691},[39,9501,9502],{"class":622},"replace\n",[39,9504,9505],{"class":614,"line":701},[39,9506,9507],{"class":622},"replace-first\n",[39,9509,9510],{"class":614,"line":709},[39,9511,9512],{"class":622},"reverse\n",[39,9514,9515],{"class":614,"line":1823},[39,9516,9517],{"class":622},"split\n",[39,9519,9520],{"class":614,"line":1837},[39,9521,9522],{"class":622},"split-lines\n",[39,9524,9525],{"class":614,"line":4967},[39,9526,9527],{"class":622},"trim\n",[39,9529,9530],{"class":614,"line":6142},[39,9531,9532],{"class":622},"trim-newline\n",[39,9534,9535],{"class":614,"line":6160},[39,9536,9537],{"class":622},"triml\n",[39,9539,9540],{"class":614,"line":6185},[39,9541,9542],{"class":622},"trimr\n",[39,9544,9545],{"class":614,"line":6208},[39,9546,9547],{"class":622},"upper-case\n",[11,9549,9550],{},"Search for functions with \"split\" in their name. There is also \"apropos\" but it doesn't show namespaces -- \"apropos-better\" does, and \"find-name\" is an alias of that, so is better.",[605,9552,9554],{"className":9338,"code":9553,"language":9340,"meta":156,"style":156},"user=> (find-name \"split\")\n(split-at split-with clojure.string\u002Fsplit clojure.string\u002Fsplit-lines net.cgrand.parsley.grammar\u002Fsplit-empty-prods)\n",[194,9555,9556,9568],{"__ignoreMap":156},[39,9557,9558,9560,9563,9566],{"class":614,"line":615},[39,9559,9347],{"class":622},[39,9561,9562],{"class":1909},"find-name",[39,9564,9565],{"class":649}," \"split\"",[39,9567,653],{"class":622},[39,9569,9570,9572,9575],{"class":614,"line":157},[39,9571,4222],{"class":622},[39,9573,9574],{"class":1909},"split-at",[39,9576,9577],{"class":622}," split-with clojure.string\u002Fsplit clojure.string\u002Fsplit-lines net.cgrand.parsley.grammar\u002Fsplit-empty-prods)\n",[11,9579,9580],{},"You can also use a regex! Not sure how useful this is... but here we are getting all the functions that start with an \"s\" and in with a \"t\".",[605,9582,9584],{"className":9338,"code":9583,"language":9340,"meta":156,"style":156},"user=> (find-name #\"^s.*t$\")\n(set short sort sorted-set spit split-at struct clojure.set\u002Fselect clojure.string\u002Fsplit clojure.test\u002Fset-test net.cgrand.sjacket\u002Fshift net.cgrand.sjacket\u002Fshift-right net.cgrand.sjacket\u002Fstr-pt net.cgrand.sjacket\u002Fsubedit)\n",[194,9585,9586,9598],{"__ignoreMap":156},[39,9587,9588,9590,9592,9596],{"class":614,"line":615},[39,9589,9347],{"class":622},[39,9591,9562],{"class":1909},[39,9593,9595],{"class":9594},"sFxd3"," #\"^s.*t$\"",[39,9597,653],{"class":622},[39,9599,9600,9602,9604],{"class":614,"line":157},[39,9601,4222],{"class":622},[39,9603,6031],{"class":1909},[39,9605,9606],{"class":622}," short sort sorted-set spit split-at struct clojure.set\u002Fselect clojure.string\u002Fsplit clojure.test\u002Fset-test net.cgrand.sjacket\u002Fshift net.cgrand.sjacket\u002Fshift-right net.cgrand.sjacket\u002Fstr-pt net.cgrand.sjacket\u002Fsubedit)\n",[266,9608,9610],{"id":9609},"learning-about-things","Learning About Things",[11,9612,9613],{},"Once you've found your function, you'll want to learn more about it and maybe give it a try.",[11,9615,9616],{},"\"doc\" can be used to get the documentation associated with a function. This is pretty cool! It shows the full name of the function, its signature, and it's documentation.",[605,9618,9620],{"className":9338,"code":9619,"language":9340,"meta":156,"style":156},"user=> (doc print)\n-------------------------\nclojure.core\u002Fprint\n  Prints the object(s) to the output stream that is the current value\n  of *out*.  print and println produce output for human consumption.\n",[194,9621,9622,9632,9637,9642,9653],{"__ignoreMap":156},[39,9623,9624,9626,9629],{"class":614,"line":615},[39,9625,9347],{"class":622},[39,9627,9628],{"class":1909},"doc",[39,9630,9631],{"class":622}," print)\n",[39,9633,9634],{"class":614,"line":157},[39,9635,9636],{"class":622},"-------------------------\n",[39,9638,9639],{"class":614,"line":637},[39,9640,9641],{"class":622},"clojure.core\u002Fprint\n",[39,9643,9644,9647,9650],{"class":614,"line":656},[39,9645,9646],{"class":622},"  Prints the object(",[39,9648,9649],{"class":1909},"s",[39,9651,9652],{"class":622},") to the output stream that is the current value\n",[39,9654,9655,9658,9660],{"class":614,"line":668},[39,9656,9657],{"class":622},"  of *out*.  print and println produce output ",[39,9659,4725],{"class":618},[39,9661,9662],{"class":622}," human consumption.\n",[11,9664,9665],{},"Note that you can tab-complete",[605,9667,9669],{"className":9338,"code":9668,"language":9340,"meta":156,"style":156},"user=> (doc print\u003Ctab>\nprint          print-ctor     print-dup      print-method   print-simple   print-str\nprintf         println        println-str\n",[194,9670,9671,9680,9685],{"__ignoreMap":156},[39,9672,9673,9675,9677],{"class":614,"line":615},[39,9674,9347],{"class":622},[39,9676,9628],{"class":1909},[39,9678,9679],{"class":622}," print\u003Ctab>\n",[39,9681,9682],{"class":614,"line":157},[39,9683,9684],{"class":622},"print          print-ctor     print-dup      print-method   print-simple   print-str\n",[39,9686,9687],{"class":614,"line":637},[39,9688,9689],{"class":622},"printf         println        println-str\n",[11,9691,9692],{},"If you don't know what you're looking for, you can also try find-doc. This will search both the name and the documentation itself for your string or regex.",[605,9694,9696],{"className":9338,"code":9695,"language":9340,"meta":156,"style":156},"user=> (find-doc \"split\")\n; ..... too long to include ;)\n",[194,9697,9698,9709],{"__ignoreMap":156},[39,9699,9700,9702,9705,9707],{"class":614,"line":615},[39,9701,9347],{"class":622},[39,9703,9704],{"class":1909},"find-doc",[39,9706,9565],{"class":649},[39,9708,653],{"class":622},[39,9710,9711],{"class":614,"line":157},[39,9712,9713],{"class":1628},"; ..... too long to include ;)\n",[11,9715,9716],{},"THE ULTIMATE: Get the source for a function!",[605,9718,9720],{"className":9338,"code":9719,"language":9340,"meta":156,"style":156},"user=> (source print)\n(defn print\n  \"Prints the object(s) to the output stream that is the current value\n  of *out*.  print and println produce output for human consumption.\"\n  {:added \"1.0\"\n   :static true}\n    (binding [*print-readably* nil]\n      (apply pr more)))\n",[194,9721,9722,9730,9740,9745,9750,9762,9772,9789],{"__ignoreMap":156},[39,9723,9724,9726,9728],{"class":614,"line":615},[39,9725,9347],{"class":622},[39,9727,6824],{"class":1909},[39,9729,9631],{"class":622},[39,9731,9732,9734,9737],{"class":614,"line":157},[39,9733,4222],{"class":622},[39,9735,9736],{"class":618},"defn",[39,9738,9739],{"class":7461}," print\n",[39,9741,9742],{"class":614,"line":637},[39,9743,9744],{"class":649},"  \"Prints the object(s) to the output stream that is the current value\n",[39,9746,9747],{"class":614,"line":656},[39,9748,9749],{"class":649},"  of *out*.  print and println produce output for human consumption.\"\n",[39,9751,9752,9755,9759],{"class":614,"line":668},[39,9753,9754],{"class":622},"  {",[39,9756,9758],{"class":9757},"sXSQT",":added",[39,9760,9761],{"class":649}," \"1.0\"\n",[39,9763,9764,9767,9770],{"class":614,"line":674},[39,9765,9766],{"class":9757},"   :static",[39,9768,9769],{"class":664}," true",[39,9771,6815],{"class":622},[39,9773,9774,9777,9780,9783,9786],{"class":614,"line":685},[39,9775,9776],{"class":622},"    (",[39,9778,9779],{"class":618},"binding",[39,9781,9782],{"class":622}," [*print-readably* ",[39,9784,9785],{"class":664},"nil",[39,9787,9788],{"class":622},"]\n",[39,9790,9791,9794,9797],{"class":614,"line":691},[39,9792,9793],{"class":622},"      (",[39,9795,9796],{"class":1909},"apply",[39,9798,9799],{"class":622}," pr more)))\n",[11,9801,9802],{},"Not everything is a function. Heck, sometimes you might not know what sort of thing you're looking at. But we can find out.",[605,9804,9806],{"className":9338,"code":9805,"language":9340,"meta":156,"style":156},"user=> (type 5)\njava.lang.Long\nuser=> (type 5.2)\njava.lang.Double\nuser=> (type \"hello\")\njava.lang.String\nuser=> (type 'hello)\nclojure.lang.Symbol\nuser=> (type {:a 5, :b 6})\nclojure.lang.PersistentArrayMap\nuser=> (type [1 2 3])\nclojure.lang.PersistentVector\nuser=> (type type)\nclojure.core$type\nuser=> (type dir)\nCompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl\u002Fdir, compiling:(\u002Ftmp\u002Fform-init5987247545872948247.clj:1:1) \nuser=> (type clojure.string\u002Fsplit)\nclojure.string$split\nuser=> (defn say-hi [] (println \"hi!\"))\n#'user\u002Fsay-hi\nuser=> (type say-hi)\nuser$say_hi\n",[194,9807,9808,9819,9824,9835,9840,9851,9856,9865,9870,9894,9899,9919,9924,9933,9938,9947,9958,9967,9973,9994,10000,10010],{"__ignoreMap":156},[39,9809,9810,9812,9815,9817],{"class":614,"line":615},[39,9811,9347],{"class":622},[39,9813,9814],{"class":1909},"type",[39,9816,6712],{"class":664},[39,9818,653],{"class":622},[39,9820,9821],{"class":614,"line":157},[39,9822,9823],{"class":622},"java.lang.Long\n",[39,9825,9826,9828,9830,9833],{"class":614,"line":637},[39,9827,9347],{"class":622},[39,9829,9814],{"class":1909},[39,9831,9832],{"class":664}," 5.2",[39,9834,653],{"class":622},[39,9836,9837],{"class":614,"line":656},[39,9838,9839],{"class":622},"java.lang.Double\n",[39,9841,9842,9844,9846,9849],{"class":614,"line":668},[39,9843,9347],{"class":622},[39,9845,9814],{"class":1909},[39,9847,9848],{"class":649}," \"hello\"",[39,9850,653],{"class":622},[39,9852,9853],{"class":614,"line":674},[39,9854,9855],{"class":622},"java.lang.String\n",[39,9857,9858,9860,9862],{"class":614,"line":685},[39,9859,9347],{"class":622},[39,9861,9814],{"class":1909},[39,9863,9864],{"class":622}," 'hello)\n",[39,9866,9867],{"class":614,"line":691},[39,9868,9869],{"class":622},"clojure.lang.Symbol\n",[39,9871,9872,9874,9876,9878,9881,9883,9885,9888,9891],{"class":614,"line":701},[39,9873,9347],{"class":622},[39,9875,9814],{"class":1909},[39,9877,4733],{"class":622},[39,9879,9880],{"class":9757},":a",[39,9882,6712],{"class":664},[39,9884,6335],{"class":622},[39,9886,9887],{"class":9757},":b",[39,9889,9890],{"class":664}," 6",[39,9892,9893],{"class":622},"})\n",[39,9895,9896],{"class":614,"line":709},[39,9897,9898],{"class":622},"clojure.lang.PersistentArrayMap\n",[39,9900,9901,9903,9905,9908,9910,9913,9916],{"class":614,"line":1823},[39,9902,9347],{"class":622},[39,9904,9814],{"class":1909},[39,9906,9907],{"class":622}," [",[39,9909,4248],{"class":664},[39,9911,9912],{"class":664}," 2",[39,9914,9915],{"class":664}," 3",[39,9917,9918],{"class":622},"])\n",[39,9920,9921],{"class":614,"line":1837},[39,9922,9923],{"class":622},"clojure.lang.PersistentVector\n",[39,9925,9926,9928,9930],{"class":614,"line":4967},[39,9927,9347],{"class":622},[39,9929,9814],{"class":1909},[39,9931,9932],{"class":622}," type)\n",[39,9934,9935],{"class":614,"line":6142},[39,9936,9937],{"class":622},"clojure.core$type\n",[39,9939,9940,9942,9944],{"class":614,"line":6160},[39,9941,9347],{"class":622},[39,9943,9814],{"class":1909},[39,9945,9946],{"class":622}," dir)\n",[39,9948,9949,9952,9955],{"class":614,"line":6185},[39,9950,9951],{"class":622},"CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl\u002Fdir, compiling:(",[39,9953,9954],{"class":1909},"\u002Ftmp\u002Fform-init5987247545872948247.clj:1:1",[39,9956,9957],{"class":622},") \n",[39,9959,9960,9962,9964],{"class":614,"line":6208},[39,9961,9347],{"class":622},[39,9963,9814],{"class":1909},[39,9965,9966],{"class":622}," clojure.string\u002Fsplit)\n",[39,9968,9970],{"class":614,"line":9969},18,[39,9971,9972],{"class":622},"clojure.string$split\n",[39,9974,9976,9978,9980,9983,9986,9988,9991],{"class":614,"line":9975},19,[39,9977,9347],{"class":622},[39,9979,9736],{"class":618},[39,9981,9982],{"class":7461}," say-hi",[39,9984,9985],{"class":622}," [] (",[39,9987,9373],{"class":1909},[39,9989,9990],{"class":649}," \"hi!\"",[39,9992,9993],{"class":622},"))\n",[39,9995,9997],{"class":614,"line":9996},20,[39,9998,9999],{"class":622},"#'user\u002Fsay-hi\n",[39,10001,10003,10005,10007],{"class":614,"line":10002},21,[39,10004,9347],{"class":622},[39,10006,9814],{"class":1909},[39,10008,10009],{"class":622}," say-hi)\n",[39,10011,10013],{"class":614,"line":10012},22,[39,10014,10015],{"class":622},"user$say_hi\n",[266,10017,10019],{"id":10018},"getting-gui","Getting GUI",[11,10021,10022],{},"Clojure comes with clojure.inspector, which gives some Swing GUI for exploring data structures.",[605,10024,10026],{"className":9338,"code":10025,"language":9340,"meta":156,"style":156},"user=> (use 'clojure.inspector)\nuser=> (inspect-tree {:a 1 :b 2 :c [1 2 3 {:d 4 :e 5 :f [6 7 8]}]})\n",[194,10027,10028,10038],{"__ignoreMap":156},[39,10029,10030,10032,10035],{"class":614,"line":615},[39,10031,9347],{"class":622},[39,10033,10034],{"class":618},"use",[39,10036,10037],{"class":622}," 'clojure.inspector)\n",[39,10039,10040,10042,10045,10047,10049,10052,10055,10057,10060,10062,10064,10066,10068,10070,10073,10076,10079,10081,10084,10086,10089,10092,10095],{"class":614,"line":157},[39,10041,9347],{"class":622},[39,10043,10044],{"class":1909},"inspect-tree",[39,10046,4733],{"class":622},[39,10048,9880],{"class":9757},[39,10050,10051],{"class":664}," 1",[39,10053,10054],{"class":9757}," :b",[39,10056,9912],{"class":664},[39,10058,10059],{"class":9757}," :c",[39,10061,9907],{"class":622},[39,10063,4248],{"class":664},[39,10065,9912],{"class":664},[39,10067,9915],{"class":664},[39,10069,4733],{"class":622},[39,10071,10072],{"class":9757},":d",[39,10074,10075],{"class":664}," 4",[39,10077,10078],{"class":9757}," :e",[39,10080,6712],{"class":664},[39,10082,10083],{"class":9757}," :f",[39,10085,9907],{"class":622},[39,10087,10088],{"class":664},"6",[39,10090,10091],{"class":664}," 7",[39,10093,10094],{"class":664}," 8",[39,10096,10097],{"class":622},"]}]})\n",[11,10099,10100],{},"NOTE: I had to do this to get jdk-1.7 swing apps to display while using xmonad (and other tiling window managers I guess). I now dropped this in my ~\u002F.zshrc. Uhg.",[605,10102,10104],{"className":9338,"code":10103,"language":9340,"meta":156,"style":156},"export _JAVA_AWT_WM_NONREPARENTING=1\n",[194,10105,10106],{"__ignoreMap":156},[39,10107,10108],{"class":614,"line":615},[39,10109,10103],{"class":622},[266,10111,10113],{"id":10112},"doing-horrible-things","Doing Horrible Things",[11,10115,10116],{},"So let's have some fun. First, let's get all the string function names. \"dir-fn\" is like dir, but returns the results instead of printing them.",[605,10118,10120],{"className":9338,"code":10119,"language":9340,"meta":156,"style":156},"user=> (def string-funcs (clojure.repl\u002Fdir-fn 'clojure.string))\n",[194,10121,10122],{"__ignoreMap":156},[39,10123,10124,10126,10129,10132,10134,10137],{"class":614,"line":615},[39,10125,9347],{"class":622},[39,10127,10128],{"class":618},"def",[39,10130,10131],{"class":7461}," string-funcs",[39,10133,444],{"class":622},[39,10135,10136],{"class":1909},"clojure.repl\u002Fdir-fn",[39,10138,10139],{"class":622}," 'clojure.string))\n",[11,10141,10142],{},"Let's turn them into their actual functions.",[605,10144,10146],{"className":9338,"code":10145,"language":9340,"meta":156,"style":156},"user=> (def real-string-funcs (map #(resolve (symbol (str \"clojure.string\u002F\" %))) string-funcs))\n",[194,10147,10148],{"__ignoreMap":156},[39,10149,10150,10152,10154,10157,10159,10161,10164,10167,10169,10172,10174,10177,10180],{"class":614,"line":615},[39,10151,9347],{"class":622},[39,10153,10128],{"class":618},[39,10155,10156],{"class":7461}," real-string-funcs",[39,10158,444],{"class":622},[39,10160,9361],{"class":1909},[39,10162,10163],{"class":622}," #(",[39,10165,10166],{"class":1909},"resolve",[39,10168,444],{"class":622},[39,10170,10171],{"class":1909},"symbol",[39,10173,444],{"class":622},[39,10175,10176],{"class":1909},"str",[39,10178,10179],{"class":649}," \"clojure.string\u002F\"",[39,10181,10182],{"class":622}," %))) string-funcs))\n",[11,10184,10185],{},"Given a function, here is how to tell how many parameters it takes (well... it might take more or less than this, but this will tell us how many params for the first definition. Good enough).",[605,10187,10189],{"className":9338,"code":10188,"language":9340,"meta":156,"style":156},"user=> (defn arg-count [f] (count (first (:arglists (meta f)))))\n",[194,10190,10191],{"__ignoreMap":156},[39,10192,10193,10195,10197,10200,10203,10206,10208,10211,10213,10216,10218,10221],{"class":614,"line":615},[39,10194,9347],{"class":622},[39,10196,9736],{"class":618},[39,10198,10199],{"class":7461}," arg-count",[39,10201,10202],{"class":622}," [f] (",[39,10204,10205],{"class":1909},"count",[39,10207,444],{"class":622},[39,10209,10210],{"class":1909},"first",[39,10212,444],{"class":622},[39,10214,10215],{"class":9757},":arglists",[39,10217,444],{"class":622},[39,10219,10220],{"class":1909},"meta",[39,10222,10223],{"class":622}," f)))))\n",[11,10225,10226],{},"Here is a handy thing that tells us if the given function can deal with a single arg.",[605,10228,10230],{"className":9338,"code":10229,"language":9340,"meta":156,"style":156},"user=> (defn single-arg? [f] (= 1 (arg-count f)))\n",[194,10231,10232],{"__ignoreMap":156},[39,10233,10234,10236,10238,10241,10243,10245,10247,10249,10252],{"class":614,"line":615},[39,10235,9347],{"class":622},[39,10237,9736],{"class":618},[39,10239,10240],{"class":7461}," single-arg?",[39,10242,10202],{"class":622},[39,10244,643],{"class":1909},[39,10246,10051],{"class":664},[39,10248,444],{"class":622},[39,10250,10251],{"class":1909},"arg-count",[39,10253,10254],{"class":622}," f)))\n",[11,10256,10257],{},"Now let's filter our string functions down to the ones that just take one argument.",[605,10259,10261],{"className":9338,"code":10260,"language":9340,"meta":156,"style":156},"user=> (def one-arg-funcs (filter single-arg? real-string-funcs))\n",[194,10262,10263],{"__ignoreMap":156},[39,10264,10265,10267,10269,10272,10274,10277],{"class":614,"line":615},[39,10266,9347],{"class":622},[39,10268,10128],{"class":618},[39,10270,10271],{"class":7461}," one-arg-funcs",[39,10273,444],{"class":622},[39,10275,10276],{"class":1909},"filter",[39,10278,10279],{"class":622}," single-arg? real-string-funcs))\n",[11,10281,10282],{},"So. We if have a one-argument function in the clojure.string namespace, let's assume it takes a string and pass in a string to it :) . The \"pr-str\" bit is so that we can pretty-print this with escaped newlines and such later.",[605,10284,10286],{"className":9338,"code":10285,"language":9340,"meta":156,"style":156},"user=> (defn one-arg-result [f] (pr-str (apply f [\"Hello\\nworld\\n\"])))\n",[194,10287,10288],{"__ignoreMap":156},[39,10289,10290,10292,10294,10297,10299,10302,10304,10306,10309,10312,10315,10318,10320,10322],{"class":614,"line":615},[39,10291,9347],{"class":622},[39,10293,9736],{"class":618},[39,10295,10296],{"class":7461}," one-arg-result",[39,10298,10202],{"class":622},[39,10300,10301],{"class":1909},"pr-str",[39,10303,444],{"class":622},[39,10305,9796],{"class":1909},[39,10307,10308],{"class":622}," f [",[39,10310,10311],{"class":649},"\"Hello",[39,10313,10314],{"class":664},"\\n",[39,10316,10317],{"class":649},"world",[39,10319,10314],{"class":664},[39,10321,1569],{"class":649},[39,10323,10324],{"class":622},"])))\n",[11,10326,10327],{},"Now let's try this on all the one-argument string functions, printing out the function name and the result pretty like.",[605,10329,10331],{"className":9338,"code":10330,"language":9340,"meta":156,"style":156},"user=> (map #(println (:name (meta %))  \"\\\"Hello\\\\nworld\\\\n\\\" ->\" (one-arg-result %)) one-arg-funcs)\nblank? \"Hello\\nworld\\n\" -> false\ncapitalize \"Hello\\nworld\\n\" -> \"Hello\\nworld\\n\"\njoin \"Hello\\nworld\\n\" -> \"Hello\\nworld\\n\"\nlower-case \"Hello\\nworld\\n\" -> \"hello\\nworld\\n\"\nre-quote-replacement \"Hello\\nworld\\n\" -> \"Hello\\nworld\\n\"\nreverse \"Hello\\nworld\\n\" -> \"\\ndlrow\\nolleH\"\nsplit-lines \"Hello\\nworld\\n\" -> [\"Hello\" \"world\"]\ntrim \"Hello\\nworld\\n\" -> \"Hello\\nworld\"\ntrim-newline \"Hello\\nworld\\n\" -> \"Hello\\nworld\"\ntriml \"Hello\\nworld\\n\" -> \"Hello\\nworld\\n\"\ntrimr \"Hello\\nworld\\n\" -> \"Hello\\nworld\"\nupper-case \"Hello\\nworld\\n\" -> \"HELLO\\nWORLD\\n\"\n",[194,10332,10333,10387,10408,10435,10462,10490,10517,10546,10572,10596,10619,10646,10669],{"__ignoreMap":156},[39,10334,10335,10337,10339,10341,10343,10345,10348,10350,10352,10355,10357,10360,10363,10366,10369,10371,10374,10376,10379,10381,10384],{"class":614,"line":615},[39,10336,9347],{"class":622},[39,10338,9361],{"class":1909},[39,10340,10163],{"class":622},[39,10342,9373],{"class":1909},[39,10344,444],{"class":622},[39,10346,10347],{"class":9757},":name",[39,10349,444],{"class":622},[39,10351,10220],{"class":1909},[39,10353,10354],{"class":622}," %))  ",[39,10356,1569],{"class":649},[39,10358,10359],{"class":664},"\\\"",[39,10361,10362],{"class":649},"Hello",[39,10364,10365],{"class":664},"\\\\",[39,10367,10368],{"class":649},"nworld",[39,10370,10365],{"class":664},[39,10372,10373],{"class":649},"n",[39,10375,10359],{"class":664},[39,10377,10378],{"class":649}," ->\"",[39,10380,444],{"class":622},[39,10382,10383],{"class":1909},"one-arg-result",[39,10385,10386],{"class":622}," %)) one-arg-funcs)\n",[39,10388,10389,10392,10394,10396,10398,10400,10402,10405],{"class":614,"line":157},[39,10390,10391],{"class":622},"blank? ",[39,10393,10311],{"class":649},[39,10395,10314],{"class":664},[39,10397,10317],{"class":649},[39,10399,10314],{"class":664},[39,10401,1569],{"class":649},[39,10403,10404],{"class":622}," -> ",[39,10406,10407],{"class":664},"false\n",[39,10409,10410,10413,10415,10417,10419,10421,10423,10425,10427,10429,10431,10433],{"class":614,"line":637},[39,10411,10412],{"class":622},"capitalize ",[39,10414,10311],{"class":649},[39,10416,10314],{"class":664},[39,10418,10317],{"class":649},[39,10420,10314],{"class":664},[39,10422,1569],{"class":649},[39,10424,10404],{"class":622},[39,10426,10311],{"class":649},[39,10428,10314],{"class":664},[39,10430,10317],{"class":649},[39,10432,10314],{"class":664},[39,10434,1653],{"class":649},[39,10436,10437,10440,10442,10444,10446,10448,10450,10452,10454,10456,10458,10460],{"class":614,"line":656},[39,10438,10439],{"class":622},"join ",[39,10441,10311],{"class":649},[39,10443,10314],{"class":664},[39,10445,10317],{"class":649},[39,10447,10314],{"class":664},[39,10449,1569],{"class":649},[39,10451,10404],{"class":622},[39,10453,10311],{"class":649},[39,10455,10314],{"class":664},[39,10457,10317],{"class":649},[39,10459,10314],{"class":664},[39,10461,1653],{"class":649},[39,10463,10464,10467,10469,10471,10473,10475,10477,10479,10482,10484,10486,10488],{"class":614,"line":668},[39,10465,10466],{"class":622},"lower-case ",[39,10468,10311],{"class":649},[39,10470,10314],{"class":664},[39,10472,10317],{"class":649},[39,10474,10314],{"class":664},[39,10476,1569],{"class":649},[39,10478,10404],{"class":622},[39,10480,10481],{"class":649},"\"hello",[39,10483,10314],{"class":664},[39,10485,10317],{"class":649},[39,10487,10314],{"class":664},[39,10489,1653],{"class":649},[39,10491,10492,10495,10497,10499,10501,10503,10505,10507,10509,10511,10513,10515],{"class":614,"line":674},[39,10493,10494],{"class":622},"re-quote-replacement ",[39,10496,10311],{"class":649},[39,10498,10314],{"class":664},[39,10500,10317],{"class":649},[39,10502,10314],{"class":664},[39,10504,1569],{"class":649},[39,10506,10404],{"class":622},[39,10508,10311],{"class":649},[39,10510,10314],{"class":664},[39,10512,10317],{"class":649},[39,10514,10314],{"class":664},[39,10516,1653],{"class":649},[39,10518,10519,10522,10524,10526,10528,10530,10532,10534,10536,10538,10541,10543],{"class":614,"line":685},[39,10520,10521],{"class":622},"reverse ",[39,10523,10311],{"class":649},[39,10525,10314],{"class":664},[39,10527,10317],{"class":649},[39,10529,10314],{"class":664},[39,10531,1569],{"class":649},[39,10533,10404],{"class":622},[39,10535,1569],{"class":649},[39,10537,10314],{"class":664},[39,10539,10540],{"class":649},"dlrow",[39,10542,10314],{"class":664},[39,10544,10545],{"class":649},"olleH\"\n",[39,10547,10548,10551,10553,10555,10557,10559,10561,10564,10567,10570],{"class":614,"line":691},[39,10549,10550],{"class":622},"split-lines ",[39,10552,10311],{"class":649},[39,10554,10314],{"class":664},[39,10556,10317],{"class":649},[39,10558,10314],{"class":664},[39,10560,1569],{"class":649},[39,10562,10563],{"class":622}," -> [",[39,10565,10566],{"class":649},"\"Hello\"",[39,10568,10569],{"class":649}," \"world\"",[39,10571,9788],{"class":622},[39,10573,10574,10577,10579,10581,10583,10585,10587,10589,10591,10593],{"class":614,"line":701},[39,10575,10576],{"class":622},"trim ",[39,10578,10311],{"class":649},[39,10580,10314],{"class":664},[39,10582,10317],{"class":649},[39,10584,10314],{"class":664},[39,10586,1569],{"class":649},[39,10588,10404],{"class":622},[39,10590,10311],{"class":649},[39,10592,10314],{"class":664},[39,10594,10595],{"class":649},"world\"\n",[39,10597,10598,10601,10603,10605,10607,10609,10611,10613,10615,10617],{"class":614,"line":709},[39,10599,10600],{"class":622},"trim-newline ",[39,10602,10311],{"class":649},[39,10604,10314],{"class":664},[39,10606,10317],{"class":649},[39,10608,10314],{"class":664},[39,10610,1569],{"class":649},[39,10612,10404],{"class":622},[39,10614,10311],{"class":649},[39,10616,10314],{"class":664},[39,10618,10595],{"class":649},[39,10620,10621,10624,10626,10628,10630,10632,10634,10636,10638,10640,10642,10644],{"class":614,"line":1823},[39,10622,10623],{"class":622},"triml ",[39,10625,10311],{"class":649},[39,10627,10314],{"class":664},[39,10629,10317],{"class":649},[39,10631,10314],{"class":664},[39,10633,1569],{"class":649},[39,10635,10404],{"class":622},[39,10637,10311],{"class":649},[39,10639,10314],{"class":664},[39,10641,10317],{"class":649},[39,10643,10314],{"class":664},[39,10645,1653],{"class":649},[39,10647,10648,10651,10653,10655,10657,10659,10661,10663,10665,10667],{"class":614,"line":1837},[39,10649,10650],{"class":622},"trimr ",[39,10652,10311],{"class":649},[39,10654,10314],{"class":664},[39,10656,10317],{"class":649},[39,10658,10314],{"class":664},[39,10660,1569],{"class":649},[39,10662,10404],{"class":622},[39,10664,10311],{"class":649},[39,10666,10314],{"class":664},[39,10668,10595],{"class":649},[39,10670,10671,10674,10676,10678,10680,10682,10684,10686,10689,10691,10694,10696],{"class":614,"line":4967},[39,10672,10673],{"class":622},"upper-case ",[39,10675,10311],{"class":649},[39,10677,10314],{"class":664},[39,10679,10317],{"class":649},[39,10681,10314],{"class":664},[39,10683,1569],{"class":649},[39,10685,10404],{"class":622},[39,10687,10688],{"class":649},"\"HELLO",[39,10690,10314],{"class":664},[39,10692,10693],{"class":649},"WORLD",[39,10695,10314],{"class":664},[39,10697,1653],{"class":649},[11,10699,10700],{},"Woo!",[738,10702,10703],{},"html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .s8-w5, html code.shiki .s8-w5{--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-sepia:#88846F}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sFxd3, html code.shiki .sFxd3{--shiki-default:#032F62;--shiki-dark:#DBEDFF;--shiki-sepia:#E6DB74}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .s_OQ2, html code.shiki .s_OQ2{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#F8F8F2}html pre.shiki code .sXSQT, html code.shiki .sXSQT{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#F8F8F2}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}",{"title":156,"searchDepth":157,"depth":157,"links":10705},[10706,10707,10708,10709],{"id":9328,"depth":157,"text":9329},{"id":9609,"depth":157,"text":9610},{"id":10018,"depth":157,"text":10019},{"id":10112,"depth":157,"text":10113},"2015-07-26T14:42-04:00",{},"\u002Ftlt-2015.07.26-exploring-clojure-in-the-repl",{"title":9314,"description":9319},"TLT - 2015.07.26 - Exploring Clojure in the REPL",[169],"2015-10-18T16:06-04:00","tTK_BrfKDe0WgQInjXcSgxYo5S1Sq23LzCHaxyyRUxM",{"id":10719,"title":10720,"body":10721,"createdAt":10785,"description":10725,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":10786,"navigation":164,"path":10787,"seo":10788,"stem":10789,"tags":10790,"updatedAt":10716,"__hash__":10791},"content\u002FTLT - 2015.06.04 - Polyglot Bridges.md","TLT_-_2015.06.04_-_Polyglot_Bridges",{"type":8,"value":10722,"toc":10783},[10723,10726,10740,10748,10751,10757,10760,10780],[11,10724,10725],{},"Tags: Polyglot, Ruby, Perl6, Python",[11,10727,10728,10729,10734,10735,797],{},"Here are the ",[136,10730,10733],{"href":10731,"rel":10732},"http:\u002F\u002Fthelackthereof.org\u002Fdocs\u002Ftalks\u002F2015-06-14%20RubyNation%20Polyglot%20Bridges\u002F2015-06-14%20RubyNation%20Polyglot%20Bridges.pdf",[140],"slides for Polyglot Bridges (pdf)"," lightning talk that I gave today at ",[136,10736,10739],{"href":10737,"rel":10738},"http:\u002F\u002Frubynation.org",[140],"RubyNation",[11,10741,10742,10743],{},"slideshare:",[136,10744,10747],{"href":10745,"rel":10746},"http:\u002F\u002Fwww.slideshare.net\u002Fawwaiid\u002Fmad-science-a-dash-of-polyglot",[140],"www.slideshare.net\u002Fawwaiid\u002Fmad-science-a-dash-of-polyglot",[11,10749,10750],{},"The most important bit:",[605,10752,10755],{"className":10753,"code":10754,"language":1288},[1286],"# Shell\nsudo apt-get install matplotlib\ngem install rubypython\n# pending a small patch for debian\u002Fubuntu 64bit\n\n# Ruby; even works in the REPL!\nrequire 'rubypython'\nRubyPython.start\nplt = RubyPython.import('matplotlib.pyplot')\n\nplt.plot([1,2,4,6,28,50,234])\nplt.ylabel('some numbers');\nplt.show\n",[194,10756,10754],{"__ignoreMap":156},[587,10758],{"src":10759},"\u002Fimg\u002Frubypython_simple_chart.png",[11,10761,10762,10763,10768,10769,10774,10775,797],{},"Or in other words: pull in this ",[136,10764,10767],{"href":10765,"rel":10766},"https:\u002F\u002Frubygems.org\u002Fgems\u002Frubypython",[140],"rubypython gem",", magically get all the python libs callable from Ruby. In this case, you get all the nice charts and graphs from pyplot. I originally played with this in ",[136,10770,10773],{"href":10771,"rel":10772},"https:\u002F\u002Fgithub.com\u002Fniner\u002FInline-Python\u002F",[140],"Perl6\u002FRakudo Inline::Python",", where it also ",[136,10776,10779],{"href":10777,"rel":10778},"https:\u002F\u002Fgist.github.com\u002Fawwaiid\u002Fef3f0abcfa96e34977b4",[140],"works fantastically",[11,10781,10782],{},"I love the idea of one community NOT completely re-writing a library in their language when it can just be used \"directly\" instead.",{"title":156,"searchDepth":157,"depth":157,"links":10784},[],"2015-06-14T01:19-04:00",{},"\u002Ftlt-2015.06.04-polyglot-bridges",{"title":10720,"description":10725},"TLT - 2015.06.04 - Polyglot Bridges",[169],"89yfAms_QN0ot05kdeiNGc5MALIdluIgQkxzOhItuPw",{"id":10793,"title":10794,"body":10795,"createdAt":10916,"description":10799,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":10917,"navigation":164,"path":10918,"seo":10919,"stem":10920,"tags":10921,"updatedAt":10922,"__hash__":10923},"content\u002FTLT - 2013.12.26 - Overtone Adventures 4.md","TLT_-_2013.12.26_-_Overtone_Adventures_4",{"type":8,"value":10796,"toc":10914},[10797,10800,10815,10818],[11,10798,10799],{},"Tags: Clojure, Overtone, Music",[11,10801,10802,10803,10808,10809,10814],{},"Today I'm playing with ",[136,10804,10807],{"href":10805,"rel":10806},"http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FOpen_Sound_Control",[140],"Open Sound Control (OSC)",", which is more general-purpose than midi but kinda similar idea. I have an android app on my phone named ",[136,10810,10813],{"href":10811,"rel":10812},"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=com.charlieroberts.Control&hl=en",[140],"Control"," which has a few existing UIs, in my case I'm playing with the multi-touch. I set it to have two touch inputs.",[11,10816,10817],{},"In my Overtone REPL, I first set it up to listen for OSC events, and dump out whatever events it sees:",[194,10819,10820,10821,10827,10846,10852,10884,10908],{"clojure":156},"\n(def server (osc-server 44100 \"osc-clj\"))\n(osc-listen server (fn [msg] (println msg)) :debug)\n**Turn off with:** (osc-rm-listener server :debug)\n",[605,10822,10825],{"className":10823,"code":10824,"language":1288},[1286],"\nI got both my laptop and phone on the wifi (which allows peer-to-peer communication) and told the Control app to connect to my laptop server (192.168.0.15 port 44100, in this case). Now when I touch the screen I get a bunch of messages about the generated OSC events. They look like:\n\n",[194,10826,10824],{"__ignoreMap":156},[11,10828,10829,10830,10833,10834,10837,10838,10841,10842,10845],{},"{:src-port 45161, ",[10831,10832],"src-host",{}," 192.168.0.25, ",[10835,10836],"path",{}," \u002Fmulti\u002F1, ",[10839,10840],"type-tag",{}," ff, ",[10843,10844],"args",{}," (0.36825398 0.3961456)}",[605,10847,10850],{"className":10848,"code":10849,"language":1288},[1286],"\nFrom this I see that the path I want to react to is \"\u002Fmulti\u002F1\" and \"\u002Fmulti\u002F2\". Dragging my fingers around, the args are the x and y coordinates normalized to (0..1). For now I'll just make it beep a bit when it gets an event. I'm hooking the first touch up so the X axis generates a frequency, and the second touch up so that the Y axis generates a frequency (just as a test), giving:\n\n",[194,10851,10849],{"__ignoreMap":156},[11,10853,10854,10855,10858,10860,10861,10875,10877,10878,10880,10881,10883],{},"(osc-handle server \"\u002Fmulti\u002F1\" (fn ",[39,10856,10857],{},"msg",[461,10859],{},"\n(let ",[39,10862,10863,10865,10866,10868,10869,10871,10872,10874],{},[461,10864],{},"\nx (nth (",[10843,10867],{}," msg) 0)",[461,10870],{},"\ny (nth (",[10843,10873],{}," msg) 1)",[461,10876],{},"\n(demo 0.1 (saw (+ 100 (* 100 x))))",[461,10879],{},"\n)",[461,10882],{},"\n))",[11,10885,10886,10887,10889,10860,10891,10901,10903,10904,10880,10906,10883],{},"(osc-handle server \"\u002Fmulti\u002F2\" (fn ",[39,10888,10857],{},[461,10890],{},[39,10892,10893,10865,10895,10868,10897,10871,10899,10874],{},[461,10894],{},[10843,10896],{},[461,10898],{},[10843,10900],{},[461,10902],{},"\n(demo 0.1 (saw (+ 100 (* 100 y))))",[461,10905],{},[461,10907],{},[605,10909,10912],{"className":10910,"code":10911,"language":1288},[1286],"\nEach touch plays for 1\u002F10th of a second, so if I drag around these overlap a bunch. In fact, if I drag around a lot then something gets backed up and the sound is delayed.\n\n",[194,10913,10911],{"__ignoreMap":156},{"title":156,"searchDepth":157,"depth":157,"links":10915},[],"2013-12-26T20:41-05:00",{},"\u002Ftlt-2013.12.26-overtone-adventures-4",{"title":10794,"description":10799},"TLT - 2013.12.26 - Overtone Adventures 4",[169],"2015-10-18T16:07-04:00","6EbkE5YYuIgxGxvQguOBEsGcLcgebkd4ouPOHaDA-n0",{"id":10925,"title":10926,"body":10927,"createdAt":10967,"description":10799,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":10968,"navigation":164,"path":10969,"seo":10970,"stem":10971,"tags":10972,"updatedAt":10922,"__hash__":10973},"content\u002FTLT - 2013.12.24 - Overtone Adventures 3.md","TLT_-_2013.12.24_-_Overtone_Adventures_3",{"type":8,"value":10928,"toc":10965},[10929,10931,10934,10953,10956,10962],[11,10930,10799],{},[11,10932,10933],{},"Good progress today -- I made a hack to get around that BUNCHES of midi issue. Needed that because when I would hit a single note on my jack-keyboard (virtual midi keyboard), I got a whole bunch of events. I'm guessing I was getting 64 of them.",[11,10935,10936,10937,10942,10943],{},"I also got ",[136,10938,10941],{"href":10939,"rel":10940},"https:\u002F\u002Fgithub.com\u002Fovertone\u002Fovertone\u002Fwiki\u002FOvertone-in-vim",[140],"Overtone Vim Integration"," working. Well technically I already had it working (had fireplace.vim installed, etc), I just didn't know it. Now I can start up the REPL in one terminal and start up vim in another. In vim do \":Require\" and it finds the running REPL and hooks into it. I also added \"nnoremap ",[10944,10945,4066,10946,10948,10949],"f1",{},[596,10947],{}," (stop)",[10950,10951,10952],"cr",{},"\" to my .vimrc, so that I can jam on F1 to make the noise stop.",[11,10954,10955],{},"Here is the file I've got now:",[605,10957,10960],{"className":10958,"code":10959,"language":1288},[1286],"(ns noise.core)\n(use 'overtone.live)\n(use 'overtone.inst.piano)\n\n(on-event [:midi :note-on]\n  (fn [e]\n    (let [note (:note e)\n          vel  (:velocity e)\n          device-name (:name (:device e))]\n      (if (= \"VirMIDI [hw:1,0,1]\" device-name)\n        (piano note vel)\n        ()\n      ) \n    ) \n  ) \n  ::midi-keyboard-handler\n)\n",[194,10961,10959],{"__ignoreMap":156},[11,10963,10964],{},"So that takes midi events specifically from that device (I picked one of my 64 virtual devices at random, seems to work) piped to the piano instrument. Next I'm going to make a new instrument of my own and hook that in!",{"title":156,"searchDepth":157,"depth":157,"links":10966},[],"2013-12-25T01:29-05:00",{},"\u002Ftlt-2013.12.24-overtone-adventures-3",{"title":10926,"description":10799},"TLT - 2013.12.24 - Overtone Adventures 3",[169],"aZsPoqGP7ZW4vvihjE6F_xdcI94UldYJ04DVcAXJbpk",{"id":10975,"title":10976,"body":10977,"createdAt":11201,"description":10799,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11202,"navigation":164,"path":11203,"seo":11204,"stem":11205,"tags":11206,"updatedAt":11207,"__hash__":11208},"content\u002FTLT - 2013.12.23 - Overtone Adventures 2.md","TLT_-_2013.12.23_-_Overtone_Adventures_2",{"type":8,"value":10978,"toc":11199},[10979,10981,10993,10996,11002,11136],[11,10980,10799],{},[11,10982,10983,10984,10989,10990,10992],{},"Today I'm watching ",[136,10985,10988],{"href":10986,"rel":10987},"http:\u002F\u002Fyoutu.be\u002FlcRQFGtFiyE",[140],"Overtone and ClojureScript"," which is a coding session of someone setting up an web UI to play Overtone stuff. Building a UI like this reminds me of the one-string guitar that I got at an art festival the other day. Clearly home-made, including an energy drink as the echo chamber. And very awesome. Also fun to see someone iterate through their development. Lots of interesting things in there, most of them I can read more or less but doesn't mean I could write them. One thing I noticed was (",[10034,10991],{}," ...) to pull in instrument libs. I'll try that.",[11,10994,10995],{},"The Cheat Sheet is interesting, but I don't know enough to actually use a lot of the things on there. Current mission is to get the instruments working.",[11,10997,10998,10999,11001],{},"Ah! I need to do (use 'overtone.inst.piano) not (",[10034,11000],{}," overtone.inst.piano).",[205,11003,11004,11007,11010,11013,11020,11023,11035,11038,11041,11044,11081,11110,11113,11119,11133],{},[208,11005,11006],{},"Now (piano) plays a note!",[208,11008,11009],{},"(odoc note) shows that it takes a bunch of params",[208,11011,11012],{},"(piano 60), (piano 65), etc plays some nice piano notes",[208,11014,11015,11016,11019],{},"I looked up named parameteters in clojure. (piano ",[11017,11018],"note",{}," 65) does what I want",[208,11021,11022],{},"Achievement unlocked ... I can now use all the intstruments on the cheat sheet!",[208,11024,11025,11026,11028,11029,11031,11032,11034],{},"Now when I do \"(piano ",[11017,11027],{}," 60) (piano ",[11017,11030],{}," 65) (piano ",[11017,11033],{}," 69)\" (still in REPL) it plays all three notes at once. Need to learn how to sequence things.",[208,11036,11037],{},"I think I'll go back to that workshop video",[208,11039,11040],{},"At 13:40 they talk about sequencing things",[208,11042,11043],{},"Play a piano note in 1 second (at (+ 1000 (now)) (piano))",[208,11045,11046,11047],{},"From their tutorial, I created:\n",[205,11048,11049,11059,11062,11065,11071,11074],{},[208,11050,11051,11052,11055,11056,11058],{},"(defn loop-beats ",[39,11053,11054],{},"time"," (at (+ 500 time) (kick)) (at (+ 1000 time) (open-hat)) (apply-at (+ 1500 time) loop-beats (+ 1500 time) ",[39,11057],{},"))",[208,11060,11061],{},"(loop-beats (now))",[208,11063,11064],{},"(stop)",[208,11066,11067,11068,11070],{},"I don't know exactly what that last ",[39,11069],{}," is for. (odoc apply-at) says it is \"argseq\" but gives no explanation.",[208,11072,11073],{},"In general this is \"temorial recursion\" -- delays a bit before calling back",[208,11075,11076,11077,11080],{},"As far as I can tell this ",[20,11078,11079],{},"does"," create new stack frames! Will eventually run out. I know this because I accidentally put the loop-beats recursion in parens which invoked it.",[208,11082,11083,11084],{},"Following the tutorial, I transformed it to use a metronome:\n",[205,11085,11086,11089,11097,11100,11107],{},[208,11087,11088],{},"(def metro (metronome 180))",[208,11090,11051,11091,11094,11095,11058],{},[39,11092,11093],{},"m beat-num"," (at (m (+ 0 beat-num)) (kick)) (at (m (+ 1 beat-num)) (open-hat)) (apply-at (m (+ 2 beat-num)) loop-beats m (+ 2 beat-num) ",[39,11096],{},[208,11098,11099],{},"Get it started: (loop-beats metro (metro))",[208,11101,11102,11103,11106],{},"Change the temp live! (metro ",[11104,11105],"bpm",{}," 200)",[208,11108,11109],{},"Stop it (stop)",[208,11111,11112],{},"Instruments take 'notes' (midi numbers), though some things take hz",[208,11114,11115,11116,449],{},"Symbolic notes can be turned into midi numbers via (note ",[11117,11118],"a4",{},[208,11120,11121,11122,449],{},"Can map a sequence of symbolic notes to midi numbers (map note ",[39,11123,11124,4066,11127,4066,11130],{},[11125,11126],"e4",{},[11128,11129],"d4",{},[11131,11132],"c4",{},[208,11134,11135],{},"Now I can make a general purpose play-note-sequence function. I'll just make it play on the beat.",[194,11137,11138,11139],{"clojure":156},"\n(defn play-song [metro beat-num notes]\n  (map-indexed (fn [index n]\n    (at (metro (+ index beat-num)) (piano :note (note n)))\n  ) notes)\n)\n```\n",[205,11140,11141,11179,11187,11190,11193,11196],{},[208,11142,11143,11144,449],{},"(play-song metro (metro) ",[39,11145,11146,4066,11148,4066,11150,4066,11152,4066,11154,4066,11156,4066,11158,4066,11160,4066,11163,4066,11165,4066,11167,4066,11169,4066,11171,4066,11173,4066,11175,4066,11177],{},[11125,11147],{},[11128,11149],{},[11131,11151],{},[11128,11153],{},[11125,11155],{},[11125,11157],{},[11125,11159],{},[11161,11162],"a0",{},[11128,11164],{},[11128,11166],{},[11128,11168],{},[11161,11170],{},[11125,11172],{},[11125,11174],{},[11125,11176],{},[11161,11178],{},[208,11180,11181,11182],{},"OK. Midi time! Looking at ",[136,11183,11186],{"href":11184,"rel":11185},"https:\u002F\u002Fgithub.com\u002Fovertone\u002Fovertone\u002Fwiki\u002FMIDI",[140],"Overtone wiki MIDI page",[208,11188,11189],{},"Fired up jack-keyboard (software midi keyboard) since I'm not at home",[208,11191,11192],{},"Apparently software midi doesn't get immediately detected. \"modprobe snd-virmidi\" gave me something I can connect to in jack",[208,11194,11195],{},"Had to restart overtone",[208,11197,11198],{},"Now I have BUNCHES of midi connections when I do (midi-connected-devices) -- like 64 of them. Too many.",{"title":156,"searchDepth":157,"depth":157,"links":11200},[],"2013-12-25T01:27-05:00",{},"\u002Ftlt-2013.12.23-overtone-adventures-2",{"title":10976,"description":10799},"TLT - 2013.12.23 - Overtone Adventures 2",[169],"2015-10-18T16:08-04:00","gEqnu9NRgpMUkmgkMZQHlRBZMapbER_gq1JMbBX6XT8",{"id":11210,"title":11211,"body":11212,"createdAt":11285,"description":10799,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11286,"navigation":164,"path":11287,"seo":11288,"stem":11289,"tags":11290,"updatedAt":11207,"__hash__":11291},"content\u002FTLT - 2013.12.22 - Overtone Adventures 1.md","TLT_-_2013.12.22_-_Overtone_Adventures_1",{"type":8,"value":11213,"toc":11283},[11214,11216,11225,11228,11231],[11,11215,10799],{},[11,11217,11218,11219,11224],{},"So I've gone through ",[136,11220,11223],{"href":11221,"rel":11222},"https:\u002F\u002Fgithub.com\u002Fovertone\u002Fovertone\u002Fwiki\u002FGetting-Started",[140],"Overtone Getting Started"," a few times, and am up and running. Only trick at all is that I already have my own jackd wrapper script to get jack started. Just like the other times that I went through this tutorial, I get to this point and say \"now what?\"",[11,11226,11227],{},"There are two different directions to explore. I have the REPL working, but it would be nice to be able to execute from a file and also do some interactive editing via Vim (or Emacs I suppose). The other path is to ... you know ... make some music (er... noise).",[11,11229,11230],{},"So I go on a reading spree. Things I learn:",[205,11232,11233,11242,11262,11265],{},[208,11234,11235,11236,11241],{},"There is a neat ",[136,11237,11240],{"href":11238,"rel":11239},"https:\u002F\u002Fgithub.com\u002Fovertone\u002Fovertone\u002Fraw\u002Fmaster\u002Fdocs\u002Fcheatsheet\u002Fovertone-cheat-sheet.pdf",[140],"Cheat Sheet",". But I don't know how to work it.",[208,11243,11244,11245,11250,11251],{},"Read a bit about ",[136,11246,11249],{"href":11247,"rel":11248},"https:\u002F\u002Fgithub.com\u002Fovertone\u002Fovertone\u002Fwiki\u002FMetronome-and-sequencing",[140],"Sequencing"," on the wiki. Learned:\n",[205,11252,11253,11256,11259],{},[208,11254,11255],{},"You can grab samples from freesounds, like: (def kick (sample (freesound-path 2086)))",[208,11257,11258],{},"You can then play that with (kick). Fun!",[208,11260,11261],{},"Something that I read before -- you kinda schedule sounds out in the future a bit. Think I saw that on a video",[208,11263,11264],{},"The main README references some video tutorials, I'm going to check them out",[208,11266,11267,11272],{},[136,11268,11271],{"href":11269,"rel":11270},"http:\u002F\u002Fskillsmatter.com\u002Fpodcast\u002Fscala\u002Fclojurex-unpanel-2894",[140],"skillsmatter clojurex unpanel",[205,11273,11274,11277,11280],{},[208,11275,11276],{},"Nice! Shows some dubstep type noise to make during a 20 minute workshop",[208,11278,11279],{},"Mentions here as I've seen elsewhere: definst uses macros to send synths to supercollider, so only a specific set of things are OK in there (not arbitrary expressions)",[208,11281,11282],{},"Shows how to sequence things a bit",{"title":156,"searchDepth":157,"depth":157,"links":11284},[],"2013-12-25T01:26-05:00",{},"\u002Ftlt-2013.12.22-overtone-adventures-1",{"title":11211,"description":10799},"TLT - 2013.12.22 - Overtone Adventures 1",[169],"q2KLuYXtC9IHzY9kzV-7dHGtBrijvhwFo5_LoKFlaaI",{"id":11293,"title":11294,"body":11295,"createdAt":11314,"description":11315,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11316,"navigation":164,"path":11317,"seo":11318,"stem":11319,"tags":11320,"updatedAt":11314,"__hash__":11321},"content\u002FTLT - 2013.02.06 - DC-Baltimore Perl Workshop 2013.md","TLT_-_2013.02.06_-_DC-Baltimore_Perl_Workshop_2013",{"type":8,"value":11296,"toc":11312},[11297],[11,11298,11299,11300,11305,11306,11311],{},"I just wrote up a call-for-people post about the ",[136,11301,11304],{"href":11302,"rel":11303},"http:\u002F\u002Fdcbpw.org\u002F",[140],"DC-Baltimore Perl Workshop"," over at ",[136,11307,11310],{"href":11308,"rel":11309},"http:\u002F\u002Fblogs.perl.org\u002Fusers\u002Fawwaiid_brock_wilcox\u002F2013\u002F02\u002Fdc-baltimore-perl-workshop-2013---presenters-wanted.html",[140],"blogs.perl.org",". I say it all there -- but in a nutshell, come and join us! :)",{"title":156,"searchDepth":157,"depth":157,"links":11313},[],"2013-02-06T20:50-05:00","I just wrote up a call-for-people post about the DC-Baltimore Perl Workshop over at blogs.perl.org. I say it all there -- but in a nutshell, come and join us! :)",{},"\u002Ftlt-2013.02.06-dc-baltimore-perl-workshop-2013",{"title":11294,"description":11315},"TLT - 2013.02.06 - DC-Baltimore Perl Workshop 2013",[169],"ur6oc_zbKAuMyhF1WOVlFQ3wKvHXqprNlR-FbwxPz4Q",{"id":11323,"title":11324,"body":11325,"createdAt":11393,"description":11329,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11394,"navigation":164,"path":11395,"seo":11396,"stem":11397,"tags":11398,"updatedAt":11399,"__hash__":11400},"content\u002FTLT - 2012.09.09 - The Flooding of Bath.md","TLT_-_2012.09.09_-_The_Flooding_of_Bath",{"type":8,"value":11326,"toc":11391},[11327,11330,11339,11342,11345,11348,11351,11354,11357,11360,11363,11366,11369,11378],[11,11328,11329],{},"Tags: Vacation, Flood, Rental Car, Rain",[11,11331,11332,11333,11338],{},"For Labor Day weekend (last week), Beth and I took off from work on Friday, rented a car, and headed out to ",[136,11334,11337],{"href":11335,"rel":11336},"http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBerkeley_Springs",[140],"Berkeley Springs, WV"," - aka \"Bath\". Nice drive up there, only a few hours away from DC. We've been around there before, and this time we decided to stay in-town so we could park our car and walk around more than we have in the past. We stayed on the top floor of a Bed & Breakfast downtown.",[11,11340,11341],{},"Saturday was a rainy day. We wandered about, looked at some junk shops, had lunch, took a long nap. I kept waking up to booming rolling thunder, but felt safe and cozy. Once we were up and about there was this weird siren that kept going off (sounded like an air raid) -- the inn keeper told me that it was their fire department and all-purpose alarm, and that it's not a big deal.",[11,11343,11344],{},"We headed to dinner and there was some noticeable water in gutters. But we only were walking a block down the road, so no real worries. The wait staff seemed a bit... off. Nervous and stressed, I'd say. We heard them start telling people who came in after us that they needed to order quickly because they were shutting down the kitchen. Specifically because of water building up behind their building and starting to come into the kitchen! No fun. So we finished quickly and boogied out of there.",[11,11346,11347],{},"Water had gotten quite a bit deeper in the street... and as we were walking back to the B&B fire trucks started to park diagonally across the road, and firemen jumped out and started directing traffic away. They were shutting down the whole road! And no wonder... the water kept rising.",[587,11349],{"src":11350},"\u002Fimg\u002Fberkeley_flooded_street_2012.jpg",[11,11352,11353],{},"Walking in, the innkeeper told us that we should go out back and consider moving our car. And... that was an understatement. I should have taken photos, but I was too busy deciding what to do. Water was up to the baseboards. I waded out -- water up to my knees! -- and moved the car. Water sloshed into the floorboards, and even though I moved the car to higher ground, I still had to go back and scoop water out. Ick!",[11,11355,11356],{},"Well, water was quickly rising and was even threatening to broach the B&B porch itself, which holds their outdoor restaurant and wine bar. After hanging out a bit longer we decided it was best for us to just abandon this whole scene. We packed up and drove back to DC. As soon as we left the road cleared and the rain stopped. It was a nice drive back to DC, and we were back in our apartment by 10:00pm. Whew! Sunday was stressful returning of a water-damaged car... and we were very pleased to have Monday to just relax :)",[587,11358],{"src":11359},"\u002Fimg\u002Fberkeley_flood_highwater_2012.jpg",[11,11361,11362],{},"Here is the high-water mark in the park. The water \"only\" went up to my knees out on the street, but in the park it was quite a bit deeper.",[587,11364],{"src":11365},"\u002Fimg\u002Fberkeley_flood_pool_2012.jpg",[11,11367,11368],{},"I unfortunately didn't get a before-photo of the pool... but it was a beautiful clean blue.",[11,11370,11371,11372,11377],{},"They say that this was a ",[136,11373,11376],{"href":11374,"rel":11375},"http:\u002F\u002Fwww.journal-news.net\u002Fpage\u002Fcontent.detail\u002Fid\u002F584006\u002FDamage-assessed-after-Berkeley-S---.html",[140],"100-Year Flood","! So I guess we shouldn't worry about going back to try again :)",[11,11379,11380,11381,6342,11386,449],{},"(Images courtesy of ",[136,11382,11385],{"href":11383,"rel":11384},"http:\u002F\u002Fwww.huffingtonpost.com\u002F2012\u002F09\u002F02\u002Fdc-flooding-submerged-cars_n_1851060.html",[140],"The Huffington Post",[136,11387,11390],{"href":11388,"rel":11389},"http:\u002F\u002Fwww.herald-mail.com\u002Fnews\u002Fphoto-galleries\u002Fhm-berkeley-springs-flood-20120902,0,1532681.photogallery",[140],"herald-mail.com",{"title":156,"searchDepth":157,"depth":157,"links":11392},[],"2012-09-09T19:31-04:00",{},"\u002Ftlt-2012.09.09-the-flooding-of-bath",{"title":11324,"description":11329},"TLT - 2012.09.09 - The Flooding of Bath",[169],"2012-09-09T19:35-04:00","n-WWrCh9UPF4yPnS3aujyaH8ZRGlpoHEbXeW1WKULZU",{"id":11402,"title":11403,"body":11404,"createdAt":11427,"description":11428,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11429,"navigation":164,"path":11430,"seo":11431,"stem":11432,"tags":11433,"updatedAt":11427,"__hash__":11434},"content\u002FTLT - 2012.08.28 - Code Comments, Yo.md","TLT_-_2012.08.28_-_Code_Comments,_Yo",{"type":8,"value":11405,"toc":11425},[11406,11412,11415,11422],[11,11407,11408,11409,11411],{},"I've traditionally thought of code comments as having two audiences. One audience is me, or whomever will be taking over the code after me. This consists of notes or hints as to what I was thinking when I wrote something. Typically these are regular code comments, possibly right on the end of a line. The second audience is the users of my code. Usually this is other programmers, in the case of a library (as opposed to the consumer of a resulting UI, which I guess is a sort of third non-engineer audience who doesn't read ",[20,11410,194],{}," comments). This second group is the one for which you typically use POD (or similar in other languages - javadoc).",[11,11413,11414],{},"Increasingly, however, I have decided to act as though there is only one audience. When you separate code out the way I describe above, you immediately run into a question -- what do you do for a private method? You don't expect the users of your library to call it, and yet you might have some high-level usage guide that goes beyond what you might put in an inline comment. Same thing for private instance variables, or other internal helper functions.",[11,11416,11417,11418,11421],{},"I've also noticed that I have two different sets of code that I write, and for each there is ultimately one audience. The first is at work. Here I am writing code that my peers will use. But my peers will also ",[20,11419,11420],{},"maintain"," the code itself. Similarly, I also write code for open-source projects. For the most part my code here will be consumed - but if and when I do actually get contributions to the library, the contributors are the consumers first and contributors second. They are pretty much exactly like the people at my work.",[11,11423,11424],{},"So I've settled on physically organizing my code into two sections, but using POD (or similar) for all of the usage or explanation-centric comments, and I treat my reader as a single audience. I put the public API methods all together, and notate them as a single section in my code, perhaps with a preamble with an example usage. I then put all of the private methods together, with a header that marks them as private -- but then I document them as if they were public. Because no matter what, from the perspective of the code IN my library, they ARE public.",{"title":156,"searchDepth":157,"depth":157,"links":11426},[],"2012-08-29T07:04-04:00","I've traditionally thought of code comments as having two audiences. One audience is me, or whomever will be taking over the code after me. This consists of notes or hints as to what I was thinking when I wrote something. Typically these are regular code comments, possibly right on the end of a line. The second audience is the users of my code. Usually this is other programmers, in the case of a library (as opposed to the consumer of a resulting UI, which I guess is a sort of third non-engineer audience who doesn't read code comments). This second group is the one for which you typically use POD (or similar in other languages - javadoc).",{},"\u002Ftlt-2012.08.28-code-comments-yo",{"title":11403,"description":11428},"TLT - 2012.08.28 - Code Comments, Yo",[169],"DhmXQKwbfVlq93A5sMWVU9lxkX8cJWFMEfMkC473_Mg",{"id":11436,"title":11437,"body":11438,"createdAt":11472,"description":11473,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11474,"navigation":164,"path":11475,"seo":11476,"stem":11477,"tags":11478,"updatedAt":11479,"__hash__":11480},"content\u002FTLT - 2012.08.20 - First Day in CS440.md","TLT_-_2012.08.20_-_First_Day_in_CS440",{"type":8,"value":11439,"toc":11470},[11440,11461],[11,11441,11442,11443,11448,11449,11454,11455,11460],{},"I'm watching the first video for the ",[136,11444,11447],{"href":11445,"rel":11446},"http:\u002F\u002Fwww.cs.colostate.edu\u002F~anderson\u002Fcs440\u002Findex.html",[140],"CSU CS440 Intro to AI"," class, taught by ",[136,11450,11453],{"href":11451,"rel":11452},"http:\u002F\u002Fwww.cs.colostate.edu\u002F~anderson\u002F",[140],"Chuck Anderson",". Man... so far this looks great. In addition to delicious shout outs to Turing and Hume and so on, tossed out a reference to the ",[136,11456,11459],{"href":11457,"rel":11458},"http:\u002F\u002Fxkcd.com\u002F632\u002F",[140],"XKCD"," take on some AI concepts. Did I mention that we are using a wiki rather than WebCT as our primary interaction point? hmm!",[11,11462,11463,11464,11469],{},"I haven't seen the video for the ",[136,11465,11468],{"href":11466,"rel":11467},"http:\u002F\u002Fwww.cs.colostate.edu\u002F~ghosh\u002Fcourses\u002Fcs414-f12\u002Fyr2012fa\u002F",[140],"CSU CS414 Object-Oriented Programming"," course.",{"title":156,"searchDepth":157,"depth":157,"links":11471},[],"2012-08-20T21:22-04:00","I'm watching the first video for the CSU CS440 Intro to AI class, taught by Chuck Anderson. Man... so far this looks great. In addition to delicious shout outs to Turing and Hume and so on, tossed out a reference to the XKCD take on some AI concepts. Did I mention that we are using a wiki rather than WebCT as our primary interaction point? hmm!",{},"\u002Ftlt-2012.08.20-first-day-in-cs440",{"title":11437,"description":11473},"TLT - 2012.08.20 - First Day in CS440",[169],"2012-08-20T21:24-04:00","rnZzM3ZtKq0PD_j69K5If5dLf7yii56bjXNhSN7-QgI",{"id":11482,"title":11483,"body":11484,"createdAt":11533,"description":11534,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11535,"navigation":164,"path":11536,"seo":11537,"stem":11538,"tags":11539,"updatedAt":11533,"__hash__":11540},"content\u002FTLT - 2012.07.10 - Hi Eliza.md","TLT_-_2012.07.10_-_Hi_Eliza",{"type":8,"value":11485,"toc":11531},[11486,11492,11495,11498,11504,11510,11513,11519,11522,11525,11528],[11,11487,11488,11489,11491],{},"Eliza: I am the psychotherapist.  Please, describe your problems.  Each time",[461,11490],{},"\nyou are finished talking, type RET twice.",[11,11493,11494],{},"Me: My friend Mike doesn't know who you are.",[11,11496,11497],{},"Eliza: Why do you say that?",[11,11499,11500,11501,11503],{},"Me: Because I mentioned you and he said that he hasn't heard of you. Asked",[461,11502],{},"\nme if you were some sort of reference.",[11,11505,11506,11507,11509],{},"Eliza: Is it because you mentioned me and he said that he has not heard of I",[461,11508],{},"\nasked you if I was some sort of reference that you came to me?",[11,11511,11512],{},"Me: Yes, exactly!",[11,11514,11515,11516,11518],{},"Eliza: Earlier you said you mentioned me and he said that he has not heard of",[461,11517],{},"\nI asked you if I was some sort of reference?",[11,11520,11521],{},"Me: Right. Because a lot of lore from the '80s came from you.",[11,11523,11524],{},"Eliza: Does it bother you that a lot of lore from the '80s came from me?",[11,11526,11527],{},"Me: No, I rather enjoy it.",[11,11529,11530],{},"Eliza: Maybe your plans have something to do with this.",{"title":156,"searchDepth":157,"depth":157,"links":11532},[],"2012-07-10T12:20-04:00","Eliza: I am the psychotherapist.  Please, describe your problems.  Each time\nyou are finished talking, type RET twice.",{},"\u002Ftlt-2012.07.10-hi-eliza",{"title":11483,"description":11534},"TLT - 2012.07.10 - Hi Eliza",[169],"ZOhp_e1VLCmz7MZkTtqc9I7d40-QR20b88AljOJacow",{"id":11542,"title":11543,"body":11544,"createdAt":11606,"description":11548,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11607,"navigation":164,"path":11608,"seo":11609,"stem":11610,"tags":11611,"updatedAt":11612,"__hash__":11613},"content\u002FTLT - 2011.10.11 - PPW 2011 Wrap-Up.md","TLT_-_2011.10.11_-_PPW_2011_Wrap-Up",{"type":8,"value":11545,"toc":11604},[11546,11549,11558,11561,11564,11595],[11,11547,11548],{},"Tags: Perl, PPW, Conference",[11,11550,11551,11552,11557],{},"This weekend I attended ",[136,11553,11556],{"href":11554,"rel":11555},"http:\u002F\u002Fpghpw.org\u002Fppw2011\u002F",[140],"PPW2011"," - I think this is my 3rd PPW, and my fourth perl conference in Pittsburgh (YAPC::NA 2009 was there).",[11,11559,11560],{},"The theme this year was \"DevOps\", and I think maybe that was not quite to my taste (though does seem practical). I like talks that push my understanding and stretch my mind, whereas the talks tended toward solid best practices for corporate environments. I gave a talk on debugging, and I even feel that my own talk went that way a bit :)",[11,11562,11563],{},"Favorite talks:",[205,11565,11566,11573,11580,11588],{},[208,11567,11568],{},[136,11569,11572],{"href":11570,"rel":11571},"http:\u002F\u002Fpghpw.org\u002Fppw2011\u002Ftalk\u002F3502",[140],"Postmodern Module Packaging",[208,11574,11575],{},[136,11576,11579],{"href":11577,"rel":11578},"http:\u002F\u002Fpghpw.org\u002Fppw2011\u002Ftalk\u002F3803",[140],"Running an online game",[208,11581,11582,11587],{},[136,11583,11586],{"href":11584,"rel":11585},"http:\u002F\u002Fpghpw.org\u002Fppw2011\u002Ftalk\u002F3878",[140],"Mo is Less"," (lightning)",[208,11589,11590],{},[136,11591,11594],{"href":11592,"rel":11593},"http:\u002F\u002Fpghpw.org\u002Fppw2011\u002Ftalk\u002F3861",[140],"A Dominus Chrestomathy",[11,11596,11597,11598,11603],{},"That last one was a set of mini-talks by Mark-Jason Dominus, which included one of my all-time favorites, ",[136,11599,11602],{"href":11600,"rel":11601},"http:\u002F\u002Fperl.plover.com\u002Fyak\u002Fdebruijn\u002F",[140],"Debugging the de Bruijn Sequence",". Highly recommended!",{"title":156,"searchDepth":157,"depth":157,"links":11605},[],"2011-10-11T20:05-04:00",{},"\u002Ftlt-2011.10.11-ppw-2011-wrap-up",{"title":11543,"description":11548},"TLT - 2011.10.11 - PPW 2011 Wrap-Up",[169],"2011-10-16T09:09-04:00","oJ2v0J6Ws99ckGzg1jZPJmi-IyOC63TSwjcNBgqNXZw",{"id":11615,"title":11616,"body":11617,"createdAt":11676,"description":11621,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11677,"navigation":164,"path":11678,"seo":11679,"stem":11680,"tags":11681,"updatedAt":11612,"__hash__":11682},"content\u002FTLT - 2011.08.07 - DC Perl Mongers August 2011 Meeting.md","TLT_-_2011.08.07_-_DC_Perl_Mongers_August_2011_Meeting",{"type":8,"value":11618,"toc":11674},[11619,11622,11631,11634,11640,11643,11646,11652,11655,11662,11668,11671],[11,11620,11621],{},"Tags: Perl, DCPM, Programming",[11,11623,11624,11625,11630],{},"Last Tuesday was our monthly ",[136,11626,11629],{"href":11627,"rel":11628},"http:\u002F\u002Fdc.pm.org",[140],"DC Perl Mongers"," meeting.",[11,11632,11633],{},"We dove right in, talking about how perl caches various values for a variable to be used in different contexts. So, for example, let's say you start off with a number, but then use it in string context, perl will cache both the string and the number. This can be shown using cpan:Devel::Peek like this:",[605,11635,11638],{"className":11636,"code":11637,"language":1288},[1286],"main:001:0> use Devel::Peek\nmain:002:0> my $x = \"34\"\n34\nmain:003:0> Dump($x)\nSV = PV(0xb22d558) at 0xb237290\n  REFCNT = 2\n  FLAGS = (POK,pPOK)\n  PV = 0xb249458 \"34\"\\0\n  CUR = 2\n  LEN = 4\n",[194,11639,11637],{"__ignoreMap":156},[11,11641,11642],{},"I often use cpan:Devel::REPL at meetings so that we can interactively explore things as a group, which is what I'm doing here.",[11,11644,11645],{},"The first time we dump $x, you can see it has a \"PV\" which holds the string \"34\". But after we use it in a number context, adding 17 to it, you can see that the dump shows both the original string version, and a new \"IV\" containing the integer version:",[605,11647,11650],{"className":11648,"code":11649,"language":1288},[1286],"main:004:0> $x + 17\n51\nmain:005:0> Dump($x)\nSV = PVIV(0xa0fe6b8) at 0xb237290\n  REFCNT = 2\n  FLAGS = (IOK,POK,pIOK,pPOK)\n  IV = 34\n  PV = 0xb249458 \"34\"\\0\n  CUR = 2\n  LEN = 4\n",[194,11651,11649],{"__ignoreMap":156},[11,11653,11654],{},"So this, as far as I know, is mainly an efficiency hack that perl does, the theory being that if you used it once in string context or number context or whatever, maybe you'll do it again.",[11,11656,11657,11658,11661],{},"Very quickly the question came up as to what happens when you ",[1030,11659,11660],{},"change"," $x, and how does perl know what cached values to trust. Well that's where the 'FLAGS' part of the SV dump comes in. It shows which of the cached values are OK to use. So when we increment $x numerically:",[605,11663,11666],{"className":11664,"code":11665,"language":1288},[1286],"main:006:0> $x++\n34\nmain:007:0> Dump($x)\nSV = PVIV(0xa0fe6b8) at 0xb237290\n  REFCNT = 2\n  FLAGS = (IOK,pIOK)\n  IV = 35\n  PV = 0xb249458 \"34\"\\0\n  CUR = 2\n  LEN = 4\n",[194,11667,11665],{"__ignoreMap":156},[11,11669,11670],{},"The flags have been trimmed down. I don't remember what all the flags mean, but you can look at perlguts or other docs for that :) . Notice that the string version of the original \"34\" is still there! Perl doesn't waste time erasing it. Instead, if string context is used again a new cached value will overwrite the existing one.",[11,11672,11673],{},"Well that was surely a good start to the meeting :)",{"title":156,"searchDepth":157,"depth":157,"links":11675},[],"2011-08-07T11:25-04:00",{},"\u002Ftlt-2011.08.07-dc-perl-mongers-august-2011-meeting",{"title":11616,"description":11621},"TLT - 2011.08.07 - DC Perl Mongers August 2011 Meeting",[169],"K4VDIEk4Xbeh3SMQM_acOrYLcLQLUoK0nwbcGPBVxpc",{"id":11684,"title":11685,"body":11686,"createdAt":11773,"description":11690,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11774,"navigation":164,"path":11775,"seo":11776,"stem":11777,"tags":11778,"updatedAt":11779,"__hash__":11780},"content\u002FTLT - 2011.04.07 - Funky Function Filters in Perl6.md","TLT_-_2011.04.07_-_Funky_Function_Filters_in_Perl6",{"type":8,"value":11687,"toc":11771},[11688,11691,11699,11702,11708,11711,11717,11720,11726,11729,11732,11738,11741,11747,11750,11756,11759,11765,11768],[11,11689,11690],{},"Tags: Perl6, Rakudo, Programming",[11,11692,11693,11694,11698],{},"A while back I wrote about ",[136,11695,11697],{"href":11696},"\u002Ftlt-2006.03.03-funky-function-filters","TLT - 2006.03.03 - Funky Function Filters",". Let me refresh your memory - we have a Python and a Ruby snippet and we translate it into Perl5. The code is a toy to show some fancy shmancy lambda (unnamed functions) usage. The idea is to take a list of functions, filter them, and then with the remaining ones show what happens with parameters from -10 to 10.",[11,11700,11701],{},"Python example:",[605,11703,11706],{"className":11704,"code":11705,"language":1288},[1286],"for f in filter(lambda f: f(-1)>=f(1),\n                [lambda x:x, lambda x:x**2, lambda x:x**3]):\n    for x in range(-10, 11):\n        print x, f(x)\n",[194,11707,11705],{"__ignoreMap":156},[11,11709,11710],{},"Ruby translation:",[605,11712,11715],{"className":11713,"code":11714,"language":1288},[1286],"for f in [lambda { |x| x }, lambda { |x| x**2 }, lambda { |x| x**3 }\n         ].select { |f| f.call(-1) >= f.call(1) }\n    for x in -10..10\n        print x, f.call(x)\n    end\nend\n",[194,11716,11714],{"__ignoreMap":156},[11,11718,11719],{},"My perl5 translation:",[605,11721,11724],{"className":11722,"code":11723,"language":1288},[1286],"for my $f (grep { $_->(-1) >= $_->(1) }\n        ((sub{shift}, sub{(shift)**2}, sub{(shift)**3})) {\n  for my $x (-10..10) {\n    print \"$x: \",$f->($x),\"\\n\";\n  }\n}\n",[194,11725,11723],{"__ignoreMap":156},[11,11727,11728],{},"Today I thought I'd give a stab at a perl6 translation (using the 2011.01 Rakudo Star release). I started with a straightforward translation from the perl5, then switched to perl6 idioms.",[11,11730,11731],{},"Perl6 translation:",[605,11733,11736],{"className":11734,"code":11735,"language":1288},[1286],"for (* ** 1, * ** 2, * ** 3).grep({ $_.(-1) >= $_.(1) }) -> $f {\n  for -10 .. 10 -> $x {\n    say \"$x: { $f.($x) }\"\n  }\n}\n",[194,11737,11735],{"__ignoreMap":156},[11,11739,11740],{},"The first line is a doozy! This is similar in some ways to the perl5 translation, though the grep now shows up on the righthand-side of the list like in Ruby. The biggest difference to me is in the list of lambdas:",[605,11742,11745],{"className":11743,"code":11744,"language":1288},[1286],"(* ** 1, * ** 2, * ** 3)\n",[194,11746,11744],{"__ignoreMap":156},[11,11748,11749],{},"I mean... what does THAT mean?! Let's take the last one, \"* ** 3\". Translated into English:",[605,11751,11754],{"className":11752,"code":11753,"language":1288},[1286],"Whatever to-the-power-of 3\n",[194,11755,11753],{"__ignoreMap":156},[11,11757,11758],{},"Wait wait... \"whatever\"? The Whatever-Star is a fancy thing from perl6 that took me a while to work out, and there may still be some nuances that I'm missing. In this context it magically makes a closure... er... lambda, that takes one parameter which it puts where you see the '*'.",[605,11760,11763],{"className":11761,"code":11762,"language":1288},[1286],"# Whatever-Star notation\n* ** 3\n\n# Pointy-block notation\n-> $x { $x ** 3 }\n\n# Subref notation\nsub ($x) { $x ** 3 }\n",[194,11764,11762],{"__ignoreMap":156},[11,11766,11767],{},"(Note: that last one should be SLURPY! But I don't know how to do that apparently)",[11,11769,11770],{},"Enjoy... Whatever!",{"title":156,"searchDepth":157,"depth":157,"links":11772},[],"2011-04-07T17:51-04:00",{},"\u002Ftlt-2011.04.07-funky-function-filters-in-perl6",{"title":11685,"description":11690},"TLT - 2011.04.07 - Funky Function Filters in Perl6",[169],"2011-10-16T09:08-04:00","fzAeoLy0nvQgJVc63u-iu0oAuO86sesdXfYeIsoNCsY",{"id":11782,"title":11783,"body":11784,"createdAt":11870,"description":11690,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11871,"navigation":164,"path":11872,"seo":11873,"stem":11874,"tags":11875,"updatedAt":11870,"__hash__":11876},"content\u002FTLT - 2011.03.13 - Wishing on a Whatever Star.md","TLT_-_2011.03.13_-_Wishing_on_a_Whatever_Star",{"type":8,"value":11785,"toc":11868},[11786,11788,11791,11797,11804,11807,11810,11813,11816,11819,11822,11828,11831,11837,11840,11846,11849,11852,11861,11863],[11,11787,11690],{},[11,11789,11790],{},"The \"Whatever-Star\" was at first alarming to me! I first noticed it when I learned how to shuffle an entire list. The Whatever-Star can do some other stuff, too. But that's ok, we'll start with this.",[605,11792,11795],{"className":11793,"code":11794,"language":1288},[1286],"my @shuffled = \u003C alice bob carol dave erik frank >.pick(*);\n",[194,11796,11794],{"__ignoreMap":156},[11,11798,11799,11800,11803],{},"Now... in the past I've tried \".pick(1)\" which gets me one name at random. Then \".pick(2)\" will give me two, and not repeat. If I put in too many then it'll only give me back what it can, in this case all six names. But \".pick(",[20,11801,11802],{},")\" ... that doesn't even look valid! The documentation says (though I can't recall where) that it is the same as \".pick(Inf)\". When I picked more than there were, it stopped when there was nothing to pick. So this makes sense... try to pick an infinite number and we'll just get them all. Nice. Still kinda weird about the '","' though.",[11,11805,11806],{},"So then I, mistakenly, thought that maybe \"pick\" was special. Maybe they hooked the parser up so that it could, like, \"know\" that pick could be passed this '*', which I learned is named \"Whatever\". I couldn't have been closer to the truth! Except without the \"special\" bit. Time to do a bit of exploring!",[11,11808,11809],{},"Let's try to figure out how this works without resorting to such tedious things as reading documentation, source code, or IRC, shall we? RTFM my eye. If pick is special, then I shouldn't be able to add something that behaves similarly. Wait, let's do this formal like.",[11,11811,11812],{},"THEOREM: (1,2,3,4).pick(*) is somehow special, and can't be replicated without modifying the compiler.",[11,11814,11815],{},"PROOF:",[11,11817,11818],{},"Let's start by assuming that it is NOT special, and attempt to do a proof-by-contradiction (constructivists be damned�). Then we should be able to create our own method that can behave specially when '*' is passed.",[11,11820,11821],{},"First, what class is .pick(*) working on, anyway? Let's ask rakudo.",[605,11823,11826],{"className":11824,"code":11825,"language":1288},[1286],"> (1,2,3,4,5).WHAT\nParcel()\n",[194,11827,11825],{"__ignoreMap":156},[11,11829,11830],{},"Parcel. OK, whatever that is. So all we gotta do is slap a new method on there and see what we get. (google... google... irc... (yes, contrary to the overall anti-research basis. But it's ok because we're in parenthesis)). OK, here we go.",[605,11832,11835],{"className":11833,"code":11834,"language":1288},[1286],"> use MONKEY_TYPING; augment class Parcel { method yo($x) { say \"I like to eat $x.\" } }\n!class_init_384\n> (1,2,3,4,5).yo('fishies')\nI like to eat fishies.\n",[194,11836,11834],{"__ignoreMap":156},[11,11838,11839],{},"Well that was easy :) . Now for the BIG TEST!",[605,11841,11844],{"className":11842,"code":11843,"language":1288},[1286],"> (1,2,3,4,5).yo(*)\nI like to eat Whatever()\u003C0xb2f5a7c>.\n",[194,11845,11843],{"__ignoreMap":156},[11,11847,11848],{},"OMG it worked! So I actually get a parameter, and it is an instance of Whatever. Well then.",[11,11850,11851],{},"THEOREM DISPROVED.",[11,11853,11854,11855,11860],{},"I then decided to actually cast about for how things use this. Here's a great example, the ",[136,11856,11859],{"href":11857,"rel":11858},"https:\u002F\u002Fgithub.com\u002Frakudo\u002Frakudo\u002Fblob\u002Fmaster\u002Fsrc\u002Fcore\u002FAny-list.pm#L190",[140],"Rakudo Any-list pick whatever implementation",". You can see that they use multi-methods to easily deal with the Whatever case separately from other passed values.",[15,11862],{},[11,11864,11865,11867],{},[39,11866,4248],{}," I actually like constructivists, and welcome a constructive version of this non-proof.",{"title":156,"searchDepth":157,"depth":157,"links":11869},[],"2011-03-13T11:05-04:00",{},"\u002Ftlt-2011.03.13-wishing-on-a-whatever-star",{"title":11783,"description":11690},"TLT - 2011.03.13 - Wishing on a Whatever Star",[169],"AstGsdfJE2_ukaqyYPSagKrlliYZIDCGdM0yE-AsGX0",{"id":11878,"title":11879,"body":11880,"createdAt":11914,"description":11884,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11915,"navigation":164,"path":11916,"seo":11917,"stem":11918,"tags":11919,"updatedAt":11920,"__hash__":11921},"content\u002FTLT - 2011.03.12 - Filter Rocking.md","TLT_-_2011.03.12_-_Filter_Rocking",{"type":8,"value":11881,"toc":11912},[11882,11885,11894,11909],[11,11883,11884],{},"Tags: Coffee, Music",[11,11886,11887,11888,11893],{},"On my way to Safeway, I stopped in at ",[136,11889,11892],{"href":11890,"rel":11891},"http:\u002F\u002Fwww.filtercoffeehouse.com\u002F",[140],"Filter Coffee"," to see how they are doing. The nearby Safeway (The Secret Safeway) is closed, but this is still roughly on the way to The Soviet Safeway anyhow. A seat was open so down I plopped.",[11,11895,11896,11897,11902,11903,11908],{},"First they played the entire Rage Against The Machine, ",[136,11898,11901],{"href":11899,"rel":11900},"http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FThe_Battle_of_Los_Angeles_(album)",[140],"Battle of Los Angeles"," album, and now we're on to the Ramones with Blitzkrieg Bop. Sounds like they're going to play this ",[136,11904,11907],{"href":11905,"rel":11906},"http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FGreatest_Hits_(Ramones_album)",[140],"whole album"," too.",[11,11910,11911],{},"Good music, good mocha. Where was I on my way to again?",{"title":156,"searchDepth":157,"depth":157,"links":11913},[],"2011-03-12T16:16-05:00",{},"\u002Ftlt-2011.03.12-filter-rocking",{"title":11879,"description":11884},"TLT - 2011.03.12 - Filter Rocking",[169],"2011-03-12T16:36-05:00","ZVi7BQyNJ8AXonvDH-mvrUg5K39db3u3j7d_Y9DXNDw",{"id":11923,"title":11924,"body":11925,"createdAt":11940,"description":11929,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":11941,"navigation":164,"path":11942,"seo":11943,"stem":11944,"tags":11945,"updatedAt":11940,"__hash__":11946},"content\u002FTLT - 2010.11.16 - I Knew A Girl.md","TLT_-_2010.11.16_-_I_Knew_A_Girl",{"type":8,"value":11926,"toc":11938},[11927,11930],[11,11928,11929],{},"This song popped into my head today, and the muse took it all the way to a recording!",[11,11931,11932,444,11935,449],{},[440,11933],{"controls":164,"preload":442,"src":11934},"\u002Fdocs\u002Fmusic\u002Fi_knew_a_girl.mp3",[136,11936,448],{"download":11937,"external":156,"href":11934},"docs\u002Fmusic\u002Fi_knew_a_girl.mp3",{"title":156,"searchDepth":157,"depth":157,"links":11939},[],"2010-11-16T21:53-05:00",{},"\u002Ftlt-2010.11.16-i-knew-a-girl",{"title":11924,"description":11929},"TLT - 2010.11.16 - I Knew A Girl",[169],"GqGSlD14D9v9WVSBPPbjGsG8mAELMmvhifiNiIVyf_Q",{"id":11948,"title":11949,"body":11950,"createdAt":12005,"description":12006,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12007,"navigation":164,"path":12008,"seo":12009,"stem":12010,"tags":12011,"updatedAt":12005,"__hash__":12012},"content\u002FTLT - 2010.09.03 - DC Perl Mongers Rakudo Star Pizza Party.md","TLT_-_2010.09.03_-_DC_Perl_Mongers_Rakudo_Star_Pizza_Party",{"type":8,"value":11951,"toc":12003},[11952,11960,11963,11980,11992,12000],[11,11953,11954,11955,11959],{},"We're starting our usual monthly ",[136,11956,11629],{"href":11957,"rel":11958},"http:\u002F\u002Fdc.pm.org\u002F",[140]," meeting a bit early this Tuesday (September 7th) to have a little pizza and celebrate Rakudo-Star! Arrive at 6:30pm at the Starbucks at 18th and K Street NW (call me, Brock, if you miss us and need to be let in, number on the website) if you want food. But feel free to wander in any time thereafter, we usually stay as late as 10:00pm. We'll swoop down and look for people at the normal 7:30pm time too :)",[11,11961,11962],{},"Other activities:",[205,11964,11965,11968,11971,11974,11977],{},[208,11966,11967],{},"Bring your laptop!",[208,11969,11970],{},"Installing Rakudo-Star",[208,11972,11973],{},"Giving hands-on tutorials",[208,11975,11976],{},"Beginner and Advanced welcome!",[208,11978,11979],{},"Never been to DC.pm before? No problem, come have some free pizza!",[11,11981,11982,11983,11987,11988,11991],{},"Please put your name on ",[136,11984,11985],{"href":11985,"rel":11986},"http:\u002F\u002Fdc.pm.org\u002FRakudo-Star_Party",[140]," (or email the mailing list, which can be found at ",[136,11989,11957],{"href":11957,"rel":11990},[140],") so we know how much food to get.",[11,11993,11994,11995,11999],{},"If you have any questions, email the list or me directly -- ",[136,11996,11998],{"href":11997},"mailto:awwaiid@gmail.com","awwaiid@gmail.com"," will do :)",[11,12001,12002],{},"About Rakudo Star: \"Rakudo Star\" is a useful and usable distribution of Perl 6. Current releases are aimed at \"early adopters\" of Perl 6. We can tell you ALL about it when you arrive :)",{"title":156,"searchDepth":157,"depth":157,"links":12004},[],"2010-09-03T20:45-04:00","We're starting our usual monthly DC Perl Mongers meeting a bit early this Tuesday (September 7th) to have a little pizza and celebrate Rakudo-Star! Arrive at 6:30pm at the Starbucks at 18th and K Street NW (call me, Brock, if you miss us and need to be let in, number on the website) if you want food. But feel free to wander in any time thereafter, we usually stay as late as 10:00pm. We'll swoop down and look for people at the normal 7:30pm time too :)",{},"\u002Ftlt-2010.09.03-dc-perl-mongers-rakudo-star-pizza-party",{"title":11949,"description":12006},"TLT - 2010.09.03 - DC Perl Mongers Rakudo Star Pizza Party",[169],"Rq97jyk-MMvNTqQ7kliddgTi8omfoeUsNssHol9i7Qc",{"id":12014,"title":12015,"body":12016,"createdAt":12035,"description":12020,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12036,"navigation":164,"path":12037,"seo":12038,"stem":12039,"tags":12040,"updatedAt":12035,"__hash__":12041},"content\u002FTLT - 2010.08.15 - Chinese Spam.md","TLT_-_2010.08.15_-_Chinese_Spam",{"type":8,"value":12017,"toc":12033},[12018,12021,12024,12027,12030],[11,12019,12020],{},"Ever since I got my terminals and mutt all working well with international characters, I've been fascinated by the Chinese spam I get. First of all it looks neat to see in a terminal. But sometimes I throw it into google translate just to see what it is I'm getting spammed about, and every now and then it's mildly interesting. Take this for example:",[188,12022,12023],{},"\n任可一种管理绩效的产生，首先都是原于一种先进的管理理念。而任何一种先进的管理理念都必须有一种适合它的管理模式作为载体。人们似乎都很乐意去接受先进的理念，并且善于以最惊人的速度去传播。可是人们在践行的过程中得到的结果却是参差不齐。就象丰田的精益理念早就传遍了整个世界一样，而世界却始终未能复制出第二个“丰田”。这究竟是为什么呢？主要原因在于人们虽然已经接受了新的理念，却没有能够找到其精髓的所在。因此也就无法去设计一种适合自身需要的管理模式来作为载体\n",[11,12025,12026],{},"Which translates (probably very poorly since it is machine translation, but good enough for bloggin') to:",[188,12028,12029],{},"\nEither a management performance can be produced, first of all are the original in an advanced management concept. The possession of any advanced Management philosophy that it must have a suitable management model as a carrier. People seem very willing to accept advanced ideas And good at the most to spread at an alarming rate. But people in the course of practice the results obtained is mixed. On Like Toyota's lean philosophy had already spread throughout the world as the world has never been able to replicate the second \"Toyota.\" Is this why? Although the main reason is that people have accepted the new idea, but not able to find its essence Lies. Therefore will not be able to design a management model for their own needs as a carrier.\n",[11,12031,12032],{},"As someone who has been involved with companies who adopt Lean-like philosophies, I couldn't agree more!",{"title":156,"searchDepth":157,"depth":157,"links":12034},[],"2010-08-15T22:40-04:00",{},"\u002Ftlt-2010.08.15-chinese-spam",{"title":12015,"description":12020},"TLT - 2010.08.15 - Chinese Spam",[169],"J4lO3sLtwweSrWxpwilCL8kU2vW3vSfbiNkxXStmANM",{"id":12043,"title":12044,"body":12045,"createdAt":12191,"description":12049,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12192,"navigation":164,"path":12193,"seo":12194,"stem":12195,"tags":12196,"updatedAt":12191,"__hash__":12197},"content\u002FTLT - 2010.08.01 - OPW 2010.md","TLT_-_2010.08.01_-_OPW_2010",{"type":8,"value":12046,"toc":12189},[12047,12050,12053,12062,12177,12180,12183,12186],[11,12048,12049],{},"Tags: Perl, Programming, Conference",[11,12051,12052],{},"(er... Actually I meant to post this sometime back in like February 2010. Oh well!)",[11,12054,12055,12056,12061],{},"I attended the ",[136,12057,12060],{"href":12058,"rel":12059},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002F",[140],"Orlando Perl Workshop 2010"," and had a lovely time. The talks I attended were:",[205,12063,12064,12076,12088,12105,12117,12129,12141,12153,12165],{},[208,12065,12066,12071],{},[136,12067,12070],{"href":12068,"rel":12069},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002Ftalk\u002F2499",[140],"Stevan Little (stevan) - Untitled No. 12",[205,12072,12073],{},[208,12074,12075],{},"I only saw the end of this, so I can't really comment :) . It did mention Plack a bit.",[208,12077,12078,12083],{},[136,12079,12082],{"href":12080,"rel":12081},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002Ftalk\u002F2476",[140],"Shawn Moore (Sartak) - Surviving in the Cruel, Unforgiving World",[205,12084,12085],{},[208,12086,12087],{},"A discussion of his (and other's) nethack bot, including some discussion of the internals and some strategy lessons.",[208,12089,12090,12095],{},[136,12091,12094],{"href":12092,"rel":12093},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002Ftalk\u002F2509",[140],"Tatsuhiko Miyagawa (miyagawa) - Plack: State of the art web framework superglue",[205,12096,12097],{},[208,12098,12099,12100,797],{},"Introduction to Plack, you know, a neat layer to interface ",[136,12101,12104],{"href":12102,"rel":12103},"http:\u002F\u002Fplackperl.org\u002F",[140],"Perl and a Web Server",[208,12106,12107,12112],{},[136,12108,12111],{"href":12109,"rel":12110},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002Ftalk\u002F2477",[140],"Cory Watson (gphat) - From Zero to CPAN: Adding A New Product Search to Magazines.com",[205,12113,12114],{},[208,12115,12116],{},"Both a discussion of search indexing via Solr, and talked about how he put some of the more generic libraries they used up on CPAN. This one is most likely to impact my day-job.",[208,12118,12119,12124],{},[136,12120,12123],{"href":12121,"rel":12122},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002Ftalk\u002F2510",[140],"Lucas Oman (lucas) - Roles in PHP?",[205,12125,12126],{},[208,12127,12128],{},"Yep, Lucas got roles of a sort working in PHP. But the syntax is a bit ugly. Cool anyway though.",[208,12130,12131,12136],{},[136,12132,12135],{"href":12133,"rel":12134},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002Ftalk\u002F2483",[140],"Dylan Hardison - How to Debianize a CPAN Dist",[205,12137,12138],{},[208,12139,12140],{},"I'm hoping to maemo-ize some stuff, which is a lot like Debianizing it... so this was handy.",[208,12142,12143,12148],{},[136,12144,12147],{"href":12145,"rel":12146},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002Ftalk\u002F2497",[140],"Marty Pauley (maokt) - Perl can be FUN(ctional)",[205,12149,12150],{},[208,12151,12152],{},"Fun stuff about closures and functionally things ala Higher Order Perl",[208,12154,12155,12160],{},[136,12156,12159],{"href":12157,"rel":12158},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002Ftalk\u002F2466",[140],"Matt S Trout (mst) - The Troll, the God and the Mountain",[205,12161,12162],{},[208,12163,12164],{},"Epic! Ultimately about Collection Management tools (which is an expansion of ORM more or less) that are in the works.",[208,12166,12167,12172],{},[136,12168,12171],{"href":12169,"rel":12170},"http:\u002F\u002Fperloasis.org\u002Fopw2010\u002Ftalk\u002F2463",[140],"Mark Keating (mdk\u002Fmarkie) - Keynote: The awful things we all must do and the most disgusting word you'll hear",[205,12173,12174],{},[208,12175,12176],{},"A pep talk for the community to do some good Perl Marketing!",[11,12178,12179],{},"And... I got to see aligators! Well... things that looked like them anyway.",[11,12181,12182],{},"(insert photo here)",[11,12184,12185],{},"My whirlwind trip wasn't too stressful, as it turned out. I hung out mostly with Sartak and Miyagawa, and made lots of progress on cpan:Continuity::Adapt::PSGI. Lots of side-discussion on all sorts of things too, of course.",[11,12187,12188],{},"It was a good weekend!",{"title":156,"searchDepth":157,"depth":157,"links":12190},[],"2010-08-01T19:37-04:00",{},"\u002Ftlt-2010.08.01-opw-2010",{"title":12044,"description":12049},"TLT - 2010.08.01 - OPW 2010",[169],"tn08ppLBjyFlU4o_gvmadKkoshv5IeNK6OLev8acd90",{"id":12199,"title":12200,"body":12201,"createdAt":12216,"description":12205,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12217,"navigation":164,"path":12218,"seo":12219,"stem":12220,"tags":12221,"updatedAt":12216,"__hash__":12222},"content\u002FTLT - 2010.07.10 - Hotel Yorba.md","TLT_-_2010.07.10_-_Hotel_Yorba",{"type":8,"value":12202,"toc":12214},[12203,12206],[11,12204,12205],{},"I love this song so much, and it is as fun to play as I imagined.",[11,12207,12208,444,12211,449],{},[440,12209],{"controls":164,"preload":442,"src":12210},"\u002Fdocs\u002Fmusic\u002Fyorba.mp3",[136,12212,448],{"download":12213,"external":156,"href":12210},"docs\u002Fmusic\u002Fyorba.mp3",{"title":156,"searchDepth":157,"depth":157,"links":12215},[],"2010-07-10T22:56-04:00",{},"\u002Ftlt-2010.07.10-hotel-yorba",{"title":12200,"description":12205},"TLT - 2010.07.10 - Hotel Yorba",[169],"ioya1C0qq2Lyj1JJuGbNy7JCeVZkCxJ1hnGg57VIMS8",{"id":12224,"title":12225,"body":12226,"createdAt":12310,"description":12311,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12312,"navigation":164,"path":12313,"seo":12314,"stem":12315,"tags":12316,"updatedAt":12310,"__hash__":12317},"content\u002FTLT - 2010.07.10 - HTML-FormHandler, KiokuDB, and Continuity.md","TLT_-_2010.07.10_-_HTML-FormHandler,_KiokuDB,_and_Continuity",{"type":8,"value":12227,"toc":12308},[12228,12235,12241,12244,12250,12253,12259,12262,12265,12271,12274,12280,12283,12286,12293,12296,12302,12305],[11,12229,12230,12231,12234],{},"I saw some article about cpan:HTML::FormHandler, and decided I'd give it a try. I'm probably not really using it as intended... and I'm also not pushing this confluence of tech ",[1030,12232,12233],{},"nearly"," as far as it can go.",[605,12236,12239],{"className":12237,"code":12238,"language":1288},[1286],"#!\u002Fusr\u002Fbin\u002Fperl\n\nuse strict;\nuse MooseX::Declare;\nuse KiokuDB;\nuse Continuity;\n",[194,12240,12238],{"__ignoreMap":156},[11,12242,12243],{},"First we just pull in some libraries. We'll use cpan:MooseX::Declare for fun :) . Now let's make a lovely base class for our forms, to set up some good defaults an an updater.",[605,12245,12248],{"className":12246,"code":12247,"language":1288},[1286],"# Base class for all forms\nclass Form\nextends HTML::FormHandler {\n  has owner => (is => 'rw');\n  our $form_count = 0;\n  has '+name' => ( default => sub { return \"f-\" . $form_count++ } );\n  has '+html_prefix' => ( default => 1 );\n  method update {\n    if($self->validated) {\n      my $v = $self->value;\n      foreach my $field (keys %$v) {\n        eval { # ignore validation issues :)\n          $self->owner->$field($v->{$field})\n            if $self->owner->can($field);\n        }\n      }\n    }\n  }\n}\n",[194,12249,12247],{"__ignoreMap":156},[11,12251,12252],{},"That stuff about the form name is so we can display multiple forms on a page, each with it's own unique name. The update method ties my form to my actual object. I ignore errors for now... though really that's losing a big part of what cpan:HTML::FormHandler provides.",[605,12254,12257],{"className":12255,"code":12256,"language":1288},[1286],"class BasicPersonForm\nextends Form\nwith HTML::FormHandler::Render::Table {\n  has '+field_list' => ( default => sub {[\n    name => 'Text',\n    birthday => 'Text',\n    save => { type => 'Submit', value => 'Save' },\n  ]});\n}\n",[194,12258,12256],{"__ignoreMap":156},[11,12260,12261],{},"Here I'm building on my Form base, making a form specific for my Person class. This is declaratively specifying which fields to show and in what order, along with a lovely save button. In theory I'll be able to expand this into subforms and compose them and so on.",[11,12263,12264],{},"Though I'm roughly OK with listing inputs for the form, it annoys me to have to specify the types. That, at at least a basic level, should be readable from the fields to which this form is connected. So one thing I'm noodling is using the rendering and validation, but importing the types from the data class. I think the cpan:Form::Processor::Model::DBIC does this a bit.",[605,12266,12269],{"className":12267,"code":12268,"language":1288},[1286],"class Person {\n  use MooseX::Types::DateTimeX qw( DateTime );\n\n  has name => ( is => 'rw', default => sub { '' } );\n  has birthday => ( is => 'rw', isa => DateTime, coerce => 1 );\n\n  method basic_form { BasicPersonForm->new( owner => $self, init_object => $self ) }\n}\n",[194,12270,12268],{"__ignoreMap":156},[11,12272,12273],{},"My Person class is straightforward. I used the DateTimeX thingie to auto coerce stuff magically. And that basic_form method is just a helper to create a form for a given instance.",[605,12275,12278],{"className":12276,"code":12277,"language":1288},[1286],"sub main {\n  my $r = shift;\n  my $db = KiokuDB->connect(\n    'dbi:SQLite:phone.db',\n    create => 1\n  );\n  my $scope = $db->new_scope;\n\n  # This is a new person, pending some data\n  my $new_person = Person->new;\n\n  while(1) {\n\n    my @people = $db->grep(sub { ref($_) eq 'Person' })->all;\n    my @forms = map { $_->basic_form } @people;\n    foreach my $form (@forms) {\n      $r->print($form->render);\n    }\n    $r->print(\"\u003Ch3>Add person:\u003C\u002Fh3>\");\n    my $new_person_form = $new_person->basic_form;\n    $r->print($new_person_form->render);\n\n    $r->next;\n    my $params = { $r->params };\n\n    foreach my $form (@forms) {\n      $form->process( $params );\n      $form->update;\n      $db->update( $form->owner );\n    }\n\n    $new_person_form->process( $params );\n    $new_person_form->update;\n    if($new_person->name) {\n      $db->insert( $new_person );\n     \n      # And now queue up another new one\n      $new_person = Person->new;\n    }\n  }\n}\n",[194,12279,12277],{"__ignoreMap":156},[11,12281,12282],{},"This is a little Continuity app, so main gets called and passed $r, which is the request handle. After setting up our KiokuDB (with SQLite backend), I enter an endless loop of showing the forms and the processing the results. Oh, and I create a special Person instance for holding a new person.",[11,12284,12285],{},"In the loop, I grab all the people objects in the DB at once (this is a demo, so I skipped iterator\u002Fpaging stuff), make a form for each, and then render the forms. I also render the new-person object in case they want to add a new one.",[11,12287,12288,12289],{},"Next I call '$r->next', which waits for the user to submit the forms. This is Continuity magic, which inverts the web app to make it more like an interactive command line prompt. You can kinda think of this line as \"$input = ",[12290,12291,12292],"stdin",{},"\". Once that comes back I put the submitted data into a variable and use it to update each of the forms (and updating each back into the database).",[11,12294,12295],{},"Finally I check to see if they submitted data for the New-Person, and if there is anything I insert it into the DB.",[605,12297,12300],{"className":12298,"code":12299,"language":1288},[1286],"# Get things going\nContinuity->new->loop;\n",[194,12301,12299],{"__ignoreMap":156},[11,12303,12304],{},"Last but not least, we start the Continuity loop, which starts looking for requests and calling main() for each new session.",[11,12306,12307],{},"So I found this all pretty interesting, and it overlaps with some of my other object-rendering experiments. I could probably add to this for pulling field metadata from objects into forms and organizing subforms and so on. Maybe next time :)",{"title":156,"searchDepth":157,"depth":157,"links":12309},[],"2010-07-10T18:37-04:00","I saw some article about cpan:HTML::FormHandler, and decided I'd give it a try. I'm probably not really using it as intended... and I'm also not pushing this confluence of tech nearly as far as it can go.",{},"\u002Ftlt-2010.07.10-html-formhandler-kiokudb-and-continuity",{"title":12225,"description":12311},"TLT - 2010.07.10 - HTML-FormHandler, KiokuDB, and Continuity",[169],"HY-jJWe2bEbTfi4HVFhTZzcufHM16LXF5FSdED22rf8",{"id":12319,"title":12320,"body":12321,"createdAt":12399,"description":12325,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12400,"navigation":164,"path":12401,"seo":12402,"stem":12403,"tags":12404,"updatedAt":12405,"__hash__":12406},"content\u002FTLT - 2010.06.04 - Mercurial Bisect.md","TLT_-_2010.06.04_-_Mercurial_Bisect",{"type":8,"value":12322,"toc":12397},[12323,12326,12329,12332,12335,12338,12343,12346,12351,12354,12360,12367,12370,12376,12379,12385,12388,12391,12394],[11,12324,12325],{},"Tags: Mercurial, hg, Debugging, Testing",[11,12327,12328],{},"So at work we're switching over to Mercurial (hg), and I'm trying out some of the more advanced features. One which I've been looking forward to for a while is 'bisect' (which git and others have also).",[11,12330,12331],{},"The idea is straightforward. I have a unit test that fails. I know that it worked like a month ago or something. Someone committed something between then and now that made it fail. But what was it? Bisect will systematically help find it -- start in the middle, and if it was good there go back half of the remaining time. If bad, go forward. In just a few chops like this it will narrow down to the exact commit that caused an issue.",[11,12333,12334],{},"This works well in Mercurial (and Git) because it is really really fast to revert to a previous version of your code. By far the longest part of the process in the process was executing the unit test itself!",[11,12336,12337],{},"Here are the steps I went through. I'm using Mercurial 4.3, by the way.",[11,12339,12340],{},[194,12341,12342],{},"bwilcox@wickedwitch:~\u002Fdev-rel172$ hg bisect -r",[11,12344,12345],{},"First I \"reset\" the bisect. That just means, let's begin!",[11,12347,12348],{},[194,12349,12350],{},"bwilcox@wickedwitch:~\u002Fdev-rel172$ hg bisect -b",[11,12352,12353],{},"Now I marked the current revision as \"bad\", since my test fails.",[605,12355,12358],{"className":12356,"code":12357,"language":1288},[1286],"bwilcox@wickedwitch:~\u002Fdev-rel172$ hg bisect -g 51303\nTesting changeset 51497:3f631045f30d (196 changesets remaining, ~7 tests)\n124 files updated, 0 files merged, 26 files removed, 0 files unresolved\n",[194,12359,12357],{"__ignoreMap":156},[11,12361,12362,12363,12366],{},"I looked back at history before I started this and decided that this test definitely passed at revision 51303 -- that was just before our last release and all the tests passed. So here I'm saying that I know for ",[20,12364,12365],{},"sure"," that it was \"good\" at revision 51303.",[11,12368,12369],{},"Now comes the fun part.",[605,12371,12374],{"className":12372,"code":12373,"language":1288},[1286],"bwilcox@wickedwitch:~\u002Fdev-rel172$ hg bisect -c 'bin\u002Ftest_suite.pl bin\u002Ft\u002Fdefault\u002Fpnr_phase1\u002F14-task_acquisition_approval.t | grep PASS'\nChangeset 51497:3f631045f30d: bad\nResult: PASS\nChangeset 51404:8b0f3381e3f5: good\nChangeset 51449:f3b668e05928: bad\nChangeset 51415:ebc770d284d3: bad\nResult: PASS\nChangeset 51409:dfd5706dc765: good\nResult: PASS\nChangeset 51412:e33660e38ea0: good\nResult: PASS\nChangeset 51413:d1390b75856f: good\nChangeset 51414:d39f58b490ab: bad\nThe first bad revision is:\nchangeset:   51414:d39f58b490ab\nuser:        chiggins\ndate:        Tue May 18 21:34:51 2010 +0000\nsummary:     RT: https:\u002F\u002Frt.liquidation.com\u002FTicket\u002FDisplay.html?id=733702\n",[194,12375,12373],{"__ignoreMap":156},[11,12377,12378],{},"In case it isn't clear, the command that I ran is:",[605,12380,12383],{"className":12381,"code":12382,"language":1288},[1286],"hg bisect -c 'bin\u002Ftest_suite.pl bin\u002Ft\u002Fdefault\u002Fpnr_phase1\u002F14-task_acquisition_approval.t | grep PASS'\n",[194,12384,12382],{"__ignoreMap":156},[11,12386,12387],{},"This instructs Mercurial to keep going, and use my test_suite.pl command to decide whether a particular revision is \"good\" or \"bad\". The \"-c\" parameter runs what you give it and looks at the exit status to decide if it is good or bad. It just so happens that the \"grep\" command returns exit status depending on whether it found something :) . So I'm grepping for the \"PASS\" that comes at the end of a standard perl test suite to indicate that the current revision is good.",[11,12389,12390],{},"And then off it runs! Test... bad. Test... good. Test... bad. And so on, narrowing it down to the exact revision which was the first to fail the test!",[11,12392,12393],{},"From there I took a look at that revision, and immediately saw what the problem was. Easily fixed, and now my test suite passes with a clean bill of health.",[11,12395,12396],{},"Aw hells yes.",{"title":156,"searchDepth":157,"depth":157,"links":12398},[],"2010-06-04T16:59-04:00",{},"\u002Ftlt-2010.06.04-mercurial-bisect",{"title":12320,"description":12325},"TLT - 2010.06.04 - Mercurial Bisect",[169],"2010-06-07T10:29-04:00","2OKpxYFm1_bD_spq7_S25BljRoDF5mx5CNrK9d5crQE",{"id":12408,"title":12409,"body":12410,"createdAt":12429,"description":12414,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12430,"navigation":164,"path":12431,"seo":12432,"stem":12433,"tags":12434,"updatedAt":12435,"__hash__":12436},"content\u002FTLT - 2010.02.07 - Cultured Perl.md","TLT_-_2010.02.07_-_Cultured_Perl",{"type":8,"value":12411,"toc":12427},[12412,12415,12424],[11,12413,12414],{},"Tags: Perl",[11,12416,12417,12418,12423],{},"You might have stumbled upon some IBM developerWorks articles titled \"Cultured Perl\" while googling for random things. I think it's awesome and that it isn't linked to enough. Just a few weeks ago the latest article came out, ",[136,12419,12422],{"href":12420,"rel":12421},"http:\u002F\u002Fwww.ibm.com\u002Fdeveloperworks\u002Flinux\u002Flibrary\u002Fl-cpan-net-amazon-s3\u002F",[140],"Cultured Perl: Storage management on Amazon S3",", which is well written and up-to-date with the latest technologies.",[11,12425,12426],{},"Thank you, Cultured Perl!",{"title":156,"searchDepth":157,"depth":157,"links":12428},[],"2010-02-07T22:34-05:00",{},"\u002Ftlt-2010.02.07-cultured-perl",{"title":12409,"description":12414},"TLT - 2010.02.07 - Cultured Perl",[169],"2010-02-07T22:41-05:00","u7BpWyB1D-7-hWrIGnYzOI_FdMe-HyWbRi1OVxifoRY",{"id":12438,"title":12439,"body":12440,"createdAt":12471,"description":12472,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12473,"navigation":164,"path":12474,"seo":12475,"stem":12476,"tags":12477,"updatedAt":12471,"__hash__":12478},"content\u002FTLT - 2009.12.16 - Better Creox Example.md","TLT_-_2009.12.16_-_Better_Creox_Example",{"type":8,"value":12441,"toc":12469},[12442,12451],[11,12443,12444,12445,12450],{},"So I was right, I completely messed up the previous example and it wasn't electrified by ",[136,12446,12449],{"href":12447,"rel":12448},"http:\u002F\u002Fzyzstar.kosoru.com\u002F?creox",[140],"Creox"," at all. But I've rectified this situation, and for your listening pleasure (pain?), here is a smaller snippet of just the guitar part of the song, before-and-after.",[11,12452,12453,12454,444,12457,449,12460,12462,12463,444,12466,449],{},"Original acoustic guitar ",[440,12455],{"controls":164,"preload":442,"src":12456},"\u002Fdocs\u002Fmusic\u002Foh_my_baby_guitar_acoustic.mp3",[136,12458,448],{"download":12459,"external":156,"href":12456},"docs\u002Fmusic\u002Foh_my_baby_guitar_acoustic.mp3",[461,12461],{},"\nElectrified by Creox ",[440,12464],{"controls":164,"preload":442,"src":12465},"\u002Fdocs\u002Fmusic\u002Foh_my_baby_guitar_electric.mp3",[136,12467,448],{"download":12468,"external":156,"href":12465},"docs\u002Fmusic\u002Foh_my_baby_guitar_electric.mp3",{"title":156,"searchDepth":157,"depth":157,"links":12470},[],"2009-12-16T23:48-05:00","So I was right, I completely messed up the previous example and it wasn't electrified by Creox at all. But I've rectified this situation, and for your listening pleasure (pain?), here is a smaller snippet of just the guitar part of the song, before-and-after.",{},"\u002Ftlt-2009.12.16-better-creox-example",{"title":12439,"description":12472},"TLT - 2009.12.16 - Better Creox Example",[169],"7sHODFpMw7lONZuFqnbmceTOWH-WNDINKToy-GWG0HQ",{"id":12480,"title":12481,"body":12482,"createdAt":12505,"description":12506,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12507,"navigation":164,"path":12508,"seo":12509,"stem":12510,"tags":12511,"updatedAt":12512,"__hash__":12513},"content\u002FTLT - 2009.12.06 - Music Play.md","TLT_-_2009.12.06_-_Music_Play",{"type":8,"value":12483,"toc":12503},[12484,12491,12500],[11,12485,12486,12487,12490],{},"I was playing with ",[136,12488,12449],{"href":12447,"rel":12489},[140]," the other day, which can make an acoustic guitar sound electric (amongst other things). I recorded a quick song... but it doesn't sound nearly as electric when I listen to it now as it did when I first recorded it (and now I wonder if I even had my Jack settings right for recording what I was hearing...). But it did end up with a fun crackly sound on the voice I think. Listen for yourself:",[11,12492,12493,12494,444,12497,449],{},"\"Oh my baby\" ",[440,12495],{"controls":164,"preload":442,"src":12496},"\u002Fdocs\u002Fmusic\u002Foh_my_baby.mp3",[136,12498,448],{"download":12499,"external":156,"href":12496},"docs\u002Fmusic\u002Foh_my_baby.mp3",[11,12501,12502],{},"And it gave me an excuse to add an mp3 player plugin :)",{"title":156,"searchDepth":157,"depth":157,"links":12504},[],"2009-12-07T00:04-05:00","I was playing with Creox the other day, which can make an acoustic guitar sound electric (amongst other things). I recorded a quick song... but it doesn't sound nearly as electric when I listen to it now as it did when I first recorded it (and now I wonder if I even had my Jack settings right for recording what I was hearing...). But it did end up with a fun crackly sound on the voice I think. Listen for yourself:",{},"\u002Ftlt-2009.12.06-music-play",{"title":12481,"description":12506},"TLT - 2009.12.06 - Music Play",[169],"2009-12-07T00:07-05:00","3jPHJI2vE6bK2iwm_lTV-GCvUks-MCmvRyV3Rda3zlY",{"id":12515,"title":12516,"body":12517,"createdAt":12587,"description":12521,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12588,"navigation":164,"path":12589,"seo":12590,"stem":12591,"tags":12592,"updatedAt":12593,"__hash__":12594},"content\u002FTLT - 2009.11.15 - The Internets Make Programming Easy.md","TLT_-_2009.11.15_-_The_Internets_Make_Programming_Easy",{"type":8,"value":12518,"toc":12585},[12519,12522,12525,12534,12540,12543,12573,12576,12582],[11,12520,12521],{},"Tags: C++, Programming, UIUC, Data Mining, Homework",[11,12523,12524],{},"In the class I'm taking (Intro to Data Mining) we get to implement a classifier. Alas... we must use either C++ or Java. I haven't programmed in either for quite a few years, and even with further pursuit I'm not allowed to use OCaml.",[11,12526,12527,12528,12533],{},"That's OK! Best to stretch my mind out a bit. I'm afraid I'm getting rusty at being multi-lingual in my old age anyway, so this is good exercise. First thing first, I have to read in the training data. But best start with the basic Hello World even before that. Google... I figure I'll ",[136,12529,12532],{"href":12530,"rel":12531},"http:\u002F\u002Fwww.cplusplus.com\u002Fdoc\u002Ftutorial\u002Fprogram_structure\u002F",[140],"start with the basics",", and now I have:",[605,12535,12538],{"className":12536,"code":12537,"language":1288},[1286],"#include \u003Ciostream>\nusing namespace std;\n\nint main() {\n  cout \u003C\u003C \"Hello World!\" \u003C\u003C endl;\n  return 0;\n}\n",[194,12539,12537],{"__ignoreMap":156},[11,12541,12542],{},"I don't even remember doing that std namespace thing last time I programmed in C++. Oh well. It runs! So from there I just keep searching and adding...",[205,12544,12545,12552,12559,12566],{},[208,12546,12547],{},[136,12548,12551],{"href":12549,"rel":12550},"http:\u002F\u002Fwww.cppreference.com\u002Fwiki\u002Fio\u002Fexamples",[140],"Read a file",[208,12553,12554],{},[136,12555,12558],{"href":12556,"rel":12557},"http:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F236129\u002Fc-how-to-split-a-string",[140],"Split the lines (I use a boost library way)",[208,12560,12561],{},[136,12562,12565],{"href":12563,"rel":12564},"http:\u002F\u002Fwww.yolinux.com\u002FTUTORIALS\u002FLinuxTutorialC++STL.html",[140],"Put it all into a two-dimensional vector, and then dump it using iterators",[208,12567,12568],{},[136,12569,12572],{"href":12570,"rel":12571},"http:\u002F\u002Fkengine.sourceforge.net\u002Ftutorial\u002Fg\u002Fstdmap-eng.htm",[140],"Create a key-value map (and dump with iterators!)",[11,12574,12575],{},"... and just like magic I am now reading the file, parsing it, and counting the frequency of items. Ahh the hive mind! Here's the result... it's messy and unstructured but damn... it works!",[605,12577,12580],{"className":12578,"code":12579,"language":1288},[1286],"\u002F\u002F Compile: g++ -o demo main.cpp\n#include \u003Ciostream>\n#include \u003Cfstream>\n#include \u003Cvector>\n#include \u003Cboost\u002Falgorithm\u002Fstring.hpp>\n#include \u003Cmap>\n\nusing namespace std;\n\ntypedef map\u003Cstring, int> ItemSet;\n\nint main() {\n  cout \u003C\u003C \"Hello World!\" \u003C\u003C endl;\n  ifstream fin(\"data\u002Ftrain1.txt\");\n  \u002F\u002F ifstream fin(\"data\u002Fsmall_train.txt\");\n  string s;\n  vector\u003C vector\u003Cstring> > d;\n\n  ItemSet itemset;\n\n  while(getline(fin,s)) {\n    vector\u003Cstring> row;\n    \u002F\u002F cout \u003C\u003C \"Read from file: \" \u003C\u003C s \u003C\u003C endl;\n    boost::split(row, s, boost::is_space());\n    d.push_back(row);\n  }\n\n  vector\u003C vector\u003Cstring> >::iterator d_iter;\n  vector\u003Cstring>::iterator row_iter;\n\n  for(d_iter = d.begin(); d_iter != d.end(); d_iter++) {\n    cout \u003C\u003C \"[ \";\n    for(row_iter = d_iter->.begin(); row_iter != d_iter->end(); row_iter++) {\n      cout \u003C\u003C *row_iter \u003C\u003C \" \";\n      itemset[*row_iter]++;\n    }\n    cout \u003C\u003C \"]\" \u003C\u003C endl;\n  }\n\n  cout \u003C\u003C \"Itemset:\" \u003C\u003C endl;\n\n  ItemSet::iterator itemset_iter;\n  for(itemset_iter = itemset.begin(); itemset_iter != itemset.end(); itemset_iter++) {\n    cout \u003C\u003C itemset_iter->first \u003C\u003C \" : \" \u003C\u003C itemset_iter->second \u003C\u003C endl;\n  }\n\n  return 0;\n}\n",[194,12581,12579],{"__ignoreMap":156},[11,12583,12584],{},"I'll keep going like this for a bit, but then I'll start organizing into actual objects and such. There is a good chance that I'll switch data structures, or perhaps not even bother keeping all this in memory. Most likely I'm also violating some other C++ socio-political norms. Fun!",{"title":156,"searchDepth":157,"depth":157,"links":12586},[],"2009-11-15T23:18-05:00",{},"\u002Ftlt-2009.11.15-the-internets-make-programming-easy",{"title":12516,"description":12521},"TLT - 2009.11.15 - The Internets Make Programming Easy",[169],"2010-07-07T11:36-04:00","sszlNOaKmnf7tRXejfVxbl0l4WAa7iLwwYB97UylIPo",{"id":12596,"title":12597,"body":12598,"createdAt":12617,"description":12618,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12619,"navigation":164,"path":12620,"seo":12621,"stem":12622,"tags":12623,"updatedAt":12617,"__hash__":12624},"content\u002FTLT - 2009.08.25 - Now I Have A Real Blog.md","TLT_-_2009.08.25_-_Now_I_Have_A_Real_Blog",{"type":8,"value":12599,"toc":12615},[12600,12609],[11,12601,12602,12603,12608],{},"I was just exploring the latest and greatest ",[136,12604,12607],{"href":12605,"rel":12606},"http:\u002F\u002Foddmuse.org\u002F",[140],"Oddmuse"," modules, and see that someone made it easy to embed youtube\u002Fgoogle videos. So now I feel like I have a real blog and I can post the random crap that everyone else does! To prove it, here is a totally awesome song my friends turned me on to:",[11,12610,12611,12612],{},"[YouTube:nstI0bjTqwQ](\u002F",[8566,12613],{"width":8568,"height":8569,"src":12614,"frameBorder":6760,"allow":8571,"allowFullScreen":164},"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002Fnsti0bjtqwq)",{"title":156,"searchDepth":157,"depth":157,"links":12616},[],"2009-08-25T23:15-04:00","I was just exploring the latest and greatest Oddmuse modules, and see that someone made it easy to embed youtube\u002Fgoogle videos. So now I feel like I have a real blog and I can post the random crap that everyone else does! To prove it, here is a totally awesome song my friends turned me on to:",{},"\u002Ftlt-2009.08.25-now-i-have-a-real-blog",{"title":12597,"description":12618},"TLT - 2009.08.25 - Now I Have A Real Blog",[169],"x6pbPSteYLBqjeRmynWjW_r7EwNG26rc2yUWELiVnrY",{"id":12626,"title":12627,"body":12628,"createdAt":12677,"description":12632,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12678,"navigation":164,"path":12679,"seo":12680,"stem":12681,"tags":12682,"updatedAt":12683,"__hash__":12684},"content\u002FTLT - 2009.08.25 - Trace With State.md","TLT_-_2009.08.25_-_Trace_With_State",{"type":8,"value":12629,"toc":12675},[12630,12633,12636,12639,12642,12645,12654,12663],[11,12631,12632],{},"Tags: Perl, Debugging, Idea",[11,12634,12635],{},"I've got to get this idea written down so that I can go back to doing other things... it is too distracting as-is.",[11,12637,12638],{},"In a nutshell -- more or less cpan:Devel::Trace except that at each step you record all of the lexical (global?) state. Then you can not only see the full execution history of your program, but the value of every variable at every point.",[11,12640,12641],{},"Now of course from the idea comes all of these questions -- do we store all that or just some of it (just what changes). Do we only keep local lexical scope at each step since the rest can be reconstructed? How do we record this... do we summarize it somehow? And so on.",[11,12643,12644],{},"But ignoring all that... the next idea that comes to my mind is to toss this into CGI::Inspect as a module, so that you can use the GUI browse not just the current lexical state (there is already a plugin for that), but also the complete historical state as well.",[11,12646,12647,12648,12653],{},"I got the idea from the ",[136,12649,12652],{"href":12650,"rel":12651},"http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FOmniscient_Debugger",[140],"Omniscient Debugger",", but I'd actually seen it before in its more highly evolved form in the OCaml Debugger. The OCaml Debugger doesn't have to actually save all that state though, since in a lovely functional language you can actually just reconstruct the previous state (I believe). Still.",[11,12655,12656,12657,12662],{},"(If you're still reading and want something even MORE insane, then your homework is to use Nothingmuch's ",[136,12658,12661],{"href":12659,"rel":12660},"http:\u002F\u002Fblog.woobling.org\u002F2009\u002F08\u002Freset-hack-shift-return-0.html",[140],"delimited continuations in perl"," and make it so that you can actually resume any of the historical states).",[11,12664,12665,12666,12670,12671,797],{},"Code might eventually show up at ",[136,12667,12668],{"href":12668,"rel":12669},"http:\u002F\u002Fthelackthereof.org\u002Fprojects\u002Fperl\u002FDevel-TraceState",[140]," or perhaps ",[136,12672,12674],{"href":12673},"\u002Fdevel-tracestate","Devel-TraceState",{"title":156,"searchDepth":157,"depth":157,"links":12676},[],"2009-08-25T22:12-04:00",{},"\u002Ftlt-2009.08.25-trace-with-state",{"title":12627,"description":12632},"TLT - 2009.08.25 - Trace With State",[169],"2010-03-16T21:52-04:00","rR8qZBwvAnNBbiD70U03yI9tbZLsg3TgyIdBlvc_8uw",{"id":12686,"title":12687,"body":12688,"createdAt":12712,"description":12692,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12713,"navigation":164,"path":12714,"seo":12715,"stem":12716,"tags":12717,"updatedAt":12718,"__hash__":12719},"content\u002FTLT - 2009.05.08 - Pause My Music.md","TLT_-_2009.05.08_-_Pause_My_Music",{"type":8,"value":12689,"toc":12710},[12690,12693,12701,12704],[11,12691,12692],{},"Tags: perl, linux, music",[11,12694,12695,12696,12700],{},"Oh how I love linux... perl... scriptability. I have a fun little command line music player named ",[136,12697,12699],{"href":12698},"\u002Fpolly","Polly",". It is pretty minimalist, really just starting whatever player I like with whatever preferences I like on a whole directory tree of files. One thing that is annoying is that I have to switch over to the terminal and it ^Z to pause and then do 'fg' to play.",[11,12702,12703],{},"So I finally decided to write a simple pause toggle script. I approached this in the most brute force way I could... I just take the list of all my media players and send a massive STOP (effectively ^Z) command to all to pause, and then a massive CONT (effectively 'fg') to all to continue. To determine if I want to pause or continue, I just look to see if I have any paused player processes.",[605,12705,12708],{"className":12706,"code":12707,"language":1288},[1286],"my @commands = qw( ogg123 mpg123 mplayer vlc sidplay2 );\nmy $cmd = join '\\|', @commands;\n\nif(`ps a -o state,cmd | grep '$cmd' | grep ^T`) {\n  map { `killall -SIGCONT $_ 2>\u002Fdev\u002Fnull` } @commands;\n} else {\n  map { `killall -SIGSTOP $_ 2>\u002Fdev\u002Fnull` } @commands;\n}\n",[194,12709,12707],{"__ignoreMap":156},{"title":156,"searchDepth":157,"depth":157,"links":12711},[],"2009-05-08T16:03-04:00",{},"\u002Ftlt-2009.05.08-pause-my-music",{"title":12687,"description":12692},"TLT - 2009.05.08 - Pause My Music",[169],"2009-07-11T19:19-04:00","FWSRxhnU4zIfgoBJKftPzwYos3jj4QnCW6oHIYSkdb4",{"id":12721,"title":12722,"body":12723,"createdAt":12778,"description":12779,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12780,"navigation":164,"path":12781,"seo":12782,"stem":12783,"tags":12784,"updatedAt":12785,"__hash__":12786},"content\u002FTLT - 2008.11.29 - DNA Memory.md","TLT_-_2008.11.29_-_DNA_Memory",{"type":8,"value":12724,"toc":12776},[12725,12734,12746,12755,12758,12761,12770,12773],[11,12726,12727,12728,12733],{},"Scott linked an article from new scientist, ",[136,12729,12732],{"href":12730,"rel":12731},"http:\u002F\u002Fwww.newscientist.com\u002Farticle\u002Fmg20026845.000-memories-may-be-stored-on-your-dna.html",[140],"Memories may be stored on your DNA",", which relates with what has been on my mind lately.",[11,12735,12736,12737,12742,12743,797],{},"I was reading about some hardware evolution experiments while at the bookstore the other day. They were using a ",[136,12738,12741],{"href":12739,"rel":12740},"http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FField-programmable_gate_array",[140],"FPGA"," to create (evolve) a sine wave generator, if I recall correctly. The end result of the first run worked perfectly, but had some bizarre attributes -- it programmed a section of the gate array but didn't wire that section to the rest. When the unconnected section was turned off, the circuit no longer worked. It also didn't work when the same design was put onto an identical FPGA. As far as the experimenters could tell, the evolved solution depended upon some subtle property of ",[1030,12744,12745],{},"that specific FPGA chip",[11,12747,12748,12749,12754],{},"In other words: ",[136,12750,12753],{"href":12751,"rel":12752},"http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FGenetic_programming",[140],"GP"," solutions cheat like hell.",[11,12756,12757],{},"They will use absolutely any available subtle or side-effect aspects of environmental conditions to push themselves to the next rung on the fitness ladder. An important lesson that I've taken from GP is that artificial \u002F automatic program generation mostly results in programs that make almost no sense from a human programmer perspective, at least partly because of all this cheating. The solutions produced by GP are mostly twisted convoluted things which mostly don't look like they work at all, let alone solve anything.",[11,12759,12760],{},"When a human abstracts things, it ends up taking a much more layered structure, with the meat of the problem usually ending up on the highest layer. Automatic techniques do not succumb to such niceties.",[11,12762,12763,12764,12769],{},"Speaking of human abstraction, I recently stumbled upon the ",[136,12765,12768],{"href":12766,"rel":12767},"http:\u002F\u002Fwww.plover.com\u002FDiscordia\u002F",[140],"Discordia page of Mark-Jason Dominus"," which makes a keen observation with fascinating attributes - \"In a well-designed computer program, No two components are alike, or even similar.\" Conceptually, that is, all similar aspects of a program are abstracted. Good programs are themselves not like the beautiful fractals of recursion that lay in the mind of their creator or the algorithms that they represent. You could perhaps think of them as the compressed version -- the most informationally dense form of the logic, information theory might say.",[11,12771,12772],{},"Now take it full circle... from the biological inspired computation back to biology. Biological evolution cheats just like artificial evolution does. At first glance we see all this lovely DNA-level abstraction... but as they dig in they find all sorts of trickery that operates on all levels low and high. Like throwing in some assembly (or even better, some binary executable blobs) into the middle of my blog software. The re-use of DNA (or perhaps the coating on DNA was it?) as memory storage in the brain is completely typical.",[11,12774,12775],{},"If the designers were indeed intelligent, they sure didn't plan on doing any maintenance.",{"title":156,"searchDepth":157,"depth":157,"links":12777},[],"2008-11-30T00:01-05:00","Scott linked an article from new scientist, Memories may be stored on your DNA, which relates with what has been on my mind lately.",{},"\u002Ftlt-2008.11.29-dna-memory",{"title":12722,"description":12779},"TLT - 2008.11.29 - DNA Memory",[169],"2015-07-26T12:53-04:00","pVuoPMSgu3h7RrvbcXd7C8Zin-ejA4715bciGjDbL7E",{"id":12788,"title":12789,"body":12790,"createdAt":12797,"description":12794,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12798,"navigation":164,"path":12799,"seo":12800,"stem":12801,"tags":12802,"updatedAt":12797,"__hash__":12803},"content\u002FTLT - 2008.10.21 - Slow Android Development.md","TLT_-_2008.10.21_-_Slow_Android_Development",{"type":8,"value":12791,"toc":12795},[12792],[11,12793,12794],{},"It's been over 4 hours since Android was released... but still no port to the Neo. Pft.",{"title":156,"searchDepth":157,"depth":157,"links":12796},[],"2008-10-21T23:53-04:00",{},"\u002Ftlt-2008.10.21-slow-android-development",{"title":12789,"description":12794},"TLT - 2008.10.21 - Slow Android Development",[169],"fFthDuKBrpzAbVUibpBFr3AISW9n-hIlNPvTeJLRDro",{"id":12805,"title":12806,"body":12807,"createdAt":12826,"description":12811,"draft":160,"extension":161,"image":162,"mastodonThread":162,"meta":12827,"navigation":164,"path":12828,"seo":12829,"stem":12830,"tags":12831,"updatedAt":12683,"__hash__":12832},"content\u002FTLT - 2008.07.24 - OSCON Lighnting Talk.md","TLT_-_2008.07.24_-_OSCON_Lighnting_Talk",{"type":8,"value":12808,"toc":12824},[12809,12812,12815,12818],[11,12810,12811],{},"Tags: OSCON, perl, continuity, lightning talk, oscon2008, REPL",[11,12813,12814],{},"At the last minute I ended up giving a Lightning talk at OSCON 2008 (in the Perl track). I showed my Devel::REPL + Continuity debugging tool.",[11,12816,12817],{},"Here are my notes:",[605,12819,12822],{"className":12820,"code":12821,"language":1288},[1286],"Lightning Talk OSCON 2008\n\nBrock Wilcox\nawwaiid@thelackthereof.org\n\nSee also:\n* Continuity\n* Continuity::REPL\n* Devel::REPL\n* Carp::REPL\n* PadWalker\n\n# .... These were then run in the REPL ....\n# counter.pl at:\n#   http:\u002F\u002Fthelackthereof.org\u002Fprojects\u002Fperl\u002FContinuity-Monitor\u002Feg\u002Fcounter.pl\n\nuse PadWalker 'peek_my';\nmy $h = peek_my 23;\n${ $h->{'$counter'} } = 77;\n\n# Then...\n\nsub new_prompt {\n  my ($request) = @_;\n  $request->print(\"Muahahaha!\");\n  return old_prompt(@_);\n}\n\n*old_prompt = *prompt;\n*prompt = *new_prompt;\n",[194,12823,12821],{"__ignoreMap":156},{"title":156,"searchDepth":157,"depth":157,"links":12825},[],"2008-07-24T20:47-04:00",{},"\u002Ftlt-2008.07.24-oscon-lighnting-talk",{"title":12806,"description":12811},"TLT - 2008.07.24 - OSCON Lighnting Talk",[169],"mSdqtvhkLH0_wwZJOunXpN3cgqLmnubqDT2sc0HPS_o",1778988315691]