Introduction
There are many programming paradigms like Imperative, Procedural, Object-Oriented and Functional programming. In this wikipedia article, you can read about them. In this article, I will talk about how to use the Natural Language Programming Paradigm in the Ring programming language. After reading this article, you will become ready to create a new language that uses Natural Language Programming.
Background
You can read the following articles:
- The Ring Programming Language
- Natural Language Programming in the Ring programming language
Using the Code
The Ring language comes with a library for Natural Language Programming. To use the library, at the start, you have to load it first.
load "naturallib.ring"
We will write the natural code in a Text file, for example, program.txt.
When we say Hello to the Machine, It can reply! and when we
say count from 1 to 5 it will understand us, Also if we said count from 5 to 1 it will
understand us too!
We expect the next output:
Hello, Sir!
The Numbers!
1
2
3
4
5
I will count Again!
5
4
3
2
1
As you can see, we start programming by typing the problem definition, think of this as writing requirements in a language that we can understand and implement but very near to the problem domain where non-programmers can understand it too.
Now to execute the natural code, we will create a new Ring source code file: start.ring.
In start.ring, we will define the language and the commands.
File: start.ring
load "stdlib.ring"
load "naturallib.ring"
New NaturalLanguage {
SetLanguageName(:MyLanguage)
SetCommandsPath(CurrentDir()+"/../command")
SetPackageName("MyLanguage.Natural")
UseCommand(:Hello)
UseCommand(:Count)
RunFile("program.txt")
}
The NaturalLanguage
class contains the following methods:
SetLanguageName(cLanguageName)
setCommandsPath(cFolder)
SetPackageName(cPackageName)
UseCommand(cCommandName)
SetOperators(cOperators)
RunFile(cFileName)
RunString(cString)
Using these methods, we defined a language called MyLanguage
. We have a folder for the language commands.
Each command will define a class that belongs to the MyLanguage.Natural
package.
We will define two commands, Hello
and Count
.
So we must have two files for defining the commands in the CurrentDir()+”/../command” folder.
To define new command, we can use the DefineNaturalCommand
object.
This object provides the following methods:
SyntaxIsKeyword(aPara)
SyntaxIsKeywordNumber(aPara)
SyntaxIsKeywordNumberNumber(aPara)
SyntaxIsKeywordNumbers(aPara,nCount)
SyntaxIsKeywordString(aPara)
SyntaxIsKeywordStringString(aPara)
SyntaxIsKeywordStrings(aPara,nCount)
SyntaxIsKeywordExpression(aPara)
SyntaxIsKeywordExpressionExpression(aPara)
SyntaxIsKeywordExpressions(aPara,nCount)
SyntaxIsCommand(aPara)
SyntaxIsCommandNumber(aPara)
SyntaxIsCommandNumberNumber(aPara)
SyntaxIsCommandNumbers(aPara,nCount)
SyntaxIsCommandString(aPara)
SyntaxIsCommandStringString(aPara)
SyntaxIsCommandStrings(aPara,nCount)
SyntaxIsCommandExpression(aPara)
SyntaxIsCommandExpressionExpression(aPara)
SyntaxIsCommandExpressions(aPara,nCount)
File: hello.ring
DefineNaturalCommand.SyntaxIsKeyword([
:Package = "MyLanguage.Natural",
:Keyword = :hello,
:Function = func {
See "Hello, Sir!" + nl + nl
}
])
To defined the Hello
command, we used the SyntaxIsKeyword()
method in the DefineNaturalCommand
object.
DefineNaturalCommand
is an object from the Natural Library class.
We passed three parameters to define the command (Package Name, Keyword & Anonymous function).
File: count.ring
DefineNaturalCommand.SyntaxIsKeywordNumberNumber([
:Package = "MyLanguage.Natural",
:Keyword = :count,
:Function = func {
if not isattribute(self,:count_times) {
AddAttribute(self,:count_times)
Count_Times = 0
}
if Expr(1) > Expr(2) {
nStep = -1
else
nStep = 1
}
if Count_Times = 0 {
see nl+"The Numbers!" + nl
Count_Times++
else
see nl + "I will count Again!" +nl
}
for x = Expr(1) to Expr(2) step nStep {
see nl+x+nl
}
CommandReturn(fabs(Expr(1)-Expr(2))+1)
}
])
To define the Count
command, we have used the SyntaxIsKeywordNumberNumber()
method.
This method accept three parameters:
- The package Name: We selected "
MyLanguage.Natural
" as our package name - The Keyword: It's "
Count
" and we can write it as :count
to get the same result - Anonymous Function: Will be executed when we have the
Count
command
Inside the Anonymous Function, we used Expr()
method to get the values after the Count
command
- Expr(1) ---> The first expression (
Number
) after the command - Expr(2) ----> The second expression (
Number
) after the command.
We use isattribute()
and addattribute()
functions to add an attribute to be used in our anonymous function.
We defined <span class="p">:</span>
count_times
attributes, it's value is 0
.
if not isattribute(self,:count_times) {
AddAttribute(self,:count_times)
Count_Times = 0
}
Using this attribute, we can know if we are counting for the first time or the second time.
if Count_Times = 0 {
see nl+"The Numbers!" + nl
Count_Times++
else
see nl + "I will count Again!" +nl
}
We will determine the count direction (from low to high or from high to low) based on the expressions values.
if Expr(1) > Expr(2) {
nStep = -1
else
nStep = 1
}
To return the output from the anonymous function to the Natural Library, we use the CommandReturn()
method.
We need this output if we have nested commands, but in our example, it's not important.
CommandReturn(fabs(Expr(1)-Expr(2))+1)
Let us test our work. Add more text for fun (don't do that in real programs!).
Points of Interest
When we program using this way, we get:
- Very high level of readability
- Our users can easily understand our programs
- Requirements become part of the implementation (Real Code)
- Users can modify programs based on new requirements that can be expressed using the same language as previous requirements
- The Ring programming language lets us focus on using the Natural Language Programming paradigm without thinking about the hard technical details like correctness, parsing & performance
- It's a research topic, you can do a Masters or PhD in this area if you have new ideas and results
- Since the Natural Code is very small, and close to the problem, this reduces programming errors and increases productivity
History
The Ring is an innovative and practical general-purpose multi-paradigm language:
- In November 2011, the idea of the new language was conceived
- In Sept. 2013, the design and the implementation of the Ring programming language is started
- In April 2015, the language name is selected
- In May 2015, the Compiler was implemented
- In Sept. 2015, the Documentation was done
- In January 2016, the Ring 1.0 was released
- In October 2016, the Ring 1.1 was released
- In January 25, 2017, the Ring 1.2 was released
- In May 15, 2017, the Ring 1.3 was released
- In June 29, 2017, the Ring 1.4 was released
- In July 11, 2017, the Ring 1.4.1 was released