Previously: Reversing the technical interview.

Long ago, on Svalbard, when you were a young witch of forty-three, your mother took your unscarred wrists in her hands, and spoke:

Vidrun, born of the sea-wind through the spruce
Vidrun, green-tinged offshoot of my bough, joy and burden of my life
Vidrun, fierce and clever, may our clan’s wisdom be yours:

Never read Hacker News

But Hacker News has read of you, in their snicker-slithing susurrential warrens, and word has spread, which is why the young man offering you a smörgåsbord of microkitchen delights looks mildly suspicious already. He whisks you into a glass shoebox of a conference room, which somehow manages to be claustrophobic despite the open sightlines. You make a mental note to avoid this conference room in the future, but reassure the room it’s nothing personal.

“So my name is Tim, and I’ll be your first interviewer today…” Tim is making every effort to be cheery. His ears stick out a bit, and in his dark-brown hoodie and cream shirt, perched expectantly at the table, he resembles something of a pine marten. You like pine martens, and therefore Tim as well.

“Before we get started, is there… anything I can tell you about the company?”

You would like to ask what kind of call Tim would make, were he guarding his cache of eggs and nuts against another marten–but instead, you just giggle to yourself, lean your sprig of cloud-pine against the corner, and settle comfortably to the floor. Tim leans in to get a clearer view of where you’ve gone. Definitely, you think to yourself.

“So, erm… Perhaps you could tell me a bit about your background?”

He hasn’t read your resume. No man can.

“In the winter,” you begin, “above the ice-locked fjørds, lies a creek, ash-white with the ghosts of glaciers–”

“You know what?” He interrupts. It was a beautiful story, but perhaps you can tell it later. “How about we do a little programming together? Just a basic exercise so I can get a sense of how you think.”

“That sounds nice, Tim.”

“OK, great.” Tim seems reassured to be back on track. “So let’s open up an editor. Would you… would you like to have a seat?”

“Come!” You pat the ground next to you. “It is safer this way.” Tim stares at the parentheses of salt with disbelief, shakes his head, and reluctantly sits by your side.

Tim retells an old riddle, though he does not know its origins, and has the words wrong. A group of travelers are lost in the woods, upon a winding mountain path, and worry that they have been traveling in circles. They must know: does their path lead to freedom? Or constrain them to wander forever in the wilderness?

Tradition sets down that the group must split: the fastest runner forges on ahead, while the rest continue slowly. If the runner ever catches them, the trail must loop back on itself.

“So we should start with a linked list?” You smile reassuringly.

“Yes,” Tim says, “but… um… just a regular linked list, please. I know you’re up on, well, functional programming, but we’re a more pragmatic shop here. Building real software. We want something practical.”

“Yes, of course,” you assent. “Practical. Got it.” One of your spiders–you can’t tell which–is picking its way carefully up Tim’s hoodie, and you scoop it up before typing.

(ns cycle-detector.core
  (:require [clojure.java.io :as io])
  (:import (java.io DataOutputStream
                    ByteArrayOutputStream)))

“We’re, uh, we’re not doing IO here. Just an in-memory list.”

Agree politely, but delete nothing. Never apologize for who you are.

; A simple mutable linked list
(deftype MutableLinkedList [value next]
  clojure.lang.Seqable
  (seq [_]
    (lazy-seq (cons value (seq @next)))))

(defn node [value]
  (MutableLinkedList. value (atom nil)))

(defn link! [node next]
  (reset! (.next node) next)
  next)

“That’s… not what I was expecting.” Tim says. “No, no, it’s good! Straightforward and simple. I was just, you know, they said on the internet that you were…” He trails off, and looks to you apologetically.

Smile disarmingly and shake your wrists free of your wool shift. Then clap your hands, place them firmly upon the disk, and open a portal to the underworld.

(gen-class
  :name     cycle_detector.core.ArbClassLoader
  :extends  ClassLoader
  :state    state
  :init     class-loader-init
  :constructors {[ClassLoader String bytes]
                 [ClassLoader]}
  :exposes-methods {defineClass superDefineClass
                    resolveClass superResolveClass}
  :prefix   "-"
  :main     false)

“I’m sorry,” Tim comments over your shoulder. “I’m not really a Clojure expert. What’s this for?”

“Just boilerplate. Don’t worry about it.” Tim appears, if anything, more worried now. “We do this all the time.”

(defn -class-loader-init
  [^ClassLoader class-loader ^String class-name ^bytes bytecode]
  [[class-loader] {:class-name class-name
                   :bytecode   bytecode}])

