A starting point
MELBOURNE
MELBOURNE
language introduction
The official source
What you need to know to start
WHAT IS MELBOURNE ?
A rule engine inspired by Prolog : easy to write and read, powerful and flexible.
WHY MELBOURNE ?
For fun
WHO DEVELOPED MELBOURNE ?
Franck DANSAERT, in 2022, on his spare time in addition to music composition.
WHERE CAN I TRY MELBOURNE ?
The Melbourne Sandbox has been developed for iPad and is compatible with MacOS. You can download the application at the link below :
https://apps.apple.com/fr/app/melbourne-sandbox/id6443409136
MELBOURNE IS BASED ON THREE CONCEPTS
-
Knowledge
-
Atom
-
Rules
A KNOWLEDGE is composed of Atoms separated by whitespaces
// Example
Leia is the sister of Luke
AN ATOM is either a fact, a variable or a function.
An atom in small cap or capitalised or using a symbol is considered as a fact (ex: Leia, Luke, &, <, etc.)
An atom in uppercase is a variable (ex: X, TITLE, etc.)
An atom starting with the character $ is a pre-defined function (ex: $add<Int>, $modulus<Int>, etc.)
AN ATOM CAN BE IDENTIFIED by atoms using parenthesis and comma. We use identifiers when we are talking about things in general and the listener/reader does not know exactly what we are referring to.
// Examples of atoms with identifiers
Leia(age(20),weight(52),name(Skywalker))
RULES explain how to infer knowledge from existing or inferred knowledges. A rule can be defined using variables and functions using the following format.
// Example 1:
X is therefore Y:
X is Z
Z is Y
// Example 2:
X is the sister of Y:
X is a girl
The mother of X is Z
The mother of Y is Z
// Example 3:
X(Age(Y)) can drink:
$greater<Int>(Y,18)
KNOWLEDGE AND RULES are edited in the editor located in the upper screen. You can write for instance in the "Knowledge & Rules" editor the following text.
X is therefore Y:
X is Z
Z is Y
Franck is Human
Human is Mortal
THE COMMANDS are entered in the editor located in the lower screen. This is where you access the knowledge and query Melbourne. The query is a knowledge or infered knowledge using variables. Melbourne will infer all the possible values of the variables consequently once the "Enter" key pressed. Each query should end with a question mark ("?"). Some examples hereafter using the previous example.
Franck is X ?
// returns [X=Human]
X is Y ?
// returns [Y=Human, X=Franck] or [Y=Mortal, X=Human]
Franck is therefore Y ?
// returns [Y=Mortal]
COMMAND CAN ANSWER COMPLEX QUERIES as the given example hereafter
// KNOWLEDGE & RULES
Kenobi(age(20))
Anakin(age(9))
X can drink:
X(age(A))
$greater<Int>(A,18)
// COMMAND
X can drink ?
// returns [X=Kenobi]
ALTERNATIVE RULES CAN BE DEFINED to handle different scenarios.
// KNOWLEDGE & RULES
The car is light blue
The scooter is yellow
light blue is a color
yellow is a color
The color of the OBJECT is COLOR:
The OBJECT is X
X is a color
COLOR = X
The color of the OBJECT is COLOR:
The OBJECT is X1 X2
X1 X2 is a color
COLOR = $add<String>(X1,X2) // please note that you cannot use a whitespace to separate X1 and X2 : whitespace separates Atoms and cannot be used in an Atom's name
COMMAND
The color of the scooter is X ? // returns [X=yellow]
The color of the car is X ? // returns [X=lightblue]
RULES can be formulaed as question as illustrated hereafter :
Rhodri reigned between years 844 and 878
WHEN X reigned:
X reigned between years X1 and X2
WHEN = $add<String>(X1,-,X2)
WHEN Rhodri reigned ? // returns [WHEN=844-878]
HOW TO INTERPRET THE RESULTS :
If the command returns false, it means that either the statement is false or there is no solution to the assertion. For instance, using the given example above :
Kenobi(age(30)) ?
// will return false, because the age of Kenobi is 20 and not 30
Kenobi(weight(X)) ?
// will return false, because there is not solution to this assertion as no weight has been given
If the command returns true, it means that the statement is true ! For instance :
Kenobi(age(20)) ?
// will return true, because the age of Kenobi is 20 indeed
COMMENTS can be added in the Knowledge & Rules editor using the "//" symbol : all the text after this symbol will be ignored.
THE "=" and "!=" SYMBOLS have been defined, not as an allocation command but as an equality & difference test. For instance it is possible to write the followings :
// RULES
Z = X + Y:
Z = $add<Int>(X,Y)
Z = X +Y:
X = $subtract<Int>(Z,Y)
// COMMANDS
X = 10 + 1 ?
// will return [X=11]
11 = X + 2 ?
// will return [X=9]
These symbols are in fact rules which have been coded by default in Melbourne. These rules are given hereafter for education purpose to show how to define your own symbols
X = X:
true
X != Y:
$not<Bool>($equal<String>(X,Y))
THE "@" SYMBOL has been defined to confirm if an atom is an identifier of an Atom. Hereafter some examples.
Skywalker(Anakin,Lea,Luc)
Anakin @ Skywalker ? // returns true
X @ Skywalker ? // returns [X=Anakin] or [X=Leia] or [X=Luc]
Lightsabers(Darthvador(red),Luc(green))
Darthvador(COLOR) @ Lightsabers ? // returns [COLOR=red]
The @ symbol can be used to implement complex function such as the following :
// KNOWLEDGES
bike is assembly of parts(wheel,frame)
frame is assembly of parts(rearframe,frontframe)
rearframe is assembly of parts(bolt,nut)
basicpart(wheel)
basicpart(bolt)
basicpart(nut)
basicpart(frontframe)
// RULES
PART is part of X:
X is assembly of Y
SYSTEM @ Y
PART is part of SYSTEM
PART is part of X:
X is assembly of Y
PART @ Y
basicpart(PART)
//COMMANDS
X is part of bike ? // returns [X=bolt] or [X=wheel] or [X=frontframe] or [X=nut]
nut is part of X ? // returns [X=rearframe]
THE "..." SYMBOL defines none, one or more consecutive Atoms. This symbol can be used if only the beginning of a Knowledge has to be considered in a rule. Herefater an example. Please note that atoms mentionned or defined after these supension points will be ignored.
The car is big and fast
The OBJECT is X1:
The OBJECT is X1 ...
The car is X ? // returns [X=big]
The DEBUG ? command can be used to check the syntax correctness of the knowledges and rules. It will warn you about possible infinite loops, misspelled knowledge, etc. The debug functions are still limited but will help you to avoid basic mistakes. To debug your code, type in the command window :
DEBUG ?
SOME FUNCTIONS have been coded at this stage
Manipulating Integer
$add<Int> $add<Int>(10,20,30) // returns 60 (10+20+30)
$subtract<Int> $subract<Int>(100,20,30) // returns 50 (100-20-30)
$product<Int> $product<Int>(2,3,4,5) // returns 60 (2*3*4*5)
$max<Int> $max<Int>(2,3,4) // returns 4
$min<Int> $min<Int>(2,3,4,5,10,20) // returns 2
$modulus<Int> $modulus<Int>(10,3) // returns 1 (10%3)
$equal<Int> $equal<Int>(10,10) // returns true
$smaller<Int> $smaller<Int>(2,3,4,5,6) // returns true (2<3<4<5<6)
$greater<Int> $greater<Int>(10,5,3) // returns true (10>5>3)
Manipulating Double
$add<Double> $add<Double>(10.0,20.0,30.0) // returns 60.0 (10+20+30)
$subtract<Double> $subract<Double>(100.0,20.0,30.0) // returns 50.0 (100-20-30)
$product<Double> $product<Double>(2.0,3.0,2.0) // returns 12.0 (2*3*2)
$divide<Double> $product<Double>(1.0,2.0,2.0) // returns 0.25 (1/2/2)
$max<Double> $max<Double>(2.0,3.0,4.0) // returns 4.0
$min<Double> $min<Double>(2.0,3.0)) // returns 2.0
$equal<Double> $equal<Double>(10.0,10.0) // returns true
$smaller<Double> $smaller<Double>(2,3,4,5,6) // returns true (2<3<4<5<6)
$greater<Double> $greater<Double>(10,5,3) // returns true (10>5>3)
Manipulating String
$add<String> $add<String>(toto,tata,titi) // returns tototatatiti
$equal<String> $equal<String>(tutu,toto) // returns false
$smaller<String> $smaller<String>(franck,victor,zozo) // returns true (franck<victor<zozo)
$greater<String> $greater<String>(Z,B,A) // returns true (Z>B>A)
Manipulating Boolean
$and<Bool> $and<Bool>(true,false,true) // returns false
$not<Bool> $not<Bool>(false) // returns true
$and<Bool> $and<Bool>(true,false,false) // returns true
Manipulating Array (strings separated by a semicolon without whitespace, e.g. 10;20;50)
$encode<Array> $encode<Array>(10,20,30) // return 10;20;30
$first<Array> $first<Array>(toto;tata;titi) // returns toto
$last<Array> $last<Array>(toto;tata;titi) // returns titi
$tail<Array> $tail<Array>(toto;tata;titi) // returns tata;titi
$add<Array> $add<Array>(to;ta;ti,1;2;3,A;B;C) // returns to;ta;ti;1;2;3;A;B;C
$sort<Array> $sort<Array>(toto;tata;titi) // returns tata;titi;toto
$sort<Array> $sort<Array>(10.0,-3.0,-30.0) // returns -30.0;-3.0;10.0