Também disponível em: Português

Conversations with GPT-3

8 minutes read · 2020-12-06

Lately I have been playing AI Dungeon, a web-based text game that’s set up very much like a classic text adventure: It gives you an initial story blurb, and you type in commands (e.g., walk north or pick up axe) to explore the world and advance.

The key twist is that there’s no hardcoded implementation of how the game world works. The commands are fed into an AI model that simply “autocompletes” a plausible storyline. Beyond some input trickery to make sure the AI remembers the “context” around the setting and your character, it’s all free-form text.

While sometimes it prints out the odd or nonsensical result that one would normally associate with AI-generated content, I found that it works scarily well. The high-end AI model (“Dragon”) uses GPT-3 behind the scenes and is really, really good at producing good, engaging storylines.

Since GPT-3 is trained from a huge dataset of internet content, I thought it would be interesting to “interview” it inside the game world to see what it had to say on a variety of topics. I started a “Custom” game, and to nudge it in the direction of giving me high quality, intellectually meaningful results (instead of just channeling every single Internet troll in existence) I started with the following prompt:

You are sitting in front of the great oracle that can answer any question. Their eyes stare through you, fixated into the distance. This being has existed for eons. They look at you and say “what is your question?”

Thoughts on React 17

9 minutes read · 2020-09-10

On August 10 Facebook released version 17.0.0-rc0 of the React JavaScript framework. This is a pretty unusual React release in that it has fundamentally no new features. Instead, it contains a very small set of breaking changes designed to facilitate the migration to future versions of the library.

3 years of React 16

Given that the JavaScript ecosystem typically moves at breakneck pace, it’s almost impossible to believe that the 16.x line of React releases has now been going on for almost three years, with full backwards compatibility:

From 16.0 to 16.13.1, the experience of using React was completely transformed: A lot of features that were previously experimental or unergonomic to use got first-class support (Like portals and context) and we went through a lot of trials in composability, by means of Higher Order Components, Render Props and ultimately Hooks in 16.8.

What was once a Class-based object-oriented UI framework is now a Pure-functional, algebraic effects-inspired scheduler for arbitrary computation, that yeah, is still pretty good for building UIs.

And all of that without breaking backwards compatibility: Assuming you were not using private or experimental APIs (and were not depending on a library that did it) the same project written for React 16.0 should still run under React 16.13.1, with maybe a couple warnings.

Preserving that compatibility is one of the biggest accomplishments (and selling points) of React as a framework, and it makes sense: Facebook has a massive codebase with thousands of components and pages that it needs to maintain, so API stability is a must.

All of that comes at a cost, though. Some of the highly anticipated features (like Concurrent mode and Suspense for data fetching) ended up taking way more work than expected, and will require breaking backwards compatibility. React 16.9 already deprecated a bunch of lifecycle methods and saw them marked as UNSAFE_ for concurrent mode. It looks like the React team has decided it’s finally time to move on, and start shedding support for those deprecated methods for good.

Before they can do that though, they’re introducing an escape hatch for legacy codebases that can’t upgrade, in the form of React 17, by officially supporting a workflow where multiple versions of the React framework can more easily coexist in the same page side by side, and even nested “inside” each other. Unfortunately, getting that to work properly requires some breaking changes, albeit very small ones.

Pure CSS Halftone Effect

