Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

讨论: 适合中文用户的编程语言和IDE, 侧重于现有语言/IDE不具备的特性 #11

Open
nobodxbodon opened this issue Aug 1, 2017 · 83 comments
Labels
长期 原则上仅对索引帖适用

Comments

@nobodxbodon
Copy link
Member

nobodxbodon commented Aug 1, 2017

一个用户对象是中文为母语的开发者的编程语言以及配套开发环境, 应该有哪些特殊的功能, 才有存在的价值和维持开源的社区动力? 暂且不讨论如何实现的问题, 先搜集需求和探讨设计. 这个目标虽然是远期的, 但总要一步步实现, 希望这里能迈出第一步.

基于早先的讨论, 个人整理的一些如下. 视野有限, 仅作抛砖引玉:

开发环境
    集成语言源码(编译器,标准库等),方便用户修改/改进语言本身或丰富库,并方便验证修改对已有项目的影响. 理想情况是开发环境本身也能在自身中导入进行开发
    集成代码版本控制功能, 语言开发团队对语言/标准库与用户库/项目提供版本控制服务, 以提高团队开发效率, 促进共享, 提升整体代码水平
    提示/帮助文档贯穿整个开发过程
    集成语言解释器
    内置适合编程的中文输入法
    可以导入其他编程语言的项目
语言本身
    内置语法最简化, 可扩展性高. 想到的类似例子是Scheme/Lisp
    保证代码可读性的前提下优化性能/效率
    支持与其他编程语言的集成
    源码版本间易于比较
    易于理解的中文反馈信息, 包括编译错误/警告, 运行时错误等等

下面是参考易语言相关平台的官方文档,挑选出的一些. 本人没有易语言实践经验:

火山:
    支持中英文代码切换
易语言:
    代码即文档源程序风格统一
易语言飞扬:
    类自然语言编程 - 支持宏定义(和可扩展性高一致)
@nobodxbodon nobodxbodon added the 长期 原则上仅对索引帖适用 label Aug 1, 2017
@nobodxbodon
Copy link
Member Author

2000年的论文: 自然语言和计算机编程语言的比较. 自然语言是以中文为主要分析对象的.

@ice1000
Copy link

ice1000 commented Aug 2, 2017

I think there should be some IntelliJ IDEA Chinese language patch.

I've seen that once.

@nobodxbodon
Copy link
Member Author

这个补丁是汉化IDEA界面还是有支持中文代码开发的功能?

@ice1000
Copy link

ice1000 commented Aug 2, 2017

汉化界面啊。。

@nobodxbodon
Copy link
Member Author

恩 开发环境有中文界面是一个必需特性.

@lightrabbit
Copy link

我觉得TypeScript+VSCode的组合也挺适合的,TypeScript的解释器支持UTF8编码,然后编译出来的JavaScript也支持,同时VSCode可以提供很好的代码提示功能。只要实现了根据拼音首字母或者拼音的部分来匹配中文标识符,就可以极大地提高编码时输入的效率。像下面这样:
demo

@nobodxbodon
Copy link
Member Author

@lightrabbit 有兴趣的话方便在首页添加个TypeScript的中文代码例程吗?

只要实现了根据拼音首字母或者拼音的部分来匹配中文标识符

这个好像和"内置适合编程的中文输入法"的想法有点交集. 话说看你的示例里好像没有用额外的输入法? 是visual studio已经能够识别拼音了吗?

@nobodxbodon nobodxbodon changed the title 讨论: 适合中文用户使用的编程语言和开发环境 讨论: 适合中文用户使用的编程语言和开发环境, 侧重于现有语言和IDE不具备的特性 Aug 5, 2017
@nobodxbodon nobodxbodon changed the title 讨论: 适合中文用户使用的编程语言和开发环境, 侧重于现有语言和IDE不具备的特性 讨论: 适合中文用户的编程语言和IDE, 侧重于现有语言/IDE不具备的特性 Aug 5, 2017
@nobodxbodon
Copy link
Member Author

感觉题目有些误导, 修正了一下. 之后会随着讨论进行而更新特性列表.

@lightrabbit
Copy link

@nobodxbodon 这个就是上面的插件提供的功能,只是因为VSCode修改了代码中的匹配算法,和菜单面板里的不同了,所以那个插件对于新版的VSCode,暂时不能提供代码中用拼音匹配中文标识符的功能。

@taostein
Copy link

taostein commented Aug 7, 2017 via email

@nobodxbodon
Copy link
Member Author

@lightrabbit 哦! 真难得, @cleverdango 是这个插件的作者吧, 有幸ta也在组里. 像这种专门针对中文用户的项目感觉最适合用中文编程了. 确实, 插件就是受制于IDE. 像Firefox插件在火狐决定放弃xul支持之后社区一片怨声载道.

@taostein 惭愧, 在下对这两个编辑器仅限于在linux里看看log文件的使用程度. 请问这些非图形界面的IDE在支持中文编程方面有什么特殊需要吗? 比如输入法和自动补全, 和图形界面的IDE相比有什么不同吗?

@cleverdango
Copy link

@nobodxbodon 这个坑就是 @lightrabbit 挖的,部分代码也是他写的当时因为有些别的原因所以没有分开commit

@cleverdango
Copy link

你们可以把 @lightrabbit 拉到组里讨论,他比我更懂些技术细节

@nobodxbodon
Copy link
Member Author

请帖已经发给 @lightrabbit . 不知是否收到.
自动补全和输入法确实是IDE易用性的很重要一部分. 个人感觉拼音输入匹配中文标识符的功能是个好切入点, 因为用拼音输入的用户比例最大, 而且和现有的自动补全无缝集成. 好像在基于现有IDE的前提下没想到更用户友好的方式. 不知你们有兴趣/动力继续维护它吗? 比如跟进新版vscode的问题?

@lightrabbit
Copy link

@nobodxbodon 插件受制于IDE这个,也是我选择VSCode的原因。因为VSCode是开源的,你可以直接看它的源码并且修改它的源码。而那个vscode-pinyin的本质其实也是对vscode的源码进行修改,让它支持拼音匹配。然后插件所做的事情其实是把原版的vscode中负责匹配的部分替换成修改后的vscode。
继续维护的话,主要是近期事情很多很忙,所以没有多余的精力来做这方面的事情……

@qwas982
Copy link

qwas982 commented Sep 2, 2017

关于这个问题,我认为用code block 加载汉语编程语言的编译器就行了,有很多现成的IDE可以用。

@nobodxbodon
Copy link
Member Author

@qwas982 个人觉得, 现有IDE加上中文语言编译器是一个基础. 有些功能是有中文特色而且现有IDE默认不自带的. 比如上面 @lightrabbit@cleverdango 开发的在自动补全中支持拼音输入. 还有一些在顶楼的列表中. 其中个人比较看重的是第二条:

集成代码版本控制功能, 语言开发团队对语言/标准库与用户库/项目提供版本控制服务, 以提高团队开发效率, 促进共享, 提升整体代码水平

可以想象成, 开发环境和类似github的代码版本管理系统再加上类似Maven/NPM的库管理平台(解决依赖问题, 标准化代码和文档等)无缝集成. 所有使用这个开发环境的用户都可以选择把自己的库/代码直接分享, 其他用户可以在开发环境中搜索和利用其他人分享的库/代码并直接在自己的项目中使用, 这样可以最大限度地互相学习, 减少重复开发, 以此来抵消部分后发劣势, 使得第三方库和代码的积累尽快赶上老牌主流编程语言.

@nobodxbodon
Copy link
Member Author

在Z语言讨论群里版大介绍了一个在线中文编程环境: http://quzsc.huangyipeng.cn/web/ 目测像是汉化了JQuery的接口, 因为JQuery就用#号按照ID取HTML元素:

界面.容器.添加标题("第一个中文程序");
界面.容器.添加按钮("我的按钮",{编号:"按钮001"});
界面("#按钮001").点击(函数(){
     界面.消息框("我的按钮");    
});

