duangsuse::Echo
717 subscribers
4.26K photos
130 videos
583 files
6.48K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
Forwarded from Deleted Account
黑客是为了挑战最有难度的技术,就像Unix那样,像Linux那样,他们主要是为了提供更好更牛的东西,他们不破解软件,他们用自己的能力重写一套更牛逼的软件。他们还像telegram一样,支持1.5GB的文件 ,支持20万人的群,无限人数的channel,以及足够开放的平台……这才是真正的hacker精神
#Python 有这种工程师,我也是服了,也是 NB。 #Low #China
#Kotlin 是好事,你看那 Deprecated 本来就应该换了(而且 Kotlin 的 annotation class kotlin.Depreacted 还带了 IDE 自动替换(比如,val T.isUserAMonkey get() = … 能够换成 .isMonkeyUser 自动的;

至于 Null safety (Nullability) 更是 Kotlin 比 #Java 化腐朽为神奇的地方(当然,in/out 型变性声明而不是 ?super/?extends 类型上下限界也是一个优秀之处),这实在可以说是 Kotlin 最骄傲的地方之一。

它既然觉得 str: String?, 你 str!! 一下就可以拿到 kotlin.String! 了(也可以用 ?. 安全 Null 传导),不过如果真的是 null 引用的话,就会抛出 KotlinNullPointerException


val files: Array<File>? = …
files.forEach { f -> f.close() } // Unsafe use of a nullable receiver of type Array<File!>?
(fn as (String) -> *)(json["user_nickname"]) // Type mismatch: inferred type is String? but String was expected
Forwarded from 羽毛的小白板
duangsuse::Echo
#Kotlin 是好事,你看那 Deprecated 本来就应该换了(而且 Kotlin 的 annotation class kotlin.Depreacted 还带了 IDE 自动替换(比如,val T.isUserAMonkey get() = … 能够换成 .isMonkeyUser 自动的; 至于 Null safety (Nullability) 更是 Kotlin 比 #Java 化腐朽为神奇的地方(当然,in/out 型变性声明而不是 ?super/?extends 类型上下限界也是一个优秀之处),这实在可以说是…
你会爱上 Kotlin 的,尤其是:如果你写算法的话
Java 简直能把 C++ 写5行的代码写10行,而且还不如 Kotlin 可移植
我几乎不写 Java,更看不上 Groovy 那种辣鸡语言,JRuby 和 JPython 试过,不太喜欢。不过 Scala 我是不常用,Eta(Haskell for the JVM) 的 IDEA 支持不好

Groovy 怎么辣鸡呢?IDEA 2019 打开你的 Groovy (我只用 Gradle)脚本看看,你会发现一堆 type error
这 TMD 绝对不是 JetBrains 人懒的锅。

import static System.out
def doge = "🐕"
out.println("Emmm ${doge}.") // can't be applied to GString


谁叫你弄个什么鬼 GString 的???难道你要惰性求值???
还有(好像是 Gradle Action<in T> 专属的),谁告诉你 it 可以被隐式作为 this 的?
['1','2','3'].map { println(replace('1','')) }
为什么 def 也可以用来不带参数元组的定义?你们的作用域是怎么做的?为什么给人感觉那么奇怪?脚本语言就可以如此随便?

脚本语言随便起来是可以很随便的,比如那个 0+'1' != '1'+0'0'==0 的 JavaScript。
有些完全是『工程派』的人是不了解这些事情的,他们只是觉得写得越少/多越好,嗯…… 所以才有了类似 Ant XML、SOAP("Simple" Object Accessing Protocol) 这种东西。

他们写的时候就只会以一种思路、一种视角看一个示例程序甚至完全不看,就是想当然地设计,设计出类似 Java 的 type wildcard 的东西(当然这个还是比较保守的),因为不管你在某些方面再好,也总有自己还没学过的方面。

