首页 文章 精选 留言 我的

精选列表

搜索[AI编程],共10000篇文章
优秀的个人博客,低调大师

微软开源早期编程语言 GW-BASIC

微软通过一篇博客文章宣布开放GW-BASIC的源代码。并表示,自从MS-DOS 1.25 和 2.0 开源后,社区中要求同样开源 BASIC 语言的呼声颇高。因此微软选择将 1983 年以来的 8088 汇编语言开源出来,但仅作历史参考和教育用途,不再接收任何修改源码的拉取请求。 GW-BASIC 是 BASIC 的一个方言版本,诞生于1983 年 2 月 10 日,作为MS-DOS的一个组成部分而问世。根据微软的介绍,它是从 IBM Advanced BASIC/BASICA 衍生而来的 BASIC 解释器,本身也是 Microsoft BASIC 的端口。 GW-BASIC 和微软提供给IBM PC的BASICA完全兼容,不同的是,后者依赖于ROM中的 BASIC 解释器,而前者并不需要。所以,GW-BASIC 能在众多 IBM PC 兼容机器上运行。在 70 和 80 年代后期,BASIC 被移植到许多 OEM 平台上,并适应了当时流行的几种处理器,包括 8088、6502、6809,Z80 等。 就像那个年代的所有其他软件(例如 MS-DOS)一样,GW-BASIC 的源代码 100% 由汇编语言编写而成 。微软解释,当时也可以选择 FORTRAN、LISP、COBOL、RPG、CPL/BCPL 和 C等高级语言,然而这类语言的编译器比较昂贵,代码生成效率也不高,还受空间和性能限制,不适合家用或个人计算机。并且在早期编写 PC 软件时,每个字节、每条指令都需要为内存做考虑,汇编语言是不二之选。 迄今为止,微软已经发布了各种 BASIC 实现方案,其历史可以追溯到比尔·盖茨和保罗·艾伦在微软发布的第一款产品,即用于 Altair 8800 的 BASIC 解释器。 不少人希望808x 以外的处理器的实现也能够开源,不过微软表示,目前无法提供这些资源。

优秀的个人博客,低调大师

TypeScript 3.6 发布,微软脚本编程语言

