/tmp/duangsuse.sock
23 subscribers
303 photos
3 videos
92 files
337 links
从 duangsuse::Echo (@dsuse) 跟进出来的分支,将在作者恢复原帐号访问的时候合并删除。
Download Telegram
#Math 今天上午的数学笔记(以后可能按周更新)

上午看了人教《高中数学 必修 5》,解三角形的前几面,入门了一点 naive 的数学等式分析能力。

首先,是要从一个三角形函数的定义 推出三角形里边长之间的关系,有一个式子:

Rt triangle ABC:
(a / sin A) = (b / sin B) = c
where sin 角 = 斜边 / 对边

且 C=1 的时候... 忘了,之后是推广到了锐角三角形上,作了个边 CD 垂直居中边 CB 然后利用 sin 的性质 sin A = {三角形CDB CB 边上的高}

然后我几何数学推导(是的,之前我只知计算... 套用模板的)的也是第一次看,就没有考虑到那方面的东西

我就有一个问题:为什么它说 (a / sin A) aka. (a / (c / a)) 这个是正确的(是的,对你们就是 immediate 的)
甚至我知道它是指 (a / sin A) = c 都想了半天(开始我怀疑是利用了相等的传递性,可是就不知道是把两个子式 =c 传递过去了...);然后我就想,为什么是 = c 呢?

首先当然是万能(划掉)的列举法,算法设计的时候一个强有力(迫真)的思路

泛化成等式 a / (b / a) = b (之前搞错成 b / a / a 了....),我考虑了 a=1 b=10; a=3 b=15 的情况,第二个 case 失败了
之前我还迫真变形一次,结果在上面那个三等式子里消除了第二个等号(除法消除因子变换)... 我把 c 跨等号约掉了(所以我觉得很奇怪,为什么项和一个等号直接消失了),即使不知道做了什么 😂