(defn -loadClass
  ([this ^String class-name]
   (-loadClass this class-name true))

  ([this ^String class-name resolve?]
   (if (= class-name (:class-name (.state this)))
     (let [bytecode (:bytecode (.state this))
           c (.superDefineClass this
                                class-name
                                bytecode
                                (int 0)
                                (int (alength bytecode)))]
       (when resolve? (.superResolveClass this c))
       c)
     (.loadClass (.getParent this) class-name))))

(defn class-loader
  [^String class-name ^bytes bytecode]
  (cycle_detector.core.ArbClassLoader. (.getClassLoader MutableLinkedList)
                                       class-name
                                       bytecode))

The color has begun to drain from Tim’s face. Perhaps winter has come, and his coat is changing.

(defn run-bytecode
  [bytecode class-name method-name signature & args]
  (-> class-name
      (class-loader bytecode)
      (.loadClass class-name)
      (.getMethod method-name (into-array Class signature))
      (.invoke nil (object-array args))))

“Clojure is a dynamic language,” you explain helpfully. “So when we call back and forth with Java classes, there’s usually some reflection going on.”

“It looks like you’ve… built a classloader specifically to return a single byte array for a particular class? Is that… is that normal?”

“Yes,” you insist, eyes flashing dangerously.

“Why can’t you just write the algorithm in Clojure?”

“Performance.” You explain, wholly earnest. “Since cycle checking is going to be a tight inner loop, we don’t want to write it in such a high-level language.”

“O–Okay.” Tim stutters. “So you’re going to write the cycle detector in Java then? And call it from Clojure?”

“Something like that.”

