program-in-chinese / overview

中文编程的历史、现状和展望。issue 中进行相关问题的讨论.
https://zhuanlan.zhihu.com/codeInChinese
GNU General Public License v3.0
383 stars 34 forks source link

简单易用的中文编程(脚本)语言原型 #33

Closed nobodxbodon closed 5 years ago

nobodxbodon commented 7 years ago

早先算是开了个头: 实践"两周自制脚本语言"一书

昨天也被 @qingseshaohua 提醒一个很重要的方向是让更多人能够容易用编程的方式解决自己的问题. 因此打算在3个月内试着做一个原型出来.

由于时间精力非常有限, 打算尽量把工作量减到最小. 有所为, 有所不为. 下面是一些初步设想.

nobodxbodon commented 7 years ago

@wkgcass 还望你多多指点, 时日不多, 弯路能少走一点都好.

nobodxbodon commented 7 years ago

想象中的代码样子(非常不严谨), 空格只为表示分词, 实际可能不需要:

所有行 字符串 数组
测试文件 打开 c:/test.txt
当 测试文件 未读完, 当前行 读行 测试文件, 所有行 添加 当前行
所有行 每 行, 分行打印 行序号 + ": " + 行
wkgcass commented 7 years ago
  1. 如果不支持面向对象特性,那么调java会有点奇怪。至少像js那样稍微支持下吧(es2015的)
  2. 中文编程语言如果按照英文语言的书写方式那就是现在的易语言,感觉很怪异
  3. 语法高亮不费时间,用atom编辑器做高亮很方便
  4. 解释型其实也不比编译型好写,编译也可以是弱类型/动态类型的(因为JVM有反射),解释型还是编译型就看你喜好了
  5. 其实中文编程不好确定语法,毕竟中文本身就没有拉丁语系的严谨。如果语法不设置太多,也不要求自洽的话,后面实现还是挺快的
nobodxbodon commented 7 years ago

如果不支持面向对象特性,那么调java会有点奇怪。至少像js那样稍微支持下吧(es2015的)

确实, 如果不能创建一个Java对象, 就只能调用静态方法了. 考虑把OO作为第二阶段迭代的内容. 第一个迭代越短越好 :)

中文编程语言如果按照英文语言的书写方式那就是现在的易语言,感觉很怪异

你觉得楼上的写法会不会好点? 语法还没总结, 现在有点乱.

语法高亮不费时间,用atom编辑器做高亮很方便

赞! 请问有代码可供学习吗?

解释型其实也不比编译型好写,编译也可以是弱类型/动态类型的(因为JVM有反射),解释型还是编译型就看你喜好了

编译成bytecode感觉是额外的工作量吧? 刚看了一下What takes more time? Building an interpreter or a compiler?, 对于快速开发和原型验证来说, 从解释器开始比较省工的样子. 之前的考虑是, 在语言定位上, 首先是用来做一些日常系统工作, 包括文档/文件操作, 文本处理, 基本网络通信等等. 请 @qingseshaohua 和 @chencun 多多建议, 哪些功能是用户最常用的, 或者必备的.

其实中文编程不好确定语法,毕竟中文本身就没有拉丁语系的严谨。如果语法不设置太多,也不要求自洽的话,后面实现还是挺快的

语法希望能尽量从简. 自洽还是想尽量做到为好, 请教这方面有什么心得?

ghost commented 7 years ago

之前我在学习Lisp的时候,根据自己的一些对于编程的理解,折腾出一个不成型的编程语言,它的设计目标之一就是支持全中文的编程模式,也基本上达到了这个目标。

最初有这个想法的时候,是试用Python实现的,这是最初的版本。后来因为找工作的缘故,所以又学了Java并用其改写之,语言设计上也有一些变动。通过这个小项目也找到了工作,可却是做Rails开发的工作。

目前是跟一个加拿大外包过来的外卖项目,技术上主要是web相关的那些东西。工作以后,这个项目闲置了有一段时间了。后来被拉进我们这个中文编程组里面,又有兴趣重新折腾一下这些代码。最近的计划是准备用coffeescript重写一遍,然后发布到npm上去。

现有的代码主要的一个缺陷是求值器没有实现尾递归优化,这对于lisp这一类使用递归取代循环的语言可以说是很严重的,所以这个语言目前没有任何实用的可能,主要的用途,是用来展现下语言设计上的一些想法。

ghost commented 7 years ago

语言最终看上去大概是这个样子,以下是一段实现快速排序算法的代码:

