duangsuse::Echo
https://github.com/lice-lang/lice 冰封哥都退团了,emmm,之前听说实现 expr 是有啥问题来着
之前不知道是怎么回事搞混了 call-by-name 和 call-by-need,我以为 by-name 是惰性求值,by-need 是重复求值
肯定不是我自己记岔了!第一次看到 call-by-name 它好像被人拿来做是惰性求值的意思了……
肯定不是我自己记岔了!第一次看到 call-by-name 它好像被人拿来做是惰性求值的意思了……
duangsuse::Echo
关于 Reflex 这门语言,我这里已经有不少(本来不是为它设计) 的稿子了,但因为都是 JVM 语言所以都可以用,就来汇总一下 看了刚才的示例我感觉非常 excited,分分钟想弄出个大新闻 🐸 这是一门多范式 JVM 编程语言,支持特性包括: + 基本的值、计算、顺序、分支、循环、递归 + 支持高阶函数、Block (closure) + Java 没有太多值类型,所以都是按引用传递 + 支持语言层面的惰性求值(call-by-need),惰性求值是针对函数的返回值、参数,不支持列表等 Iterable…
这一段定义了和 Java 的 interop,
+ Reflex 是一门多范式、动态类型的 JVM 语言,它支持多态,在语法上支持类型标记。
+ 控制流,Reflex 支持顺序、分支、循环、递归。
+ Reflex 支持高阶函数和 Block (closure),函数参数都是按
+ 语言层面支持(针对函数参数和返回值的)惰性求值和(针对返回值的)表达式作为值
+ 惰性求值使用标准库
在 Java 的层面看来,收到的对象是
在 Java 的层面看来,收到的对象是
+ 允许使用反射访问任何 Java API,内部语法
如果属性以
+
+
+ 所有带
创建的所有函数,都由
对象上面的方法,内部使用
函数或方法(不包含
+ 可以使用
+ 内部支持
+ 对于 Nullable type 支持
需要注意的一点是,
+ 标准库还扩展了
+ infix operator 定义类似这样:
如果 infix operator 的名字两侧包含空白,代表它需要左/右侧有一定数量的空白字符
如果 infix operator 的最右侧是
+ Reflex 是一门多范式、动态类型的 JVM 语言,它支持多态,在语法上支持类型标记。
+ 控制流,Reflex 支持顺序、分支、循环、递归。
+ Reflex 支持高阶函数和 Block (closure),函数参数都是按
java.lang.Object 引用传递+ 语言层面支持(针对函数参数和返回值的)惰性求值和(针对返回值的)表达式作为值
+ 惰性求值使用标准库
lazy {} 函数创建,如果将惰性块保存到本地变量或者作为 Reflex 函数的参数、从函数返回,不求值。lazy 是软关键字在 Java 的层面看来,收到的对象是
org.duangsuse.reflex.rhs.Lazily
+ 表达式使用 expr Name = Expr : Stmt 语法创建,表达式在每一个要求值的地方求值,表达式可以作为返回值,这种情况返回表达式而不计算,expr 是关键字。在 Java 的层面看来,收到的对象是
org.duangsuse.reflex.rhs.Expression + 允许使用反射访问任何 Java API,内部语法
(.) (::)、标准库 (.$ #) (::$ #) (?.$ #) (?::$ #)
+ o.method 不可以使用,这个语法只能用来表示索引属性 Val / Var
public final o.XXX, public o.XXX 字段、public o.getXXX(), public o.setXXX() 方法如果属性以
is, has 开头,则查找方法时不添加 get/set 前缀+
o.method(_) 进行 Partial application (WIP,目前先 reserve 这个 _)+
o::method 来引用某个 receiver 上的方法+ 所有带
$ 的语法,表示访问非公开属性/字段/方法,都由标准库提供(import std.reflect)创建的所有函数,都由
java.lang.Runnable, org.duangsuse.reflex.fn.Function[0-7] 提供Function0<R>, Function1<T0, R>, ... 对象上面的方法,内部使用
Method0<A>: Consumer<A>, Method1<A1>, ... Method7 实现函数或方法(不包含
this)的参数个数不能大于 7,vararg 关键字可以支持变长参数,内部支持 SAM(Single Abstract Method) 自动代理实现ExprOrBlock = (EQ Expr | Block)+ 可以使用
val Type.Name[: Type] get(L R) ExprOrBlock [ set(L Name R) ExprOrBlock ] 扩展 getter+ 可以使用
fun Type.Name ArgList[: Type] ExprOrBlock 扩展方法+ 内部支持
(is) (as?) (as) 操作符+ 对于 Nullable type 支持
(?:) (!!) 操作符需要注意的一点是,
T? 和 T 的差别在于 T? 可能是 null + 标准库还扩展了
infix fun Any?.in(container: Any?) = container.contains(this)
infix fun Any?.`!in`(container: Any?) = container.contains(this) 方法+ infix operator 定义类似这样:
(infixl | infixr) LitInt (L ... R) infix fun 默认 precedence 和 (.) 相当如果 infix operator 的名字两侧包含空白,代表它需要左/右侧有一定数量的空白字符
如果 infix operator 的最右侧是
#,代表它接受一个标识符作为参数,对应 fun 将被传入 org.duangsuse.reflex.data.Name 实例
duangsuse::Echo
这一段定义了和 Java 的 interop, + Reflex 是一门多范式、动态类型的 JVM 语言,它支持多态,在语法上支持类型标记。 + 控制流,Reflex 支持顺序、分支、循环、递归。 + Reflex 支持高阶函数和 Block (closure),函数参数都是按 java.lang.Object 引用传递 + 语言层面支持(针对函数参数和返回值的)惰性求值和(针对返回值的)表达式作为值 + 惰性求值使用标准库 lazy {} 函数创建,如果将惰性块保存到本地变量或者作为 Reflex…
然后是在操作和内部值的层面:
2D 表示不需要
Literal:
Bool
Int
Real
注意这里
Name (任何在 Java 中有效的标识符,除了包含
typedef Name EQ Type其中,EQ 的判断方法是
const Name EQ Expr
fun Name (L ArgList R)[: Type] [LSQ LocalList RSQ] BlockOrExpr2D : Stmt
do (I ArgList I) | (ArgList.) BlockOrExprNoEQ2D : Expr
loop(L Name R) [(while | until) Expr] Block : Stmt
break(L Name R) : Expr
continue(L Name R) : Expr
WhenBr = when LB { Expr => Expr } [else => Expr] RB
| when NL l:Layout Expr (l Expr)*
WhenInfix = when Expr LB {infix Expr => Expr} [else => Expr] RB | {- 2D part -}
WhenEq = when Expr LB { Expr => Expr } [else => Expr] | {- 2D part -}
When: Expr = WhenBr, WhenInfix, WhenEQ
Var = var Name : Expr
Call = Name (L Args R) [ Block ] : Expr
Infix = Expr infix Expr : Expr {- 大意,因为分 infixl/infixr - }
eval(branch).equals(subject), 方便支持模式匹配2D 表示不需要
where 语法,就可以判定使用基于缩进的块(=) (+) (-) (*) (/) (mod)我们不把负数当数,所以没有类似 Kotlin 的 unaryMinus 语法,但有一个
(>) (>=) (<) (<=) (==) (!=)
neg 一元操作符(还是 std.prelude 里面的)inv 操作没有对应语法Literal:
Bool
true false Int
0xAF 1_23 0b10 0xFFl
其中,下划线不能连续出现Real
0.1 0.1f 1.0e10
Str "abc" "User($name)" "${1+1}" "\t\v\a\b\n\r\f" "\x00" "\u0000" "\U0000_0000" (<<heredoc ...)注意这里
\U 中间的划线是必须写上的Name (任何在 Java 中有效的标识符,除了包含
$ 的部分) `name` (建模的时候我把标识符也考虑进去了,虽然它表示对存储的引用,我觉得必要时它也是值……)上面那两条消息就是 #Reflex 的基本设计了,那 numpreety.js 也不是多好写,我先写点看看 🤔
JavaScript 真是辣鸡,我去找点 ES6 to 5 的翻译器,结果我只找到 Babel 和 traceur 两个,而且 traceur 的那个还一年没更了
Babel 的那个根本不能即装即用,亏得它还弄的花里胡哨的彩色啊…… 还啥啥啥定律,我看以后不如用 Kotlin.js 写好了
ES6 都麻烦的要死,为毛现在还是 Next,明明是必品啊,TMD 我写单文件就麻烦,node 本来已经只是包装了还包装不好,看看人家 Ruby
Babel 的那个根本不能即装即用,亏得它还弄的花里胡哨的彩色啊…… 还啥啥啥定律,我看以后不如用 Kotlin.js 写好了
ES6 都麻烦的要死,为毛现在还是 Next,明明是必品啊,TMD 我写单文件就麻烦,node 本来已经只是包装了还包装不好,看看人家 Ruby
已经足够把 babel 那一些不方便的 ES6 换掉了,虽然不如 Kotlin 好用
Google 不知道是怎么搞的,难道 Google 的前端都是吃干饭的?怎么才弄出那一点东西还不维护了,NPM 上都是几年前更新
Google 不知道是怎么搞的,难道 Google 的前端都是吃干饭的?怎么才弄出那一点东西还不维护了,NPM 上都是几年前更新
numpreety.es6
4.5 KB
tsc numpreety.ts --out numpreety.es6 欸不错啊,体积这么小
duangsuse::Echo
numpreety.es6
我写了很多流 operator,不过还是不吼 emmm,没写出我开始想的那个算法,有点麻烦了
算法果然还是脑袋清晰的时候写纸上方便,要不然很容易糊涂的 😭
算法果然还是脑袋清晰的时候写纸上方便,要不然很容易糊涂的 😭
#Ruby
Dir.glob('.*').let { |fs| fs.zip(fs.map { |name| name.gsub(//){$1} }).each { |c| o,n=c; File.rename(o, n) } }
duangsuse::Echo
#Ruby Dir.glob('.*').let { |fs| fs.zip(fs.map { |name| name.gsub(//){$1} }).each { |c| o,n=c; File.rename(o, n) } }
def bulkRename(re_src = /.*/, re_ext, fmt_dst)
src = Dir.glob(re_src)
new_names = src.map { |name| name.gsub(re_dst, fmt_dst) }
for old, new in src.zip(new_names)
File.rename(old, new)
end
end#bulk.rb
def bulkRename(re_src, pat_dst, fmt_dst)
re_dst = Regexp.new(pat_dst)
selected = Dir.glob(re_src)
for name in selected
newnam = name.gsub(re_dst, fmt_dst)
puts("mv #{name} #{newnam}")
File.rename(name, newnam)
end
end
case ARGV.size # Just br size is OK
when 0 then warn("Usage: #{$0} [select] re_dst fmt_dst")
when 1 then puts(Dir.glob($*[0]))
when 2 then bulkRename('*', $*[0], $*[1])
when 3 then bulkRename($*[0], $*[1], $*[2])
end
#move_back.rb
for ln in $<.each_line do
next unless ln.start_with?('mv')
_mv, src, dst = ln.split
puts("mv #{dst} #{src}")
end