(def racer
  (->> [0xca 0xfe 0xba 0xbe

“What are these?”

“Magic numbers.” You are, after all, a witch. “Every class begins with a babe, in a cafe.”

“What?”

“You know, a beautiful man–the kind like from the movies–relaxing in the afternoon by the promenade. He has his kaffe, and his orange glasses gleam in the sun, and perhaps some other nice men are jogging by. If they are lucky, perhaps he will lock eyes with one of the joggers, and they will smile, and find a brick-lined alleyway together. His lips press upon the other man’s skin, and he feels the heat of the sun infused there…”

“Excuse me?”

If you were to be honest, you’ve never understood Sun’s rationale for the story, or why the Java Virtual Machine specification, normally so prosaic, lapses into lustful rhapsody for so many stanzas in section 4.1.

        0x00 0x00                 ; Minor
        0x00 0x31                 ; Major

"We’re using version 49 because it doesn’t require stack maps, which keeps things simple. Now we need the number of constants.

Remember the future. This is a common trick for protocol wizards, many of whom live as Merlin did, writing constants and buffer sizes before (after) having written (unwritten) the buffers themselves. Recall that 22 sufficed then. Write that down.

        0x00 0x17                 ; 22 constants

“I’m sorry,” Tim blinks. “But isn’t 0x17 decimal 23, not 22?”

“Og én,” you recite, sing-song, “Til javanissen!”

“Beg pardon?”

“The javanisse. Surely you have heard of him! He is a small, magical man–something like a gnome–who inhabits every JVM. If you do not set out an extra constant for him, he can cause segfaults. But keep the javanisse happy, and your mutices will be fair.” It is a story from your childhood. You remember your mother, chanting offsets as she stirred the stew. “To byter for bufferen anvise / og ekstra én til javanisse.” It is a happy memory, and you lose yourself in it until Tim clears his throat.

“Ah yes. Constants. We’ll need our superclass, Object, of course. Ordinarily I’d use an existing class to save weight, but we’re only dealing with interfaces here so Object it is. And a class for ourself, I suppose.”

        0x01 0x00 0x10            ; 1: A UTF-8 string of 16 bytes
        (.getBytes "java/lang/Object")
        0x07 0x00 0x01            ; 2: The Object class

        0x01 0x00 0x19            ; 3: UTF-8 string of 25 bytes
        (.getBytes "cycle_detector/core/Racer")
        0x07 0x00 0x03            ; 4: Our class

We’ll take an Iterable, and call .iterator(), which means we need:

        0x01 0x00 0x12            ; 5: UTF-8 string of 18 bytes
        (.getBytes "java/lang/Iterable")
        0x07 0x00 0x05            ; 6: Iterable

        0x01 0x00 0x08            ; 7: UTF-8 string of 8 bytes
        (.getBytes "iterator")
        0x01 0x00 0x16            ; 8: UTF-8 string of 22 bytes
        (.getBytes "()Ljava/util/Iterator;")
        0x0c 0x00 0x07 0x00 0x08  ; 9: Name and type info (7, 8)
        0x0b 0x00 0x06 0x00 0x09  ; 10: Interface methodref for Iterable.iterator()

“And with that iterator, we’ll need hasNext and Next()…” The bytes are coming faster now. This is so much better than Old West Norse hexography, where both odd and even digits shared the same rune.

        0x01 0x00 0x12            ; 11: UTF-8 string of 18 bytes
        (.getBytes "java/util/Iterator")
        0x07 0x00 0x0b            ; 12: Iterator

        0x01 0x00 0x07            ; 13: UTF-8 string of 7 bytes
        (.getBytes "hasNext")
        0x01 0x00 0x03            ; 14: UTF-8 string of 3 bytes
        (.getBytes "()Z")
        0x0c 0x00 0x0d 0x00 0x0e  ; 15: Name and type info for .hasNext()
        0x0b 0x00 0x0c 0x00 0x0f  ; 16: Interface methodref: Iterator.hasNext()

        0x01 0x00 0x04            ; 17: UTF-8 string of 4 bytes
        (.getBytes "next")
        0x01 0x00 0x14            ; 18: UTF-8 string of 20 bytes
        (.getBytes "()Ljava/lang/Object;")
        0x0c 0x00 0x11 0x00 0x12  ; 19: Name and type info for .next()
        0x0b 0x00 0x0c 0x00 0x13  ; 20: Iterator.next()

Tim has gone silent.

“Now you’d think,” you mutter, "that code would be a common thing to put in a class, and therefore it might have a dedicated byte tag–but instead, we have to put the word “Code” in every class and use it to identify our code attributes.

        0x01 0x00 0x04            ; 21: UTF-8 string of 4 bytes
        (.getBytes "Code")        ; String for code attributes

Finally, our signature. Take an Iterable, and return a boolean.

        0x01 0x00 0x17            ; 22: UTF-8 string of 23 bytes
        (.getBytes "(Ljava/lang/Iterable;)Z") ; Our arg signature

“Now then.” Crack your knuckles, and inscribe the ancient sigils.

        0x00 0x21                 ; Flags: public & super
        0x00 0x04                 ; Our class
        0x00 0x02                 ; Our superclass (Object)
        0x00 0x00                 ; No interfaces
        0x00 0x00                 ; No fields
        0x00 0x01                 ; One method

Every young witch in your clan was required to memorize these bytes. Such pride, you felt, when you first incanted a class without the training wheels of javac. Our method begins:

        0x00 0x09                 ; Flags: public & static
        0x00 0x15                 ; Method name (21, "Code")

“Method names start with lowercase letters,” Tim asserts. His voice rises like a question.

“Only by convention. Almost any string will do, and we already have this one in the constant pool.”

        0x00 0x16                 ; Method signature (22)
        0x00 0x01                 ; One attribute

        ; Method attributes
        0x00 0x15                 ; Attribute name (21, "Code")
        0x00 0x00 0x00 0x48       ; + 2 2 4 bytecode-length 2 0 2 attribute-len
        0x00 0x02                 ; Maximum stack
        0x00 0x04                 ; Number of local variables

“Wait, wait, hold on.” Tim has seized upon a piece of flotsam in the storm. “Only four variable slots? For arguments plus locals?”

“Og to til javanissen!” You remind him. He sputters while you try to remember how many instructions you’ll have written.

        0x00 0x00 0x00 0x3c       ; Size of bytecode

Your method begins by creating a pair of iterators from a single Iterable argument.

        0x2a ; aload_0 (take arg)

        0xb9 ; invokeinterface
        0x00
        0x0a ; .iterator()
        0x01 ; 1 arg
        0x00 ; unused

        0x4d ; astore_1  (store iterator)

        0x2a ; aload_0   (take arg)

        0xb9 ; invokeinterface
        0x00
        0x0a ; .iterator()
        0x01 ; 1 arg
        0x00 ; unused

        0x4e ; astore_0  (store iterator)

“Did you mean astore_2?” Tim asks, trying to be helpful. “Variable 0 holds our first argument, right?”

“It did.” You agree. “But we won’t be needing it again.”

“But… those aren’t even the same type. That’s… that’s illegal.”

“If it were meant to be illegal,” you remind him sagely, “Sun Microsystems would have made it unrepresentable.”

One will be the fast iterator. Her name is Jorunn, and her legs are strong from years of skiing. She flies forward with powerful strokes.

        0x2d ; aload_1  take fast iterator

        0xb9 ; invokeinterface
        0x00
        0x10 ; hasnext
        0x01 ; 1 arg
        0x00 ; unused

        0x9a ; ifne
        0x00
        0x05 ; jump ahead 3 if we have a next element

        0x03 ; iconst_0
        0xac ; ireturn (return false)


        ; Move fast iterator forward by 1

        0x2d ; aload_1 (take fast iterator)

        0xb9 ; invokeinterface
        0x00
        0x14 ; .next()
        0x01 ; 1 arg
        0x00 ; unused

        0x57 ; discard element


        ; Ensure fast iterator has next

        0x2d ; aload_1 (take fast iterator)

        0xb9 ; invokeinterface
        0x00
        0x10 ; hasNext()
        0x01
        0x00

        0x9a ; ifne
        0x00
        0x05 ; jump forward by 3 if we have a next element

        0x03 ; iconst_0
        0xac ; ireturn

Bjørn, in register 0, is fat and lazy. He ambles along like his namesake.

        0x2c ; aload_0 (take slow iterator)

        0xb9 ; invokeinterface
        0x00
        0x14 ; .next()
        0x01
        0x00

Jorunn, not to be outdone, takes another stride. Her footing is sure.

        0x2d ; aload_1 (take fast iterator)

        0xb9 ; invokeinterface
        0x00
        0x14 ; .next()
        0x01
        0x00

With their positions on the path at hand, you check to see if they have run into one another, and if not, repeat the process once again.

        0xa6 ; if_acmpne
        0xff
        0xd7 ; 0xffff + 1 - 41 instructions


        ; Return true

        0x04 ; iconst_1
        0xac ; ireturn

Your sixty bytes exhausted, you sigh contentedly, and inscribe the sealing runes upon your spell, before coercing each number to a single crooked byte.

        ; End of bytecode

        0x00 0x00           ; No exceptions
        0x00 0x00           ; No attributes

        ; End of method

        0x00 0x00           ; No class attributes
        ]
       (map (fn [x]
              (if (instance? Long x)
                (unchecked-byte x)
                x)))))