有些人只看着所谓的测试文档覆盖率,所谓的持续集成,所谓的工程标准。
可是他们注意力的重点,几时才会放到自己要实现的东西本身上来呢?

再看看某些所谓的中文编程语言,他们到底在做个什么呢?老祖宗的好东西全给糟蹋了,中文了你还用逗号切参数列表,中文了你还把“”拿来和""一起都记字符串,中文你还管 boolean 叫布耳,中文你还把 break; continue 翻译成『打断』『继续』,翻译个驴唇不对马嘴,不够用心。

对所有编程语言里语言是中文的,若它属辣鸡设计,
锤爆(它)
Forwarded from dnaugsuz
…… 你没有提到 return 有个副作用是下面的代码都别想执行了,那当然是没这个问题了

其次有一个不容易被注意到的细节:?: return?: throw 居然是一样的,都 TM 是普通版文法
Kotlin 傻逼了! return 怎么可以是表达式?
你试试 fun op() { println(null ?: return as Nothing) }
Forwarded from dnaugsuz
iseki 觉得 return 能够和 throw 一样被作为表达式吗 🤔
fun op() { do { println(null ?: continue as Nothing) } while(true) }
我觉得好奇怪啊
Forwarded from iseki
返回Nothing不行吗
Forwarded from dnaugsuz
我觉得不行,这样容易混淆……
我觉得可以提供语法糖,但不能是表达式

我很讨厌 fun op() { do { println(listOf(return, continue, break, throw Exception())) } while(false) } 可以解析甚至执行的情况
Forwarded from dnaugsuz
我还是无法接受 continue 可以被作为参数的 case……
println(continue) 我简直发毛
尽管类型层面我们可以检查出 println 不能被执行
Forwarded from iseki
不能编译啊,你怎么可以println(Nothing)呢
Forwarded from dnaugsuz
我是这样想的,如果没有足够的理由,『控制流』表达式我要有所取舍
比如说,一些能够不作为表达式的,return 什么的就专门提供语法糖
Forwarded from dnaugsuz
这个问题我可以到时候弄出我设计那个语言第一个编译器的时候再找其他人谈谈,
之前我没考虑过 break 什么的类型级别可以是 Noting 这件事……
我之前以为 Kotlin 是不允许这样,但我得慢慢去想,举出实际使用例子来

其实这也不是没好处,好像是可以放在 block(closure) 里面的,不过我也不是很确定。

我打算设计的这门语言叫『绝句』,这里有一个简单的例子:

引记法 绝句.区间.数域 (投、换)
对何<项>皆有
括物(我: 行<项>) 为
私下、尾递归的事 二分查找(你: 项、区: 数域): 引数? 为
量 中针 = 区的中值
判我[中针],
是你,回中针
大你,重写(区=区投末,中针前。) “逗号文法 确保(一行(1、2、3).全是,它 不小 一。)”
“二分查找(你, 区.mapBegin { 中针.dec() })”
小你,重写(区=区换始(中针))
“编译器知道没有其他情况”

记得我当初设计的时候(重写是后来设计的一个特性)重写被弄成了个值是『断止』类型的表达式 🤔

一个细节是,它在类型层面建模了 Kotlin 没建模的 Exceptions,这个建模被称为『无常类型检查』

//!语者 无例之物
//!语者 此即存储
对何<值者>皆有
密封的内联物 无常 为
私下的内联物 断止: 无常<*>()
私下的内联物 决常(量 你: 值者): 无常<值者>() 为
算符的事 此即值() = 你
“大致是这样吧,注意这是编译器的 intrinsics”
比如说,假设有 事 读一行(): 无常<文>