(export quick-sort (define quick-sort (lambda [L Fn] (cond
    [(<= (length L) 1) L]
    [#true (merge
        (#lambda (filter (lambda [i] (< (Fn i) (Fn (car L)))) (cdr L)) Fn)
        [(car L)]
        (#lambda (filter (lambda [i] (>= (Fn i) (Fn (car L)))) (cdr L)) Fn)
    )]
))))

这个语言用以实现完全中文化的途径是这样的。语言的核心是一组元算子与一些字面量的混合体,所有的成型代码都是由语言核心的这些元素衍生定义出来的,通过中文化语言核心的表示法,并在编程的过程中继续使用中文化的标识符命名,那么由此而来,整个语言的所有代码,除了一些括号引号之类无所谓语言差别的内容,便都是中文化的了。

举例如下。在这个语言中,定义是算子 define,而二元加法的算子是 add,匿名函数的算子是 lambda,现在我们建立一个三元的加法算子,用英文代码的表述是:

(define add3 (lambda [a b c] (add (add a b) c)))

在这里,我们只需将 define add lambda 三个元算子中文化,如改写为 定义 加 算子 这三个名词,其余的符号一应改为中文,则得到了:

(定義 三元求和 (算子 [甲 乙 丙] (加 (加 甲 乙) 丙)))

所谓元算子,就是不由其他算子定义的算子,是固化在语言设计中的那些,嗯,也可以叫做函数,如果这样好理解一些的话。

一个更复杂的例子如下

(define options (lambda [M N] (map (let [[NK (dict-keys N)]] (lambda [m] (let [k (car m)] (if (in k NK) (dict-get-item N k) m)))) M)))
; (定义 合并选项 (算法 [元选项 变选项] (迭代 (使 [[诸键 (取诸键 变选项)]] (算法 [选项] (使 [键 (取首项 选项)] (若 (有 键 诸键) (取项 变选项 键) 选项)))) 元选项)))

大概是这样一个样子。

当时准备面试的时候,还写过挺长的一个说明文档,更加详细些,我回去找找,然后在此粘贴一下。

nobodxbodon commented 7 years ago

@NER000 哦! 类Lisp的语法? 期待啊! 以前一个学期的课就是用Scheme逐步实现一个Scheme语言子集的非常初步的编译器, 还是挺怀念的. 上面的例子里 lambda 有的对应"算法", 有的是"算子", 是笔误吗?

以前也考虑过设计类lisp语法的, 因为当时很深的印象就是语法的简约. 不过后来被它(们)在商业上的冷遇吓住了.

不知你对顶楼列出的那些目标有什么看法?

ghost commented 7 years ago

我在试图将这个语言中文化的过程中,遇到的一个主要的困难其实是,目前中文中的词汇,并不能很好的表达我们使用英文编程时那些概念。最明显的,我们都知道map与reduce操作,我们也知道他们的用法,但是,用中文中如何表达这个两个词汇呢,我想了许久都没有找到合适的。再比如apply函数,其实就是表达 (apply Fn [1 2 3]) === (Fn 1 2 3) 这样一个含义,将集合中的参数展开到函数上,这用中文又该如何表达呢,我曾将其翻译为 "施用" ,然后自己都觉得很奇怪。

在我前文提到的语言中,主要就是以下词汇表中词汇,直接粘过来Java代码了。

class Const {

    static final String NameOfPreviousValue = "_";

    static final String ConsolePrompt = "REPL";

    static final String SystemFinishedPrompt = "System finished with";

    static final String ErrorPrefix = "*** System Error: %s";
    static final String AssertionPrefix = "*** Assertion Fail: %s";
    static final String ErrorNotFoundSymbol = "Not found symbol '%s'";
    static final String ErrorNotFoundFile = "Not found file '%s'";
    static final String ErrorNotMatch = "Match not match";
    static final String ErrorSyntaxIncorrectInput = "输入不完整,缺少闭合括号。";
    static final String ErrorSyntaxTooMuchChars = "输入不完整,存在多余的词法单位。";
    static final String ErrorSyntaxUndefined = "Undefined literal '%s'";
    static final String ErrorSyntaxIncorrectEscape = "Incorrect escape";
    static final String ErrorCircleInsert = "Can not insert into one's itself";
    static final String ErrorNameAlreadyExist = "Name already exist in current environment '%s'";
    static final String ErrorArgsAmount = "Arguments amount error, '%s' @ %s";
    static final String ErrorType = "Incorrect type";
    static final String ErrorExternalSymbol = "Forbidden to update external name '%s'";
    static final String ErrorCannotExportInSubEnv = "cannot export symbol in sub environment";
    static final String ErrorCannotImportInSubEnv = "cannot import module in sub environment";

    static final String ImportNameSeparator = "-";

    static final String ExprType = ":expr";
    static final String ListType = ":list";
    static final String NumberType = ":number";
    static final String StringType = ":string";
    static final String BlobType = ":blob";
    static final String ExceptionType = ":exception";
    static final String HandleType = ":handle";
    static final String NoneType = ":none";
    static final String SymbolType = ":symbol";
    static final String TypeType = ":type";
    static final String BoolType = ":bool";
    static final String LambdaType = ":lambda";

    static final String Main = "main";
    static final String MainArgs = "args";

    static final String ValueOfLambdaType = "closure";
    static final String ValueOfListType = "[]";
    static final String ValueOfExprType = "()";
    static final String ValueOfNoneType = "#none";
    static final String ValueOfBoolTypeTrue = "#true";
    static final String ValueOfBoolTypeFalse = "#false";

    static final String LambdaToStringFormat = "(lambda %s %s)";

    static final String BoundArgs = "#args";
    static final String BoundLambda = "#lambda";

    static final String Define = "define";
    static final String Update = "update";

    static final String Cond = "cond";
    static final String Is = "is";
    static final String Eq = "eq";
    static final String EqOp = "=";
    static final String Lambda = "lambda";
    static final String Progn = "progn";
    static final String If = "if";
    static final String Apply = "apply";
    static final String Quote = "quote";
    static final String Let = "let";
    static final String Match = "match";
    static final String Import = "import";
    static final String Export = "export";
    static final String Eval = "eval";
    static final String Type = "type";
    static final String Length = "length";
    static final String Assert = "assert";
    static final String Exit = "exit";

    static final String Input = "input";
    static final String Output = "output";

    static final String Get = "get";
    static final String Set = "set";
    static final String Insert = "insert";
    static final String Delete = "delete";
    static final String Copy = "copy";

    static final String Substr = "substr";
    static final String Concat = "concat";
    static final String Encode = "encode";
    static final String Decode = "decode";

    static final String And = "and";
    static final String Or = "or";
    static final String Not = "not";

    static final String Add = "add";
    static final String AddOp = "+";
    static final String Sub = "sub";
    static final String SubOp = "-";
    static final String Mul = "mul";
    static final String MulOp = "*";
    static final String Div = "div";
    static final String DivOp = "/";
    static final String Mod = "mod";
    static final String ModOp = "%";

    static final String Gt = "gt";
    static final String GtOp = ">";
    static final String Ge = "ge";
    static final String GeOp = ">=";
    static final String Lt = "lt";
    static final String LtOp = "<";
    static final String Le = "le";
    static final String LeOp = "<=";
}

将以上这些名词中文化之后,这个语言在表现上就是完全中文化的,这些其实也就是一般语言中的那些关键字一类的东西。

nobodxbodon commented 7 years ago

关键词的中文化确实是个需要推敲的话题. 之前也聊到对C/Lua的中文关键词进行一致化的问题. 相信集思广益能够总结出合适的. 'apply'的话, '应用'/'施展'/'套用'如何?

wkgcass commented 7 years ago

@NER000 的提议感觉还不错,可以考虑一下

但是中文和“标点符号”的相性似乎都有点差(你想,古代人为啥标点符号最多是个“.”),特别是全/半角切换麻烦。所以这点还得再考虑下。 如果打算写成函数式的语言,可以参考下Haskell或者ML的语法。函数curry化,且调用时不必要的地方均不带括号。

add :: Int -> Int -> Int
add a b = a + b
add 1 2

fac :: Int -> Int
fac 0 = 1
fac n = n * fac (n - 1)

换成中文写出来就是这样:

加 类型为 整数 整数 整数
加 参数1 参数2 = 参数1 + 参数2
加 1 2

阶乘 类型为 整数 整数
阶乘 0 = 1
阶乘 数 = 数 * 阶乘 (数 - 1)

(其实还是感觉有点怪怪的,毕竟现在不管数学还是计算机科学,所有变量都是字母+数字代替) (另外类型标记也可以去掉,我只是照搬haskell写法而已)

swizl commented 7 years ago

之前做lua和c的中文关键字时,也纠结过命名问题。一开始想找个贴切的、大家都能接受的词,后来想想纠结个球,先做出来再说,有更合适的词以后再改。众口难调的话,自己喜欢什么词,自己拿代码改去。

wkgcass commented 7 years ago

apply是application的动词形式。application是指,将一个函数应用在某个参数上这一过程。(详见lambda calculusbeta-规约) 中文直接翻译就是“应用”,其实也能说得通

wkgcass commented 7 years ago

@nobodxbodon

Atom高亮其实就是一个cson文件,里面配置正则表示的语法规则(当然还有少许显式的状态机配置) 好久以前写的,官方有指引,不过我现在找不到了。我贴一个latte-lang的高亮吧: https://github.com/wkgcass/Atom-Latte-lang-Highlighting 我当时也是参考别人高亮写的,比如protobuf的高亮: https://github.com/changnet/language-protobuf


编译到字节码有几个很大的好处,那就是自然而然的让JVM帮你处理异常、GC、优化代码。 这几样都要花些功夫,特别是优化。 优化并不是简单的活。要知道javac除了常量折叠以外什么优化都没做,所有优化都在JVM里进行,想在编译期做到JVM的JIT那样的优化是比较难的。 编译到JVM也不难,自己抽象一套字节码结构的类,然后基于asm写一个生成器就好了。不过可能要稍微加点类型信息进去。 (当然,如果程序量足够小,比如几十行,放在一个上下文里运行完上下文就结束那种,做不做GC、优化都无所谓了,甚至异常处理也可以不搞,直接往上下文外面抛)

nobodxbodon commented 7 years ago

@wkgcass 多谢高亮示例.

当然,如果程序量足够小,比如几十行,放在一个上下文里运行完上下文就结束那种,做不做GC、优化都无所谓了,甚至异常处理也可以不搞,直接往上下文外面抛

第一版的目标可能就是这样了. 可能更像shell脚本语言的子集. 打算先从抽象语法树开始, 暂时不定具体词法.

nobodxbodon commented 7 years ago

第一版打算在24号前, 开发非常小的一个功能集:

FedoraLinux1 commented 7 years ago

我把一小段Python代码,翻译成了中文,个人觉得应该比较有代表性,比较符合中文使用习惯。

由于缩进问题,我还是贴图片比较好,链接如下: https://pbs.twimg.com/media/DJ79-dwUMAETimD.jpg

@nobodxbodon 已经添加入GitHub,感谢!

https://gist.github.com/qingseshaohua/9717f2750468f1a0801c235673a86567

如果有翻译这块的问题,我想我能帮上一些忙。 ps,诸位大神已经在创造一门新语言了,为何还要纠结从英文的字面意思上翻译过来? 从其功用,中文叫法习惯上去定义它,应该会更好。

nobodxbodon commented 7 years ago

@qingseshaohua 多谢! 这样和周蟒/中蟒的方向可能比较近吧. 另外请问, 以你的经验, 易语言用户对易语言的哪些功能需求比较大? 还有哪些功能是易语言需要改进或者添加的?

关于分享代码, 可以试试创建github gist: https://gist.github.com/ 比如https://gist.github.com/rfyodorov/2ae5dbf7e1c5d2685b4e

FedoraLinux1 commented 7 years ago

@nobodxbodon 关于需求(暂时能想起来的):

1,高度集成的支持库,与示例代码(对于常见的各种功能,都有集成支持库,比如界面库,常用组件库,数据库类的MySQL,系统操作类,还有对Windows的API各种等。) 2,对于各种函数命令的详细释义(鼠标指针在某个命令上,按F1就能显示出来某个命令的详细解释) 3,语法提示,键盘敲入某条命令的首字母,就列出候选项。 最大的需求其实就是 都是中文的。

易语言需要改进或者添加的地方:

由于长期不更新,或者更新一些无关紧要的东西,易语言已经跟不上时代了。 1,编译器。易语言自有的编译器是一个很蛋疼的东西,编译出来的文件,还需要带上支持库才能运行,而且受数字公司和电脑管家误报影响很大。当然也可以“静态编译”但这个静态确实调用vc的,最通用的是vc6,想想这是多么老的东西了。 2,无法支持大型项目的开发,因为它的源码是一个单独且集成的文件(各种资源都在一起),这也是导致它无法被主流商业公司选择的原因。ps,小型项目没问题。这也导致了难以协同开发的问题。 3,不支持Unicode,不支持64位系统(这个不支持是指无法编译64位程序,与它本身就不是64位的) 4,IDE丑,影响敲代码的心情,试问现在还有哪个软件的界面是这样丑的。

这些都是大的问题,小的细节太多了,说不完,下次有机会再说吧

nobodxbodon commented 7 years ago

@qingseshaohua 赞! 多谢分享.

由于本人对Java相对熟悉一点, 所以从开始就打算用Java实现这个原型. 这样对unicode和64位系统, 以及非windows系统的支持应该是与生俱来的. 副作用就是依赖JRE. 最好是做可执行包避免用户额外安装JRE, 有额外工作量.

另外, 打算把解释器和运行环境都集成在IDE里. 这样绕过了生成独立运行程序的一步, 也让代码分享更有意义. 缺点就是, 所有的源码都需要用这个IDE运行. 安装和运行它有额外的开销(硬盘几十-几百兆, 内存可能几百兆)

1,高度集成的支持库,与示例代码(对于常见的各种功能,都有集成支持库,比如界面库,常用组件库,数据库类的MySQL,系统操作类,还有对Windows的API各种等。)

这些恐怕要慢慢积累, 其实大多数提到的库都已经实现了, 只不过接口是英文的. 我们主要的工作量就是把这些接口进行中文封装, 以及文档翻译. 另外可以从Java调用系统 API, 可能优先考虑JNA

2,对于各种函数命令的详细释义(鼠标指针在某个命令上,按F1就能显示出来某个命令的详细解释) 3,语法提示,键盘敲入某条命令的首字母,就列出候选项。

现在还在考虑是依赖现有IDE开发插件还是重新开发一个. 两种可能都费工不小. 释义和自动补全确实非常重要. 不过, 还不确定是否能够在三个月内实现.

无法支持大型项目的开发,因为它的源码是一个单独且集成的文件(各种资源都在一起),这也是导致它无法被主流商业公司选择的原因。ps,小型项目没问题。这也导致了难以协同开发的问题。

这个原型主要应用目标可能还是一些简单任务. 比如: 把一个目录下所有.txt文件内容全部合并到一个文本文件, 每个文件内容之后添加一个换行 等等之类. 不过源码的模块化还是希望尝试实现的.

wkgcass commented 7 years ago

模块化直接抄C的#include就好了。第一版就可以加上去了吧

nobodxbodon commented 7 years ago

编程环境想和命令行/聊天软件接近, 就像: screen shot 2017-09-21 at 1 23 37 am 试着从头开始做, 用JavaFX.

wkgcass commented 7 years ago

别这么搞啊。。。命令行吧,你反正又不显示图片

nobodxbodon commented 7 years ago
nobodxbodon commented 7 years ago

把"解释器"集成到了编程环境演示里: screen shot 2017-09-23 at 4 34 35 pm

qwas982 commented 7 years ago

这个设计有点像Wolfram语言,https://www.zhihu.com/question/22860404

nobodxbodon commented 7 years ago

界面的思路确实有点像, 希望做到交互性和聊天接近. 语法可能会更接近自然语言(而且是中文的). 另外, 这个的首要目标是处理本地资源/文件. 而WL好像只有收费的pro版支持数据或者文件上传处理. 感觉数据上传一般用户不一定会信任. WL比较知识密集型, 有很多专业数据. 这个暂时更侧重日常功能性, 当然只要有数据, 集成起来也是可能的.

现实骨感, 一步一步来吧, 这两天还不知道能不能把条件语句搞定.

nobodxbodon commented 7 years ago

最简单的条件语句: screen shot 2017-09-24 at 4 56 40 pm 下面为了试验实用性, 添加文件处理接口, 比如: 拷贝c:\test.txt为c:\test.bak 然后是类似循环的功能, 比如:

找 c:\下载目录 所有txt文件
拷贝每个文件到c:\文本目录 下
qwas982 commented 7 years ago

我觉得迄今为止, 我们研究的都是虚拟机语言.在别人已有的某一条件基础上进行探讨和开发.这势必会产生强烈的依赖性.这为中文编程带来了无法自主的后果. 不过还是先设计出实验性成品再说吧,支持你@nobodxbodon 有需要分配任务给我们吗? 大家一起完成,速度更快些

nobodxbodon commented 7 years ago

其实这个项目是比较急功近利的. 以我对自己的了解, 如果是自己八百年都不会用的工具, 恐怕是不大有动力维持的. 由于现在工作还时不时要做一些文件处理之类的琐事, 而我又对shell或者perl脚本不熟, 所以打算从这个方面的功能入手. 期望值请尽量放低一些, 最有可能做出来的是非常不通用的一个工具集而已. 如果自己能够用上那么几次而且还算顺手, 就已经谢天地了. 在像样的原型建立之前, 恐怕任务分配比较难, 毕竟自己都没有一个很清晰的路线图, 属于走一步看一步的阶段. 欢迎各位建议一些日常常用而又不大找得到好用的工具的文件处理用例, 尽量一起考虑.

当然很希望看到的是其他中文编程语言的创造. 成型的各种领域和用户群的英文编程语言应该不下百种, 未成型的实验语言应该不下千/万种. 中文编程语言的尝试还是太少太少了(当然在下也是孤陋寡闻, 肯定有很多尝试不知道).

转一篇有点共鸣的文章: 编程语言:变革创业思维的工具. 工具就应该是用户随着自己的需要创造出来的. 所有用户都有这个资格创造适合自己的工具. 而适合自己的往往也会适合其他一些人. 如果足够好用, 别人也会开始用, 这样的发展应该是比较自然和合理的.

qwas982 commented 7 years ago

噢~ 原来如此 看来要建造中文编程语言,是任重道远啊 一个人力量不够,但现在已知的编程语言好像都是某个人设计的,而不是群体共同创造.

nobodxbodon commented 7 years ago

之前工作里想用脚本实现的一个简单事情: linux系统里, 有些每天新产生的文件是用日期命名的, 比如xx20170924_1, xx20170924_2..., 每个文件都可以用某个命令行指令解压. 我当时想做的就是把这一批某一目录下带有"20170924"的文件全都解压到某个目录下. 所以这个脚本语言一个必需的功能是能够调用外部命令, 而且能够在linux命令行下运行(不依赖图形界面) <-- 从这个角度来说我应该先放下之前的界面, 先按 @wkgcass 说的先搞定命令行才对.

话说这种功能估计按键精灵能搞定, 可惜它不支持linux, 而且它不开源.

一个人力量不够,但现在已知的编程语言好像都是某个人设计的,而不是群体共同创造.

虽然传统上多数是一人主导, 不过一些有企业背景的编程语言应该都是团队参与吧, 比如Go之类.

qwas982 commented 7 years ago

企业创造的一般就是为企业服务了 还有C#. 看来要创造一门语言,还需要做大量的研究和调查.收集整理一大堆资料.真不是一个人能完成的.得想其他办法

nobodxbodon commented 7 years ago

企业创造的一般就是为企业服务了

肯定是从企业自己需求出发的, 但是肯定也更多考虑到未来和同行企业的用途

看来要创造一门语言,还需要做大量的研究和调查.收集整理一大堆资料.真不是一个人能完成的.得想其他办法

很难一概而论吧. 能人很多, 尤其是编程上. 有些事我可能挤牙膏似的要做一年, 别人可能一个周末就搞定了. 另外, 远的不说(主页上列出的中文编程语言应该都是单人主导的), 近的 @wkgcass 的https://github.com/wkgcass/Latte-lang 应该也是单人项目, https://github.com/vczh/tinymoe 也是吧.

qwas982 commented 7 years ago

大佬确实可以仅凭一人之力就能做到,看起来,这些大佬一切以英文为主. 我看了他们设计的新的编程语言,看起来和现有某一英文编程语言没有什么区别,毫无意义.重复造的轮子没有多大价值.可能他们投入的精力与方向根本就不是中文编程.他们似乎看不起中文.甚至,连中文关键字都懒得创造一个版本.既然如此,初学者何不直接学其他覆盖面更广的语言呢.那些语言似乎没有存在的意义.或许只是别人的玩具而已.

nobodxbodon commented 7 years ago

@qwas982 这话偏颇了吧. 首先, 对编程语言设计有兴趣和实力的开发者都是值得互相学习和探讨的. 虽然他们设计的语言是英文编程语言, 不意味着它们在设计和特性上没有长处和优势. 并且, 本身开源和创造的过程就是一个自我提升/学习和共享的过程, 请不要把设计英文编程语音和中文编程语言对立起来.

兼收并蓄, 而不是非此即彼

qwas982 commented 7 years ago

@nobodxbodon 我明白你的意思,我这样说的原因是,我曾经向vczh请教过关于怎么创造一门汉语编程语言,还询问了他为何不创造中文编程语言,他给的回复相当轻视,轻蔑,认为我只是为了满足民族自尊心这样的妄加揣测,并且最后还把我拉黑了,在知乎上.我现在依然无法回复他的答案(刚刚试了).由此我得出,这厮不过是仗着自己懂英文并且会c++就崇洋媚外, 逆向种族主义罢了.

nobodxbodon commented 7 years ago

@qwas982 已跑题太多, 请到此为止, 参考版规. 这里需要的是技术探讨和协作, 而不是对立和爆料. 前者能够团结, 后者只能散沙.

buyouyuan commented 7 years ago

其实看看这几天的讨论,我们又在转圈圈呢. 又回到1、是否重新设计一款新的语言 ; 2、汉化一款西文语言。 其实这并不矛盾。 反正我是这样想的,刚开始要汉化C语言,用汉化的来开发中文编程语言。过一段时间,感觉不爽。 又在想用中文怎么从零开始开发编程语言。我一直是这样,在这两种中转圈圈。晕啊! 对于上楼说的,其实不用管别人。 走自己 的路,让别人去说吧。坚持我所正确的,总会看到光明的! 以此共勉!

wkgcass commented 7 years ago

@nobodxbodon 之所以说先做命令行,并不只是考虑实现成本和兼容性,而是作为一种编程语言,它本身应当仅仅提供最基本的功能,例如变量赋值、新建对象、函数调用等,可能再加上一些“方便人书写”的语法糖。但是很少会有把实际工程考虑的东西紧密整合到语言中去的。这些“方便工程使用”的东西一般会做成标准库,或者默认导入的函数/全局变量。 至于图形界面,或者人机交互这些,应当在语言做完后,再用这个语言来写(或者把语言编译部分封装起来,再写其他代码调用)。

wkgcass commented 7 years ago

与实际功能密切耦合的叫做DSL(domain specific language),而不是编程语言(programming language)。如果你真的很需要文件方面的功能并且想整合进语言的话,你应该声称这是一种DSL。

wkgcass commented 7 years ago

@qwas982

依赖JVM是没问题的。

  1. openjdk是开源的,而且还有J9这种开源产品。
  2. 从0实现一个后端难度很高。不用JVM的语言,基本都选择LLVM做后端了。
  3. 自己做后端没有兼容性用不了社区的东西,对于个人开发者这是不可接受的(企业有能力推一个社区出来,像go这种设计得烂的不行的现在都能火,个人组织是没有能力的)。

另外我写的语言纯粹就是我喜欢这些功能,想在同一种语言里面同时使用。是否有实际意义,我觉得要看发展了。当初js和python都是创始人写着玩,第一版是一两周写出来的。现在都火的不行。但是两者设计其实都有问题(为了填坑,python3直接不兼容2;现在大家都在骂es5之前的特性)。


我写Latte-lang之前为了写Java不那么痛苦,写了一个库封装了一些internal dsl,但是用起来还是别扭。过了半年突然意识到,语言是没有完美的,除非你自己写一个。自己写的才是真正适合自己的,如果不适合,那就改到适合为止。 我个人是认为编程语言适合用英语写,因为习惯了,大概到现在怎么也有十万行代码了吧,这些都是英文能不习惯吗= = 如果你认为中文更适合自己,那就用写个中文的呗,不用管别人怎么说。


话说轮子就这性格,也不针对你一个= =

nobodxbodon commented 7 years ago

@wkgcass 就像楼上的例子, 现在打算做的可能更像是shell脚本语言的一个微缩版, 有条件/(隐性)变量/外部命令调用. 函数和作用域可能是第二步的. 第一个小目标是能完成那个文件处理的例子, 算个中文语法作交互的小工具吧, 离像样的DSL都有距离. issue的题目暂时就不改了 :)