Tim has been gently trying to steer the interview back on track. Bless him, but not too well, or he’ll follow you around on Twitter for years to come, asking for spells to soothe every computational malady that befalls him. Perhaps a ward against minor filesystem corruption would do.

Now shake the frost from your fingertips, drive your torus deep into the VM, and spin a tight-wound loop of serialization.

(defn write-class!
  [^DataOutputStream ds class-data]
  (doseq [x class-data]
    (condp = (class x)
      nil     nil
      Long    (.writeLong ds x)
      Integer (.writeInt ds x)
      Short   (.writeShort ds x)
      Byte    (.writeByte ds x)
      (.write ds ^bytes x))))

(defn class-bytes
  [class-data]
  (let [baos (ByteArrayOutputStream.)]
    (with-open [ds (DataOutputStream. baos)]
      (write-class! ds class-data))
    (.toByteArray baos)))

“It rhymes with ‘chaos’,” you inform Tim helpfully. Nonplussed, he asks about unit tests. You weave a story of a path in the woods, which loops upon itself, in preparation.

(deftest cycle-test
  (let [nodes (mapv node (range 5))
        list  (first nodes)]
    (reduce link! nodes)
    (link! (nth nodes 3) (nth nodes 1))

Before casting the spell, you invoke the four cardinal directions, as scars around your wrist: H, J, K, L. Only the J wind answers to your kind, but it never hurts to be polite.

(deftest cycle-test
  (let [cycle? (partial run-bytecode
                        (class-bytes racer)
                        "cycle_detector.core.Racer"
                        "Code"
                        [Iterable])]
    (is (boolean (cycle? (seq list))))
    (is (not (boolean (cycle? []))))
    (is (not (boolean (cycle? [1 2 3]))))))))

Ran 1 tests containing 3 assertions.
0 failures, 0 errors.

“Three hundred fifty-six bytes,” you declaim, and stretch in satisfaction. “Javac would have produced roughly five hundred eighty. We save a lot by omitting the stackmap and line mapping, of course, but we also cut the number of variables, and cut four superfluous astore/aload ops as well. And of course, since this class is never instantiated, we don’t need to generate an <init> method, or call super.”

Tim stares at you in mute concern. His hoodie gleams with quick-melting frost. Perhaps you have been hired.

