Skip to content

plum v0.0.19

Choose a tag to compare

@github-actions github-actions released this 01 Sep 18:20
· 100 commits to main since this release

Plum is a small, statically typed, compiled language.

plum check and plum build now agree.

Eight programs your editor approved and the build refused

plum check is what runs on every keystroke in an editor. When it
accepts something the compiler then rejects, you find out at the worst
possible moment — after the code is written and you have moved on.

Eight constructs did exactly that:

match n { 1 | 2 => .. }     // or-patterns aren't supported yet
(1, 2).to_string()          // .to_string() on a tuple isn't supported
().to_string()              // Unit has no .to_string()
r.to_string()               // on a Ref: use .get().to_string()
f.to_string()               // a closure has no .to_string()
c.to_string()               // on a CStr: use .as_string()
let r = 1..5;               // '..' is only supported as a `for` iterand
show(ref(1))                // where `let show [T] (x: T) = x.to_string()`

Every one of those messages is a good message. They were arriving from
the wrong tool, at the wrong time. They come from plum check now,
worded the same, suggestions included.

This rejects programs 0.0.18 accepted — and every one of them already
failed to build.
If your project compiles today it will compile on
0.0.19. What changes is when you hear about the ones that don't.

[T: Show], the third bound

The last of those eight needed more than a message move. Inside a
generic, x.to_string() cannot know what x is:

let show [T] (x: T): String = x.to_string()

show(1)          // fine
show(ref(1))     // call to show: T is Ref[Int], but show requires T
                 // to have a text form, and this one has none

Checked at the call, where the type is concrete, and it follows the
value: a function that renders nothing itself but passes its T to one
that does inherits the requirement.

Show joins Ord and Eq as a bound you can declare — [T: Show]
and is then required of callers whether or not the body renders
anything.

Type signatures you can read

Hover and completion were showing the compiler's internal parse-tree
notation:

before:  let Option.map (o: (gt Option T)) (f: (fn (T) -> U)): (gt Option U)
after:   let Option.map (o: Option[T]) (f: (T) -> U): Option[U]

A standard-library reference that cannot go stale

STDLIB.md lists all 161 entries across 18 sections,
generated by the compiler (plum stdlib-reference) and checked against
it on every build. It replaces a hand-written prose list that had
drifted: 32 functions existed and were documented nowhere, including
Ref.get, Ref.set, Sender.send and Receiver.recv.

Tuples also work rather better than the README claimed — nested, inside
arrays, as struct fields, returned from generic functions. Only
.to_string() on one is missing, which is now one of the eight above.

Upgrading

Nothing that compiled under 0.0.18 fails under 0.0.19.

The checker rejects more than it did, and every addition is a program
the compiler was already refusing. If you worked around one of them, the
workaround is still correct and no longer necessary.