至于图形界面,或者人机交互这些,应当在语言做完后,再用这个语言来写(或者把语言编译部分封装起来,再写其他代码调用)。

同意, 下面就要把它独立出来(其实一开始就是, 不过为了方便演示"编程环境"就放一块了). 这个原型估计是做不到用它写开发界面了.

上面说的"隐性"变量就是这种, 一时想不到哪种语言里有:

找 c:\下载目录 所有txt文件
拷贝每个文件到c:\文本目录 下

第二行里的"文件"就像for(File file : files) 里的File file一样, 不过不用显式命名. (感觉这个坑很大, 特别是循环复杂起来之后. 自己也没想全呢) 还有个坑(脑洞), 就是用'它'和'它们'指代当前/最近的变量

wkgcass commented 7 years ago

@nobodxbodon “它”感觉可以加上。像groovy就支持这种写法:

list.map { it > 10 }

不过最好不要指代最近一个变量,那样加一行代码程序就崩了,可以参考groovy,或者haskell的do notation。 另外如果这么设计的话做成函数式语言比较顺。过程式的CPS风格用的不多

qwas982 commented 7 years ago

@nobodxbodon 好,我明白,我要向大家道歉,抱歉.既然如此,我觉得大家应该通力合作,各自发挥自己擅长的那一面.