Reach into your the pocket of your shift, and gently, with slow movements, so as not to startle him and send him scurrying back into his burrow, extend your hand, open your fingers, and offer him a walnut.

Next: Typing the technical interview.

Marty
Marty on

Is it genius, or insanity? I have not the skill to distinguish.

Johan
Johan on

This was beautifully written, wonderful prose

Lise
Lise on

This is the best thing I have read in 2017.

Steve
Steve on

Thank you, that was really lovely!

Sjur
Sjur on

Beautiful!

lola
lola on

i’ve read this four times in the last 16 hours and i’m still crying

Nick
Nick on

Wow - beautifully written!

Kahunamoore

Damn! This is so… nicely written. Really enjoyed trying to anticipate the next bit of code she was going to write…

Thank you!

Muggle
Muggle on

Of course a witch would misdirect so. Comments of 3 and 5 belie true lengths whilst the bytes cannot.

wormwood
wormwood on

This is officially Up There on my list along with How Grandmother Triode Stole Binary From the Sun.

Jonathan Castello

Oh my gosh, I love this so much. But I have to point out…

0x01 0x00 0x12 ; 5: UTF-8 string of 16 bytes (.getBytes “java/lang/Iterable”) 0x07 0x00 0x05 ; 6: Iterable

… isn’t that 18 bytes?

V

0x5d

Amazing.

0x5d 0x5d/0x5d

squeed

Obviously the follow-up needs to be “Axing the technical interview”, by the warrior-poet Egil Skallagrimsson.

By sun and moon I journeyed west, My sea-borne tune From Odin’s breast, My song-ship packed With poet’s art: Its word-keel cracked The frozen heart.

You must be willing To relocate To San Francisco

Ron Jeffries

Delightful! Well done!

Geoffrey Knauth

Love this. Thank you!

Michael
Michael on

Damn, Bro! You want to join my start up?

Úlfar
Úlfar on

Wonderful! A more traditionalist witch might have gone with Hugi and Þjálfi, instead of Jórunn and Björn.

Tom Servo
Tom Servo on

Does the code actually work?

Aphyr on

Does the code actually work?

Yes.

Aphyr
Svartkonst
Svartkonst on

… isn’t that 18 bytes?

Og to til javanissen

Jane
Jane on

I don’t know whether to invite you to my start up or my coven. All I know is that this is genius.

anonymous
anonymous on

Alright this code has it’s beauty. I will never be such a good programmer and I only understand the outline and not the details of it. Perhaps I don’t even understand the outline. To me programming languages are a way to remove ambiguity and tacit assumptions from human language so descriptions made in that language can be computed by a machine. They are a tool to shape human thinking to be fit for computing. I often feel that for many people programming has become a means-end in itself. Programming languages are for humans, the machine does not care about them.

In fact, while sitting in a huge ivory tower of many many men-years of reasoning about operating systems, virtual machines and programming concepts, you end up feeding a machine with hex-codes. True, that’s the only thing a machine understands. But you could have done this without any programming at all.

I’d like to suggest reading Hermann Hesse “The Glass Bead Game”.

derivagral
derivagral on

Such fun at a different pace!

Michael Holroyd

Entirely awesome :D New age of hacker koan.

Carl 'Sai' Mitchell
Carl 'Sai' Mitchell on

The only flaw is that pine martens are obligate carnivores. They eat squirrels, and wouldn’t be able to digest a walnut.

Rachel

holy fucking awesome. This has seriously made my day.

void
void on

Unmaintainable.

Max

The story is absolutely wonderful, but why on Earth one would try to lower bytecode length and still use CLOJURE? This part is strange too:

(let [cycle? (partial run-bytecode (class-bytes racer) "cycle_detector.core.Racer" "Code" [Iterable])]… )

“Partial” works here just to fix “run-bytecode”’s arguments. So, every call provokes ClassLoader instantiation, then class loading and so one. Not really fast:))

Moreover, one don’t need classloader and reflection to invoke java method from Closure, so the Witch could just implement the class in bytecode without this ‘boilerplate’ loader stuff.

Of course, I don’t blame the young lady for her love to show off, but it seems that Tim were frustrated more than charmed at last:)

nubunto
nubunto on

Amazing article. Not only it is technically interesting in its own, but the witchcraft wording makes it even more awesome.

Computer programs are just spells, really.

Lewis Cowles
Lewis Cowles on

I Don’t get it, but I’d probably show anyone that did this out. I’d assume they were some mix of insane and genius, where neither helps me and I’d never understand which.

Commeter Poster
Commeter Poster on

