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
本来数学不好,还要写这个自己都不知道是为什么要那么写的东西
何况刚才我写的链表也缺了点东西,比如 insert 操作…… 它应该可以加在 iterator 上面
但是单就这个数据结构的实现上来看,我觉得还有很多应该思考建模方式的东西
既然本频道之前的东西都没上 LICENSE,这次的代码也不上了,妮妮萌萌系爱抄抄吧,只要你们会就行了。

一些代码留着下次可以继续测试和复用,比如 Feeder
StreamFeeder 有点累了,没写出来(即便是写出来也不需要太大力气,而且可以继续写方便复用的解析器框架

它不依赖我写的 Linked.List,话说 Linked.List 把 ProGuard 的 partial evulation 都给弄炸了,还说找不到 calc.Linked.Cons 和 calc.Slice 的公共超类?莫名其妙,即便 Cons 是属于 sealed class 的 data class。
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 对泛型兼容也主要是编译器上下工夫,类文件格式其实是没有变化,只是加了点元数据


就是这样