@buyouyuan 你说得对,我现在也是这样,我觉得是我的能力局限了我的步伐,但是短时间内又无法提升能力,于是只能横向发展.尽力找别的出路,共勉共勉.

@wkgcass 膜拜大佬,经过你的讲解,我明白我是无法深入后端的,毕竟菜鸟水平,只能拿别人的东西用,最多搞搞前端,我比较赞同你的这个观点---"应当在语言做完后,再用这个语言来写"---. 我观察过现在比较接近人类自然语言的程序语言几乎都是类虚拟机语言,都建立在虚拟机基础上,如果是面对现实的前提的话,我觉得我们的方向应该一致为---[在某一虚拟机语言的基础上构建或修改],现在中文编程社区成员的方向普遍不一致,并且,成员们的水平参差不齐,不如分配下任务,大佬做后端,菜鸟丰富前端.不知您意下如何?像你和@nobodxbodon @swizl 都有一定的程序语言功底.你们都会java或其他某种虚拟机语言,所以请你们创造DSL,面对菜鸟的语法糖部分做成一个或多个接口,既能兼容汉语 中文或亚洲文字,又能兼容英语西文拉丁语系.在不同的语言文化里,可能词法和语法不尽相同,但语意是相同的,比如;

这是一个苹果 This is an apple これはリンゴです Das ist ein Apfel Это яблоко

