# Cursed Rust: Printing Things The Wrong Way

### — Let's have some fun with 'Hello, world!'

Tagged withdevrust

There is a famous story about a physicist during an exam at the University of Copenhagen. The candidate was asked to describe how to determine a skyscraper's height using a barometer. The student suggested dangling the barometer from the building's roof using a string and then measuring the length of the string plus the barometer's height. Although technically correct, the examiners were not amused.

After a complaint and a reevaluation, the student offered various physics-based solutions, ranging from dropping the barometer and calculating the building’s height using the time of fall, to using the proportion between the lengths of the building's shadow and that of the barometer to calculate the building's height from the height of the barometer. He even humorously suggested simply asking the caretaker in exchange for the barometer.

The physicist, as the legend goes, was Niels Bohr, who went on to receive a Nobel Prize in 1922. This story is also known as the barometer question.

## Why Is This Story Interesting?

The question and its possible answers have an important didactic side effect: they convey to the learner that one can also get to the solution with unconventional methods — and that these methods are often more interesting than the canonical solution because they reveal something about the problem itself.

There is virtue in learning from unconventional answers to conventional questions. To some extent, this fosters new ways of thinking and problem-solving, which is an essential part of innovation.

## Applying The Same Principle To Learning Rust

One of the first examples in any book on learning Rust is the "Hello, world!" program.

``````fn main() {
println!("Hello, world!");
}
``````

It's an easy way to test that your Rust installation is working correctly.

However, we can also have some fun and turn the task on its head: let's find ways to print "Hello, world!" without using `println!`.

Let's try to come up with as many unconventional solutions as possible. The weirder, the better! As you go through each of the solutions below, try to understand why they work and what you can learn from them.

This started as a meme, but I decided to turn it into a full article after the post got a lot of attention.

It goes without saying that you should never use any of these solutions in production code. Check out this enterprise-ready version of hello world instead.

## Solution 1: Desugaring `println!`

``````use std::io::Write;

write!(std::io::stdout().lock(), "Hello, world!");
``````

This solution is interesting, because it shows that `println!` is just a macro that expands to a call to `write!` with a newline character appended to the string.

The real code is much weirder. Search for `print` in this file if you want to be amazed. `write!` itself desugars to a call to `write_fmt`, which is a method of the `Write` trait.

There is a real-world use case for this: if you want to print things really fast, you can lock `stdout` once and then use `write!`. This avoids the overhead of locking `stdout` for each call to `println!`. See this article on how to write a very fast version of `yes` with this trick.

## Solution 2: Iterating Over Characters

``````"Hello, world!".chars().for_each(|c| print!("{}", c));
``````

This shows that you can implement `println!` using Rust's powerful iterators. Here we iterate over the characters of the string and print each one of them.

`chars()` returns an iterator over Unicode scalar values.

## Solution 3: Impl `Display`

``````struct HelloWorld;

impl std::fmt::Display for HelloWorld {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Hello, world!")
}
}

println!("{HelloWorld}");
``````

This teaches us a little bit about how traits work in Rust: We define a struct that implements the `Display` trait, which allows us to print it using `print!`. In general, `Display` is intended to make more complex types printable, but it is also possible to implement it for a hardcoded string!

## Solution 4: Who Needs `Display`?

How about we create our own trait instead of using `Display`?

``````trait Println {
fn println(&self);
}

impl Println for &str {
fn println(&self) {
print!("{}", self);
}
}

"Hello, world!".println();
``````

We can exploit the fact that we can name our trait methods however we want. In this example, we choose `println`, making it look like it is part of the standard library.

This completely turns the `println!` macro on its head. Instead of passing a string as an argument, we call a method on the string itself!

## Solution 5: Who Needs `println!` When You Got `panic!`?

``````panic!("Hello, world!");
``````

There are other ways to print things in Rust than using `println!`. In this case, we use `panic!`, which prints the string (as a side-effect) and immediately terminates the program. It works as long as we only want to print a single string...

## Solution 6: I ♥︎️ Closures

``````(|s: &str| print!("{}", s))("hello");
``````

Rust allows you to call a closure directly after its definition. The closure is defined as an anonymous function that takes a string slice as an argument and prints it. The string slice is passed as an argument to the closure.