思成.展示源代码(); 

#20 和它的不同在于, 目标用户是设计师和初学者, 而不是通用前端开发者.

@qwas982
Copy link

qwas982 commented Sep 5, 2017

@nobodxbodon 你说的不错,我很赞同,我还完善了一下我的思路。

我想到一个新思路

利用现有基础,站在巨人的肩膀上,借鉴前人的经验。

手动汉化不如自动汉化。
我们可以用自己现阶段会的某种语言,比如 javascript java python等语言写一个【源代码翻译器】,翻译C/C++的编译器gcc、llvm的源代码,调用Google 的|谷歌翻译|(谷歌已经在去年将它升级到了具有机器学习的人工智能翻译水平)去自动翻译其中的代码,然后保存为汉语源代码,然后再把这个源代码通过现成的编译器编译为支持汉语的新gcc或llvm编译器可执行程序,然后在我们用vs或者code::block(或其它语言的IDE)的时候通过加载编译器,就可以在强大现有的IDE中使用汉语编程了。这是汉化C/C++这种语言的一个思路,也可以将其用于汉化其他语言,比如javascript java python。
因为这个【源代码翻译器】本质上是个文本翻译器。
对翻译的策略,我们可以给他设置一个规则,比如语言保留的关键字和已占用的命名空间用我们协商好的汉语词汇列表,非保留和占用的,如;库、模板、STL等,如果是英文单词就直接翻译,如果是缩写就手动翻译一处,其它相同的缩写就自动替换。

@qwas982
Copy link

qwas982 commented Sep 5, 2017

这样做的好处是可以兼容现有语言的资源。反正是机器自动智能的翻译,即便是海量的源代码文件或者各种库、模板等也是可以轻易翻译完的。只不过校验需要一定的人手和时间,不过这应该已经很容易了。我觉得此举就像我们买了苏联的su-30 、su-35后将它国产化并自己生产出歼-11,、歼-15一样。完全消化并掌握这项技能。现在还有全新的歼-20,也就是说以后我们有创造全新语言的可能性,什么图形化编程,人工智能编程,自动化编程都不在话下。

@ice1000
Copy link

ice1000 commented Sep 5, 2017

请正确拼写我国战斗机的名字,那个字是,歼灭的意思,你那个字是狡猾险恶的意思

@ice1000
Copy link

ice1000 commented Sep 5, 2017

另:是code::block,不是

code::black

@nobodxbodon
Copy link
Member Author

@qwas982 机器翻译(个人觉得"智能"一词最近有被用滥的倾向)远没有达到理想境界, 而且它针对的是自然语言, 而非源码中使用的命名. 自然语言的上下文往往能为机器翻译利用, 而源代码离自然语言本身很远. 虽然没有尝试过, 但我估计机器翻译只能按照单词"直译"(还不考虑Camel命名的分词问题, 还有英文代码随处可见的缩写问题). 你可以试试取一段实际项目的代码, 试试用google translate出来的样子.

另外, 请麻烦你修正一下 @ice1000 指出的用词问题, 谢谢.

@qwas982
Copy link

qwas982 commented Sep 5, 2017

@ice1000 感谢指出,已修正。

@duangsuse
Copy link

duangsuse commented Dec 31, 2019

https://duangsuse-valid-projects.github.io/Share/绝句/绝句词法#解析器实现-kotlin-literate