虽然[形]在改变,但[神]不变,都是表示一个意思,语意是相同的.因此也可以相通,题外话,我仿佛看到了通过借助计算机实现在人类个体间使用心电感应一类的交流或沟通方式. 这个接口看起来就像这样; ------------------------------------ ↓ ← ← ←←←←←←←←←←语言字符A←←←自然语言A ------------------------------------ ↓
{[X]VM}←←后端←←←← 语法糖 ○ 接口←←←←←←←←←←←←←语言字符B←←←自然语言B ------------------------------------ ↑ ------------------------------------ ↑ ← ← ←←←←←←←←←←语言字符C←←←自然语言C

"○"是一个类似路由表的交换机或路由器的存在. 我想的这个思路是引用---前段---中段---后段---这种模式再进行二叉图分解设计,或者说构建更多的过渡带.

                                         ---(前段)---中段---后段---
                                             ↓
                               ( ---(前段)---中段---后段---)
                                    ↓
                        (---前段---中段---后段---)

刚开始不需要考虑效能等问题,只要能实现这一功能就行,首先,需要"有".这是基础.

nobodxbodon commented 7 years ago

@wkgcass 刚看了groovy的it, 隐式参数(Implicit parameter)好像跟我设想的不大一样. 我是往自然语言的用法靠, 而groovy的是对函数定义的语法简化. haskell的do annotation没怎么理解和'它'的联系...