(补充,是看错了,其实式子是 a / (a / b) = b.... 还是很奇怪

这时候我才想到:啊! (b / a) 问的不是 『b 里面有几个 a』 么? 所以问 『a 里面有几个『b 里面有的 a』』难道不是 b 么?
还是好奇怪啊...

👆上面的补充,修改之后(你看上面那个结论还是令人困惑,因为它的确是错的)

这时候我才想到:(a / b) 问的不是 『a 里面有几个 b』 么? 所以问 『a 里面有几个『a 里面有的 b』』难道不是 b 么?
初级、中级和高级开发人员之间的差异

作为程序员,你身边的同事有工作 6 年的中级程序员,也有工作 3 年的高级程序员。你可能会很疑惑,初级、中级和高级开发人员之间的差异究竟在哪里?你是初级、中级或高级开发人员,不仅仅取决于你的编程经验有多少年。初级开发人员甚至可以比高级开发人员年纪更大。
归根结底都是由技术决定的。这并不意味着高级开发人员必须是全栈的专家,但可以肯定地说,高级开发人员远比初级和中级开发人员熟练。
但是,高级开发人员与中级和初级开发人员的区别不仅仅在于编码技能。那么他们到底有什么区别呢?知识显然,高级开发人员比初级和中级开发人员拥有更多的知识。了解设计模式、体系架构、自动化测试、性能、安全等是初级开发人员与中级和高级开发人员缩小知识差距的好方法。
了解软件开发中应该如何做是很重要的。但是仅仅知道这些东西并不能使你成为一名高级开发人员。知识储备并不是开发者之间最大的区别,它只是其中一个因素。
编码不管大多数人是怎么看待编码的,但它并不只是与计算机的通信。编码是与人通信和指导计算机工作。最终,代码被编译成 0 和 1。
代码必须对将来使用它的其他开发人员来说容易理解。一个以前从未见过这些代码的新团队应该能够运行代码并处理新特性或进行错误修复。这就是初级开发人员和高级开发人员之间最大的区别所在。
在这个比较中,我将不考虑中级开发人员,因为中级开发人员在编码技能方面是一个灰色地带。显然,它介于初级和高级之间,可能更倾向于高级。这主要与经验有关,因为中级开发人员可能至少经历过一个完整的开发周期。他们犯了许多最简单的错误,并从中吸取了教训。
如何辨别初级开发人员?初级开发人员缺乏经验。有些人刚刚毕业,开始了他们的第一份全职工作。初级开发人员的心态通常是让代码工作就好。可以正常工作的软件和优秀的软件在他们看来是相同的。
编写简洁的代码是困难的,这是初级开发人员做不到的。初级开发人员通常会编写花哨的代码。你可以通过一行古怪的代码和过于复杂的抽象来识别初级开发人员。初级开发人员往往会用这种方式炫耀自己的技术,试图让其他开发人员知道他们编码有多好,这是错误的。
那么高级开发人员呢?当查看高级开发人员的代码时,你可能会想:这就是全部吗?剩下的代码呢?高级开发人员编写简洁、简单甚至是愚蠢的代码。这是开发人员在编程方面所能具备的最重要的品质之一。高级开发人员遵循 KISS 原则:保持简单,愚蠢(Keep it simple, stupid)。
高级开发人员和初级开发人员思考代码的方式是不同的。高级开发人员编写代码的时候将考虑可维护性和可扩展性。这与初级开发人员的思维方式完全不同:高级开发人员考虑的是必须使用代码的人员,而初级开发人员只是考虑让代码在计算机上工作。
不仅仅是编码技能除了编码技能,还有其他一些因素可以告诉你他们是什么类型的开发人员。
一般来说,初级开发人员执行...

PC版:https://www.cnbeta.com/articles/soft/875779.htm
手机版:https://m.cnbeta.com/view/875779.htm
/tmp/duangsuse.sock
#tech #dev #statement
编写简洁的代码是困难的,这是初级开发人员做不到的。初级开发人员通常会编写花哨的代码。你可以通过一行古怪的代码和过于复杂的抽象来识别初级开发人员。初级开发人员往往会用这种方式炫耀自己的技术,试图让其他开发人员知道他们编码有多好,这是错误的。 本频道

那么高级开发人员呢?当查看高级开发人员的代码时,你可能会想:这就是全部吗?剩下的代码呢?高级开发人员编写简洁、简单甚至是愚蠢的代码。这是开发人员在编程方面所能具备的最重要的品质之一。高级开发人员遵循 KISS 原则:保持简单,愚蠢(Keep it simple, stupid)。 本苏(duangsuse)对drakeet君的话 的脚注们

人和人之间的差距到底是什么,就叫理论大佬列几个式子让学生写、FP 大佬列引两条式子,费三四分钟写一行、OI 大佬想一分钟费五分钟写七八行 pass、你断断续续想半天,最后写十分钟改两分钟,最终成品四五行、小部分人想五分钟写十分钟暴力查错二十分钟弄出来十几行易错/难维护/难看懂/低性能的代码、绝大部分人想半天觉得莫名其妙,查下资料抄过来解决,找不到就玩完了、少部分人,完全写不出来。

我觉得人和人之间的差距,不是体现在你看过什么/见过什么/做过什么、不在你的『经验』和外行对你的『认可』、
不是体现在什么你会、别人花个两分钟/十分钟/三五天学习训练也能做出来的事情,而是在那些你即得易见平凡,别人想破脑袋也弄不懂/懒得想的事情上。

高级开发人员和初级开发人员思考代码的方式是不同的。高级开发人员编写代码的时候将考虑可维护性和可扩展性。这与初级开发人员的思维方式完全不同:高级开发人员考虑的是必须使用代码的人员,而初级开发人员只是考虑让代码在计算机上工作。 本苏也说过,创造的时候从使用的角度看问题;使用的时候从创造的角度看问题

#Mark 一下
Forwarded from duangsuse::Echo (duangsuse /'dʊɔːŋ sjuːz/ | [⃪PLD, FPλ])
默写 DockerFile

FROM openjdk:8u181-jdk-alpine3.8 AS builder

ADD . /app
WORKDIR /app

RUN ./gradle shadowjar \\
&& cp server*.jar server.jar

FROM openjdk:8u181-jre-alpine3.8 AS runner
COPY --from builder /server.jar .
ENTRYPOINT ["java", "-jar", "server.jar"]

第二遍

FROM openjdk:8u181-jdk-alpine3.8 AS builder
ADD . /app/
WORKDIR /app/

RUN chmod +x gradlew \\ ./gradlew shadowJar \\
cp build/libs/server*.jar server.jar

FROM openjdk:8u181-jdk-alpine3.8 AS runner
WORKDIR /app/
COPY --from=builder server.jar .
ENTRYPOINT ["java", "-jar", "server.jar"]
.travis.yml

language: minimal
service:
- docker

install:
- VERSION=$(git rev-list --count HEAD)
- echo $DOCKER_PASSWORD | docker login $DOCKER_REGISTRY -u $DOCKER_USER --password-stdin
script:
- docker build -t "$DOCKER_REGISTRY/$DOCKER_IMGNAME:$VERSION" .
depoly:
- provider: script
script: docker push $DOCKRE_REGISTRY/$DOCKER_IMGNAME:$VERSION
on:
tags: true
/tmp/duangsuse.sock
.travis.yml language: minimal service: - docker install: - VERSION=$(git rev-list --count HEAD) - echo $DOCKER_PASSWORD | docker login $DOCKER_REGISTRY -u $DOCKER_USER --password-stdin script: - docker build -t "$DOCKER_REGISTRY/$DOCKER_IMGNAME:$VERSION"…
第二遍,我们需要 docker 的 build, depoly

language: minimal
service:
- docker

install:
- VERSION=$(git rev-list --count HEAD)
- VERSION_HEAD=$(git rev-parse --verify HEAD | head -c7)
- echo $DOCKER_PASS | docker login --password-stdin $DOCKER_REGISTRY -u $DOCKER_USER

script:
- PKGID="$DOCKER_REGISTRY/$DOCKER_IMGNAME:$VERSION"
- docker build -t $PKGID .

deploy:
- provider: script
script: docker push $PKGID
on:
tags: true
🤔 本来我没设计这个 1: 2: 的,看来要增加新模式匹配特性了...
那个 match 的语法没有新起一行,但是我感觉可以用(2D 文法)
我会给这些特殊的单 match 语句添加特别的文法规格的
Forwarded from dnaugsuz
就像这样:

//! StrictLanguage
def fizzBuzz(rng: Range = 1...100)
for n in rng match n
1: _ |*| 3 + 0 => cout << "Fizz " << n
2: _ |*| 5 + 0 => cout << "Buzz " << n
1: & 2: => print "FizzBuzz " << n
Forwarded from dnaugsuz
要是我的 GalScript 反向模式匹配真的可以写出来,就可以这么写了

match [*'®'.repeat(rc), *'©'.repeat(cc)] = "®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®©©©©©©©©©©©©©©©©©©©©©©©©"

println("(R): ", rc) println("(C):", cc)


不过这是不可能的,因为我还没打算支持方法调用参数的反向模式匹配...
Forwarded from dnaugsuz
目前只能反向模式匹配 self,不能反向参数,所以只能

match [*rc.timesStr('®'), *cc.timesStr('©')] = "®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®©©©©©©©©©©©©©©©©©©©©©©©©"

而且也没有重复 repeat pattern,只有 ES6 的 expand operator
Forwarded from dnaugsuz
就像这样:

//! StrictLanguage
def fizzBuzz(rng: Range = 1...100)
for n in rng match n
1: _ |*| 3 + 0 => cout << "Fizz " << n
2: _ |*| 5 + 0 => cout << "Buzz " << n
1: & 2: => print "FizzBuzz " << n
Forwarded from dnaugsuz
我这周打算给 GeekApk 未来的脚本系统设计的一门多范式编程语言,支持编译到 Java/ES5/ES6 和利用 GalVM 虚拟机解释
Forwarded from dnaugsuz
而且这货还支持 implicit、cross inlined definition(不过 implicit 参数只能查找调用的一层作用域和 object instance )

语言总体主要是面向对象和函数式(此外也有点过程式和描述式的感觉),支持 rewrite 尾递归重写、渐进类型支持 type patterns(多态),此外它还支持反向模式匹配(match n+1 = 2 这种)
不太支持参数化类型(没有用户自定义的),但有函数类型、Map 类型什么的
Forwarded from dnaugsuz
实现的难点在学校里已经考虑过了,我觉得是时间问题

难点一方面在解析器上,它是 2D syntax,支持缩进语义所以非常灵活
一方面是在新的 reverse pattern matching 上面,我下了好大功夫设计,而且还很难实现(但是一些基础的 reverse pattern 不难实现)

譬如上面那个 match x + 1 = n 这个,n=1
此时解释实现需构造一个 MixPattern 对象 MixPattern(+1, Unknown("x")) 就可以了,它接受一个输入,然后把输入 -1 交给 Unknown("x") 匹配,就可以得到一个副作用,执行完就有了未知数 x 的值

另外一个实现问题就是 reverse method call pattern 可以从参数和返回值推导回 self,可是 self 的类型是什么?如果把实现调用接口的类型一个一个排除就太 inefficient 了

这就必须使用 1. 显示类型标记声明了但是没有定义的变量 2. is pattern,这个 pattern 断言了未知数一定是某个类型,就可以确定反向计算的接受者(receiver) 类型了(从而可以拿到对应 match 方法的实现进行反向计算)

match s.repace("aaa", "bbb") = "xbbb"
// Inefficient
match (s is Str).repace("aaa", "bbb") = "xbbb"
// OK

val s: Str
match s.repace("aaa", "bbb") = "xbbb"
// OK

可是这就意味着 reverse pattern matching 的某些组合需要参考它子项目的属性,而且必须是有传递性的(因为不能保证永远是 (s is Str), (s is Str + 'a') 也是一样...)
这个我还没想好....

目前需要这个功能的好像还只有 reverse method call pattern 一个,我觉得大概可以在解析类型推导的时候解决

GalScript 里有函数和方法的区分,但是目前不打算支持函数的反向模式匹配... 因为函数没有隐式的 self 参数,就必须可以这么干了

let add(x, 1) = 2
let sub(x, -2) = 1

可是这很麻烦(特别是对应的 match operator fn 实现起来... 它得知道啥是未知啥是已知。我有办法(implicit & match fn)可是我觉得很鸡肋 ),而且 GalScript 又不是确切的逻辑式语言,支持部分反向计算本意是作为 Pattern matching 的扩充,这样的话对 GalScript 不好

... 算了,我还是不支持 first-class pattern 的 custom match operator,然后支持 implicit 参数的 match operator fn 的推导算了...
就像这样:

class Str kind [char]
match operator fn repeat where
(implicit self, n: Nat)(it: Str) { self = it.take(n)[0..findSeqLength] } // 注意这不是 scala 的 currying 表示,()() 只是分割不同类型参数的语法糖....
(self, implicit n: Nat)(it: Str) { n = it.substrTakeWhile(self::startsWith).size }
fn findSeqLength(implicit it: Str) {...}
GalScript 的 cross 和 implicit、prefix operators、decorators 可以编写 async/await 关键字

%async def co jsonRpc(ctx, cont, url)
val resp = await http.GET(url)
if match resp is Error => fail
val json = await json.parse(resp.body)
if match json is Error => fail
away json

+ async 是什么?它是一个 decorator,就是高阶函数调用的简记法,它给内部的函数提供 coroutine context 和(传递下去,Thunk 函数的 callback)
+ def co 是什么?GalScript 有类似 ES6/Python 的 Generator 函数,它是自己包含状态可以挂起的状态机
+ ctx, cont 都可以拥有 implicit 的类型 def %async(...)(Fn ... -> ... -> ...) implicit x is Int, y is Int ....
+ await, away 是 prefix operator def,也可以拥有隐式的参数 implicit ctx: Cont, implicit cont: Fn
+ fail 该怎么实现(返回一个 error)?await 的 yield 该怎么办?有 cross inline,就可以办到了。所以他们都是 cross def

cross def fail(implicit Error as e) { return e }
dnaugsuz
实现的难点在学校里已经考虑过了,我觉得是时间问题 难点一方面在解析器上,它是 2D syntax,支持缩进语义所以非常灵活 一方面是在新的 reverse pattern matching 上面,我下了好大功夫设计,而且还很难实现(但是一些基础的 reverse pattern 不难实现) 譬如上面那个 match x + 1 = n 这个,n=1 此时解释实现需构造一个 MixPattern 对象 MixPattern(+1, Unknown("x")) 就可以了,它接受一个输入,然后把输入 -1 交给…
GalScript 还有一个特性,就是 Kotlin 也支持的 first-class delegates,它可以制造引用、惰性求值(虽然 GalScript 本身就支持)什么的

class Box(val x: Any)
operator as val = x
operator set val { x = it }

就可以把一个右值(rhs value) 变成一重引用左值(lhs value) 了,除了可以再次赋值外,和原来的东西无异

有意思的是 GalScript 的 set 关键字其实是用来定义 "enumeration" 的

set TrafficLight { RED, GREEN, BLUE }
本频道也对 editor duangsuse 的失败感到可惜(不过接下来

FROM openjdk:8u181-jdk-alpine3.8 AS builder
ADD . /app
WORKDIR /app
RUN chmod +x gradlew \\
&& ./gradlew shadowJar \\
&& mv build/libs/server-*.jar server.jar

FROM openjdk:8u181-jre-alpine3.8 AS runner
WORKDIR /app
COPY --from=builder /app/server.jar .
ENTRYPOINT ["java","-jar", "server.jar"]

//
language: minimal
service:
- docker
script: docker build -t $IMGID .
install: docker login $DOCKER_REGISTRY -u $DOCKER_USER <dockp --password-stdin
deploy:
- provider: script
script: docker push $IMGID
on: [tags: true]

before_install:
- REV=$(git rev-list --count HEAD)
- IMGID="$DOCKER_REGISTRY/$DOCKER_IMAGE:$REV"
- echo $DOCKER_PASS >dockp
Forwarded from duangsuse::Echo (duangsuse /'dʊɔːŋ sjuːz/ | [⃪PLD, FPλ])
很不幸的是,我最终因为拖延症没能完成,我决定剩下的时间,完成一点文字工作。祝好。