In practice, this can be useful for defining a closure that is only used once and for which you don't want to come up with a name.

## Solution 7: C Style

``````extern crate libc;
use libc::{c_char, c_int};
use core::ffi::CStr;

extern "C" {
fn printf(fmt: *const c_char, ...) -> c_int;
}

fn main() {
const HI: &CStr = match CStr::from_bytes_until_nul(b"hello\n\0") {
Ok(x) => x,
Err(_) => panic!(),
};

unsafe {
printf(HI.as_ptr());
}
}
``````

You don't even need to use Rust's standard library to print things! This example shows how to call the C standard library's `printf` function from Rust. It's unsafe because we are using a raw pointer to pass the string to the function. This teaches us a little bit about how FFI works in Rust.

Credit goes to /u/pinespear on Reddit and @brk@infosec.exchange.

## Solution 8: C++ Style

We're well into psychopath territory now... so let's not stop here. If you try extremely hard, you can bend Rust to your will and make it look like C++.

``````use std::fmt::Display;
use std::ops::Shl;

#[allow(non_camel_case_types)]
struct cout;
#[allow(non_camel_case_types)]
struct endl;

impl<T: Display> Shl<T> for cout {
type Output = cout;
fn shl(self, data: T) -> Self::Output {
print!("{}", data);
cout
}
}
impl Shl<endl> for cout {
type Output = ();
fn shl(self, _: endl) -> Self::Output {
println!("");
}
}

cout << "Hello World" << endl;
``````

The `Shl` trait is used to implement the `<<` operator. The `cout` struct implements `Shl` for any type that implements `Display`, which allows us to print any printable type. The `endl` struct implements `Shl` for `cout`, which prints the newline character in the end.

Credit goes to Wisha Wanichwecharungruang for this solution.

## Solution 9: Unadulterated Control With Assembly

All of these high-level abstractions stand in the way of printing things efficiently. We have to take back control of your CPU. Assembly is the way. No more wasted cycles. No hidden instructions. Pure, unadulterated performance.

``````use std::arch::asm;

const SYS_WRITE: usize = 1;
const STDOUT: usize = 1;

fn main() {
#[cfg(not(target_arch = "x86_64"))]
panic!("This only works on x86_64 machines!");

let phrase = "Hello, world!";
let bytes_written: usize;
unsafe {
asm! {
"syscall",
inout("rax") SYS_WRITE => bytes_written,
inout("rdi") STDOUT => _,
in("rsi") phrase.as_ptr(),
in("rdx") phrase.len(),
// syscall clobbers these
out("rcx") _,
out("r11") _,
}
}

assert_eq!(bytes_written, phrase.len());
}
``````

If you're wondering why we use Rust in the first place if all we do is call assembly code, you're missing the point! This is about way more than just printing things. It is about freedom! Don't tell me how I should use my CPU.

Okaaay, it only works on x86_64 machines, but that's a small sacrifice to make for freedom.

Submitted by isaacthefallenapple.

## Solution 10: "Blazing Fast"

Why did we pay a premium for all those CPU cores if we aren't actually using them? Wasn't fearless concurrency one of Rust's promises? Let's put those cores to good use!

``````use std::sync::{Arc, Mutex};
use std::time::Duration;

fn main() {
let phrase = "hello world";
let phrase = Arc::new(Mutex::new(phrase.chars().collect::<Vec<_>>()));

let mut handles = vec![];

for i in 0..phrase.lock().unwrap().len() {
let phrase = Arc::clone(&phrase);
let handle = thread::spawn(move || {
thread::sleep(Duration::from_millis(((i + 1) * 100) as u64));
print!("{}", phrase.lock().unwrap()[i]);
});
handles.push(handle);
}

for handle in handles {
handle.join().unwrap();
}
println!();
}
``````

Here, each character is printed in a separate thread. The threads are spawned in a loop, and each thread sleeps for a certain amount of milliseconds before printing its character. This uses the full power of your CPU to print a string! It might not always consistently print the characters in the right order (hey, scheduling is hard!), but that's a worthwhile trade-off for all the raw performance gains.