指代最近一个变量,那样加一行代码程序就崩了

如果是"当前"的变量(新变量挨个放到堆栈里), 不会崩吧, 就是复杂起来的话可读性可能有点差, 和自然语言类似, 比如:

拷贝c:\压缩文件.zip 到 d:\临时目录
解压它为 解压文件.txt     <- 当前变量是 d:\临时目录\压缩文件.zip 这个文件对象
读它所有行               <- d:\临时目录\解压文件.txt 这个文件对象
每行如果包含"错误"输出它到d:\错误记录.txt             <- 需要有循环作用域, 当前变量是'行'
删除它                <- d:\临时目录\解压文件.txt 这个文件对象, 假设删除文件后变量也从堆栈中删除
删除它                <- d:\临时目录\压缩文件.zip 这个文件对象, 就有点尴尬了, 还不如用全文件路径

另外如果这么设计的话做成函数式语言比较顺。过程式的CPS风格用的不多

感觉很可能是混搭...试试看从功能开始设计会成个咋样的东西吧

nobodxbodon commented 7 years ago

@qwas982 多谢理解. 道路已经够艰辛, 望相濡以沫.

看你的思路想起一些关于不同编程语言的代码互相转换的讨论, 比如这里, 虽然好像理论上可行(假设库都有对应的), 但是至今没有一个框架做成. 个人感觉和汉化现有编程语言有类似问题--工作量太大, 要跟着每个语言的新版本进行升级, 还不用说有些语言的新特性很可能不能被这个框架支持. 如果牵涉到自然语言理解, 就比代码分析更复杂的多了.