TypeScript 3.6 已经发布了,更新内容如下: 使用更严格的生成器(Stricter Generators) TypeScript 3.6 引入了对迭代器和生成器函数(generator functions)的更严格检查。在早期版本中,生成器的使用者无法区分一个值是来自yield 操作或是从生成器返回。 另外,生成器仅仅假设yield 类型是任意的: 以第一段代码为例,在TypeScript 3.6 中,检查器会知道curr.value 的正确类型应为string,并在最后一个示例中纠正对 next() 的错误调用。这要归功于因在Iterator和IteratorResult类型声明中进行的一些更改而引入部分新的类型参数,以及TypeScript 用于代表称为Generator类型的生成器。 该版本中 Iterator 类型允许用户说明 yield 类型、返回的类型和 next 可以接受的类型。 在此基础上,新类型 Generator 是一个 Iterator,它同时存在 return 和 throw 方法,并且是可迭代的。 为了区分返回的值和生成的值,TypeScript 3.6 将 IteratorResult 类型转换为联合类型: type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>; interface IteratorYieldResult<TYield> { done?: false; value: TYield; } interface IteratorReturnResult<TReturn> { done: true; value: TReturn; } 简而言之,这意味着在直接处理迭代器时,将能够适当地缩小迭代器的值。 为了正确表示可以从调用 next( ) 传入生成器的类型,TypeScript 3.6 还可以推断生成器函数主体内的某些 yield 用途。 如果你希望显式,还可以使用显式返回类型从 yield 表达式强制执行返回、yield 和计算的值的类型。如下,只能用布尔值调用 next( ),并且取决于 done 的值,value 要么是 string,要么是 number。 /** * - yields numbers * - returns strings * - can be passed in booleans */ function* counter(): Generator<number, string, boolean> { let i = 0; while (true) { if (yield i++) { break; } } return "done!"; } var iter = counter(); var curr = iter.next() while (!curr.done) { console.log(curr.value); curr = iter.next(curr.value === 5) } console.log(curr.value.toUpperCase()); // prints: // // 0 // 1 // 2 // 3 // 4 // 5 // DONE! 更精确的数组扩展 在默认情况下,TypeScript 使用一个更简单的发射,它只支持数组类型,并支持使用 --downlevelIteration 标志在其他类型上进行迭代。在此标志下,发出的代码更准确,但要大得多。但是,在某些边缘情况下,受支持的数组还是存在一些差异,如下: [...Array(5)] 等效于以下数组: [undefined, undefined, undefined, undefined, undefined] 但是,TypeScript将原始代码转换为以下代码: Array(5).slice(); 这是不一样的,Array(5)生成长度为 5 的数组,但没有属性: 当 TypeScript 调用 Slice( ) 时,它还会创建一个数组,其中包含尚未设置的索引。 3.6 版本引入了一个新的 __spreadArrays 助手,用于精确地模拟 ECMAScript 2015 中在 --downlevelIteration 之外中发生的情况。__SpreadArray 也可在 tslib 中使用。 Improved UX Around Promises Promise是当前处理异步数据的最常见方法之一,不幸的是,使用Promise面向对象的 API 通常会让使用者感到困惑。因此针对Promise被错误处理的情况,TypeScript 3.6 引入了一些改进。 例如,在将其传递给另一个函数之前,Promise忘记.then()或者await内容通常是很常见的。TypeScript 的错误消息现在是专用的,并告知使用者他们可能应该考虑使用await关键字。 另外还提供快速修复: 更好的 Unicode支持标识符 当发射到 ES 2015或其他时,3.6 版本包含更好地支持标识符中的 Unicode 字符: 在 SystemJS 中支持import.meta 3.6 版本支持在将 module 目标设置为 system 时,将 import.meta 转换为 context.meta。 get and set Accessors Are Allowed in Ambient Contexts 在早期版本的 TypeScript 中,并不允许在环境上下文中 set 和 get 访问器,其基本原理是,就写入和读取这些属性而言,访问器与属性并没有区别;然而,由于 ECMAScript 的类字段提案可能与现有版本的 TypeScript 中的行为不同,则需要一种方法来沟通这种不同的行为,以便在子类中提供适当的错误。 因此 TypeScript 3.6 中,用户可以在环境上下文中编写getter 和 setter。 环境类和函数可以合并 在以前版本中,在任何情况下合并类和函数都是有错的。此版本中,环境类和函数(带有 declare 修饰符的类/函数,或 .d.ts 文件中的类/函数)可以合并。如下内容: 而不需要使用: 它的一个优点是可以轻松地表达可调用的构造函数模式,同时允许名称空间与这些声明合并(因为 var 声明不能与名称空间合并)。 APIs to Support--buildand--incremental TypeScript 3.6增加了两组用于操作项目引用和增量式程序构建的 API。 对于 --incremental,用户可以使用createIncrementalProgram 和 createIncrementalCompilerHost API。用户还可以使用新的 readBuilderProgram 函数从该API 生成的 .tsbuildinfo 文件中重新补充旧的程序实例,该函数仅用于创建新程序(即不能修改返回的实例,它仅用于其他 Create*Program 函数中的oldProgram 参数)。 New TypeScript Playground 此版本中,新的 TypeScript playground支持许多新的选择,包括: target 选项(允许用户从 ES5 切换到 ES3、es2015、esnext 等) 所有标记(包括 strict) 对普通 JavaScript 文件的支持(使用 allowJS 和 CheckJS) 当共享链接到 playground 示例时,这些选项也会持续存在,这样用户就可以更可靠地共享示例。 Semicolon-Aware Code Edits 像 Visual Studio 和 Visual Studio Code 这样的编辑器可以自动应用快速修复、重构和其他转换,比如从其他模块自动导入值。这些转换由 TypeScript 驱动,老版本的 TypeScript 无条件地在每条语句的末尾添加分号;不幸的是,这不符合许多用户的样式指南,许多用户对编辑器插入分号不满意。 在此版本中,在应用这类编辑时,TypeScript 可以检测文件是否使用分号。如果你的文件是缺少分号,TypeScript 则不会添加分号。 Smarter Auto-Imports JavaScript 有许多不同的模块语法或约定:ECMAScript 标准、Node 支持的模块语法或约定(CommonJS)、AMD、System.js 等等。在大多数情况下,TypeScript 将默认使用 ECMAScript 模块语法自动导入,在具有不同编译器设置的某些 TypeScript 项目中,或者在具有普通 JavaScript 和 Require 调用的 Node 项目中,这通常是不合适的。 在 3.6 版本中,在决定如何自动导入其他模块之前,它会查看现有的导入。 Breaking Changes 类成员 constructor 现在是构造函数 根据 ECMAScript 规范,名为 constructor 的方法的类声明现在是构造函数,无论它们是使用标识符名称声明,还是使用字符串名称声明。 DOM 更新 在 lib.dom.d.ts 中已经删除或更改了许多声明,这包括(但不限于)以下内容: 全局 window 不再定义为类型 Window,而是定义为类型 Window & type of globalThis。在某些情况下,将其类型称为 typeof window GlobalFetch 移除了,而是使用 WindowOrWorkerGlobalScope Navigator上的某些非标准属性已经消失 experimental-webgl 移除了,而是使用webgl和webgl2 JSDoc 注解不再合并 在 JavaScript 文件中,TypeScript 只会在紧接 JSDoc 注解之前确定声明的类型。 关键字不能包含转义序列 以前,关键字被允许包含转义序列。3.6 版本不再允许: 关于 TypeScript 3.6 更多信息,请见TypeScript 网站。使用 npm 命令获取: npm install -g typescript 还可以通过以下方式获得编辑器支持: 下载Visual Studio 2019/2017 Visual Studio Code Sublime Text 3 via PackageControl 发布说明: https://devblogs.microsoft.com/typescript/announcing-typescript-3-6/

