duangsuse::Echo
最近 CSS 和 JavaScript 都宣布了一个管道操作符,还不能使用。尽管反复看,前一个只记得住使用范围(<table>)… 后一个只记得住作用(简化连锁函数调用)… 真是要多用才能理解,才能记住。
不过,这个 Qualified class instance creation 可不是新的 Java Feature 了(至少是 Java 1.2 就有),新的是
var local variable type inference (Java 10+),Java 以前一直是显式类型的语言呢,现在终于有了 Type inference。
duangsuse::Echo
#tech #daily #Java #JavaScript #dev 🐱 duangsuse 的学习日常 ⭐️ + 程序设计语言::Closure、Pattern Matching、Stream、Generators #pl #cs + 程序设计语言类型::这些名词,你知道吗?(涉及 Parameteric Polymorphism 和 Empty Types(aka. Bottom types)、Product types、Subtyping 等内容) + 高性能计算::C 语言和高性能计算、x86…
如你们所见,很多,所以一天是无法完成的,所以这个列表慢慢累积...
先默写一下 Java 和 Kotlin 的 Modifiers
== Java
Class members
Classes
先默写一下 Java 和 Kotlin 的 Modifiers
== Java
Class members
abstract final static strictfp volatile stransientProcedural
native synchronized== Kotlin
Classes
abstract open finalClass members
enum annotation data sealed
abstract open final override lateinitProcedural
const
suspend infix operator inline external tailrec
Access controlpublic private protected interal
Parametersvararg crossinline noinline
Parameterized Type Variancein out
Type Parametersreified#Java #Kotlin https://gist.github.com/duangsuse/dfc532a16f547459bcf3f4f8d922d849 更新了一个字
https://gist.github.com/duangsuse/dfc532a16f547459bcf3f4f8d922d849/revisions
Void 改成了 Nothing
其实 Unit 也可以,反正 Void 类型只有一种可能的值:null
Nothing? 和 Unit 也都是一样(被 Rust 称为 Zero Size Types,因为他们在值的层面讨论只有一种可能性:Unit 就是 object Unit、Nothing? 就是 null、Void 也是 null),而 Nothing 类型没有可能的值(Empty Type/Bottom Type,这个名字是来源与它在子类型层次结构里处于最底端的缘故)
https://gist.github.com/duangsuse/dfc532a16f547459bcf3f4f8d922d849/revisions
Void 改成了 Nothing
其实 Unit 也可以,反正 Void 类型只有一种可能的值:null
Nothing? 和 Unit 也都是一样(被 Rust 称为 Zero Size Types,因为他们在值的层面讨论只有一种可能性:Unit 就是 object Unit、Nothing? 就是 null、Void 也是 null),而 Nothing 类型没有可能的值(Empty Type/Bottom Type,这个名字是来源与它在子类型层次结构里处于最底端的缘故)
val empty: Nothing? = null
虽然 Nothing? 的语义很正常,但是 unsupported [Array<Nothing> in return type is illegal]
...Gist
Essay: Android cancellable asynchronous task API abstractoin in Kotlin
Essay: Android cancellable asynchronous task API abstractoin in Kotlin - Essay-Android-AsynchronousTaskAbstractoin.kt
duangsuse::Echo
#tech #daily #Java #JavaScript #dev 🐱 duangsuse 的学习日常 ⭐️ + 程序设计语言::Closure、Pattern Matching、Stream、Generators #pl #cs + 程序设计语言类型::这些名词,你知道吗?(涉及 Parameteric Polymorphism 和 Empty Types(aka. Bottom types)、Product types、Subtyping 等内容) + 高性能计算::C 语言和高性能计算、x86…
这次就有一些我最想先弄的东西:
+ 程序设计语言::Closure、Pattern Matching、Stream、Generators #pl #cs
+ 程序设计语言类型::常见名词
+ 数据库::关系代数 #db
+ Java 的二进制流读写器 #bin
+ Java 的 Android android.content.SharedPreferences 代理库 Prefer
+ {软件架构, Android}::编写 Android ShutdownService
+ Kotlin::简单的 Realm ORM + RecyclerView Android 应用
+ JavaScript ES6: sm.ms.js
+ Kotlin::Shell execute
+ Kotlin OkHttp 同步/异步封装
+ 程序设计语言::Closure、Pattern Matching、Stream、Generators #pl #cs
+ 程序设计语言类型::常见名词
+ 数据库::关系代数 #db
+ Java 的二进制流读写器 #bin
+ Java 的 Android android.content.SharedPreferences 代理库 Prefer
+ {软件架构, Android}::编写 Android ShutdownService
+ Kotlin::简单的 Realm ORM + RecyclerView Android 应用
+ JavaScript ES6: sm.ms.js
+ Kotlin::Shell execute
+ Kotlin OkHttp 同步/异步封装
#security https://t.me/dsuses/2956 🤔 说起来我之前一直丢脸地不知道加盐是什么原理... 嘛其实也未必,我知道 hash 算法、局部敏感的 hash 算法、HashMap、SHA 算法,可是之前知道的没有这么详细
比如说,对我的名字计算 sha256 值:
不过也可以这样,允许用户设置一个『盐』值,我们把这些信息以一种我们自己知道可以重复(幂等)的方式混淆到原数据上面,作为一种预处理:
一般直接用 concat 就可以了
比如说,对我的名字计算 sha256 值:
import java.security.*
val sha256 = MessageDigest.getInstance("SHA-256")
sha256.reset()// fold Left
sha256.update(("duangsuse" as? java.lang.String)?.getBytes())
fun <T : Number> Iterable<T>.hexDigest(): String = this.fold(StringBuilder()) { acc, it -> acc.append(String.format("%02x", it)) }.toString()
fun <T : Number> Array<T>?.hexDigest(): String? = this?.toList()?.hexDigest()
fun ByteArray?.hexDigest(): String? = this?.asList()?.hexDigest()
fun MessageDigest.mkHash(bs: ByteArray): ByteArray = this.run { reset() }.run { update(bs); digest() }
val String.bytes: ByteArray? get() = (this as? java.lang.String)?.getBytes()
val name_shasum = "duangsuse".bytes?.let { sha256.mkHash(it) }.hexDigest()
但是如果 cracker 有一个 hash 字典,然后它知道我名字的 hash 值是 e3b0c44...
我就傻冒了,我的身份将被冒充,并且他这个肮脏侥幸的数学破坏者会弄到我的明文密码 😭不过也可以这样,允许用户设置一个『盐』值,我们把这些信息以一种我们自己知道可以重复(幂等)的方式混淆到原数据上面,作为一种预处理:
一般直接用 concat 就可以了
inline fun String.salted() = System.getProperty("salt", "") + this
只要每次计算 hash 的时候都先按照可重复的方法预处理,就可以增强 hash 的保密效果,不那么容易碰撞了,也可以进行同样的身份验证。Telegram
duangsues.is_a? SaltedFish
为了防止撞库攻击,很多人都建议任何密码相同(或相关)的用户修改自己的密码。
~想法~
所以,改成什么?
1.自己要能记忆
2.不同网站/程序不一样
3.不同密码之间无关连
思考了一下
希望:“即使断网也能查看密码”
所以要在本地完成计算。
同时“希望能在任何平台算出密码”
所以不想使用密码管理器。
~实施~
于是决定:
1.想好一个"盐"(可以有任何字符,长度也可以很大),记下来。
2.将其和要设置的网站的域名拼接
3.计算sha256
4.取最后几位作为该网站密码,位数建议多点(8…
~想法~
所以,改成什么?
1.自己要能记忆
2.不同网站/程序不一样
3.不同密码之间无关连
思考了一下
希望:“即使断网也能查看密码”
所以要在本地完成计算。
同时“希望能在任何平台算出密码”
所以不想使用密码管理器。
~实施~
于是决定:
1.想好一个"盐"(可以有任何字符,长度也可以很大),记下来。
2.将其和要设置的网站的域名拼接
3.计算sha256
4.取最后几位作为该网站密码,位数建议多点(8…
duangsuse::Echo
…8103 年 SHA256 早被撞烂了吧🌚
现在还好哇,我们现在很多文件验证也是用 SHA-256
何况我不是密码学的人不懂这些东西,我们只是用来写应用而已,很多 JVM 程序员这辈子干过和密码学最近的也不过就是用 IDEA 自动生成的 * 31
何况我不是密码学的人不懂这些东西,我们只是用来写应用而已,很多 JVM 程序员这辈子干过和密码学最近的也不过就是用 IDEA 自动生成的 * 31
int hashCode(); 算法了,我以后只要不是要忽略某些字段的 hashCode,再也不会让 IDEA 去自动生成这种无意义的代码
duangsuse::Echo
这次就有一些我最想先弄的东西: + 程序设计语言::Closure、Pattern Matching、Stream、Generators #pl #cs + 程序设计语言类型::常见名词 + 数据库::关系代数 #db + Java 的二进制流读写器 #bin + Java 的 Android android.content.SharedPreferences 代理库 Prefer + {软件架构, Android}::编写 Android ShutdownService + Kotlin::简单的…
这周份的 duangsuse::Echo 技术日常!包括计算机科学、关系代数、程序设计语言理论相关内容!
= 程序设计语言::Closure、Pattern Matching、Stream、Generators #PL #CS
Closure[wiki]: aka. Proc(Ruby)、闭包、Block、Chunk(Lua, 不完全是, Lua 里 Closure 等价的概念是自动内存管理和存储层的 UpValue 和 Proto,当然得配成一对才是闭包, Chunk 说的实际上是『一段完整的程序』)、Lambda(Lisp, Scheme, Haskell, Scala, etc.)、匿名函数(JavaScript, 虽然 ES6 也是有”箭头函数“的)
Python 和 ES6 的 decorators,也是基于他们的高阶函数支持而设计的。
代码块实际上是『上下文代码的一部分』,其概念源于 Lambda calculus — 函数可以返回函数,而『函数作为值』本身的意思,就是函数可以”独立“于调用栈的存储空间而存在,这意味着函数要知道自己定义时的作用域以保证再次执行时不会出 undefined reference 错 — 它可以『携带』自己所需要的定义离开一层函数调用栈帧,这就是 Lexical Scoping
非常明显的行为是,返回的 λy.... 里依然可以访问到 λx.... 里的变量 x
可是有人要写这样的程序:比如把
但是很不幸,函数式编程和面向对象混合的多范式成了主流;随处用高阶函数 Higher-Order-Function 和指定 receiver 的方法;于是这种辣鸡代码写起来不再有难度:
在 ES6 里支持模式识别的一种子集:
Destructuring assignment 解构赋值
我只知道,ES6 支持:
+ List pattern like
+
详情 MDN
Scala 的 Pattern Matching 详情这里
(比 ES6 的牛逼多了,因为 ES6 的只是结构赋值、Scala 的不仅可以解构赋值还可以判定)
因为上面定义了:Maybe a 可能是 Just a 或者 Nothing,它是 a 的 Sum type (tagged union)
Stream:
流式 API,充分利用对象自治性,是面向对象架构必须有的东西
= 程序设计语言::Closure、Pattern Matching、Stream、Generators #PL #CS
Closure[wiki]: aka. Proc(Ruby)、闭包、Block、Chunk(Lua, 不完全是, Lua 里 Closure 等价的概念是自动内存管理和存储层的 UpValue 和 Proto,当然得配成一对才是闭包, Chunk 说的实际上是『一段完整的程序』)、Lambda(Lisp, Scheme, Haskell, Scala, etc.)、匿名函数(JavaScript, 虽然 ES6 也是有”箭头函数“的)
Python 和 ES6 的 decorators,也是基于他们的高阶函数支持而设计的。
代码块实际上是『上下文代码的一部分』,其概念源于 Lambda calculus — 函数可以返回函数,而『函数作为值』本身的意思,就是函数可以”独立“于调用栈的存储空间而存在,这意味着函数要知道自己定义时的作用域以保证再次执行时不会出 undefined reference 错 — 它可以『携带』自己所需要的定义离开一层函数调用栈帧,这就是 Lexical Scoping
(lambda x.
lambda y. x) 1 ; res0=λy. 1(res0 2) ; 1非常明显的行为是,返回的 λy.... 里依然可以访问到 λx.... 里的变量 x
def foo()而以前我们直接用 Java 的 Collections framework 会这么写(虽然这里好像都是在用 [Array...):
a = 1 # 闭包里包含了这个局部变量,如果 lambda 被当成值返回,这个变量将会被保存
[1,2,3].map { |x| x + a } #=> [2,3,4]
end
public static final void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
非常愚蠢(但还是比汇编和 while 循环好多了)于是就有了 forEach,正如后来的 tryWithResource 和 Autoboxing 一样public static final void main(String... args) {
for (String s : args) System.out.println(s);
}
大括号保不保留就是一个见仁见智的问题,支持者认为不保留好看,不支持的人觉得重构麻烦容易出错,当然控制流跳转的 return 怎么用也是一样的见仁见智问题。可是有人要写这样的程序:比如把
int[] 变成 boolean[], 这要求 forEach 做它做不到的事情:先预备好一个同样维度的数组;知道当前在哪次循环;然后下标赋值目标数组,也就是说得同时读写两个数组,都需要下标public static final void main(String[] args) {
boolean[] args_bs = new boolean[args.length];
Predicate<String> predicate = s -> s.length > 10;
for (int i = 0; i < args.length; i++) {
args_bs[i] = predicate.test(args[i]);
}
}
于是又有了 init; p; op 的 for statement....但是很不幸,函数式编程和面向对象混合的多范式成了主流;随处用高阶函数 Higher-Order-Function 和指定 receiver 的方法;于是这种辣鸡代码写起来不再有难度:
fun profiteer(giftList: String)Pattern Matching[wiki]:
= fun output(writer: PrintStream)
= giftList
.split("\n")
.map(::Gift) // Constructor, (String) -> Gift
.map { it.mapIncreasePrice(10.dollars()) }
.forEach(writer::println)
在 ES6 里支持模式识别的一种子集:
Destructuring assignment 解构赋值
我只知道,ES6 支持:
+ List pattern like
[a, b = 2, c], [head, ...tail]
+ Object pattern { length: 2 = -1 }
+ 当然上面的 Object destruct 也可以用 ES6 的同名属性变量语法糖+
let { length } = [1] 里的 {length} 说的其实是 {length:length}, 给它指定了默认的键:length详情 MDN
Scala 的 Pattern Matching 详情这里
(比 ES6 的牛逼多了,因为 ES6 的只是结构赋值、Scala 的不仅可以解构赋值还可以判定)
def escape(s: String) = s match {
case 'q' :: xs => "\\q" ++ escape(xs);
case 'x' :: xs => "\\x" ++ escape(xs);
case x :: xs => x ++ escape(xs);
}
这种的 ES6 的解构赋值就做不到,不过也是因为模式匹配搞基一点的原因,所以会有诸如 Pattern exhaustiveness 之类的问题(比如 Haskell 里的 Maybe)data Maybe a = Just a | Nothing deriving (Eq, Show)可是
class FromMaybe a where
fromMaybe :: Maybe a -> a
instance FromMaybe String where
fromMaybe (Just s) = s
instance FromMaybe String... 会报错,因为 (
fromMaybe
:: Maybe a -> a) 只定义了解构
(Just ...) 这个数据构造器的解构器,到 Nothing 这个 case 就傻眼了(因为上面定义了:Maybe a 可能是 Just a 或者 Nothing,它是 a 的 Sum type (tagged union)
data Maybe a where实际上
Just :: a -> Maybe a
Nothing :: Maybe a
Sum type is a data structure used to hold a value that could take on several different, but fixed, types.
FromMaybe 这个用来进行 operator overloading 的 Typeclass 是完全设计错误的 ,它的 (fromMaybe
:: Maybe a -> a) 类型签名真的就是很愚蠢啊(除非有默认值,否则
(Maybe a) -> a 就是完全没有意义的事情)!Stream:
流式 API,充分利用对象自治性,是面向对象架构必须有的东西
val preference by lazy { Prefer.from(UserPreference::class) }
preference
.beginTx()
.setUserName("duangsuse")
.setIcon(File("duangsuse.png"))
.setAge(preference.age)
.delete("oldUserName")
.put("newUserNameNth", preference.read("newUserNameNth").or(0).inc())
.commit()
preference.userName //=> "duangsuse"
preference.length //=> 5
preference.has("user_name") //=> true
Generators[wiki]: aka. Coroutine(Lua), Fiber(in Ruby), Goroutine(Go), Suspend function/Coroutine(Kotlin), Generators(Python, JavaScript ES6, CSharp), Continuation(Scheme, Continuation 是一个抽象的程序执行状态,比 Coroutine 概念大一些)
duangsuse::Echo
啊嗨! java.lang.Deprecated 是什么鬼类型…
Kotlin:
交叉 inline 哦,双重 inline 那就叠在一起好了,免得 return 不到地方
交叉 inline 哦,双重 inline 那就叠在一起好了,免得 return 不到地方
inline infix fun <A, B, C> ((A) -> B).andThen(crossinline op: (B) -> C) = { x: A -> op(invoke(x)) }
REPL 里好像有问题,就infix fun <A, B, C> ((A) -> B).andThen(op: (B) -> C) = { x: A -> op(invoke(x)) }
inline fun <T> eq(me: T): (T) -> Boolean = { other -> me == other }
fun Class<*>.static() = object { public operator fun get(name: String): Field = this@static.getDeclaredField(name) }
fun assertSignedMinMax<reified T>(klass: Class<T>)
= fun assertLen(len: Int)
= (klass)
😶 没力气写了...println("forall x in Int. x in [2^32, 2^32-1]") (
duangsuse::Echo
这周份的 duangsuse::Echo 技术日常!包括计算机科学、关系代数、程序设计语言理论相关内容! = 程序设计语言::Closure、Pattern Matching、Stream、Generators #PL #CS Closure[wiki]: aka. Proc(Ruby)、闭包、Block、Chunk(Lua, 不完全是, Lua 里 Closure 等价的概念是自动内存管理和存储层的 UpValue 和 Proto,当然得配成一对才是闭包, Chunk 说的实际上是『一段完整的程序』)、Lambda(Lisp…
import static java.lang.System.out;如果使用 Coroutine,就可以写更优雅的 Clock 了
import java.util.Iterator;
class Clock implements Iterable<Boolean> {
private boolean state;
public Clock(boolean initialState) {state = initialState;}
public Clock() {this(false);}
class ClockIterator implements Iterator<Boolean> {
@Override public boolean hasNext() {return true;}
@Override public Boolean next() { state = !state; return state; }
}
@Override public Iterator<Boolean> iterator() {return new ClockIterator();}
}
public final class ClockMain {
public static void main(String... args) throws InterruptedException {
Clock clock = new Clock();
for (boolean b : clock) {
out.print(b ? "🕐Tick" : "🕒Tock");
Thread.sleep(500);
out.write(0x1b); out.print("[6D"); // https://en.wikipedia.org/wiki/ANSI_escape_code#DL
}
}
}
,再比如,如果使用控制结构:
= 程序设计语言类型::常见名词
= 数据库::关系代数 #DB
duangsuse::Echo
#Java #code 里面有个 inner class
当然,你也可以使用 Qualified class instance creation,只是因为 Java 有 inner class 自动绑定上父域类的状态而已
@Override public Iterator<Boolean> iterator() {return new Clock().new ClockIterator();}
duangsuse::Echo
import static java.lang.System.out; import java.util.Iterator; class Clock implements Iterable<Boolean> { private boolean state; public Clock(boolean initialState) {state = initialState;} public Clock() {this(false);} class ClockIterator implements…
然后我们还可以去写一个更 precious 的 Clock,它不仅会 Tick tock 还能记录时间,它被称为:TimedClock
也很简单,代码里几乎不需要什么修改
(这里明显不是教你怎么用 Generator,因为 yield 太简单了很多人章口就莱,是教你们怎么用 Iterator + switch 在 Java8 里手动写基于状态 🐔 的 Generator)
也很简单,代码里几乎不需要什么修改
(这里明显不是教你怎么用 Generator,因为 yield 太简单了很多人章口就莱,是教你们怎么用 Iterator + switch 在 Java8 里手动写基于状态 🐔 的 Generator)
duangsuse::Echo
也相当鬼畜,不过还没有教到使用 switch 进行自由控制流跳转的局面,待会会为大家做现场的表演~
修一下 bug、增加 Tick Thock,下面有更加 excited 的 clock。