Novel Programming Language Features

  ·   4 min read

🔐 Secret type #

In Google’s experimental language Rune, which is “is a programming language developed to test ideas for improving security and efficiency”, they introduce a new Secret type with a number of interesting properties.

A Secret type has the following properties (as described in Rune and derivative third-party libraries inspired by Rune):

  1. Secrets can wrap any primitive value
  2. Secrets may not have their value printed or logged
  3. Secrets have their values encrypted at-rest
  4. Values derived from Secrets become Secrets themselves (described as “viral” or “sticky”)
  5. Secret booleans may not be used in control flow (otherwise it would be trivial to determine the secret boolean value with a simple if/else)
  6. Equality checks between Secrets are guaranteed to be performed in constant time, mitigating timing side-channel attacks
  7. Secrets are automatically zeroed out and garbage collected once out-of-scope
// Pseudocode examples

// Rule 1: secrets can wrap any primitive value
secret int x = 5
secret string name = "Greg"

// Rule 2: cannot print or log secrets
print(x) // ERROR

// Rule 4: values derived from secrets must also be secret
secret int y = x + 1
int z = x + 1 // ERROR

// Rule 5: secret booleans cannot be used in control flow
secret bool isBlog = true
if (isBlog) { // ERROR
  publish()
}

// Rule 6: constant-time equality checks to prevent timing side-channel attacks
secret string userCode = promptUserForCode()
secret string serverVerificationCode = ...
if (userCode == serverVerificationCode) { // constant-time string comparison, O(1)
  success()
}

⛓ Cascade operator .. #

The builder pattern is a typical pattern in modern programming, where a class method performs some action or mutation, and then returns the instance. This allows a developer to chain together multiple method calls:

Spell fireballSpell = Spell.create("Fireball")
  .setHotkey("F")
  .setDamage(25)
  .setRange(300)
  .setSoundEffect(...)
  .build()

This is sometimes useful for classes that can have many fields and values, rather than having a constructor with lots of parameters. One could imagine the messiness of the above Spell constructor otherwise: __init__(spell_name, hotkey, damage, range, sound_effect, way_too_many_other_parameters, ...).

The downside is that for each of these methods, we need boilerplate that sets an internal value and returns the instance.

WurstScript adds what it calls the “cascade operator”. As described in the documentation:

The cascade operator .. is similar to the normal . operator and can be used for calling methods, but instead of returning the result of the called method, the cascade operator returns the receiver. This makes it possible to easily chain function calls on the same variable.

The example they provide illustrates this nicely:

CreateTrigger()
  ..registerAnyUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER)
  ..addCondition(Condition(function cond))
  ..addAction(function action)

// is equivalent to

let temp = CreateTrigger()
temp.registerAnyUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER)
temp.addCondition(Condition(function cond))
temp.addAction(function action)

⏲ Time/duration primitives #

When we want to work with times, dates, and operations like adding or calculating differences between them, we turn to datetime classes. For instance, Python has the datetime and timedelta classes to represent times and durations respectively.

These are handy, but what if a programming language could understand these types natively?

Let’s compare two examples:

# Python
from datetime import datetime, timedelta

some_date = datetime(2024, 3, 31, 12, 30, 0)
some_date_later = somedate + timedelta(days=2, hours=3, seconds=17)
# Native pseudocode
some_date = d'2024/03/31 12:30 EST'
some_date_later = some_date + (3d 3h 17s)

This feature would translate well to Python, especially given a number of “string types” already exist, like f-strings, b-strings, etc. The equivalent of a timedelta, which I would name as a duration primitive, would be parsed by a d-string, and it is a combination of numeric values followed by their corresponding duration identifier, like d for days, h for hours, s for seconds, and so forth.

// A C# example demonstrating a duration primitive as a first-class citizen!
int myVal = 5;
bool myBool = true;
string myStr = "hello world!";

// 1. `mo` and `mi` disambiguate month and minute
//    `m` would preferably be disallowed to avoid mishaps
// 2. spaces supported for readability
duration myDur = 1y 2mo 3d 4h 5mi 6s 7ms 8us 9ns; 

Besides the direct benefit of not needing to import libraries to do this (time-related logic seems quite frequent to be hidden away behind libraries, doesn’t it?), we can avoid confusion when passing arguments for durations.

In both languages and third-party libraries, we see methods like sleep, wait, setTimeout, setInterval, or may have to provide a timeout value to methods like in a test suite or a web request. Do you remember which ones take seconds vs. milliseconds? And when you provide those values, how often are you either hardcoding values like 86400 (number of seconds in a day), or calculating them inline, sleep(24 * 60 * 60)?

With a duration primitive we can:

  • write semantic code
  • provide values without magic numbers or calculations
  • not rely on imports to handle such a common task

Thoughts or comments on this post? Send me an email at greg@greglang.me!