优秀的个人博客,低调大师

Flink实战(三) - 编程范式及核心概念

1 基本的 API 概念 Flink程序是实现分布式集合转换的常规程序(例如,过滤,映射,更新状态,加入,分组,定义窗口,聚合)。最初从源创建集合(例如,通过从文件,kafka主题或从本地的内存集合中读取)。结果通过接收器返回,接收器可以例如将数据写入(分布式)文件或标准输出(例如,命令行终端)。 Flink程序可以在各种环境中运行,独立运行或嵌入其他程序中。执行可以在本地JVM中执行,也可以在许多计算机的集群上执行。 根据数据源的类型,即有界或无界源,您可以编写批处理程序或流程序,其中 DataSet API用于批处理 DataStream API用于流式处理。 注意:在显示如何使用API的实际示例时,我们将使用StreamingExecutionEnvironment和DataStream API。 DataSet API中的概念完全相

优秀的个人博客,低调大师

Go语言——没有对象的面向对象编程

本文译自Steve Francia在OSCON 2014的一个PPT,原作请前往:https://spf13.com/presentation/go-for-object-oriented-programmers/ 对我来说,最吸引我的不是Go拥有的特征,而是那些被故意遗漏的特征。 —— txxxxd 为什么你要创造一种从理论上来说,并不令人兴奋的语言? 因为它非常有用。 —— Rob Pike Go中的“对象” 要探讨Go语言中的对象,我们先搞清楚一个问题: Go语言有对象吗? 从语法上来说, Go中没有类(Classes) Go中没有“对象”(Objects) 到底什么是对象? 对象是一种抽象的数据类型,拥有状态(数据)和行为(代码)。 —— Steve Francia 在Go语言中,我们这样声明一个类型: 类型声明(Struct) type Rect struct { width int height int } 然后我们可以给这个Struct声明一个方法 func (r *Rect) Area() int { return r.width * r.height } 用起来就像这样 func main() { r := Rect{width: 10, height: 5} fmt.Println("area: ", r.Area()) } 我们不光可以声明结构体类型,我们可以声明任何类型。比如一个切片: 类型声明(Slice) type Rects []*Rect 同样也可以给这个类型声明一个方法 func (rs Rects) Area() int { var a int for _, r := range rs { a += r.Area() } return a } 用起来 func main() { r := &Rect{width: 10, height: 5} x := &Rect{width: 7, height: 10} rs := Rects{r, x} fmt.Println("r's area: ", r.Area()) fmt.Println("x's area: ", x.Area()) fmt.Println("total area: ", rs.Area()) } https://play.golang.org/p/G1OWXPGvc3 我们甚至可以声明一个函数类型 类型声明(Func) type Foo func() int 同样的,给这个(函数)类型声明一个方法 func (f Foo) Add(x int) int { return f() + x } 然后用起来 func main() { var x Foo x = func() int { return 1 } fmt.Println(x()) fmt.Println(x.Add(3)) } https://play.golang.org/p/YGrdCG3SlI 通过上边的例子,这样看来,其实 Go有“对象” 那么我们来看看 “面向对象”的Go 如果一种语言包含对象的基本功能:标识、属性和特性,则通常认为它是基于对象的。 如果一种语言是基于对象的,并且具有多态性和继承性,那么它被认为是面向对象的。 —— Wikipedia 第一条,我们在上边的例子看到了,go中的type declaration其实满足了Go语言是基于对象的。那么, Go是基于对象的,它是面向对象的吗? 我们来看看关于第二条,继承性和多态性 继承 提供对象的复用 类是按层级创建的 继承允许一个类中的结构和方法向下传递这种层级 Go中实现继承的方式 Go明确地避免了继承 Go严格地遵循了符合继承原则的组合方式 Go中通过嵌入类型来实现组合 组合 提供对象的复用 通过包含其他的对象来声明一个对象 组合使一个类中的结构和方法被拉进其他类中 继承把“知识”向下传递,组合把“知识”向上拉升 —— Steve Francia 嵌入类型 type Person struct { Name string Address } type Address struct { Number string Street string City string State string Zip string } 给被嵌入的类型声明一个方法 func (a *Address) String() string { return a.Number + " " + a.Street + "\n" + a.City + ", " + a.State + " " + a.Zip + "\n" } 使用组合字面量声明一个Struct func main() { p := Person{ Name: "Steve", Address: Address{ Number: "13", Street: "Main", City: "Gotham", State: "NY", Zip: "01313", }, } } 跑起来试试 func main() { p := Person{ Name: "Steve", Address: Address{ Number: "13", Street: "Main", City: "Gotham", State: "NY", Zip: "01313", }, } fmt.Println(p.String()) } https://play.golang.org/p/9beVY9jNlW 升级 升级会检查一个内部类型是否能满足需要,并“升级”它 内嵌的数据域和方法会被“升级” 升级发生在运行时而不是声明时 被升级的方法被认为是符合接口的 升级不是重载 func (a *Address) String() string { return a.Number + " " + a.Street + "\n" + a.City + ", " + a.State + " " + a.Zip + "\n" } func (p *Person) String() string { return p.Name + "\n" + p.Address.String() } 外部结构的方法和内部结构的方法都是可见的 func main() { p := Person{ Name: "Steve", Address: Address{ Number: "13", Street: "Main", City: "Gotham", State: "NY", Zip: "01313", }, } fmt.Println(p.String()) fmt.Println(p.Address.String()) } https://play.golang.org/p/Aui0nGa5Xi 这两个类型仍然是两个不同的类型 func isValidAddress(a Address) bool { return a.Street != "" } func main() { p := Person{ Name: "Steve", Address: Address{ Number: "13", Street: "Main", City: "Gotham", State: "NY", Zip: "01313", }, } // 这里不能用 p (Person类型) 作为 Address类型的IsValidAddress参数 // cannot use p (type Person) as type Address in argument to isValidAddress fmt.Println(isValidAddress(p)) fmt.Println(isValidAddress(p.Address)) } https://play.golang.org/p/KYjXZxNBcQ 升级不是子类型 多态 为不同类型的实体提供单一接口 通常通过泛型、重载和/或子类型实现 Go中实现多态的方式 Go明确避免了子类型和重载 Go尚未提供泛型 Go的接口提供了多态功能 接口 接口就是(要实现某种功能所需要提供的)方法的列表 结构上的类型 vs 名义上的类型 “如果什么东西能做这件事,那么就可以在这使用它” 惯例上就叫它 某种东西 Go语言采用了鸭式辩型,和JavaScript类似。鸭式辩型的思想是,只要一个动物走起路来像鸭子,叫起来像鸭子,那么就认为它是一只鸭子。 也就是说,只要一个对象提供了和某个接口同样(在Go中就是相同签名)的方法,那么这个对象就可以当做这个接口来用。并不需要像Java中一样显式的实现(implements)这个接口。 接口声明 type Shaper interface{ Area() int } 然后把这个接口作为一个参数类型 func Describe(s Shaper) { fmt.Println("Area is: ", s.Area()) } 这样用 func main() { r := &Rect{width: 10, height: 5} x := &Rect{width: 7, height: 10} rs := &Rects{r, x} Describe(r) Describe(x) Describe(rs) } https://play.golang.org/p/WL77LihUwi “如果你可以重新做一次Java,你会改变什么?” “我会去掉类class,” 他回答道。 在笑声消失后,他解释道,真正的问题不是类class本身,而是“实现”的继承(类之间extends的关系)。接口的继承(implements的关系)是更可取的方式。 只要有可能,你就应该尽可能避免“实现”的继承。 —— James Gosling(Java之父) Go的接口是基于实现的,而不是基于声明的 这也就是上边所说的鸭式辩型 接口的力量 io.Reader type Reader interface { Read(p []byte) (n int, err error) } Interface Read方法读取最多len(p) bytes的数据到字节数组p中 返回读取的字节数和遇到的任何error 并不规定Read()方法如何实现 被诸如 os.File, bytes.Buffer, net.Conn, http.Request.Body等等使用 io.Writer type Writer interface { Write(p []byte) (n int, err error) } Interface Write方法写入最多len(p) bytes的数据到字节数组p中 返回写入的字节数和遇到的任何error 并不规定Write()方法如何实现 被诸如 os.File, bytes.Buffer, net.Conn, http.Request.Body等等使用 io.Reader 使用 func MarshalGzippedJSON(r io.Reader, v interface{}) error { raw, err := gzip.NewReader(r) if err != nil { return err } return json.NewDecoder(raw).Decode(&v) } 读取一个json.gz文件 func main() { f, err := os.Open("myfile.json.gz") if err != nil { log.Fatalln(err) } defer f.Close() m := make(map[string]interface{}) MarshalGzippedJSON(f, &m) } 实用的交互性 Gzip.NewReader(io.Reader) 只需要传入一个io.Reader接口类型即可 在files, http requests, byte buffers, network connections, ...任何你创建的东西里都能工作 在gzip包里不需要任何特殊处理。只要简单地调用Read(n),把抽象的部分留给实现者即可 将 http response 写入文件 func main() { resp, err := http.Get("...") if err != nil { log.Fatalln(err) } defer resp.Body.Close() out, err := os.Create("filename.ext") if err != nil { log.Fatalln(err) } defer out.Close() io.Copy(out, resp.Body) // out io.Writer, resp.Body io.Reader } Go 简单比复杂更难:你必须努力使你的思维清晰,使之简单。但最终还是值得的,因为一旦你到了那里,你就可以移山。 —— Steve Jobs Go简单,实用,绝妙 Go做了一些伟大的事情

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册