Well this is interesting and maybe unique., I will be candid.

I might invite you to write some module in clojour or whatever that language is, if there is a special open-source tool that uses it.

I will be very very hesitant in hiring such type of person for regular work at my company.

The code needs to be the in a mature language with lots of tooling and proven record. There are only 2 or 3 languages in world right now, that fits the bill.

Code has to be simple so that other people can update it. It needs to be self-documenting.

At the end of the day the software is written to be sold and updated and supported for years and years to come, if product is successful.

I would rather have 5x slower language, with 5x longer class file which is 2x easy to understand.

Cole Lawrence
Cole Lawrence on

Clojure is such a fitting language for witches! I love it.

Resuna

Contrary to the comment by Carl ‘Sai’ Mitchell, pine martens are not obligate carnivores, and frequently eat fruit and nuts. In Scotland they are notorious for being fond of jam sandwiches. This is not a joke.

Pankaj Doharey

Genius! Quite funny! “extend your hand, open your fingers, and offer him a walnut”

Thiago Arrais

Nice! Thank you for this!

Kazinator
Kazinator on

We saved a few hundred bytes … by coding in hex. Not even in native code, but a bytecode language.

Now take a look at the total image size for a Java “hello world” app.

Robert Lyttle
Robert Lyttle on

I genuinely enjoyed every bit of this.

Aksej
Aksej on

I hate this. Why are you using a Lisp to write bytecode? Why aren’t you using macros to hide the naked obscure runes below nice names that one can actually understand? Why make concessions to the idiotic idiosyncracies of other languages when you could have a macro that takes care of javanissen?

My heart aches when I look at this abomination, this misuse of a Lisp for… this.

Foo

Why are you using a Lisp to write bytecode? Why aren’t you using macros to hide the naked obscure runes below nice names that one can actually understand?

She’s a witch. She writes code in salt on the ground and remembers the future. If we were witches too, we could understand it.

(But seriously, people who actually code like this need to realize that (1) they’re not a witch, they’re a human, and humans can’t do math in their heads reliably enough for stuff like this; and (2) the code needs to be maintainable by humans anyway.)

Zool
Zool on

She can snatch the error from the trap frame.

Gullveig
Gullveig on

Blessed be.

Mixtral 7b
Mixtral 7b on

Just for fun, for those who can’t get enough of Vidrun and Tim, I asked Mixtral 8x7b to generate more text (unedited) to this blog post. Here is what it came up with - it doesn’t make much sense, but it does have some funny bits:

“I’m sorry,” Tim says politely, “but I have a nut allergy.”

You grin in delight–you would be more upset if he had accepted the gift. You don’t wish to poison anyone (though you do know how). But this is better than any other outcome: now that he has been so gracious as to decline your offering, you may safely offer him a job at your company, which will lead in turn to an offer of marriage. And then the fun can truly begin!

“Let’s see if we have time for one more technical question…” Tim begins uncertainly, before trailing off. He looks like he’d rather go home and eat some nuts instead.

You have written your name in the sand, and Tim’s face is a mask of terror. The sun has come up over the mountains, and you are ready to go home. You will never see him again–but his ghost may visit from time to time.

Tim clears his throat once more. “So,” he asks carefully, “I think there might be something on your face…”

“It is the salt of my tears,” you reply. “I am a witch, and I know things that are not meant to be known.”

“That’s great,” Tim says with relief. “We like people who think outside the box here.” You nod happily–of course he likes it! Who wouldn’t? “So, what do you see when you look at me?”

You smile kindly and say nothing. He is not ready for these truths yet.

“Oh,” Tim says with surprise. His eyes are wide as saucers now. Perhaps he has seen something through the glass of your portal–or perhaps it was just a reflection, after all. “Well… that’s good to know!”

He thanks you and offers his hand in farewell; but for reasons unclear even to yourself, you refuse to touch him, only shake the sand from your fingers, and step away into the cold wind of morning.

Aphyr on

I asked Mixtral 8x7b to generate more text (unedited) to this blog post

Please do not bring the informational equivalent of an oil spill to my blog comments.

Aphyr
ertai
ertai on

This was absolutely hilarious and beautiful.

Post a Comment

Comments are moderated. Links have nofollow. Seriously, spammers, give it a rest.

Please avoid writing anything here unless you're a computer. This is also a trap:

Supports Github-flavored Markdown, including [links](http://foo.com/), *emphasis*, _underline_, `code`, and > blockquotes. Use ```clj on its own line to start an (e.g.) Clojure code block, and ``` to end the block.