wkgcass commented 7 years ago

@nobodxbodon 之前说“加代码崩溃”是指在一段代码中间加一些逻辑。如果加的位置后面有“它”指代,那么这个变量指代的对象很可能发生了变化。 而隐式参数可以保证同一个作用域中这个变量不会变。在你的例子里,实际上你想表达的是这件事:

拷贝"c:\压缩文件.zip" 到 "d:\临时目录" {
    解压 "它" 为 "解压文件.txt" {
        读 "它" 所有 "行"    // 定义变量 “行”
        每 "行" 如果包含"错误" {
            输出 "它" 到 "d:\错误记录.txt"
        }
    }
}

明明是多层作用域,写在同一个层级,然后还需要开发者自行分辨?这种设计太烂了,别这么搞。

nobodxbodon commented 7 years ago

@wkgcass 嗯, 我写那个例子的时候就想起dynamic scoping. 虽然这个不是, 但是可读性确实差. 看来隐式参数这种限定作用域的做法是蛮合理的.

qwas982 commented 7 years ago

@nobodxbodon 不是汉化,是创新.在字节码的基础上建立新的语言,就像能运行在jvm上的众多其他jvm语言一样,是一个分支. https://en.wikipedia.org/wiki/List_of_JVM_languages 只不过这个jvm语言专为处理汉语文化设计,但同时又兼容现有库.之后就可以用这个语言写出新的框架和库.

nobodxbodon commented 6 years ago

之前的示例任务需要在远程Linux控制台(ssh登录)进行, 而且一般无root权限. 原以为中文输入就成了问题 (zhcon应该需要root安装).

刚才意识到这个问题已经被ssh控制台解决了. 比如在windows下用putty进行ssh登录服务器, 而putty的"Remote character set"默认就是UTF8. 刚测试了一下输入和显示中文没有问题. 下面要通过简单的命令行Java程序测输入输出中文(牵涉到跨平台编解码和不同Java版本等细节问题)