尝试,
量 输入行 取者,读一行()。 “内联类没有『我』分配,无法作为通常值存储”
“或者,你也可以写 量 输入行 = 读一行()作决常”
输出 写 输入行 “编译器知道『输入行』的「推帧单位」和赋值语句的是一个,且这一句能执行必定代表无异常发生,智能转型。”
接迎 文件结束不常成『异事』,异事去写出()。 “『标识符』是绝句的一种文法”
“当然关键字<接迎>后不加空格也可以”
终焉,
“这只是个例子”
Forwarded from dnaugsuz
你这指定的好像是类型上界 <T: Any> capture<T extends "Any">
有时候我觉得类型上、下限好理解些,一个「界」字我觉得断言的不够明显,让人困惑(虽然是通用说法)
Forwarded from dnaugsuz
就是类型检查啊,Java 都是泛型擦除的实现,Kotlin 有强十倍的类型系统你还璇它……

Java 早些时候(1.5的时候才加的泛型)没泛型才这么干,到处瞎转转
现在 Kotlin 有了,你不多看点 Kotlin 最佳实践,还是先重新学学再说吧,Kotlin 不是 JDK stdlib 辣鸡。

而且什么叫做都是,链表也是么
Forwarded from dnaugsuz
我给你解释一下,拿一般的那一套,不说什么类型理论、集合不集合值不值的。

既然你已经知道 PECS(producer-extends, consumer-super) 原则什么的,就不说了。
Java 的泛型通配符是一种类型变量,?extends A 配属 A (或者说『小于A』)的任意类型,?super A 配超 A(或者说『大于A』)的任意类型
类型就是谁兼容谁的问题,CharSequence 兼容 String、Number 兼容 Integer, Long, Float,或者说兼容者是被兼容者的子类型(subtype)。
就是说任何操作 (CharSequence) -> * 都可以被 invoke("string instance")
哪怕是 xs[1], xs[2] 这种操作都一样(他们就是 Kotlin 的 operator fun get(index: Int): T) 嘛


泛型加了个参数,不过这里就出了个问题,比如说,

interface Box<T> {
T get();
<R> R let(Function<T, R> f);
}

这里我们写点使用者角度的代码,
void printNumber(Number num) { out.println(num); }
// Function<Number, Void> printNumber = out::println;
Box<Integer> ba = new ValueBox(1);
ba.let(::printNumber);
// Box<Integer>#let(Function<Integer, R>) is not acceptable for (Function<Number, Void>)

其实我们谈的 Box<T> 就是 Kotlin 的 Box<in T>,因为它的类型参数只在「消费者位置」出现,你说对应 ?super XXX,很正确,但知道不等于理解,所以要再学。

所以大家都这么写:
  <R> R let(Function<? super T, R> f);
然后对 Java8,it checks,很好可是对理解没帮助,我们应该看看 Function<T, R> 的定义:
interface Function<T, R> { R apply(T in0); }
准确的说是 Function1: (T) -> R.
所以为啥现在可以了,就是因为 Function<T, ...> 里的这个 T 成了 ?super Integer, 所以它关于它的类型参数 T 逆变(contra-variant)了(Scala 的 Function[-T], Kotlin 的 Function<in T> 或者 (T) -> *)。

所以说,为什么现在可以用了,就是因为

对于任意类型 <R>
Box<Integer>#let(Function<?super Integer, R>) 可以收 Function<Number, R> 类型的实例了

为什么要有输入/输出两种情况,就是比较对象顺序上的差异(我也不知道为什么)
为什么要有型变性,是为了完整化类型系统多态(polymorphism)的代码复用
+ 如果有某个收某类型 A 的操作 Op<A> { void op(A); }, 则对于所有的 Op<A0: ?super A> { void op(A0); } 它肯定能够 op((A) x),因为它连 A0(如 Number) 都能收自然能够收 A(如 Integer)
+ 如果有某个返回某类型 T 的操作 Ret<T> { T get(); }, 则对于所有的 Ret<T1: ?extends T> { T1 get(); } 它肯定能够 (T)get(),因为它连 T 的子类型都能返回,为什么不能返回 T

然后 Kotlin 的 * (就是说在某个「位置」被一切参数兼容,比如 Consumer<in *> 可以收 Consumer<Int>, Consumer<String>, ...) 在 in 的位置是 in Nothing, out 的位置是 out Any?

