Skip to content

Cara

๐ŸŒ‡ Cara is a programming language aiming to be pleasant to use and maintain while staying safe and dependable.

Warning

Cara is in development: @janiczek is still figuring out the design, syntax and functionality. In the meantime, some code snippets can be found in the compiler's end-to-end test suite on GitHub.

Features

To put it shortly, Cara combines:

Elm and its safety, maintainability and friendliness

Haskell and its brevity and power (in moderation)

Kotlin and its familiarity and syntax sugar

INTERCAL and its... just kidding!

Here is an incomplete list of Cara's features:

  • General-purpose
  • Compiled to automatically parallel native code via HVM...
  • ...or interpreted (handy for scripting)
  • Immutable
  • Purely functional
  • Familiar ALGOL-like syntax
  • Statically typed with automatic type inference
  • ADTs with exhaustive pattern matching

Examples

Tip

There is a large sampling of Cara programs in the end-to-end test suite.

quicksort.cara
quickSort(List[Int]): List[Int]
quickSort([]) = []
quickSort([x,...xs]) = {
  (lt, gt) = List.partition(#(x >= _), xs)
  quickSort(lt) ++ x ++ quickSort(gt)
}

[5,1,3,2,4]
  |> quickSort
  |> IO.println!
fs_script.cara
#!/usr/bin/env cara

dst = IO.ask!("Enter destination filename: ")
dstHandle = FS.open!(dst, FS.Write)

timestampFmt = "hh:mm:ss.fff"

1..10 |> IO.forEach!(\i -> IO {
  time = Time.now!()
  dstHandle |> FS.write!("[${Time.format(timestampFmt, time)}] Hello number $i\n")
})
fizzbuzz.cara
fizzbuzz(n) =
  if n % 15 == 0 then "FizzBuzz"
  else if n % 3 == 0 then "Fizz"
  else if n % 5 == 0 then "Buzz"
  else "$n"

1..20
  |> List.map(fizzbuzz)
  |> String.join(", ")
  |> IO.println!
maybe_traverse.cara
type Maybe[a] =
  | Nothing
  | Just(a)

traverse(fn: a -> Maybe[b], list: List[a]): Maybe[List[b]]
traverse(fn,list) = go(list,[])
  where
    go([],bs) = Just(List.reverse(bs))
    go([a,...as],bs) = 
      case fn(a) of
        Nothing -> Nothing
        Just(b) -> go(as,b++bs)

xs = [1,2,3,4,5]
ys = [6,7,8,9,10]
f = \n -> if n == 3 then Nothing else Just(n)

IO.println!(xs |> traverse(f)) // -> Nothing
IO.println!(ys |> traverse(f)) // -> Just([6,7,8,9,10])

Installation

Right now the language tooling is very rough around the edges: if you want to try the language out, you'll need to git clone the compiler repository.

You'll need Deno to run the compiler.

Running the compiler
git clone https://github.com/cara-lang/compiler cara-compiler
cd cara-compiler

./run.ts end-to-end-tests/int/main.cara
./debug.ts end-to-end-tests/int/main.cara
./test.ts

Tip

The .ok files across the Cara repositories are generally a good way to get an idea of how to work with the repositories. (Shout out to @secretGeek's ok tool!)

Contribute

As of Q1 2023, I (1) am still largely trying to design how the language will look and behave rather than implementing it.

  1. @janiczek

If you'd like to discuss it, feel free to open a GitHub issue or send me a message on Twitter or Mastodon. I do want to keep some creative freedom so I won't promise this will be "design by commitee" nor any kind of democracy, but I would be very happy to hear your opinions, experience and tales from the trenches! (1)

  1. "This will be impossible to parse because XYZ!"

If you instead want to contribute to the documentation (this website), feel free to head over to the website repo and make a PR or an issue!