Violets, Blogging Bathttps://fediverse.blog/@/violet@espeon.social/atom.xml2020-01-24T06:26:38.600719+00:00<![CDATA[Authorized Fetch, laziness, and the rust way]]>https://espeon.social/~/Whoa/authorized-fetch-laziness-and-the-rust-way/2020-01-24T06:26:38.600719+00:00Violets, Blogging Bathttps://espeon.social/@/violet/2020-01-24T06:26:38.600719+00:00<![CDATA[<p>We work on plume. It's actually pretty strange that we haven't talked about that at all, given that so many people write blog posts about their work. What we've done for plume thus far is:</p>
<ol>
<li>Fixed federation between mastodon and plume when the user being fetched has a very large number of posts.</li>
<li>Added syntax highlighting.</li>
<li>Fixed a bug with parsing mentions and hashtags in code blocks</li>
<li>Added an email blocklist that should towards addressing spam on open registration instances</li>
</ol>
<p>If any of those things seem impressive, they aren't really, in any grander scheme. And for all our contributions, we'd have been lost without the help of the maintainers of the project and their kindness, especially when we were starting out.</p>
<p>Plume has a long way to go, and given recent changes in the mastodon/Pleroma ecosystem(namely the introduction of authorized fetch), we have a lot to catch up on. What Plume needs, by a few bits of feedback that we've gotten from friends who have tried it out breaks down into the following:</p>
<ol>
<li>
<p>Privacy controls for blog posts.</p>
<p>Many people don't quite see the point, but, it's important to give the user at least as much control over visibility as mastodon and pleroma offer.</p>
</li>
<li>
<p>Moderation tools</p>
<p>Unless we want open registration plume servers to become hives of scum and villainy, robust moderation tools from administrator to user are required.</p>
</li>
<li>
<p>Comment control</p>
<p>As much fun as it is to comment on someone's terrible blog about how terrible it is(Please don't, people don't need extra unkindness in their life), the authors should have control over the presentation of the blog, if not everywhere, then at the <strong><em>very least</em></strong> on their home instance.</p>
</li>
</ol>
<p>But all this must wait for the massive changes in the pipe. Async code and all manner of changes. Soon it will be very different and this is not a change we feel we can contribute to.</p>
<p>We can't wait to help later on though.</p>
]]><![CDATA[Ocaml, Python, and ugly inventions in the midst of beauty]]>https://espeon.social/~/ProgramsAndTech/ocaml-python-and-ugly-inventions-in-the-midst-of-beauty/2020-01-24T03:30:21.374383+00:00Violets, Blogging Bathttps://espeon.social/@/violet/2020-01-24T03:30:21.374383+00:00<![CDATA[<p>Ocaml is a pretty language. It is simple, it is very clear, and while it lags behind the extensibility of Haskell with typeclasses and such, it is easier to use because it eschews the idea of purity through monadic IO(we still don't get IO) and lazy evaluation by default(you can get that with the Lazy module though).</p>
<p>When we started using it we were a sophomore at RPI(before we dropped out of the college due to mental health issues and constant escalating panic), and since it has improved by a fairly significant amount, especially in terms of the tooling available, but the core language has changed relatively little.</p>
<p>The language itself is based on the old Meta Language(ML) syntax, the representations extended for object orientation, it is largely functional, but not purely functional like Haskell is. It features type inference and is statically typed. It has an interpreted mode(invoked with <code>Ocaml</code>) and also supports compilation into relatively efficient native code(compiled with <code>ocamlopt</code>).</p>
<p>For package installation and Ocaml version management, the <a href="https://opam.ocaml.org/" rel="noopener noreferrer">opam</a> package manage is wonderfully simple to use and makes it possible to avoid writing all that code you need yourself using a admittedly bare standard library that comes with Ocaml.</p>
<p>If you are building a larger project or number of projects, you may use the <a href="https://github.com/ocaml/dune" rel="noopener noreferrer">dune</a> build system to compile and manage it.</p>
<p>You can also compile it to javascript with the <a href="https://ocsigen.org/js_of_ocaml/3.5.1/manual/overview" rel="noopener noreferrer">js_of_ocaml</a> tool from the Ocsigen project, as well as bucklescript.</p>
<p>It is not a <em>highly used</em> language, but it has a reasonably active ecosystem.</p>
<pre><code><span class="">
<span class=""><span class="">module type </span><span class="">Point</span></span> <span class="">=</span> <span class=""><span class="">sig</span>
<span class=""> <span class=""><span class="">type</span> <span class="">t
val zero : t
(*float should probably be replaced with an additional type parameter
but we weren't thinking about showing this off when we wrote it.*)
val distance : t -> t -> float
val add : t -> t -> t
val divide : t -> float -> t
end
</span></span></span></span></span></code></pre>
<p>This defines a type signature for that you can then feed into, for example</p>
<pre><code><span class="">
<span class=""><span class="">module</span> <span class="">K_MeansFactory</span></span> <span class=""><span class="">(</span><span class="">T</span> <span class="">:</span><span class=""> Point</span><span class="">)</span></span> <span class="">=</span> <span class=""><span class="">struct</span>
<span class=""> <span class=""><span class="">type</span> <span class="">t </span><span class="">=</span> <span class=""><span class="">{</span> <span class=""><span class="">points</span> <span class="">:</span> <span class=""><span class="">T</span><span class="">.t</span></span> <span class="">array</span><span class="">;</span></span> <span class=""><span class="">centroids</span> <span class="">:</span> <span class=""><span class="">T</span><span class="">.t</span></span> <span class="">array</span> </span><span class="">}</span></span>
</span></span><span class=""><span class="">val</span> <span class="">init</span> <span class="">:</span> <span class=""><span class="">T</span><span class="">.t</span></span> <span class="">array</span> <span class="">-></span> <span class="">int</span> <span class="">-></span> <span class="">t</span>
<span class="">(*Update the approximations of the centers of clusters,
*returning the centroid's index that each point gets and and the
*distance each centroid moves by*)</span>
</span>val update t<span class="">-></span><span class="">(<span class="">int</span> <span class="">array</span> <span class="">*</span> <span class="">float</span> <span class="">array</span>)</span>
<span class="">end</span></span>
</span></code></pre>
<p>This is abbreviated because the actual implementation is significantly longer. You may have also noted that it doesn't return the type of the K_MeansFactory, this is on account of the fact that arrays in Ocaml are mutable, and given the size of the arrays it can work with, that might not be a bad thing.</p>
<p>So, when you want to do K-means on points of two dimensional floats, you can do this:</p>
<pre><code><span class=""><span class=""><span class="">module</span> <span class="">FloatingPoint2</span></span> <span class="">=</span> <span class=""><span class="">struct</span>
<span class=""> <span class=""><span class="">type</span> <span class="">t </span><span class="">=</span> <span class="">float</span> <span class="">*</span> <span class="">float</span>
</span></span>
<span class="">let</span> <span class="">zero</span> <span class="">=</span> <span class="">(<span class="">0.0</span>, <span class="">0.0</span>)</span>
<span class=""><span class="">let</span> <span class="">distance</span> <span class="">(<span class="">ax</span>, <span class="">ay</span>)</span> <span class="">(<span class="">bx</span>, <span class="">by</span>)</span> <span class="">=</span></span>
<span class="">let</span> <span class="">cx</span> <span class="">=</span> bx <span class="">-.</span> ax <span class="">in</span> <span class="">(*The -. operator is the floating point version of the - operator.*)</span>
<span class="">let</span> <span class="">cy</span> <span class="">=</span> by <span class="">-.</span> ay <span class="">in</span> <span class="">(*Adding <span class="">"let open Float in"</span> before this usage would allow - to be used for float instead*)</span>
<span class="">Float.</span>sqrt <span class="">@@</span> <span class="">(<span class="">(cx <span class="">*.</span> cx)</span> <span class="">+.</span> <span class="">(cy <span class="">*.</span> cy)</span>)</span> <span class="">(* @@ is the ocaml composition operator, much like '$' is in haskell *)</span>
<span class=""><span class="">let</span> <span class="">add</span> <span class="">(<span class="">ax</span>, <span class="">ay</span>)</span> <span class="">(<span class="">bx</span>, <span class="">by</span>)</span> <span class="">=</span></span> <span class="">(ax <span class="">+.</span> bx, ay <span class="">+.</span> by)</span>
<span class=""><span class="">let</span> <span class="">divide</span> <span class="">(<span class="">x</span>, <span class="">y</span>)</span> <span class="">c</span> <span class="">=</span></span> <span class="">(x <span class="">/.</span> c, y <span class="">/.</span> c)</span>
<span class="">end</span></span>
</span></code></pre>
<p>The lack of polymorphic mathematical operators honestly isn't great for Ocaml, oddly the comparison operators <code>< > = >= <=</code> are polymorphic(and there is some talk in the community about how they are dangerous and thus undesirable), but they prevent some of the issues that you can get when you're coming from a C background and thus accustomed to things like automatic type promotion for integers to floats and 'seemless' interop between the two varieties of numbers.</p>
<p>This isn't the project we wanted to talk about however. That dubious honor goes to the questionably named <a href="https://github.com/epsilon-phase/Ocaml-Bot-DFA" rel="noopener noreferrer">Ocaml-Bot-Dfa</a> project we whipped up using a few libraries found in the ecosystem(<a href="https://github.com/inhabitedtype/angstrom/" rel="noopener noreferrer">Angstrom</a>, <a href="https://github.com/ocaml/Zarith" rel="noopener noreferrer">Zarith</a>, and <a href="https://github.com/thierry-martinez/pyml" rel="noopener noreferrer">pyml</a>). For a fediverse bot that does what it does, that's a lot of libraries, isn't it? Yes, it is. It also uses some <a href="https://github.com/halcy/Mastodon.py" rel="noopener noreferrer">python in order to post to mastodon</a></p>
<p>For what it's worth, we consider them all useful and fulfilling the more or less minimal requirements that we came up with through the process of developing it.</p>
<p>For example, it takes botspeak in a format like this:</p>
<pre><code><span class=""><color> = { "green"
| "blue"
| "yellow"
| "red" };
<mountain-noun> = { "hills"
| "foothills"
| "mount"
| { "devil's"
| "angel's"
| "broken"
}
"mountain"
| { "dragon's"
| "ogre's"
| "warlock's"
| "quarterback's"
| ""
}
{
"teeth"
| "crag"
}};
</span></code></pre>
<p>The rules in forms such as <code><color></code> describe collections of sequences that they can generate, and the stuff in forms like <code>{ "Hello" | "Goodbye"}</code> provide a branch point that the bot may choose between. In addition, the bot may carry a little bit(of arbitrary size) of state forwards and then reconstitute it on demand later on.</p>
<p>To be honest, it's a mess, but the delineation between the parsing, generation, and then posting into three separate modules makes most of the parts significantly easier to write, and the python code <a href="https://github.com/epsilon-phase/Ocaml-Bot-DFA/blob/master/bot.py" rel="noopener noreferrer">is simple enough</a>, but the mixture of langauges doesn't sit well with us.</p>
<p>Python isn't a dependency you can just say "This is light enough" for, it's a big language, with a big runtime, Mastodon.py does require its own dependencies too, and if you don't have them already installed then our bot program won't by any means feel lightweight, but the best option that we can find for ocaml would involve writing our own authentication code, but that is <em>just</em> enough effort that we don't much care to do it for this bot alone.</p>
<p>In either case, this is the first project we did after being away from ocaml for several years, so we're reasonably happy with it, even though it's definitely messier than it ought to be. </p>
]]><![CDATA[Distances]]>https://espeon.social/~/Whoa/distances/2020-01-22T04:47:15.228357+00:00Violets, Blogging Bathttps://espeon.social/@/violet/2020-01-22T04:47:15.228357+00:00<![CDATA[<p>This story contains what is arguably smut, but it doesn't go into any detail, so,,,, :)</p>
<p>Don't read it if you don't want to see that</p>
<hr>
<hr>
<p> I scramble over the unchanging ruins of a devastated world beneath me. Held together eternally by the very forces that took it apart. There are things around me. Some friendly, too friendly, the others less so, with a taste for blood, sweat, tears, half lusting for the products of love, and half frenzied for the blood quickened beneath the skin. My wings tear as they rub against the exposed rebar, knitting themselves together nearly as soon as they are withdrawn, the pain is not easy to ignore.</p>
<p> It is not a world designed for a bat such as myself. There's some motion ahead, my vision's good, but it's still not quite perfect, better than it was, if nothing else. They say it's at the lower end of what they say is normal for this particular phenotype. Just like I was before, as a man, as a human.</p>
<p> There is a distance between all worlds. The distance is measurable, but almost never traversable. The minimum energy path too multi-factored and recurrent to ever find one you can afford, let alone one that you'd ever make the trip for willingly. Like many people who find themselves different than they ever imagined they might be, you simply stumble into it.</p>
<p> A wolf springs out in front of me. I roll my eyes, we're not quite evenly matched, so I start to climb the wall of the ruined building to the side, while he's got weight on me, I've got the advantage here for avoiding him. He's the dog and I'm, well, not even the cat, I'm the fucking bat.</p>
<p> Of course, the wolf isn't quite so easy to discourage, empowered by the nanites that hold the world together and change us all, he leaps up and grabs my pants, pulling them off of me and exposing me. I look down at him and scowl, he's certainly not my type, "Fuck off!"</p>
<hr>
<p> We look at the story we have so far as it sits in the text editor, moldering under the uncertainty of how we have written it. It doesn't feel right, and the question becomes whether this wrongness stems from the fact we've never really experienced clambering over rubble with wings, or if it stems from the fact that we've never been chased with the promise of certain harm or rape should we fail to escape? The distance between all worlds is measurable: the measurement does not imply that it has been crossed.</p>
<hr>
<p> I climb and climb, to the top of the building. In previous years it might've been a wonderful place to live, or maybe a small office building. The windows were removed and replaced with plywood, someone cared enough to board it up, but in so doing deprived me of any context of what this place might've been. The world of the past is denied to us, one day it might see life within it again, or perhaps it still goes on. People, changed and altered, sitting at desks in front of piles of paper and computers, or sitting in their apartment, darker than it would've been, but still lit enough to enjoy a breakfast with the people that they care about.</p>
<p> I reach the top. Someone was already there, a jackal enjoying a cigarette and coughing. She looks at me with a mixture of pity and disgust. I pull myself up, my shirt is tattered and my pants still absent, underwear never included at all(it's a rare item here, in spite of the fact that clothing is still readily available).</p>
<p> I must look ridiculous to her. Every drag is accompanied by a cough. The coughing is strange though, even the damage cigarettes do can't last long against the machines that give us form. I catch my breath and try not to stare. Eventually concern wins out over politeness, "Are you okay?" I ask.</p>
<p> She nods, "I don't smoke very often. Having a bit of a rough day though." She gives me another look over, her eyes lingering on my exposed dick before she looks away, somehow a bit ashamed. "Why are you up here?"</p>
<hr>
<p> There are some distances that we shouldn't cross to discover the truth of. The animal at the back of our head stirs, irritated and afraid of the sense of failure that we might face should this story Not Come Out Right. We shake our head and take a sip of water, taking a moment to reflect on what this has to do with the subject of the zine we'd like to see published in.</p>
<p> Right, it's simple, it's how we realized we weren't a man. Lurid stories built out of sordid fantasies, which, like so much else, cannot be attained in full. We look down our chest and see the breasts we have grown and smile. Some distances can be reduced; some distances must be reduced for the sake of the story of your life.</p>
<hr>
<p> I felt myself flush, it's strange getting sized up like this, but not entirely unwelcome. She's really cool, such poise in her demeanor, wearing a pantsuit that fits her perfectly. "Uh... sorry, I was just getting away from some unwanted attention, and uh, they stole my pants."</p>
<p> She laughs; I feel myself shrink, "That's all?"</p>
<p> "Yeah…" I say quietly, my ears fall to the side, it feels like I'm getting dressed down even though she's barely even expressed an opinion on me. I cover myself up with my wings.</p>
<p> "Don't be ashamed then." She comes over to sit by me, she offers me a drag on the cigarette, I decline, she shrugs. "You don't have anything to feel shame for." There's a look in her eyes that I can't quite name; there are distances between people that can be measured.</p>
<p> She reaches down between my thighs.</p>
<hr>
<p> We feel a pang of sadness, thinking of her. The person we used to hang out with, the jackal herself. Of course, that was not the only mask she donned for us. None never quite matched our own as we tried to grow into ours.</p>
<p> She was the first trans woman we ever... played with, confessed our desires and developed a love for. She is a strange woman to us, at odds with facets of ourselves. She deserves the best, but we cannot be the ones to give that to her.</p>
<p> Some distances widen in spite of all you try.</p>
<hr>
<p> It's harder than I expected. I sip the drink with some distaste. Worse than the obvious taste of alcohol, I can taste the nanites inside trying to infect me, reprogram my body, change my soul. I don't need to worry, but it's irritating that they still play these pranks on patrons. Though, to be completely fair, I should've recognized it by the name of the drink, that and the rather salty umami taste and distinctive smell.</p>
<p> I finish it and try to get the bartender's attention. After a few moments spent in the company of what must've been a pleasant conversation with a regular here, they come over. "Could I get a" I fumble for something that's less liable to be a euphemism, unfortunately the menus within view are suggestive of little else, "whiskey sour?"</p>
<p> "Sure. Still on the tab?" they ask. I nod, and soon enough I'm nursing my discontent with something without anything in it besides Dionysus. I'm alone again in a loud bar full of people.</p>
<p> Changing one distance affects all others.</p>
<hr>
<p> We look at the coke can we're drinking now. We wish we had some whiskey, but we know better than to actualize that desire. So, we're playing a character that can. Wonderful. She shares our name, and, in many ways, is precisely what we'd like to be. Capable, strong, and, light, oh, and a bat. In spite of these differences, she is a mirror of us, and possesses all the flaws that we do, if only because she's an authorial avatar.</p>
<p> Playing characters we don't like was never our strong suit. We sigh and try again, bars are out, they're nearly unbearable for us, too loud, and without alcohol they're just extremely uncomfortable palaces of temptation and cost.</p>
<p> We look over to the telegram chat with our love, and we start over, focus on where we are. The distances between the means of groups of points may be iteratively sampled and determined, moving each centroid ever closer to the center of each cluster, this is the K-Means algorithm, perhaps with luck, it might work on the human heart.</p>
<hr>
<p> It doesn't feel great. I think. I sip on some water while hurting for something else. I look at the wall of the apartment and out the window to the city, this neighborhood's been refurbished cleared out, finished, and is in generally acceptable shape. There are shops that open at regular times and sell what supplies are available.</p>
<p> It's starting to return to normal, I think. Lot more varied body shapes than before, but, there's an element of interest in that. People less constrained, even if they tend to find themselves troubled by what they've experienced. So why am I so distraught? Whatever the answer is, I won't find it here. I put on some pants and a crumpled t-shirt and pick up the keys, open up the balcony's door, and drop off it, pulling up into a comfortable glide before settling down in an unoccupied area of sidewalk a block or two away from the apartment and walking the rest of the way, trying to avoid glances from everyone else on the sidewalk, looking straight ahead of me, eyes unfocused, trying to avoid eye contact or meaningful interaction with other people.</p>
<hr>
<p> We wince. Is that too truthful? It's basically why we don't go out much, why we avoid public spaces. Maybe it's agoraphobia? We've never had that diagnosed before. But then, perhaps, we weren't diagnosed with gender dysphoria, that didn't stop us.</p>
<p> We are afraid to do it alone mostly. Quick dashes outside to get groceries when living alone, time spent avoiding the gaze or suspicion or interaction. It's why we took so long to get on hrt. We aren't good alone, and for all our graces</p>
<hr>
<p> I steal into the park. It isn't a place for me. People are all too there. But I know that there's someone there I'm to meet. A girl(simplified gender) that I am here to meet. I find the bench she suggested.</p>
<hr>
<p> We look at the greyhound page again. We really want to go. We don't have much money; but we need to see her. It's stupid and silly, and we might end up biting off more than we can chew, but if we don't pursue the narrowing of the distances between the present and the future we desire, then we'll never reach it.</p>
<hr>
<p> We sit in the observation bubble, our wing wrapped around the catfox, watching the stars ahead of us through meters of diamond and metamaterial, the colors still drifting so very far, and so very shifted blue. The chances we'd end up here were so very slim, so few spots we could. We turn to her and lick her face. We smile at her and ask, "Did you think we'd ever end up here?"</p>
<p> She smiles and leans against me, looking at our eyes in the dimness of the light "No, but we did think we'd be happy with you." We pull her close, happy tears pooling in our eyes.</p>
<p> "Do you think we'll be happy there when we finally arrive?" We ask.</p>
<p> She nods, "We think so, but even if we don't, then we made the attempt." She says, shifting a bit uncomfortably.</p>
<p> We nod slowly, "At least we'll know ourselves for it better." We kiss her, "We love you."</p>
<p> Distances are uncertain and impermanent, but they are mutable. If we don't attempt to close them, then we are missing out on what our lives could be.</p>
]]>