Ring 编程语言中的自然语言编程





5.00/5 (13投票s)
基于面向对象编程的 Ring 编程语言中的自然语言定义
引言
2010年,我开发了一种名为Supernova的新编程语言。该语言使用一种看起来类似于自然语言语句的代码来创建简单的GUI应用程序。五年后,在Ring编程语言中,我们可以获得类似的结果,但现在我们能够在我们喜欢的或需要的任何领域中创建/使用类似于自然语言语句的代码。
Ring编程语言附带Supernova的精灵,但具有更强的通用性,并混合了其他语言的精灵。
该语言对自然语言编程和声明式编程提供了更好的支持。创新之处在于,在面向对象编程和函数式编程的基础上,通过新的实用技术来支持这些范例。Ring为程序员提供了构建类似于Supernova的自然语言或类似于REBOL和QML的声明式语言的工具,而无需了解任何关于(编译器和解析)的知识。您可以使用现成的语言构造来创建领域特定语言,而且速度非常快。
使用Ring编程语言,我们可以基于类和对象创建自然编程语言。
在Supernova语言中,我们可以输入(我想要一个窗口,窗口标题是hello world。)然后它将创建一个GUI窗口,窗口标题为“Hello, World!
”。当我2010年创建Supernova语言时,我发现使用自然代码就像使用英语一样,不受限制,我们可以获得人类语言在编程中的强大功能,但要实现这一点,我们需要一种新语言,这种语言
- 通用目的
- 实践
- 可以非常快速地创建自然语言
因此,我们可以得到一个能够最大程度提高易用性和生产力的系统。
Supernova只是对这个想法的一次测试。以一种更近距离的视角来审视它的优缺点。在测试了新的想法后,您会得到一些实际的东西。所以,继Supernova语言之后,我们就有了Ring语言。
为什么要有定义自己语言的能力,而不是仅仅交出语法然后让你用你喜欢的任何代码来解析它?
这是创新——你无需了解解析即可创建自然语句。你只需使用类,这是一个明智的决定(之后我们可以混合使用类来支持更多基于上下文的语句——我们可以更改和翻译定义的语句,还有更多!)。此外,语句在Ring World中添加,你可以在其中使用任何Ring语句。
为什么选择自然语言编程?我们不是已经可以用命令式、面向对象和函数式语言做任何事情了吗?
当你设计一门新语言时,你可以从过去学习,但你必须着眼未来,活在当下。你对自然编程的了解可能基于这些范式在实际世界中力量的旧知识,我同意你,但我看到了另一种可以应用于实际工作的技术。你所忽视的自然语言是它们是上下文敏感的,这意味着我们可以以不同的方式使用它们,并思考如何表达我们的想法。
示例(1):我想要一个包含3个按钮的窗口。
一句话,我创建了4个对象(窗口和三个按钮),并将按钮添加到窗口中。自然编程的理念就是这样高效地完成许多事情。
示例(2):接收2个数字,然后打印它们的和。
背景
您可以查看这篇文章了解Supernova编程语言,以及这篇文章了解Ring编程语言。
还可以查看以下关于Ring编程语言的教程。
Ring语言中支持自然语言的特性
(1)紧凑的语法,语句没有明确的结尾(不需要;或ENTER)
示例
See "What is your name? " give cName see "Hello " + cName
或者用另一种风格
Put "What is your name? " Get cName Put "Hello " + cName
(2)使用花括号{ },我们可以直接像使用变量/函数一样访问对象并使用其属性/方法
示例
New point # create new object using the point class
{ # access the new object attributes and methods
x = 10 # set the x attribute to 10
y = 20 # set the y attribute to 20
z = 30 # set the z attribute to 30
print() # call the print method
} # end of object access
Class Point # define the Point class
x y z # the class contains three attributes x, y & z
func print # define the print method
see x + nl + # print the x attribute
y + nl + # print the y attribute
z + nl # print the z attribute
(3)我们可以定义方法,以便在设置和获取对象属性时使用。
示例
o1 = new person
o1.name = "Mahmoud" see o1.name + nl
o1 { name = "Ahmed" see name }
Class Person
name family = "Fayed"
func setname value
see "Message from SetName() Function!" + nl
name = value + " " + family
func getname
see "Message from GetName() Function!" + nl
return "Mr. " + name
输出
Message from SetName() Function!
Message from GetName() Function!
Mr. Mahmoud Fayed
Message from SetName() Function!
Message from GetName() Function!
Mr. Ahmed Fayed
使用代码
下一个例子展示了如何创建一个定义两个指令的类
- 第一个指令是:我想要窗口
- 第二个指令是:窗口标题 = <expr>
还可以忽略诸如“the
”之类的关键字
New App
{
I want window
The window title = "hello world"
}
Class App
# Attributes for the instruction I want window
i want window
nIwantwindow = 0
# Attributes for the instruction Window title
# Here we don't define the window attribute again
title
nWindowTitle = 0
# Keywords to ignore, just give them any value
the=0
func geti
if nIwantwindow = 0
nIwantwindow++
ok
func getwant
if nIwantwindow = 1
nIwantwindow++
ok
func getwindow
if nIwantwindow = 2
nIwantwindow= 0
see "Instruction : I want window" + nl
ok
if nWindowTitle = 0
nWindowTitle++
ok
func settitle cValue
if nWindowTitle = 1
nWindowTitle=0
see "Instruction : Window Title = " + cValue + nl
ok
输出
Instruction : I want window
Instruction : Window Title = hello world
如果我们想用“and
”连接两个指令怎么办?
我们遇到了一个问题,因为在Ring中“and
”是一个关键字。
我们可以使用ChangeRingKeyword
命令来改变它。
ChangeRingKeyword
命令在编译器的扫描阶段执行(在解析之前)。
注意:请记住恢复该关键字。
语法
ChangeRingKeyword <oldkeyword> <newkeyword>
示例
ChangeRingKeyword and _and
New App
{
I want window and the window title = "hello world"
}
Class App
# Attributes for the instruction I want window
i want window
nIwantwindow = 0
# Attributes for the instruction Window title
# Here we don't define the window attribute again
title
nWindowTitle = 0
# Keywords to ignore, just give them any value
the=0 and=0
ChangeRingKeyword _and and
func geti
if nIwantwindow = 0
nIwantwindow++
ok
func getwant
if nIwantwindow = 1
nIwantwindow++
ok
func getwindow
if nIwantwindow = 2
nIwantwindow= 0
see "Instruction : I want window" + nl
ok
if nWindowTitle = 0
nWindowTitle++
ok
func settitle cValue
if nWindowTitle = 1
nWindowTitle=0
see "Instruction : Window Title = " + cValue + nl
ok
func getand
see "Using : and" + nl
输出
Instruction : I want window
Using : and
Instruction : Window Title = hello world
如果我们想为任何运算符(如“=
”运算符)定义新的行为该怎么办?
我们可以使用ChangeRingOperator
命令来进行这种更改,以隐藏运算符(更改其名称)。
然后,我们可以将该运算符用作标识符,并处理其行为。
语法
ChangeRingOperator <oldoperator> <newoperator>
现在,我们将“=
”运算符更改为“is
”。
示例
ChangeRingKeyword and _and
ChangeRingOperator = is
New App
{
I want window and the window title is "hello world"
}
ChangeRingOperator is =
Class App
# Attributes for the instruction I want window
i want window
nIwantwindow = 0
# Attributes for the instruction Window title
# Here we don't define the window attribute again
title
nWindowTitle = 0
# Keywords to ignore, just give them any value
the=0 and=0
ChangeRingKeyword _and and
func geti
if nIwantwindow = 0
nIwantwindow++
ok
func getwant
if nIwantwindow = 1
nIwantwindow++
ok
func getwindow
if nIwantwindow = 2
nIwantwindow= 0
see "Instruction : I want window" + nl
ok
if nWindowTitle = 0
nWindowTitle++
ok
func settitle cValue
if nWindowTitle = 1
nWindowTitle=0
see "Instruction : Window Title = " + cValue + nl
ok
Eval() 函数
我们可以使用Eval()
函数在运行时从string
执行代码。
语法
Eval(cCode)
示例
Eval("nOutput = 5+2*5 " )
See "5+2*5 = " + nOutput + nl
Eval("for x = 1 to 10 see x + nl next")
Eval("func test see 'message from test!' ")
test()
输出
5+2*5 = 15
1
2
3
4
5
6
7
8
9
10
message from test!
将Eval()
与我们的自然代码一起使用
func Main
cProgram = ' I want window and the window title is "hello world" '
MyLanguage(cProgram)
Func MyLanguage cCode
# We add to the code the instructions that change keywords and operators
# Because Eval() uses a new Compiler Object (the original keywords and operatos).
cCode = '
ChangeRingKeyword and _and
ChangeRingOperator = is
' + cCode
New App
{
eval(cCode)
}
Class App
# Attributes for the instruction I want window
i want window
nIwantwindow = 0
# Attributes for the instruction Window title
# Here we don't define the window attribute again
title
nWindowTitle = 0
# Keywords to ignore, just give them any value
the=0
ChangeRingKeyword and _and
and=0
ChangeRingKeyword _and and
func geti
if nIwantwindow = 0
nIwantwindow++
ok
func getwant
if nIwantwindow = 1
nIwantwindow++
ok
func getwindow
if nIwantwindow = 2
nIwantwindow= 0
see "Instruction : I want window" + nl
ok
if nWindowTitle = 0
nWindowTitle++
ok
func settitle cValue
if nWindowTitle = 1
nWindowTitle=0
see "Instruction : Window Title = " + cValue + nl
ok
BraceStart() 和 BraceEnd()
我们可以在使用{ }
之前/之后编写将要执行的代码
示例
o1 = new test {
see "Hello" + nl
}
o1 {}
class test
func bracestart
see "start" + nl
func braceend
see "end" + nl
输出
start
Hello
end
start
end
使用 BraceExprEval()
下一个例子演示了如何使用“BraceExprEval
”方法在自然代码中获取表达式。
示例
new natural {
create 5
}
class natural
create=0
lkeyword = false
func braceexpreval r
if lkeyword lkeyword=false return ok
see "expr eval" + nl
see "type: " + type(r) see nl
see "value : " see r see nl
func getcreate
lkeyword = true
see "create" + nl
输出
create
expr eval
type: NUMBER
value : 5
真实的自然代码
下一个例子是一个更高级的例子。
# Natural Code
new program {
Accept 2 numbers then print the sum
}
# Natural Code Implementation
class program
# Keywords
Accept=0 numbers=0 then=0 print=0 the=0 sum=0
# Execution
func braceexpreval x
value = x
func getnumbers
for x=1 to value
see "Enter Number ("+x+") :" give nNumber
aNumbers + nNumber
next
func getsum
nSUm = 0
for x in aNumbers nSum+= x next
see "The Sum : " + nSum
private
value=0 aNumbers=[]
输出
Enter Number (1) :3
Enter Number (2) :4
The Sum : 7
使用 BraceError()
接下来的例子演示了如何使用“BraceError
”方法来处理使用花括号{}
访问对象时出现的错误。
示例
func main
o1 = new point {
x=10 y=20 z=30
TEST
SEE test
}
class point x y z
func braceerror
see "Handle Error!" + nl
SEE "Message :" + cCatchError + nl
if ( left(cCatchError,11) = "Error (R24)" ) and not isattribute(self,"test")
see "add attribute" + nl
addattribute(self,"test")
test = 10
ok
see "done" + nl
return
输出
Handle Error!
Message :Error (R24) : Using uninitialized variable : test
add attribute
done
10
示例
new point {
x=10 y=20 z=30
test()
see "mmm..." + NL
}
class point x y z
func braceerror
see "Handle Error!" + nl
see "Message :" + cCatchError + nl
see self
see "Done" + NL
输出
Handle Error!
Message :Error (R3) : Calling Function without definition !: test
x: 10.000000
y: 20.000000
z: 30.000000
Done
mmm...
干净的自然代码
与键入字面量“literal
”相反,我们可以直接接受单词。
示例
下一个例子接受hello world而不是“hello world
”
ChangeRingKeyword and _and
ChangeRingOperator = is
New App
{
I want window and the window title is hello world
}
ChangeRingOperator is =
Class App
# Attributes for the instruction I want window
i want window
nIwantwindow = 0
# Attributes for the instruction Window title
# Here we don't define the window attribute again
title
nWindowTitle = 0
# Keywords to ignore, just give them any value
the=0 and=0
# Data
literal = ""
ChangeRingKeyword _and and
func geti
if nIwantwindow = 0
nIwantwindow++
ok
func getwant
if nIwantwindow = 1
nIwantwindow++
ok
func getwindow
if nIwantwindow = 2
nIwantwindow= 0
see "Instruction : I want window" + nl
ok
if nWindowTitle = 0
nWindowTitle++
ok
func settitle cValue
if nWindowTitle = 1
nWindowTitle=2
ok
func braceend
if nWindowTitle = 2
see "Instruction : Window Title = " + literal + nl
nWindowTitle = 0
ok
func braceerror
c= substr(cCatchError,":")
while c > 0
c= substr(cCatchError,":")
cCatchError=substr(cCatchError,c+1)
end
literal += substr(cCatchError,1)
关注点
2010年,我花了9个月的时间开发了Supernova语言。现在使用Ring,我可以在几天内实现类似Supernova的语言。基于类定义自然语言而不是创建编译器,这一点意义重大。这提高了生产力并降低了问题的复杂性。您可以创建大型自然编程语言,并且仍然能够控制项目。考虑使用Ring来实现您的下一个自然编程语言!
历史
- 2016年10月13日:初始版本
在自然编程语言方面已经做了很多工作。Ring编程语言是一种实用的编程语言,它试图将自然语言编程向前推进一步。Ring是一种新语言,于2016年1月25日发布。