Nothing
是 Kotlin 里一切类型的子类(bottom type)、Any? 则是一切类型的超类,所以区间 Nothing..Any? 就代表可接受一切类型
不过区间好像是包含两个比较的,a<=x&&x<=b 代表 x in (a..b), 类型检查只用判一次超类链


岂止是没区别,单就泛型看(这还不提 Kotlin 化腐朽为神奇的 T?, (?.) (?:) 操作)都是天壤之别呢,你去看那么多 Java 库,他们类似 Action<T>, Consumer<T> 这种都不得不对每个受参的方法写 Action<? super T>
那种雷轰感,没写过是不会明白的……

Kotlin 的 in/out 都是在类型变量声明处,此外对于 <A, B> fun copyArray(dst: Array<A>, src: Array<B>) 为保证类型安全和代码复用可在 Array<...> 里填 out B, 它会禁止对 set(Int,B) 的访问
(因为如果允许,实际上意味着 (ary as Array<Int>).set(Int, Number) 可以被使用,因为 src 可以是任何 Array<T> where T: Number,这是败坏类型安全性的)(给填 in A 也是可以的,效果一样)

成熟个毛线啊,Java 简直老掉牙了!Kotlin 写十行的代码 Java 不得不写 20 行,有些 Java 程序员能写 40 行,带上所谓的内联文档和注释和『完全覆盖』的测试!

和兼容 Java 没有关系,Java 对泛型兼容也主要是编译器上下工夫,类文件格式其实是没有变化,只是加了点元数据


就是这样
Forwarded from dnaugsuz
所以,对你的方法大概是用 Array<kotlin.Int>

我猜你是这么想到这个问题的:Java 里你用的是 final T[] xs;
可是如同 kotlin.Int 不是所谓的『primitive』一样,Kotlin 里也没有 primitive 的 generics array。
你是担心它有额外的性能开销?那就用 IntArray, CharArray 什么的…… 他们是自动拆箱(unboxing)优化的

你说你能保证,这可以理解(因为编译器不可能知道你到底想干什么),可问题是编译器也无法靠你的口头保证得知 arrays::get 是的确是 (Int) -> E,是不是?

计算机是死的,Array<T> 由于 Java 的泛型擦除(泛型参数只在类型检查时存在,除非你用 Kotlin 的 inline + reified type parameter),其实际存储是由 JVM newarray/anewarray 自动创建的,alength/xaload/xastore 指令来取长/访问实际数组对象。

List<T> 运行时全是 List<Object>, 知道他们的类型全都依赖类文件存的元数据
即便是编译期,你觉得你能保证,但谁知道你会不会写出 arrays[0] = Any().also { assert(Any() !is E) }?这样实际上就和无类型检查没啥区别了。
所以你要检查就写进类型系统的依赖数据,不检查就 Suppress,不要说自己可以保证,没有谁是敢保证自己的代码的。
比如说我就经常被 IDEA 自动推导的结果打脸(被打的是我自己的推导结果)。

另外,一般为了保证泛型的型变性(在 Kotlin 里,也就是输入输出方法被调用的可能性)安全,应该用 Array<*> 替换 Array<java.lang.Object>

如果你不向数组写东西(就是说它的 set(Int, E) 不会被使用),Array<kotlin.Int> 就可以了。
Forwarded from dnaugsuz
但它也是困难的,你试试写个 partial evaluation 的翻译器出来,带寄存器分配的那种,或者自己独立思考一下 Java 的反编译器该怎么写。
Dalvik 还好,不存在什么存储寄存器(link register) 什么栈寄存器维护的问题,要些 native compiler 还弄什么层次差啊…… 什么常量存储段啊…… Lua 还弄什么跳转链表……

iseki 你是大学生,不如照着 USTC 分享的那个 PL/0 来一次实验?
https://github.com/USTC-Resource/USTC-Course