2 minutes read · 2018-02-24
Mona Lisa (Prado's version)

My First Month With Rust

8 minutes read · 2017-03-29

Roughly a month has passed since I started using the Rust programming language as my “daily driver”, and I feel like it would be interesting to share my early impressions and thoughts about the language.

Rust's Logo

NB: The title of this post is not entirely accurate, since I had been toying on and off with the language in my free time for a while. Rust has a steep learning curve, so don't feel demotivated if you don't hit the ground running in the first month.


Rust is a systems programming language with a focus on execution speed, memory and data-race safety. It's sponsored primarily by Mozilla, who are using it to develop their next generation browser engine, Servo.

Learning Curve

My first impression of Rust was that it was significantly harder to learn than most languages I had experimented with, perhaps with the exception of Haskell. During the first weeks, it felt like I didn't know how to properly structure anything beyond the simplest programs. That was quite frustrating*.

My advice if you're struggling in this stage is to power through and keep trying to use the language, even if you can't fully understand what's going on yet or get everything to work. Much like learning git and vim, it does pay off later on. After some time, it's finally going to “click”, and you'll start to develop an intuition of how things work.

The following were my major pain points during my first month with rust:

Pain Point #1: Move Semantics

Most other languages provide either copy semantics or reference semantics for dealing with values. What that means is: if you pass a variable x into a function f(), it will receive either a copy of the value in x or a reference to it. (Depending on the language and the type of x)

Rust does away with that, and opts to use move semantics by default for most custom data types. Attempting to compile the following code:

fn f(x: String) {
    // Do something with x

fn main() {
    let x = String::from("Hello");
    println!("{}", x);

Will result in an error, since the value of x is consumed by f(), and cannot be reused by println!():

rustc 1.16.0 (30cf806ef 2017-03-10)
error[E0382]: use of moved value: `x`
 --> <anon>:8:20
7 |     f(x);
  |       - value moved here
8 |     println!("{}", x);
  |                    ^ value used here after move
  = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait

error: aborting due to previous error

Instead, you need to either explicitly clone the value of x, or take a reference and pass that instead:

fn f(x: String) {
    // Do something with x

fn g(x: &String) {
    // Do something with x

fn main() {
    let x = String::from("Hello");
    println!("{}", x);

This forces you to think about ownership, which is very convenient for providing automatic memory management and compile-time optimizations. However, it does take some time getting used to.

* It doesn't help that most of the “classic” CS 101 assignments that people will commonly implement when learning a new language—e.g. linked lists, binary trees, hash tables—all traditionally involve shared mutable state, which is heavily discouraged by the language in the first place.
† Rust was not the first programming language to introduce move semantics for values. C++11 implements it to some extent via move constructors.
‡ Primitive data types—and in fact all types that implement the Copy trait—are exempt from this rule, and are instead passed by copy.

Building a Beefy VR Workstation

7 minutes read · 2017-02-06


There are plenty of inexpensive ways to experience mobile VR, including the really cheap Google Cardboard that works with any average-sized, reasonably recent smartphone. However, when it comes to the most engaging, immersive experiences, the horsepower available on mobile platforms is, as of early 2017, simply not enough.

Having decided that I'd like to get serious about VR development, I set out to spec out and build a beefy VR workstation.

VR Workstation?

For the purposes of this article, I'll define a “VR workstation” as a high-end gaming PC, that's also well suited for software development.

The requirements for VR and gaming are very similar, though VR benefits more dramatically from higher resolution and lower output latency, whereas games have historically focused more on scene complexity, realistic materials and effects.

Being cost effective was one of the goals of this build. However, the computer is meant to be used professionally, so I targetted a higher price range/quality than I would for a hobby-only rig.

Picking a CPU: i5 or i7?

Most modern games are not CPU bound, so the key component that defines gaming performance is the graphics card, with RAM and CPU being somewhat distant seconds.

If your intent is to simply consume VR content, a 6th generation or newer Core i5 should be more than enough. However, if your intent is to write software, the extra cores on the i7 can dramatically cut compilation times—which is why I decided to get the i7.

I ended up picking the Core i7 6700K Unlocked

Graphics Card

Performance-wise, NVIDIA's new Pascal architecture on the GeForce GTX 10 Series is absolutely insane, particularly for VR. I considered buying a less expensive GeForce GTX 1070 and saving the money to buy a second graphics card later, but ended up opting for a single 1080

As it turns out, the Vulkan API—which I'm interested in the most—doesn't currently support support SLI, and all multi-GPU processing needs to basically be managed manually. By the time I'd be ready to buy the second graphics card—and when/if the standard gets updated to support SLI/Crossfire—the 11 Series will be already out, and it will be time to upgrade my GPU anyway.

As for the maker, I decided to go with EVGA based on a friend's recommendation, but it seems to be a matter of personal preference, mostly.

Due to shipping constraints at the time, my pick was the EVGA GeForce GTX 1080 SuperClocked, though I would probably recommend the FTW edition otherwise.