O Documentation


O Documentation


This is the documentation for the O programming language compiler and standard libraries. O is a high-level object-oriented general purpose programming language currently in development. The main goal of the language is to provide a free (libre) and open source environment for software development that can cater to individuals, enterprises, and huge open source communities.

O is a work in progress. It is being actively worked on. You may view the source code and follow development progress on Sourcehut (look for the projects starting 'olang-'). You can also follow @Olang on the fediverse for occasional status updates.

Ultimate FizzBuzzSplat Code Example

Ultimate FizzBuzzSplat is a variation on FizzBuzz that adds 2 additional rules. The first is the addition of "Splat", which applies to 7 in the same way "Fizz" and "Buzz" apply to 3 and 5 respectively. What makes this "ultimate" is that you also add a "Fizz" for every digit 3 in the number, add a "Buzz" for every digit 5 in the number, and add a "Splat" for every digit 7 in the number. For instance, 33 is a multiple of 3, but also has 2 '3's in it, so you would say "FizzFizzFizz".

// importing std.io for the 'term' class to read and write to the terminal
import std.io ;
// declaring our program's entrypoint
import ufbs ;
// the constructor for the entrypoint is the entrypoint of the whole programming
this() {
// the 'var' keyword can be used in place of a type to make use of type inference
// this overload of term.rdln ensures a safe read by asking again with a separate prompt on invalid input
// to parse the given type
var end = term.rdln<int>( "Enter a number: " , "No, a number: " ) ;
// we create an array literal with a range from 1 to our end point (inclusively) and pass it to a
// 'foreach' statement to iterate over each item
1 .. end | foreach {
// 'foreach' makes the implicit 'each' variable available
// first we declare our counters for 'fizz', 'buzz', and 'splat' and increment them if applicable
var fizz = each % 3 ?? 0 ## 1 ; // if 'each % 3' is 0 then it's false
var buzz = each % 5 ?? 0 ## 1 ;
var splat = each % 7 ?? 0 ## 1 ;
// now we iterate over each character in the string of our number (what makes it "ultimate")
each -> string | foreach
// the 'each' here is each character in the string, shadowing the 'each' in the parent scope, but
// this doesn't matter as we don't need the parent scope's 'each'
// the '??' '##' syntax is a ternary if and may be used as a shorthand for 'if else'
each == '3' ?? fizz ++ ##
each == '5' ?? buzz ++ ##
each == '7' ?? splat ++ ;
// we didn't need the braces because there was only one statement as the body
// if any of 'fizz', 'buzz', and 'splat' are non-zero, then we print them
// the 'a *~ b' operator concatenates 'a' to itself 'b' times
if ( fizz + buzz + splat > 0 ) term.prln( "Fizz" *~ fizz , "Buzz" *~ buzz , "Splat" *~ splat ) ;
// else just print the number
else term.prln( each ) ;
}
}

That example is rather plain and simple in order to facilitate heavy commenting to describe language features. O can do much more though. This next example is exactly the same program, but written in a more functional style and takes only a single statement.

// members of the std.io.term are statically imported so we don't need to prefix methods with the class
import static std.io.term ;
entrypoint ufbs ;
this() // braces are not needed for single-statement method bodies
// we can get the output of term.rdln directly here rather than declaring a variable
1 .. rdln<int>( "Enter a number: " , "No, a number: " ) |
// single-statement bodies don't need braces
foreach prln(
// declaring an anonymous method that takes 2 ints and returns an int (inferred)
fn ( int n , int f )
return ( n % f ?? 0 ## 1 ) + ( n -> string | where ( each == ( f -> string )[0] ) ).len ; |
// 'pipe' here is the method we piped in, so we can invoke it using pipe()
"Fizz" *~ pipe( each , 3 ) ~ "Buzz" *~ pipe( each , 5 ) ~ "Splat" *~ pipe( each , 7 ) |
// 'each' here is still in the scope of the foreach, so it is the number we're
// testing, which gets printed if the piped string has no length
pipe.len ?? pipe ## each ) ;