你们先看看这个吧,我研究一下上面是啥
(从头开始看也行,不过上面链接引的那个 # tag 好像就没意义了)
(总之慢慢的几天内绝句就会被形式化定义出来的,放心)

@duangsuse
Copy link

duangsuse commented Dec 31, 2019

欸冰封怎么还在这呢

Screenshot_2020-01-01 讨论 适合中文用户的编程语言和IDE, 侧重于现有语言 IDE不具备的特性 · Issue #11 · program-in-chinese overview

给人感觉风马牛不及的……这是人间烟火啊
有点牛逼啊 👍 ,我还以为没人能搞 🐸 大新闻的

@duangsuse
Copy link

duangsuse commented Dec 31, 2019

@zj1d 链式调用仍可以应用(它也有局限性吧)。允许参数在命名非结尾处感觉可以更加灵活地命名 API,尤其是多个参数的方法,比如indexOfSubList("st")在("test a")的位置会比较可读。

首先我觉得还是说几句:我觉得在语言都还没有定好的情况下是不应该太考虑API的,不是不应该考虑,但是语言……基础的定义、控制结构,已经确定,这必须是前提吧。

然后我还有几句,是之前我说过的:

以前我偶尔以『艺术品』的心态想到『用中文写程序』,把中文看得比编程重,结果写出来的东西不像中文更不能编程。

现在我多学习了几门『不常见』的编程语言,Haskell、Scala、Kotlin,结果写出来的东西不仅符合编程逻辑而且像中文,这真是奇怪啊。

如果你连文字都不会敲、逗号顿号傻傻分不清,是设计不出『中文编程语言』的,这一点不必多说吧。

其实它的意思是,有时候不能老盯着『中文编程』本身不放,你们看楼上的 ice1k 冰封哥,如果他想设计那做出来绝对比许多『中文编程语言』好看,因为那些人连都AVL树不会写。 😂

说点实际的,如果你没用 Haskell 写过程序或者用许多 不同的语言写过相同的程序,也不会觉得 Ruby、Lua、Julia 都在用的 end 有啥问题吧,绝大部分人,甚至少部分编程语言的实现者、以至于Pythoneer们……,居然不知道缩进可以用来蕴含 a(o1 o2 o3)b 这种嵌套信息,但 Haskell 程序员全都知道。unfortunately 许多 Haskell 程序员对『英文编程』或『中文编程』不敏感,他们懒得设计一门『中文编程语言』,所以我今天所看到全部的中文编程语言,都是不带布局的,这里我说的布局可以理解为Python的「:」。

之前我考虑过关于绝句逗号表示法的一些事情,我复制一些(因为这个东西我也是现在还在准备设计……也不算是真的设计完了,还有很多东西没看):

当然以下稿子,最终的结果我还要再修改(包括设计到现在很多残次语法已经删了、换了,没太大时效性)

https://t.me/dsuse/11778

[In reply to duangsuse::Echo]
简单的说,逗号文法就是这四种情况:

  • 直接表达式(组)
    一行(1,2,3,4)去滤出「大一」.每个,说(它)。 — 这里的 说(它) 是直接表达式
    对输入行里 检查(你)是 否 的,无效集合记它、回。
    — 这是「组」和控制流简记
    -- 若无效集存项,抛下输入无效(无效集合)。

  • 嵌套段
    若你的名字不空,
    说(你的名字)
    这是嵌套段,就是最一般的情况

  • 逗号嵌套链
    若p,若q,
    emmmmm()

嵌套链「,」的右边只接受嵌套链或嵌套段。
若p0,若p1,若p2,
这一行()
p0 p1 的收的都叫嵌套链,最后一个是嵌套段。

  • 逗号取调链
    boxA令为,它去取值()。使用()
    boxA.let { it.get() }.use()

逗号取调链就是,在使用直接表达式作为块参数的时候,

  • 后面不能跟 ./?.
  • 后面可以跟 的/去
  • 如果都没有但后面跟了名字,默认是(.)
    用一般的描述方法,就是说后面必须跟汉语访问符,不能跟英语访问符。 ——现在如你们所见,不存在所谓的洋文访问符了
    如果后面直接跟名字,。号并作 (.) 号用

比如说:宫水家.找,她:她的名字是"三叶"。手机上的最近聊天记录.数,它的发送者是泷。有若「大五十」 空则,抛下沃日("emmmm")。
唉,我看逗号块还是允许利用:指定默认的 it 吧,毕竟这是中文,把人称作「它」实在是太过分了……
这一点不用中文编程还看不出来啊woc

控制流简记是针对表达式的情况,即便回/抛下/停下/略过是语句,它也可以取而代之,
对表达式组的最后一项也一样。

当然这些(后来再修改了以后的版本)很显然都是比较容易实现的,至少比我之前想的那个能多个 若, 之类共用一个句号,或者允许 对xss里的xs,对xs里的…… 的那种强多了。

然后你上面提到的『不符合表达习惯』按你举的例子如 users.removeIf(he -> he.is穷逼() || he.not小康()) (开个玩笑)翻译过来是 用户.除去若(他 => 他.是穷逼() || 他.不小康()) (我也是瞎翻译的),说白了就是语序不正,因为中文都是把上下文放前面,users.removeIfremoveIf 其实还应该放在 predicate 后面的,比如:用户“里”去删除「是穷逼或不小康」的人
(当然是伪代码)

@duangsuse
Copy link

duangsuse commented Dec 31, 2019

另一种:str.用("bb")替换前(3)个("aa"),两种都不是简单重载,毕竟如果走接近自然语言风格的话,混搭比如用("bb")替换("aa", 3)会比较怪。

Glide.with(this).load(imageUri).into(imageView);

我想你是不是理解错了…… 那个 x.op1()op2() 不是说可以省略掉中间那个 .,那是绝句程序设计语言新加的语法特性,「记法」,类似Kotlin的 infix function 但不需要加空格…… 之所以有那种类似自然语言的表示方法,是因为绝句还有「内联物」和「扩物」(目前都是计划暂交由Kotlin编译器支持)。那种方法不是不可以,甚至我以前还有更奇妙的想法,比如弄个所谓的预处理器啥子的(其实我当时估计是连预处理器PCH, Precompile Header、Preprocessor具体处理阶段和有几个指令都不知道,虽然我不是打算要写C预处理器……)

https://t.me/dsuse/10123

[In reply to duangsuse::Echo]
待会继续说『绝句』的,我一定要先实现这个玩意... (虽然可能不如 parser 们更优雅,因为虽然它是完整的模板语言,也有被当成 CPP 这种『逐行处理』的风险... 汗)

先一言不合就念诗:

int main() {
  ~绝句 (https://www.gushiwen.org/GuShiWen_97f95d9179.aspx)~
  [] 杜甫黄鹂』;翠柳』
『白鹭』... 青天』
『西岭;『』』
『东吴』。『』
}

说这玩意是代码你们相信么?
如果这执行玩意可以打印出下面这种东西,你们相信么?

🌴🦜🦜🎵
🐦🐦🐦🐦👆🌥
🏠👅西岭📆1000years:❄️
🚪🅿️东吴🚢🚢🚢🚢
9997km

🤔???

这是今年4月28 的事情

然后 Glide.with 的那种方法我之前也考虑过,甚至我到上上个星期为止都一直是这么想的,如果你们用有 extension function 的 Kotlin 很快就能把这种思路扩展到一个可以工程实用的级别,它翻译过来大概是

Glide以(此物)加载(图像链接)至(图片视图)

其中用到的DSL方法就是 ,主要就是这个,其它的可以写在多态返回类型里嘛(比如可以「以」图像设置啥玩意、「以」Http客户端加载图像……)

@duangsuse
Copy link

duangsuse commented Dec 31, 2019

https://t.me/dsuse/12099

引记法 绝句.额联 「令为」
引记法 绝句.符号 「以」
引记法 绝句.符号 「~个」
引记法 绝句.符号 「化」

引 Apache.PortableRuntime

例 随机生成: App 为“皮一下,标准库里不一定有这个别名,当然绝句也可以用上「类物别名」的”
  实现的事 入口() 为
    说("请输入将要生成的随机数个数:")
    量 数目 = 听去数一()
    说("下面开始生成${数目}个随机数====>")
    随机数之集去取(数目个) 令为,它以(" ")去接并()。令为(::说)
    说("<========随机数已生成")
    听去行一() “暂停屏幕滚动用”

例 随机数之集:随机数集()
物 随机数集 为 “也可以是单例的”
  私下、晚成的“lateinit”变参 存池:内存池
  事 取(次:数目):行<数> 为
    存池 = 内存池()
    量 随机行:行<数> = 行一()
    解对 次里的_,随机行去加入(随便一数())。
    回随机行     
  私下的事 随便一数():数
  = 随机数器去生成随机数(1、分配器=存池)
  去化数()

不是那种毫无规则的简化,设计是相当克制的

还可以看看

https://t.me/dsuse/11812

@duangsuse
Copy link

duangsuse commented Dec 31, 2019

顺便说一句,

用("bb")替换(列表)中的("aa")

这种用法其实 Kotlin 里就已经可以实现了,甚至可以说是完美地实现。不过绝句的目标显然不可能只是这个。

//定义一个上面的 fun 可以多态的类型,当然此类型可以定义为内联的
//类型参数在取值的位置是自动推导的
data class<某值>(val 某物: 某值)
data class 位置和源<地, 某值>(val 位置: 地, val: 某值)

infix fun <某值> 用<某值>.替换(位置: MutableList<某值>) = 位置和源(位置, 某物)
infix fun <某值> 位置和源<MutableList<某值>, 某值>.中的(目标: 某值) = 位置.replaceAll { if (it==源) 目标 else it }

// 介于Kotlin貌似为了理论优雅?没这个方法,而且Collection貌似是不可随机访问的
//fun <E> MutableListE>.replaceAll(origin: E, replacement: E) {
//  for ((index, x) in withIndex()) if (x == origin) this[index] = replacement
//}

//算了是这个意思

fun 入口() {
  val 列表 = mutableListOf(1,2,3)
  用(0)替换(列表)中的(3)
  println(列表)
}

你们也看到了 Kotlin parses these code,所以理论上是可行的,至于为啥不能用是因为我不熟悉这API而且熬太晚了

所以我才说,如果我直到上上个星期还保留着的思路用于编程实践是绝对没问题的,至于为什么这样的API还没出现那就不知道喽。

没想到吧?俄罗斯人写的Kotlin用来『中文编程』反而比『中文编程』易语言更贴切。编程到了一定境界所有语言都是互通的,而且甚至不止是过程式、面向对象、函数式 hello, declarative world

@nobodxbodon
Copy link
Member Author

@duangsuse 不好意思,可惜不大会 kotlin。关于用("bb")替换前(3)个("aa")这样的语法,之前只是想在现在大多数语言的方法定义(仅支持参数位于末尾)的基础上作一个改变(进?),与其这样定义:

def replace(old, new, max):
    ...

允许这样定义(暂不讨论关键字):

def (new)替换前(max)(old):
    ...

(无意尽量避免括号等)

我觉得在语言都还没有定好的情况下是不应该太考虑API的,不是不应该考虑,但是语言……基础的定义、控制结构,已经确定,这必须是前提吧。

个人(只学过一点 PL 皮毛)觉得 api 的设计(比如上面的语法改变)会影响语言本身设计。而且也许有时牵一发动多处,比如楼上末尾牵涉到类型转换,等等。英文 api 已经基本约定俗成了所有参数在方法最后声明,因此这方面并无什么发挥空间。

如果,支持上面的方法定义用(new)替换前(max)个(old),以及如果(...)xx这样的方法命名,代码写出来也许是这样的:

文字 问好 = "你好"
[] 号码 = [1, 2, 3, 4, 5]

问好 = 问好.("吃了么")替换("好")
号码.如果(() ->  > 4)移除

(号码)中的(某数) {           // 遍历这样看起来有点像是方法调用
  (问好 + 文字(某数))      // 假定强制转换必须显式

  如果(某数 % 2 == 1) {         // 与`如果()xx`方法看起来有点像
    ...
  }
}

写出来之后会发现更多问题(个人短期内无打算深入)

之前写过一点关于语言设计和 api 的顺序,现在仍觉得,如果首先从语言设计(甚至实现)出发,往往会出现削足适履的情况。越早编写接近实用的例程,越能发现语言设计的缺漏和可优化之处。因为实用(尤其是与实际业务相关的,而非纯算法)代码将是语言推广后存量比例最大的。而接近实用意味着至少是一小部分api 设计,以及一定的标识符命名风格。

楼上的例程,个人(也许对目标人群有不同设想)第一眼感觉,“听去数一”,“解对”,“去化数”, “次里的”等等难以一目了然。另外,逗号、分号、句号、双冒号、顿号、波浪号等等似乎都是语法因素,也许会增加学习和使用负担。

语言设计时,相信忍不住会逐渐加入更多更强大的特性,期间需要不断把中文特性这个“足”塞到这些特性组成的越来越小的“履”中。几乎无法避免地,会导致包含这些特性的例程的可读性的下降(也许可写性也是)。更大的问题是,由于语言设计者自身的视角问题,往往不会觉得这种可读性的牺牲是什么问题,因为设计者本身是对特性最熟悉的人(甚至比其他使用的编程语言更熟悉)。即使对路人非常难读的代码(由于对语言特性不了解,以及试图用老思维理解新事物的本能),对语言设计者来说却是轻车熟路。

因此,个人认为,为了避免上述情况,最好是尽量一开始就从尽可能接近实用的例程出发,反过来决定 api 和语言设计。这样,至少一开始能够尽量从最终用户的视角检视例程(在真正开始设计、实现语法之前,尽量确保程序对于新手来说是“好用好懂的”)。即使在之后由于各种设计或实现原因需要改变例程,至少有个参照和基准,也不会太轻易地牺牲可读性。这也和一般项目在设计之前,在获取需求的早期尽量搜集有代表性的 user story 的思路相同。

@duangsuse
Copy link

duangsuse commented Jan 1, 2020

呃我就照着你说的一段段回复吧:

@duangsuse 不好意思,可惜不大会 kotlin。关于用("bb")替换前(3)个("aa")这样的语法,之前只是想在现在大多数语言的方法定义(仅支持参数位于末尾)的基础上作一个改变(进?),与其这样定义:

(写完本回复我又看了一下,之前那个KotlinFriceEngineDSL的封装嘛,我觉得不是很理想。)
比方说(我这里不改变命名的大含义),应该用 左上角 = 点(x, y) 的形式弄,比把两个同类动作写在两行强(或许第一次写你觉得省脑子,重写、多写点,你就会抱怨它多余了),而这只需 typealias 点<A, B> = Pair<A, B> 然后加个扩展函数即可实现。实际上这是很平常的抽提(抽象、逻辑提取)思路。
而且 加速度_左负右正写的时候觉得是中文比英文好的一点,因为它更明确 我很同意,可任何事物都有两面性。
我在写程序的时候也经常要问自己一个问题——某个重复逻辑值不值得我提出来?在Kotlin里很多时候我的回答都是「是」,但这不代表不需要问这个问题——抽象也可能给别人的理解和阅读制造难度(Java里尤其明显),而命名上过度的注释也可能给别人的使用造成难度 e.g. setPositiveSizeLimit 的 'positive' 是否应该写在名字里?况且物理上加速度方向取数论的正负数符号,这是有理论优雅性的,无须再重复强调许多遍(即便要强调也不该被完全表示在仅此属性的命名上)。

def replace(old, new, max):
    ...

我的观点:这绝对不能算作是改进,尽管它往往不会与绝大部分语言的原文法冲突也不能。(JavaScript在限制不换行的情况下也不会)

就实现可能性上,一般我们认为 someFunc(a0)aname1(a1)... 这样的模式,当然是可能与绝大部分只需要 一个参数(但不至于与需要一个 tuple 的函数)相冲突的(我是指对于老思路那些 不需要 这种特性定义的函数)

但是,如果文法上直接换成这种形式定义,其实也没什么问题(看刚才我写那Kotlin就知道的确是没啥问题,因为按Kotlin语法 f() 完后的后继只能是中缀. + 或另一个前面肯定没名字的后缀如 ()、看Z语言也知道的确是没问题)。

首先我相信绝大部分静态类型检查的编程语言设计者,尤其是重视代码一致性的程序员都讨厌一些比较容易混淆的语法,尽管也有许多人喜欢 Ruby、Python 的 "keyword arguments" def dig_a_hole(depth: 1, label: 'hole'); puts"$label $depth"; end 这种。

包括我之前在 以绝句语言翻译 你之前翻译那个 Swift 的时候我都这么想,如果参数列表可以随便hack成那样:

func 问好(_ 人: String, 在 日子: String) -> String {
    return "吃了么\(人), 今天是\(日子)."
}
问好("小黑", 在: "周三")

如果没学过,哪怕是作为一个初学者你能明白这TMD是在做什么吗?下划线是什么意思?『日子』和『在』有啥联系?还是区别?反正我是看不懂。

介于我之前发了很多 t.me 的链接估计都没人点进去看,我摘一点吊吊胃口

func 统计(得分: [Int]) -> (最小: Int, 最大: Int, 总和: Int) {
    var 最小 = 得分[0]
    var 最大 = 得分[0]
    var 总和 = 0

    for  in 得分 {
        if 分 > 最大 {
            最大 =} else if 分 < 最小 {
            最小 =}
        总和 +=}

    return (最小, 最大, 总和)
}
let 结果 = 统计(得分: [5, 3, 100, 3, 9])
print(结果.总和)
print(结果.2)”

“绝句里单引号是文档,可以在工具里看到”
“一个类/物的类型参数可以直接加入文档,参数和返回值的文档可以直接加在前面也可以独立加”
“和Kotlin,也是Markdown的”
事 统计(得分:组<>):‘最小、最大、总和’ 元三<> 为
  对得分里的分,
    判分, “一时间我也找不到更好的方法把连在一起”
      它大最大,最大 =是此分支局部的”
      它小最小,最小 =
      否则,效果
      上皆,总和令置为「+」。
  回元三(最小最大总和)
这里,
  变数 最小 初0;变数 最大 初0;变数 总和 初0 “不是一般的编程风格,但不置可否”
  “这个版本里,暂时我不会把对()()()的修改加上,请兼容前面的一部分

我觉得这样的语言对所有,甚至包括 mother tongue 是 English 的人都是莫名其妙的,而且类似的语言不在少数。

这就是一个观点的问题,也就是『脚本化』还是『规范化』两个互斥的方向,可能相关的你可以看看冰封哥的 形式验证、依赖类型与动态类型

拿一个最简单的例子:比较 Bash 和 Python
当然其实 Bash 作为一门 Shell 语言也是有『形式化』(除了heredoc字符串语法)的语法定义的。
可它的可读性、易学性真的不能与Python相比,或许你会说它们根本不一样,但 Bash 的确是程序设计语言,不过没 cshelvish Shell 那么明显而已

比方说呢?Bash 的函数不能有形式化参数,只能在函数体里 $1 $2 $3 引用,而整个脚本居然也能把 shell 的参数以 $0 $1 $2 引,好像 bash 命令是个函数一样、尽管有作用域,函数里定义的变量默认是全局作用域还需要 local 来定义一个「局部的」、尽管函数带括号,调用都是 f x y 这种形式,而且三种引号 '' "" \`给人感觉简直难以区分、file pattern 的直接裸写有效也让人经常在参数里包含一些特殊字符时遭逢莫名其妙的问题,更别提| > <符甚至2> 2&> <&- n<&-这样看了文档也好长时间才能记住的『重定向』,以及莫名其妙的 +-*/&& || declare和所谓的[]` test 这种加不加空格都有区别还有 N 种写法的『命令』了。

再比较Python和Java,就不提属于运行时特性的 eval 了(而且 Java 也完全可以利用 compiler API 或者 ClassLoader defineClass 动态编译加载到虚拟机来执行代码),不知道有没有Python能吐槽Java的某一点
介于 Java 1.7 都有 try-with-resources 了,他们没法吹 Python 的 with 这种“更自然”的 try-with(当然 Kotin 可以光明正大地藐视所有这样的『脚本语言』,因为它的标准库里一个 use 函数就定义了这个被Python视为『语法』的东西,而你甚至不需要知道那个语法是 with res as name:,IDEA 里 Ctrl-Q 一下就能立刻用上)(原来绝句也有 尝试文件去开()成某书……,这么一写我觉得不能有了)

我想他们要吹的肯定是 Python 的动态类型、duck typing,这样你就可以随性地使用任何有 size 属性的对象上的 size 来取长了,而 Java 不仅每次写 Something something = new Something(); 麻烦还要各种写 Adapter boilerplate 来解决这种问题,Oh yes my dear Python。

我就不吐槽 Python 那毫无规章的『元方法』如 lenrepr 和莫名其妙的『面向对象』设计以及基础库了,Ruby程序员一直在吐槽。
它的 : layout 式语法算是一种创新,可仅止于此,其他的设计都是极度三八极度脚本化的,简直恨不能为Bash,想想Python3都忍不住跨大版本都快抛弃向前兼容了还没改过来,我真是极度地感到惋惜。

例如Kotlin这样的语言更不可能看上这种语法,因为它可能与 infix fun 存在语义上的冲突,即便这种冲突可以解决但那可能会给语言的使用者制造一些问题(比如,随性定义了一个使用常见介词的函数,结果与其它函数库的版本冲突……实践上这尽管能解决但不该有这种问题)

至于如果一定要说静态类型的好处,其实封装、抽象、继承、多态、fail-fast 我就不用说了,引用冰封哥的一句话(貌似是,忘记从哪看的了):

一个多态就能吊打它们了

没错,一个参数类型式的多态就比它们强太多了,不论类型是否一定要显示标明,静态类型都能在更早的时候确定更多的信息(不需要很复杂的推导算法),基于这样的信息你可以无开销地弄出许多DSL和针对特定输入的优化版本程序,或者仅仅只是静态的 optional arguments 也很好。

我的另一个观点是,一门好的编程语言不应该能让它的使用者写出不好的代码,哪怕只是可能。

允许这样定义(暂不讨论关键字):

def (new)替换前(max)(old):
    ...

(无意尽量避免括号等)

貌似无论是 Python 还是 Ruby 上这种修改都没有太大问题,不过 optional arguments 和 keyword arguments 就不应该在这种形式支持了,如果更严格我觉得使用这种形式的 Python/Ruby 就不该有 optional/keyword 了,而且 Ruby 的 &op 块参数也要好好考虑怎么弄好。

def call_with_1p(n, &op); yield(1+n); end
call_with_1p(0) { |x| puts x }

不过介于 Ruby 其实已经支持这种形式(出于它有 f a b 这种无论是我还是 Haskell 大佬看了都会绝得自己酸死的 Bash 式语法)
不过要写出来是比较麻烦的,类似 trie 树地,它要判断自己的参数是不是对象 替换前 后面的后面(就是下一个参数)又是不是 什么的,比较麻烦。

但如果你觉得 用(new)替换前(max)个(old) 可以实现为 Keyword arguments 的形式(它在定义里表达原 用(x, 替换前: max, 个: old) 使用参上),我觉得相对比较好实现,不过我显然不能帮你实现(还有绝句解析器要写啊)

我觉得在语言都还没有定好的情况下是不应该太考虑API的,不是不应该考虑,但是语言……基础的定义、控制结构,已经确定,这必须是前提吧。

个人(只学过一点 PL 皮毛)觉得 api 的设计(比如上面的语法改变)会影响语言本身设计。而且也许有时牵一发动多处,比如楼上末尾牵涉到类型转换,等等。英文 api 已经基本约定俗成了所有参数在方法最后声明,因此这方面并无什么发挥空间。

是的啊,所以我刚才没说得太绝对,我自己也深有体会,比如写这个回答的时候就因为提及了Kotlin标准库的一个设计,我决定改掉一个语法,之前我以绝句重写了某JavaScript ES6的代码后我又改了绝句的一个「构词」。

而且说点不相干的,你个人研究中文编程也有几年了吧,我能给最大的建议就是:多『学』几门语言,好好斟酌比较一下它们的区别(这是别的方法无法替代的),总结出点类似「顺序、判断、重复」这样的东西来,也不必学多高大上写 LLVM 编译器前端 IRBuilder、JIT 什么的,就琢磨一下语言的设计就挺好。

如果,支持上面的方法定义用(new)替换前(max)个(old),以及如果(...)xx这样的方法命名,代码写出来也许是这样的:

文字 问好 = "你好"
[] 号码 = [1, 2, 3, 4, 5]

问好 = 问好.("吃了么")替换("好")
号码.如果(() ->  > 4)移除

(号码)中的(某数) {           // 遍历这样看起来有点像是方法调用
  (问好 + 文字(某数))      // 假定强制转换必须显式

  如果(某数 % 2 == 1) {         // 与`如果()xx`方法看起来有点像
    ...
  }
}

写出来之后会发现更多问题(个人短期内无打算深入)

呃这样我没啥可说的,我贴一个自己之前写的代码(当然也有很多在我的笔记上没发),以及一个以目前绝句设计能有效的代码吧

(这人.(朋友们).(所有(名字.("abc").起始().()))).都拿去(用户表::删掉);

(1).数到(100, () -> {
  ((/2).为零(), (终端).("偶数"))
  .否则((终端).("奇数"));
});

Consumer<?> 不可能 = (Object _) -> { throw new ImpossibleException(); };
判断(.(名字),
  倘若(.("蔡徐鲲"), ().致敬()),
  倘若(.((iKun.映射到(IKun::名字)).()), (终端)::),
  否则(不可能));
判他的名字,
  是"蔡徐鲲",我致敬(它)
  在 iKun映至「的名字」“其实不该每次去投至”,输出写它
  否则,不可能。
引记法 绝句.严格中文 「以」
引记法 绝句.集合 「滤」

变文 问好 初 "你好"

“「初」不是随便设计的,我有其它考虑这里不提”
“如果是常量可以用「常文」或「量」”
“ 量 问好:文 = "你好" ”

量 号码 = 动组一(1、2、3、4、5)
“Mutable Array (而非 Array<out T> 那种,类型系统一样但提供了一个简写法)”
“ inline fun <reified T> im(vararg items: T): Array<out T> = arrayOf(*items) ”

“绝句不支持一至九开头是因为数字也可用它们表示,”
“这也不是随便设计的。”

“介于绝句不是『脚本语言』以及例子的完整性”
事 入口() 为
  问好 = 问好去置换("好"到"吃了么")
  “量 某表 = 表一("天"到"地"、"海"到"空"、"大陆"到"长空")”
  “解对(1至10)与(1止11)里的(甲、乙),断言(甲是乙)”
“这是一般用法,「对」是存于 绝句.额联 的中缀记法”
  问好 = 问好以("么?")去置换("么")
“这是「记法」的用法,当然也可以显示用「去以」而不省略访问符”
“你上面的代码好像写错了,暂且把『移除』当成 "xs[i] = null" 处理吧”
  对号码的索引里的针,
    若号码[针]大4,号码[针]=空。
“这是绝句第一版的风格,和Kotlin差不多;到时候有了 `存储<值者>` 抽象就不一样了”
“我们也可以用函数式的风格,但这里一般风格更好,尤其是现阶段绝句没任何优化靠Kotlin的情况”
  对号码滤出不空里的,
    说("${问好}${它去化文()}") “去化文也不必写”
    若它之为奇数,效果“啥都不做”。

扩物 数 为
  记法「之」的量 之为奇数 取者,我取取余(2)是1。 “我又决定绝句要去掉 % 中缀符转用记法了”

之前写过一点关于语言设计和 api 的顺序,现在仍觉得,如果首先从语言设计(甚至实现)出发,往往会出现削足适履的情况。越早编写接近实用的例程,越能发现语言设计的缺漏和可优化之处。因为实用(尤其是与实际业务相关的,而非纯算法)代码将是语言推广后存量比例最大的。而接近实用意味着至少是一小部分api 设计,以及一定的标识符命名风格。

所以你要写啊,尽管许多语言的入门示例足够概况,但那远远不够啊。

楼上的例程,个人(也许对目标人群有不同设想)第一眼感觉,“听去数一”,“解对”,“去化数”, “次里的”等等难以一目了然。另外,逗号、分号、句号、双冒号、顿号、波浪号等等似乎都是语法因素,也许会增加学习和使用负担。

其中 听去数一,其实我也很没办法,毕竟为了语言的一致性「去」访问符根本无法省略、解对 是我刻意那么弄的,本来也可以遵循Kotlin仍用 ,它就是来描述 for ((index, item) in list) 的这种。

此外「次里的」是你理解错了(因为绝句是期望不带空格的风格的),其实它是 对(n次)里的 的意思,这里用「解对」的确是令人困惑,但你同时去掉「解」和后面的「_」后它依然是工作的,逗号后面的 body 里多一个叫「它」的变量而已。

知道「去」是 . 的意思你就知道 听去数一 其实是访问 对象上的 数一 方法了,在 Java 里这是 input.nextInt()去化数 则是 toInt() 的意思。

逗号、分号、句号、双冒号、顿号、波浪号都是语法因素

所以说才叫『中文编程』啊,你试试就会知道只要输入法质量过关,没有任何问题。

『某』 为可不带空格的『角括名字』、「某」 为中缀表示、【某文形】 为标记修饰、〖某文形〗 为块参数列表

https://duangsuse-valid-projects.github.io/Share/绝句/绝句词法

学任何语言都是要学这些表达形式的,我在设计时刻意没看Kotlin的词法规则,就是为了能设计出更贴切中文的文法表达。

语言设计时,相信忍不住会逐渐加入更多更强大的特性,期间需要不断把中文特性这个“足”塞到这些特性组成的越来越小的“履”中。几乎无法避免地,会导致包含这些特性的例程的可读性的下降(也许可写性也是)。更大的问题是,由于语言设计者自身的视角问题,往往不会觉得这种可读性的牺牲是什么问题,因为设计者本身是对特性最熟悉的人(甚至比其他使用的编程语言更熟悉)。即使对路人非常难读的代码(由于对语言特性不了解,以及试图用老思维理解新事物的本能),对语言设计者来说却是轻车熟路。

这么说吧,其实也不无道理,但我对绝句的看法是,既然它也不是特别困难而且我现在也只需要上好学,我不要他们以为、我只要我以为。

期间需要不断把中文特性这个“足”塞到这些特性组成的越来越小的“履”中。

为什么不试试以「中文」这个食材,煮盆「程序设计语言」的汤呢?我刚才说了,中文的语序是上下文如目标对象在前、关键描述在后。所以『中文编程』实际上是指『编程』,但它的前提是『以中文』;而不是『以编程』去倒贴『中文』。『中文编程』既要有『中文』更要有『编程』,只有比重视中文更重视编程的人,才有能力设计出好的『中文编程』语言。

中文它不是一种特性,而是对编程本身的描述手段,不应该说『为了让中文兼容某某语言特性』而怎么样,而是那些语言特性,必须变得适合中文,或者说被『削』的不是中文而是特性,这就要求设计者有相当的编程功底,以至于能够对每个『不合适』的特性有所斟酌取舍。

因为设计者本身是对特性最熟悉的人(甚至比其他使用的编程语言更熟悉) 我觉得这一点是非常有必要的,那个「甚至」我觉得对任何好一点的编程语言来说 都是最基本的要求,如果一个程序设计语言的设计者无法默写下它的文法,甚至只是不能以那门语言「实现」那门语言本身,那他也不配当那门语言的设计者、那语言也不是好语言。

因此,个人认为,为了避免上述情况,最好是尽量一开始就从尽可能接近实用的例程出发,反过来决定 api 和语言设计。这样,至少一开始能够尽量从最终用户的视角检视例程(在真正开始设计、实现语法之前,尽量确保程序对于新手来说是“好用好懂的”)。即使在之后由于各种设计或实现原因需要改变例程,至少有个参照和基准,也不会太轻易地牺牲可读性。这也和一般项目在设计之前,在获取需求的早期尽量搜集有代表性的 user story 的思路相同。

这也和一般项目在设计之前,在获取需求的早期尽量搜集有代表性的 user story 的思路相同。

这是现在工程界普遍的看法,我对它其实是中立态度,不过我也有其他的看法

看完之前你可能很好奇我为什么是这么想的。
即便我的数学很差,我还是觉得我有这种『在设计时能够看到使用处』的天分,所以我能在即便是核心库、标准库还未确定的情况下就开始设计语法、定特性,上文的 Kotlin Literate 部分也是一个佐证——不知道一些抽象类怎么用的时候你是没法好好定义它的。

如果你多往下翻几页,点那个 啥啥code 的按钮,就会发现那代码复制下来直接可以写进Kotlin文件编译,而我写完后也只是改了一遍修了两个非逻辑错误就编译通过了。

程序设计 本身 ,不是所有人都在说的所谓 优雅 的代码、不是看某某人的博客,也不是对有图形用户界面的应用做最优秀的界面交互设计。

刚入门的程序员扣老师枚举出的语法,战战兢兢地拿那一堆惯用法组织自己的逻辑、加入实际项目的工程师扣刻板复制的项目管理、设计模式、代码风格,

可是真正的程序设计大师 只扣 对编程的 直觉 和程序 本身的灵魂
对他们来说已经没有入门者的条条框框、刻板的约束了,回归初心,他们看到的是 程序所做的事情本身
是程序的灵魂;换十种兼容的语言和底层抽象去描述也不是问题,因为他们已经站得足够高,无须顾虑脚下低处的迷雾笼罩而可以自由地放飞视线,
不识庐山真面目,只缘身在此山

人类的本质是复读机,可是有些人就是能在不断复读的过程中领悟到所复读内容的真谛,有些人最终也只能是记忆容量大一点的复读机而已。

语法本身是你对高级程序设计语言使用的基础,项目管理和那群系统管理员做的工作一样容易令人困惑,必须强记。模式是容易复制却又很少被彻底看懂 看透
的、代码风格可以被机械化的解析、模式匹配、自然语言字典分词、自动却又很 刻板 地检查整理。

优秀的程序员 授人渔而不是授人鱼 ,看懂某个模式、弄懂某个框架或者库、语言特性、开发工具的使用,熟悉某种基本模型,是的,都很好。
但是 学一就只能得一,做不到举一反三 、用归用 忘还是会忘 ,并且既得知识非常容易失去
因为学到的浅层知识 根本没有产生联系不能做到融会贯通 ,甚至刚用完就忘者不在少数。

当然,看起来工程本来就应该是这样, 理论是知道为什么但是它不好用,实践是它好用但不知道为什么。

@duangsuse
Copy link

duangsuse commented Jan 1, 2020

当然,看起来工程本来就应该是这样, 理论是知道为什么但是它不好用,实践是它好用但不知道为什么。

Kotlin是理论和实践的完美结合,所以,用Kotlin吧!

你们有福见到 ice1000 还没被骂还真是走运,现在人家在 Telegram 直播独立重写 Agda 编译系统的呢(Agda 仅就 mixfix 这一点看『语法灵活性』早完爆 Ruby、Python、Groovy 这种了,还不谈各种 where 布局非布局切换,虽然对 Agda 和 Scala 仅谈语法都是对它们的侮辱),我之前在没写过 Haskell 的情况下盲从王垠跟着骂基Lambda演算Haskell Type System结果被踢了(那时候我连 GADT 都不知道,更不知道还能 DataKinds、TypeFamilies……)。

@duangsuse
Copy link

duangsuse commented Jan 1, 2020

你们弄的那个 项目们 还真是挺有趣的,之前没听说过那还可以那么写

这个圈三如果以后能让绝句以库的形式使用的话,那我觉得它的例程应该是这样

引记法 海龟 「~步」
引记法 海龟 「~度」

例 重复圈:海龟.图() 为
  事 画此图() 为
    计次(20),
      计次(360),
        前进(2步);左转(1度)
      左转(18度)

https://github.com/program-in-chinese/CoCaml#compiler 这个也不错啊,OCaML 毕竟是 CaML 好像 Haskell 的,也有「为……」

可惜我对几何的图形思维能力太差,根本算不出海龟的位置,根本不知道这能怎么简化

另,

http://www.chinesepython.org/ 的作者也提到了,布局文法对中文编程非常重要,这一点你们上面可能没注意到。(当然这完全不怪你们,因为只在写解析器的时候设计语言,而不能在语言还未具体定义的时候用它写许多程序的话,很难注意到居然有这种做法)

此外,ANTLR 至 v4 都是不可能直接在 grammar 层面实现布局文法的(但是可以在外部lexer里转化成隐含的类{}token,具体找ice1000的中文blog),这也是 Grammars-v4 里没 Haskell 的语法定义的原因之一。(另外的重要原因是 Haskell 的语言,偶尔带扩展现在已经有 100+ 了要支持也支持不过来啊……)

上面 ANTLR至v4、的「至」在绝句里是中缀符 .. 或者引用严格中文直接用「至」;还有「止」是 Kotlin 里 until 的意思,right-exclusive,『ANTLR止v4不支持……』听起来很自然吧?这是绝句在布局文法外支持最重要的语言特性——记法

  1. 為什么不做 中文Ruby, 中文Perl, 中文PHP ?
    這和 Python 的編程格式有很大關系。 Python 的程式是用縮排來分段的, 因此沒有了花括號 '{}', 這令程式碼符合日常語的寫作習慣, 加入了中文后程式一樣簡單易明。 因為中蟒的主要目的是教學用, 清楚的句法要比速度, 面向對象的純正度, 程式表達的密度等都來的重要。 光是這點就否決 Perl/C/Java/PHP/.... 等一大堆語言。 我本人特別不喜歡 Perl 的那种拼命用特殊標點符號作為程式暗號的做法, 這樣只會嚇坏了我們一群天真無邪的菜鳥們。

上文作者唯一没注意到的是,缩进带语义并非 Python 的专利,Haskell、Agda、CaML 都有,所以绝句也有,不过使用了「逗号表示法」「为……」「其中……」的规范化形式。

@duangsuse
Copy link

duangsuse commented Jan 1, 2020

@zj1d 链式调用仍可以应用(它也有局限性吧)。允许参数在命名非结尾处感觉可以更加灵活地命名 API,尤其是多个参数的方法,比如indexOfSubList("st")在("test a")的位置会比较可读。

或者有些英文表达直译过来有些不符中文习惯的,比如removeIf,相比直译的移除如果(...)如果(...)移除更接近一些中文用法。

所以说 某表.除去(它 -> 不能用(它)) 也行啊,不要忘了那句戒言:『只有问题必须设计新语言解决,才设计新语言』,不然会很麻烦的,那就和实践无关而归于艺术范畴了。在我看来这和『Industrial Haskell』一样令人感到奇怪。

编程是解决问题,不是制造问题。真正制造问题的学院派编程,他们制造问题的复杂度真是比那些把简单问题弄复杂的人造的复杂一万倍,小巫见大巫了。

@duangsuse
Copy link

duangsuse commented Jan 1, 2020

https://wenku.baidu.com/view/d4424def4afe04a1b071de17.html

这篇论文真是废话满篇。对 踌躇踌躇志满 的区分要么然认为是『第一级解析』上要么然认为是『第二级解析』,这种东西还能先分成 踌躇、志满,应该是一次弄完的,我也是第一次听说有个词叫『志满』。

这人大概是自然语言学者,不是编程学者,尽说些没用的。全篇我没见他贴半点有效的代码,尽是写 natural language 的 statement,还都是那种无论对计算机作为一种 solver 还是对编程本身都表义不明的。

全篇什么作用域、指针、冯·诺伊曼、文法推导处理过程,全都是拼接一样极端不全、侧偏的定义,我肯定这人是第一次写这种论文,要不然他不至于连一点整理都不会做,是啊,说的都对,有什么用?能拿来编程吗?做不做工程是不一样的,那些只看着什么中文编程中文编程的人怎么会考虑中文真正写出来项目的易读性、复用性、可移植性、健壮性、安全性?排除了编程的『中文编程』就是个笑话。

@duangsuse
Copy link

duangsuse commented Jan 1, 2020

……都支持utf8命名吧.

说真的看到你们上面举出的一些代码我都好绝望啊,难得你们对『用中文编程』那么热情还坚持了两年,可最终还是没一个能出来做工程的,不知道最近那个文言文能不能,虽然很有创意而且作者的确有两把刷子但我不感抱太大期望。

我实在是不想评价上面那个易语言式例子了,作者现在还在『中文编程』领域工作,也算是将功赎罪吧。

不提模棱两可的『变量初始化』问题,首先缩进就不明确,然后『无返回』,其实翻译成现代一点的编程语言都是 Nothingnever__Noreturn 的意思吧(所以按易语言的编程范式,叫『无值』其实都是可接受的),也不动脑子想想还直接 函数 无返回 某操无返回 某操函数 某操(): 无返回 都好啊!

例 某游戏:游戏() 为
  量 图片 = 精灵()
  实现的事 入口() 为
    图片去载入(":img/a.png")
    图片去定位(x=100、y=200)
    加入(图片)
    你图片,色罩=色元三(255、255、255)、透明度=1.0。
  实现的事 更新(间隔:数) 为
    待写

另,UTF-8 是 Unicode 文本编码的方式,请把字符集和编码方式区分开。此处应为 支持Unicode命名。提出这个说法的同学请好好学习一下 《其实你并不懂 Unicode》 以及C数据类型、甚至位长度及二进制编码相关知识…… @nobodxbodon

@nobodxbodon
Copy link
Member Author

@duangsuse 很可惜近期很难学习实验编程语言设计了。
仍然觉得这个特性(允许参数在方法非末尾声明)值得摸索(有机会的话也想试试 Z 语言)。
更广泛的讨论仍然欢迎。限于个人对 PL 的知识所限,恐怕对你的见解还需时间细细领会。

另外,组内仍有对现有语言汉化的努力。
个人从2018年初开始基本转向对中文命名(包括 api)的探索。

@duangsuse
Copy link

duangsuse commented Jan 1, 2020

@duangsuse 很可惜近期很难学习实验编程语言设计了。
仍然觉得这个特性(允许参数在方法非末尾声明)值得摸索(有机会的话也想试试 Z 语言)。
更广泛的讨论仍然欢迎。限于个人对 PL 的知识所限,恐怕对你的见解还需时间细细领会。

另外,组内仍有对现有语言汉化的努力。
个人从2018年初开始基本转向对中文命名(包括 api)的探索。

没关系,慢慢来嘛。反正也才快一年,我也会继续想办法实现我设计的程序设计语言的。
坦白说要给那么多语言设计汉化也很累,毕竟别人设计的语言还是蛮多的。

@duangsuse
Copy link

duangsuse commented Jan 1, 2020

很多人提到易语言,因为他算得上中文编程中的成功者,但是实际上因为是纯技术出身,而不是技术转产品,所以易语言是很封闭的,后面的产品更是一代不如一代,一个小团队想要蚂蚁啃大象,没有穿透力还是不行的。但是易语言生态圈也作出了不少成功的尝试,精易论坛、世桓培训都开辟了不同的道路。

首先,易语言虽然开始在瀑布单次开发无维护式应用程序编程里火了几年,但随着时代更新逐渐被淘汰而且定位尴尬,这样的情况不能称为成功,排除那些元老级的 Fortran、Ada、ML、Forth、BCPL/CPL/C、PostScript 在外,我觉得 Basic、Delphi、Smalltalk 这种才能够算是成功过。

但是实际上因为是纯技术出身,而不是技术转产品

易语言到不如觉得是产品出身更好,我相信技术不会那么烂。就像zhong4麒麟一样。对易语言里的「易」,我觉得它的涵义就像中标麒麟是为『投标中标』里的『中标』一样,根本不是为了成为『中国标准』、成为『用户觉得容易』的语言,而是为了欺骗国家、政府和人民,自称是『方便普通人学习、推广编程技术』的语言。

所以易语言是很封闭的

这点到是真的

但是易语言生态圈也作出了不少成功的尝试,精易论坛、世桓培训都开辟了不同的道路。

我这里想吐槽一句,能设计出易语言那样辣鸡语言的作者,根本不配在编程领域提『精易』这个词,更不配在程序表达和转化领域搅合,十五年如一日没有长进我也是很服了。
易语言自它公开的那一天起,即便在工程领域的确有所建树,谈『精』、『易』,凭作者对『面向对象』和对编程语言抽象能力相关技术的理解,它没那个资格。

@nobodxbodon
Copy link
Member Author

@duangsuse 刚写了《一种改进中文 API 可读性的方法:参数不限于在末尾》,尤其是后半部分的补充,是之前讨论时没想到的。

@duangsuse
Copy link

duangsuse commented Jan 4, 2020

@nobodxbodon 这倒是,但不觉得容易给学习制造问题吗?

这个思路我是很赞同的(而且对中文编程很必须),但它是属于『很「中文」但不一定「编程」』的特性,如果这样的API太多了会制造问题,而语言基础库设计不够克制、过分利用这个特性会有更大问题。

一个语言特性一旦出现,对它的滥用就不会停止,并且如果保证向前兼容也就不可能停止。

如果标准库设计不够克制,以后这种语言里可能都是这样写代码——当然这里我只能举出滥用介词的例子,我不知道可不可能有更奇怪的情况出现。

变量 翻译字典 = { ',': ','  } //...
定义 把(此书:文件)里的字符替换为全角 {
  使用(把(此书)打开)时 {
    变量 新书 = 新建文件(此书的路径)模式("w+")
    对此书的字符里的每个符 {
      如果(符)在(翻译字典)里 { 在(新书)里写(翻译字典里(符)的值) }
      否则 { 在(新书)里写(符) }
    }
    新书写至系统()
  }
}

看起来好像是没什么问题,实现起来稍微有点算法基础的人也能以 trie 树这样较为简单的数据结构实现。

可是为什么不这么写呢:

量 全角:表<字、字> = 表一(','''“等等”)
扩物 文件 为
  事 全角转化() 为
    量 新书 = 同名新建()
    对我去读全文本()里的每个符,
      新书写(全角去取值())
    新书去
量 全角=建表(','到',' “...”)
事 文件.全角化 = 内容替换,
  它去看,[c] 全角[c]。
事 文件.内容替换(:函1<文、文>) 为
  量 新=此函1(读全文本())
  文件(路径、"w+")去写(新)

另外,习语言举的例子:在(文本:section)节(文本:key)项写入(文本:strVal)

INI在"Fruits"节"TotalCost"项写入"100 CNY"

一般面向对象里可以认为是这么封装的:

INI["Fruits"]["TotalConst"] = "100CNY"
INI.sections["Fruits"].entries["TotalConst"] = "100CNY"
INI section "Fruits" entry "TotalConst" = "100CNY"

从这个角度我听人说『英文逻辑比中文严谨』是真的,因为它每个部分分得很开,xs[1]xss[1][1] 没有特别的『语法』支持。
可是这里有个问题,如果所有类似 INI[sectionName][entryName] 这样的「子结构取/置」都被写成

INI在(sectionName)节(entryName)项写入(strValue)
INI在(sectionName)节(entryName)项读出

那么 fun processSection(section: INI.Section) 该怎么写?在大型应用里这是完全有可能的吧。

如果新建一个 INI在(sectionName)节 “的引用”,那 API 是不是就更难记忆了呢?
或许可以用 completion,可依照这么灵活的『函数调用』方法,我不是特别相信在导入足够多、单个抽象足够复杂的时候它还能正常被用来写 real-world 的应用程序。要知道标准库的确是可以放很多操作和数据模型的,要是每个都可能采用 在…… 这类的调用模式…… 我到时候去看看。

语言的设计是需要深思熟虑的,仅有创意、不融合对代码一致性(同时也和学习成本有关)不能造出既自然又能够被用于实际工程实践的『中文编程语言』。

比如我对 某个语言特性 就想了半天。

引记法 绝句.额联 「以」
引记法 绝句.严格中文 「~始」

事 入口() 为
  "Hello world"以("a")始
  "Hello world"去试始为("a")

用类似 Kotlin infix 的解决方案更规范、更一致,不至于让语言显得太『灵活』,其实 infix+内联class 也是这个技巧的一种实现方法。

也许,这个特性会成为中文编程语言的一个“标志”呢。

去学校三天绝句程序设计语言的『第一人称』『第二人称』『第三人称』都被整理出来了,

  • 第一人称 面向对象的/ 可带标签如 我[某事]
  • 第二人称 ,支持语法:若你判你对…里的你……
  • 第三人称 //,支持语法:逗号块、中缀链、对…里的……

同时还添加了中后缀逻辑修饰符(新语法)「不」

所以原来的 不属不存于不大 之类的都可以不必再特别规定了,isEmpty『~为空』这种也不需要再写冗余的模板 val T.isNotEmpty get() = !isEmpty 了。

@nobodxbodon
Copy link
Member Author

nobodxbodon commented Apr 26, 2020

@laowu2019 编写的vs code插件, auto-correct 基础上实现了中文标点符号自动替换为英文标点符号的原型。用到一个模拟键盘输入的模块

基本思路就是利用文档变化事件获取最后输入的字符,如果该字符匹配中文句号等标点符号,就先删除该符号,然后模拟键盘输入相应的英文符号。如果不模拟键盘输入的话,不会弹出自动提示、参数建议等等。这个node模块找了半天才找到
接下来可以考虑在注释中就禁用替换

有没有可能监听键盘事件,如果是中文句号就替换成英文句点,省得删除再模拟输入?

@laowu2019
Copy link

找到一个新的VSCode内置方法写入字符,不需要引入外部模块。遗憾的是不能穿透python插件原生支持的jupyter notebook,期待大家帮忙解决。

@liuxilu
Copy link

liuxilu commented Mar 2, 2022

#11 (comment) 「方法名参数位置」
相关:Multi-Part Method Names - RemObjects Elements

顺便,「用("bb")替换(列表)中的("aa")」非常恶劣,主体应该突出在前,如「替换(列表)中的("bb")为("aa")」

@MaOrKsSi
Copy link

MaOrKsSi commented Mar 29, 2022 via email

@xgongya
Copy link

xgongya commented Mar 29, 2022 via email

@liuxilu
Copy link

liuxilu commented Mar 29, 2022

这听起来很熟悉。「这是理工科,用中文写什么代码?」。我只能说,每人都有自己的「理工科」。
不管是系统函数还是自定义函数,参数写在两头、主体夹在中间,都不是好主意。

@nobodxbodon
Copy link
Member Author

@liuxilu 日语编程语言抚子中,因使用日语语法有些参数在前的例子:

締め切りは「{今年}/12/20」
今日から締め切りまでの日数差を表示   // 显示从今天到截止日期的天数差异,“今日から締め切りまでの日数差”为显示内容

参考:《关于日语编程语言“抚子”的解释》摘要(一)

@MaOrKsSi
Copy link

MaOrKsSi commented Mar 31, 2022 via email

@nobodxbodon
Copy link
Member Author

@MaOrKsSi 建议了解一下 UX。

@MaOrKsSi
Copy link

MaOrKsSi commented Apr 2, 2022 via email

@MaOrKsSi
Copy link

MaOrKsSi commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
长期 原则上仅对索引帖适用
Projects
None yet
Development

No branches or pull requests