Adapt to your problem domain with declarative patterns that express logic, functions and objects.
Interactively develop in the browser and compile to efficient, safe WASM you can run anywhere.
Prototype quickly and gradually add expressive type constraints as your codebase evolves.
Visual or textual. Functional or object oriented. Fully dynamic or type checked. Informal is distilled from concepts proven in languages like Python, Haskell, Smalltalk, Prolog, Elixir, APL and Clojure. Choose the style that's right for your project, so you can focus on the problems that really matter.
// Experience live coding that instantly reacts to your changes
greeting
isMorning(now())
|
else
|
|
---|---|---|
locale == "en-US"
|
"Good Morning!"
|
"Hello!"
|
locale == "ml-IN"
|
"സുപ്രഭാതം"
|
"നമസ്കാരം"
|
// Declaratively order exactly $15.05 worth of appetizers
appetizers:
"Mixed Fruit": 2.15
"French Fries": 2.75
"Side Salad": 3.35
"Hot Wings": 3.55
"Mozarella Sticks": 4.20
"Sampler Plate": 5.80
Order: String in appetizers
fn total(orders: [Order, 1..8]): sum(appetizers[order.item])
// We'd like exactly $15.05 worth of appetizers please...
print order where total(order) == 15.05
// In fact, give me all of those orders
for order in orders where total(orders) == 15.05:
print order
// Define the pattern for a valid Date
daysPerMonth:
"January": 31
"February": 28 | 29
"March": 31
"April": 30
"May": 31
"June": 30
"July": 31
"August": 31
"September": 30
"October": 31
"November": 30
"December": 31
type Year: Integer in [1901..2038]
fn isLeapYear(year: Year): year % 4 == 0
// Functions can match on patterns
fn dateRange("February", year: isLeapYear): 29
fn dateRange("February", year): 28
fn dateRange(month, _): daysPerMonth[month]
// Types define the pattern for structure
type Date:
year: Year
month: String in daysPerMonth
day: Integer in [1..dateRange(month, year)]
From prototype to production, Informal adapts to the ever-changing requirements of a growing project. Add contractual guarantees to your program with gradual types, isolate complex functionality with independent modules or even transform the language itself with macros.
fn simpleDifference(start, end): end - start
// The return type can be inferred
fn typedDifference(start: Integer, end: Integer): end - start
// Enforce constraints with types
fn safeDifference(start: Positive Integer, end: Integer and start < end) Positive Integer :
end - start
// A concurrent file line counter by file type
class LineCounter:
LineCounter(counter=0)
fn process(contents: String):
counter += contents.lines().length()
fn report(fileType: String): print "$fileType : $count"
fn report(default): print "Other : $count"
counters:
"html": new LineCounter()
"js": new LineCounter()
default: new LineCounter()
for file in Directory("."):
_, filetype = file.extension
// Send a concurrent message (<-) to process the file.
counters[filetype]<-process(file.read())
for fileType, counter in counters:
counter<-report(fileType)
// From syntax, to compiler, to the editor...
// Every layer of the language is extensible.
class Article:
Article(title: String, author: String)
fn render():
// An embedded HTML syntax block.
#html:
<div>
<h1>${ title }</h1> by <p>${ author }</p>
</div>
a = Article(title="On <blink>Escaping</blink>", author="R Morris")
print a.render()
Software development is a collaborative process. Informal gives you the tools to create great software together across the internet.