Forwarded from dnaugsuz
一般来说好像不要用这个语法,因为不知道它的人会感到困扰,如果是实践就用 reversed 吧。
Forwarded from dnaugsuz
不是吧,是不是
另外
lambda x: x 的意思啊?rev rev id 可是逻辑式编程和计算机辅助定理证明的入门例子呢另外
::n 好像这个语法也被 TCP 使用了?那它就更不该经常在实际项目里用了,切记啊。Forwarded from undefined + 1 = NaN
那
k=lambda x: x[::-1], k(x[::-1]) 呢?Forwarded from dnaugsuz
不是一样吗?而且这里 k 应该叫 f 更好的
然后那个 Lambda 后面不是该跟表达式,表达式后面又有
应用序Y组合子(Applicative Order Y Combinator) 里我喜欢把别人经常叫 x 的函数给叫成 c 或者 k,我认为那是 continuation 之类的意思,看起来好高级呢。
(f str[::-1]) where
f = \s. s[::-1] 然后那个 Lambda 后面不是该跟表达式,表达式后面又有
',' 是啥意思……Python3 没这语法吧应用序Y组合子(Applicative Order Y Combinator) 里我喜欢把别人经常叫 x 的函数给叫成 c 或者 k,我认为那是 continuation 之类的意思,看起来好高级呢。
Y = \f. (\x. f (x x)) (\x. f (x x))Lambda 演算很长我这里不能细说,总之
My_Y = \f. (\c. f (c c)) (\c. f (c c))
\formal. body 是对 body 的一种抽象(比如,把x装进冰箱里,其中x是一个物体,装冰箱=\x. ……)、(f x) 的项目并列是对抽象 f 的一种应用,也就是提供它的参数,一般lambda演算都是单参+高阶函数(返回函数的函数)实现多参函数的,用『currying』的方式逐步填完所有body里依赖的参数。Forwarded from dnaugsuz
>>>
而且 Python 里 Lambda 好像不能递归引用自身,Kotlin 里的 Block 也一样(不知道是不是叫 Block 呢)(毕竟它主要是作为「函数值」的,当然不能引用自身啊)
k=lambda x: x[::-1], k(x[::-1])
NameError: name 'k' is not defined而且 Python 里 Lambda 好像不能递归引用自身,Kotlin 里的 Block 也一样(不知道是不是叫 Block 呢)(毕竟它主要是作为「函数值」的,当然不能引用自身啊)
呃我就照着你说的一段段回复吧:
> @duangsuse 不好意思,可惜[不大会 kotlin](https://zhuanlan.zhihu.com/p/32242763)。关于`用("bb")替换前(3)个("aa")`这样的语法,之前只是想在现在大多数语言的方法定义(仅支持参数位于末尾)的基础上作一个改变(进?),与其这样定义:
>
> ```python
> def replace(old, new, max):
> ...
> ```
**我的观点:这绝对不能算作是改进,尽管它往往不会与绝大部分语言的原文法冲突也不能。(JavaScript在限制不换行的情况下也不会)**
就实现可能性上,一般我们认为 `someFunc(a0)aname1(a1)...` 这样的模式,当然是可能与绝大部分只需要 *一个参数*(但不至于与需要一个 `tuple` 的函数)相冲突的(我是指对于老思路那些 *不需要* 这种特性定义的函数)
**但是**,如果文法上直接换成这种形式定义,其实也没什么问题(看刚才我写那Kotlin就知道的确是没啥问题,因为按Kotlin语法 `f()` 完后的后继只能是[中缀](https://kotlinlang.org/docs/reference/grammar.html#disjunction)如 `.` `+` 或另一个前面肯定没名字的后缀如 `()`、看[Z语言](https://zhuanlan.zhihu.com/p/40356993)也知道的确是没问题)。
首先我相信绝大部分静态类型检查的编程语言设计者,尤其是重视代码一致性的程序员都讨厌一些比较容易混淆的语法,尽管也有许多人喜欢 Ruby、Python 的 "keyword arguments" `def dig_a_hole(depth: 1, label: 'hole'); puts"$label $depth"; end` 这种。
包括我之前在 [以绝句语言翻译](https://t.iss.one/dsuse/12118) 你之前翻译那个 Swift 的时候我都这么想,如果参数列表可以随便hack成那样:
```
func 问好(_ 人: String, 在 日子: String) -> String {
return "吃了么\(人), 今天是\(日子)."
}
问好("小黑", 在: "周三")
```
如果没学过,哪怕是作为一个初学者你能明白这TMD是在做什么吗?下划线是什么意思?『日子』和『在』有啥联系?还是区别?反正我是看不懂。
>介于我之前发了很多 t.iss.one 的链接估计都没人点进去看,我摘一点吊吊胃口
```swift
“func 统计(得分: [Int]) -> (最小: Int, 最大: Int, 总和: Int) {
var 最小 = 得分[0]
var 最大 = 得分[0]
var 总和 = 0
for 分 in 得分 {
if 分 > 最大 {
最大 = 分
} else if 分 < 最小 {
最小 = 分
}
总和 += 分
}
return (最小, 最大, 总和)
}
let 结果 = 统计(得分: [5, 3, 100, 3, 9])
print(结果.总和)
print(结果.2)”
“绝句里单引号是文档,可以在工具里看到。”
“一个类/物的类型参数可以直接加入文档,参数和返回值的文档可以直接加在前面也可以独立加”
“和Kotlin,也是Markdown的”
事 统计(得分:组<数>):‘最小、最大、总和’ 元三<数、数、数> 为
对得分里的分,
判分, “一时间我也找不到更好的方法把「对」和「判」连在一起”
它大最大,最大 = 它。 “「它」是此分支局部的”
它小最小,最小 = 它。
否则,效果。
上皆,总和令置为「+分」。
回元三(最小、最大、总和)
这里,
变数 最小 初0;变数 最大 初0;变数 总和 初0 “不是一般的编程风格,但不置可否。”
“这个版本里,暂时我不会把对「变(属)(名)初(言)」的修改加上,请兼容前面的一部分。”
```
我觉得这样的语言对所有,甚至包括 mother tongue 是 English 的人都是莫名其妙的,而且类似的语言不在少数。
这就是一个观点的问题,也就是『脚本化』还是『规范化』两个互斥的方向,可能相关的你可以看看冰封哥的 [形式验证、依赖类型与动态类型](https://zhuanlan.zhihu.com/p/50792280)
拿一个最简单的例子:比较 Bash 和 Python
当然其实 Bash 作为一门 Shell 语言也是有『[形式化](https://my.safaribooksonline.com/book/operating-systems-and-server-administration/unix/1565923472/syntax/lbs.appd.div.3)』(除了heredoc字符串语法)的语法定义的。
可它的可读性、易学性真的不能与Python相比,或许你会说它们根本不一样,但 Bash 的确是程序设计语言,不过没 `csh`、[elvish Shell](https://elv.sh/) 那么明显而已
比方说呢?Bash 的函数不能有形式化参数,只能在函数体里 `$1 $2 $3` 引用,而整个脚本居然也能把 shell 的参数以 `$0 $1 $2` 引,好像 `bash` 命令是个函数一样、尽管有作用域,函数里定义的变量默认是全局作用域还需要 `local` 来定义一个「局部的」、尽管函数带括号,调用都是 `f x y` 这种形式,而且三种引号 `''` `""` `\`\`` 给人感觉简直难以区分、file pattern 的直接裸写有效也让人经常在参数里包含一些特殊字符时遭逢莫名其妙的问题,更别提 `|` `>` `<` 符甚至 `2>` `2&>` `<&-` `n<&-` 这样看了文档也好长时间才能记住的『重定向』,以及莫名其妙的 +-*/ `&& ||` `declare` 和所谓的 `[]` test 这种加不加空格都有区别还有 N 种写法的『命令』了。
再比较Python和Java,就不提属于运行时特性的 `eval` 了(而且 Java 也完全可以利用 compiler API 或者 `ClassLoader` `defineClass` 动态编译加载到虚拟机来执行代码),不知道有没有Python能吐槽Java的某一点
介于 Java 1.7 都有 try-with-resources 了,他们没法吹 Python 的 `with ` 这种“更自然”的 try-with(当然 Kotin 可以光明正大地藐视所有这样的『脚本语言』,因为它的标准库里[一个 `use` 函数](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/use.html)**就定义了这个被Python视为『语法』的东西,而你甚至不需要知道那个语法是 `with res as name:`**,IDEA 里 <kbd>Ctrl-Q</kbd> 一下就能立刻用上)(原来绝句也有 `尝试文件去开()成某书……`,这么一写我觉得不能有了)
我想他们要吹的肯定是 Python 的动态类型、duck typing,这样你就可以随性地使用任何有 `size` 属性的对象上的 `size` 来取长了,而 Java 不仅每次写 `Something something = new Something();` 麻烦还要各种写 Adapter boilerplate 来解决这种问题,Oh yes my dear Python。
我就不吐槽 Python 那毫无规章的『元方法』如 `len`、`repr` 和莫名其妙的『面向对象』设计以及基础库了,Ruby程序员一直在吐槽。
它的 `:` layout 式语法算是一种创新,可仅止于此,其他的设计都是极度三八极度脚本化的,简直恨不能为Bash,想想Python3都忍不住跨大版本都快抛弃向前兼容了还没改过来,我真是极度地感到惋惜。
例如Kotlin这样的语言更不可能看上这种语法,因为它可能与 `infix fun` 存在语义上的冲突,即便这种冲突可以解决但那可能会给语言的使用者制造一些问题(比如,随性定义了一个使用常见介词的函数,结果与其它函数库的版本冲突……实践上这尽管能解决但不该有这种问题)
至于如果一定要说静态类型的好处,其实封装、抽象、继承、多态、fail-fast 我就不用说了,引用冰封哥的一句话(貌似是,忘记从哪看的了):
> 一个多态就能吊打它们了
没错,一个参数类型式的多态就比它们强太多了,不论类型是否一定要显示标明,静态类型都能在更早的时候确定更多的信息(不需要很复杂的推导算法),基于这样的信息你可以无开销地弄出许多DSL和针对特定输入的优化版本程序,或者仅仅只是静态的 optional arguments 也很好。
**我的另一个观点是,一门好的编程语言不应该能让它的使用者写出不好的代码,哪怕只是可能。**
> 允许这样定义(暂不讨论关键字):
>
> ```python
> def 用(new)替换前(max)个(old):
> ...
> ```
>
> (无意尽量避免括号等)
貌似无论是 Python 还是 Ruby 上这种修改都没有太大问题,不过 optional arguments 和 keyword arguments 就不应该在这种形式支持了,如果更严格我觉得使用这种形式的 Python/Ruby 就不该有 optional/keyword 了,而且 Ruby 的 `&op` 块参数也要好好考虑怎么弄好。
```ruby
def call_with_1p(n, &op); yield(1+n); end
call_with_1p(0) { |x| puts x }
```
不过介于 Ruby 其实已经支持这种形式(出于它有 `f a b` 这种无论是我还是 Haskell 大佬看了都会绝得自己酸死的 Bash 式语法)
不过要写出来是比较麻烦的,类似 trie 树地,它要判断自己的参数是不是对象 `替换前` 后面的后面(就是下一个参数)又是不是 `个` 什么的,比较麻烦。
但如果你觉得 `用(new)替换前(max)个(old)` 可以实现为 Keyword arguments 的形式(它在定义里表达原 `用(x, 替换前: max, 个: old)` 使用参上),我觉得相对比较好实现,不过我显然不能帮你实现(还有绝句解析器要写啊)
> > 我觉得在语言都还没有定好的情况下是不应该太考虑API的,不是不应该考虑,但是语言……基础的定义、控制结构,已经确定,这必须是前提吧。
>
> 个人(只学过一点 PL 皮毛)觉得 api 的设计(比如上面的语法改变)会影响语言本身设计。而且也许有时牵一发动多处,比如[楼上](https://github.com/program-in-chinese/overview/issues/11#issuecomment-569463904)末尾牵涉到类型转换,等等。英文 api 已经基本约定俗成了所有参数在方法最后声明,因此这方面并无什么发挥空间。
是的啊,所以我刚才没说得太绝对,我自己也深有体会,比如写这个回答的时候就因为提及了Kotlin标准库的一个设计,我决定改掉一个语法,之前我以绝句[重写了某JavaScript ES6的代码](https://duangsuse-valid-projects.github.io/Share/%E7%BB%9D%E5%8F%A5/%E7%BB%9D%E5%8F%A5%E8%AF%8D%E6%B3%95#%E7%A4%BA%E4%BE%8B)后我又改了绝句的一个「构词」。
而且说点不相干的,你个人研究中文编程也有几年了吧,我能给最大的建议就是:多『学』几门语言,好好斟酌比较一下它们的区别(这是别的方法无法替代的),总结出点类似「顺序、判断、重复」这样的东西来,也不必学多高大上写 LLVM 编译器前端 `IRBuilder`、JIT 什么的,就琢磨一下语言的设计就挺好。
> 如果,支持上面的方法定义`用(new)替换前(max)个(old)`,以及`如果(...)xx`这样的方法命名,代码写出来也许是这样的:
>
> ```java
> 文字 问好 = "你好"
> 数[] 号码 = [1, 2, 3, 4, 5]
>
> 问好 = 问好.用("吃了么")替换("好")
> 号码.如果((数) -> 数 > 4)移除
>
> 对(号码)中的(某数) { // 遍历这样看起来有点像是方法调用
> 说(问好 + 文字(某数)) // 假定强制转换必须显式
>
> 如果(某数 % 2 == 1) { // 与`如果()xx`方法看起来有点像
> ...
> }
> }
> ```
>
> 写出来之后会发现更多问题(个人短期内无打算深入)
呃这样我没啥可说的,我贴一个自己[之前](https://t.iss.one/dsuse/11776)写的代码(当然也有很多在我的笔记上没发),以及一个以目前绝句设计能有效的代码吧
```java
把(这人.的(朋友们).中(所有(名字.以("abc").起始().的()))).都拿去(用户表::删掉);
从(1).数到(100, (它) -> {
若((它/2).为零(), 向(终端).写("偶数"))
.否则(向(终端).写("奇数"));
});
Consumer<?> 不可能 = (Object _) -> { throw new ImpossibleException(); };
判断(他.的(名字),
倘若(它.是("蔡徐鲲"), 向(它).致敬()),
倘若(它.是(在(iKun.映射到(IKun::名字)).中()), 向(终端)::写),
否则(不可能));
```
```plain
判他的名字,
是"蔡徐鲲",我致敬(它)
在 iKun映至「的名字」“其实不该每次去投至”,输出写它
否则,不可能。
```
```plain
引记法 绝句.严格中文 「以」
引记法 绝句.集合 「滤」
变文 问好 初 "你好"
“「初」不是随便设计的,我有其它考虑这里不提”
“如果是常量可以用「常文」或「量」”
“ 量 问好:文 = "你好" ”
量 号码 = 动组一(1、2、3、4、5)
“Mutable Array (而非 Array<out T> 那种,类型系统一样但提供了一个简写法)”
“ inline fun <reified T> im(vararg items: T): Array<out T> = arrayOf(*items) ”
“绝句不支持一至九开头是因为数字也可用它们表示,”
“这也不是随便设计的。”
“介于绝句不是『脚本语言』以及例子的完整性”
事 入口() 为
问好 = 问好去置换("好"到"吃了么")
“量 某表 = 表一("天"到"地"、"海"到"空"、"大陆"到"长空")”
“解对(1至10)与(1止11)里的(甲、乙),断言(甲是乙)”
“这是一般用法,「对」是存于 绝句.额联 的中缀记法”
问好 = 问好以("么?")去置换("么")
“这是「记法」的用法,当然也可以显示用「去以」而不省略访问符”
“你上面的代码好像写错了,暂且把『移除』当成 "xs[i] = null" 处理吧”
对号码的索引里的针,
若号码[针]大4,号码[针]=空。
“这是绝句第一版的风格,和Kotlin差不多;到时候有了 `存储<值者>` 抽象就不一样了”
“我们也可以用函数式的风格,但这里一般风格更好,尤其是现阶段绝句没任何优化靠Kotlin的情况”
对号码滤出不空里的,
说("${问好}${它去化文()}") “去化文也不必写”
若它之为奇数,效果“啥都不做”。
扩物 数 为
记法「之」的量 之为奇数 取者,我取取余(2)是1。 “我又决定绝句要去掉 % 中缀符转用记法了”
```
> 之前写过一点关于[语言设计和 api 的顺序](https://zhuanlan.zhihu.com/p/85081589),现在仍觉得,如果首先从语言设计(甚至实现)出发,往往会出现削足适履的情况。越早编写接近实用的例程,越能发现语言设计的缺漏和可优化之处。因为实用(尤其是与实际业务相关的,而非纯算法)代码将是语言推广后存量比例最大的。而接近实用意味着至少是一小部分api 设计,以及一定的标识符命名风格。
所以你要写啊,尽管许多语言的入门示例足够概况,但那远远不够啊。
> 对[楼上](https://github.com/program-in-chinese/overview/issues/11#issuecomment-569958947)的例程,个人(也许对目标人群有不同设想)第一眼感觉,“听去数一”,“解对”,“去化数”, “次里的”等等难以一目了然。另外,逗号、分号、句号、双冒号、顿号、波浪号等等似乎都是语法因素,也许会增加学习和使用负担。
其中 `听去数一` 的 `去`,其实我也很没办法,毕竟为了语言的一致性「去」访问符根本无法省略、`解对` 是我刻意那么弄的,本来也可以遵循Kotlin仍用 `对`,它就是来描述 `for ((index, item) in list)` 的这种。
此外「次里的」是你理解错了(因为绝句是期望不带空格的风格的),其实它是 `对(n次)里的` 的意思,这里用「解对」的确是令人困惑,但你同时去掉「解」和后面的「_」后它依然是工作的,逗号后面的 body 里多一个叫「它」的变量而已。
知道「去」是 `.` 的意思你就知道 `听去数一` 其实是访问 `听` 对象上的 `数一` 方法了,在 Java 里这是 `input.nextInt()`、`去化数` 则是 `toInt()` 的意思。
>逗号、分号、句号、双冒号、顿号、波浪号都是语法因素
所以说才叫『中文编程』啊,你试试就会知道只要输入法质量过关,没有任何问题。
>『某』 为可不带空格的『角括名字』、「某」 为中缀表示、【某文形】 为标记修饰、〖某文形〗 为块参数列表
https://duangsuse-valid-projects.github.io/Share/绝句/绝句词法
学任何语言都是要学这些表达形式的,我在设计时刻意没看Kotlin的词法规则,就是为了能设计出更贴切中文的文法表达。
> 语言设计时,相信忍不住会逐渐加入更多更强大的特性,期间需要不断把中文特性这个“足”塞到这些特性组成的越来越小的“履”中。几乎无法避免地,会导致包含这些特性的例程的可读性的下降(也许可写性也是)。更大的问题是,由于语言设计者自身的视角问题,往往不会觉得这种可读性的牺牲是什么问题,因为设计者本身是对特性最熟悉的人(甚至比其他使用的编程语言更熟悉)。即使对路人非常难读的代码(由于对语言特性不了解,以及试图用老思维理解新事物的本能),对语言设计者来说却是轻车熟路。
这么说吧,其实也不无道理,但我对绝句的看法是,既然它也不是特别困难而且我现在也只需要上好学,我不要他们以为、我只要我以为。
`期间需要不断把中文特性这个“足”塞到这些特性组成的越来越小的“履”中。`
为什么不试试以「中文」这个食材,煮盆「程序设计语言」的汤呢?我刚才说了,中文的语序是上下文如目标对象在前、关键描述在后。所以『中文编程』实际上是指『编程』,但它的前提是『以中文』;而不是『以编程』去倒贴『中文』。『中文编程』既要有『中文』更要有『编程』,只有比重视中文更重视编程的人,才有能力设计出好的『中文编程』语言。
`因为设计者本身是对特性最熟悉的人(甚至比其他使用的编程语言更熟悉)` 我觉得这一点是非常有必要的,那个「甚至」我觉得对任何好一点的编程语言来说 **都是最基本的要求,如果一个程序设计语言的设计者无法默写下它的文法,甚至只是不能以那门语言「实现」那门语言本身,那他也不配当那门语言的设计者、那语言也不是好语言。**
> 因此,个人认为,为了避免上述情况,最好是尽量一开始就从尽可能接近实用的例程出发,反过来决定 api 和语言设计。这样,至少一开始能够尽量从最终用户的视角检视例程(在真正开始设计、实现语法之前,尽量确保程序对于新手来说是“好用好懂的”)。即使在之后由于各种设计或实现原因需要改变例程,至少有个参照和基准,也不会太轻易地牺牲可读性。这也和一般项目在设计之前,在获取需求的早期尽量搜集有代表性的 user story 的思路相同。
`这也和一般项目在设计之前,在获取需求的早期尽量搜集有代表性的 user story 的思路相同。`
这是现在工程界普遍的看法,我对它其实是中立态度,不过我也有[其他的看法](https://duangsuse-valid-projects.github.io/Share/%E5%AF%B9drakeet%E7%9A%84%E4%B8%80%E4%BA%9B%E8%AF%9D/%E5%AF%B9drakeet%E7%9A%84%E4%B8%80%E4%BA%9B%E8%AF%9D.html#%E6%95%8F%E9%94%90%E7%9A%84%E4%B8%8D%E6%98%AF%E4%BD%A0%E7%9A%84%E4%BA%BA%E4%B8%8D%E6%98%AF%E4%BD%A0%E7%9A%84%E8%AE%A4%E7%9F%A5%E8%80%8C%E6%98%AF%E4%BD%A0%E6%89%80%E6%9C%89%E7%9A%84%E7%9C%9F%E7%9F%A5)。
>程序设计 **本身** 的 _道_ ,不是所有人都在说的所谓 _优雅_ 的代码、不是看某某人的博客,也不是对有图形用户界面的应用做最优秀的界面交互设计。
刚入门的程序员扣老师枚举出的语法,战战兢兢地拿那一堆惯用法组织自己的逻辑、加入实际项目的工程师扣刻板复制的项目管理、设计模式、代码风格,
可是真正的程序设计大师 **只扣** 对编程的 **直觉** 和程序 **本身的灵魂** ,
对他们来说已经没有入门者的条条框框、刻板的约束了,回归初心,他们看到的是 **程序所做的事情本身** ,
是程序的灵魂;换十种兼容的语言和底层抽象去描述也不是问题,因为他们已经站得足够高,无须顾虑脚下低处的迷雾笼罩而可以自由地放飞视线,
_不识庐山真面目,只缘身在此山_ **_中_** 。
**人类的本质是复读机,可是有些人就是能在不断复读的过程中领悟到所复读内容的真谛,有些人最终也只能是记忆容量大一点的复读机而已。**
语法本身是你对高级程序设计语言使用的基础,项目管理和那群系统管理员做的工作一样容易令人困惑,必须强记。模式是容易复制却又很少被彻底看懂 **看透**
的、代码风格可以被机械化的解析、模式匹配、自然语言字典分词、自动却又很 **刻板** 地检查整理。
优秀的程序员 **授人渔而不是授人鱼** ,看懂某个模式、弄懂某个框架或者库、语言特性、开发工具的使用,熟悉某种基本模型,是的,都很好。
但是 **学一就只能得一,做不到举一反三** 、用归用 **忘还是会忘** ,并且既得知识非常容易失去
因为学到的浅层知识 **根本没有产生联系** 、 **不能做到融会贯通** ,甚至刚用完就忘者不在少数。
当然,看起来工程本来就应该是这样, _理论是知道为什么但是它不好用,实践是它好用但不知道为什么。_
function *nextSiblings(e) { for (let c = e; c!=null; c=c.nextSibling) yield c; }
function *takeWhile(p, xs) { for (let x of xs) if (p(x)) { yield x; } else break; }
class SaveIterator {
constructor(gen) {
this.gen = gen;
this.res0 = gen.next();
this.lastItem = this.res0.value;
}
*iterator() {
if (this.res0.done) return;
yield this.lastItem;
for (let item of this.gen) {
this.lastItem = item;
yield item;
}
this.lastItem = undefined;
this.res0.done = true; //no next
}
[Symbol.iterator] = this.iterator;
} #JavaScriptForwarded from dnaugsuz
我讨厌一个结构,用 yaml, java, ruby, xml, groovy, atom, kotlin, scala 这 N 种表达方式,何况其中还有些有出入的部分,比如 Java 的实际上不能算是 Markup 系模型。
Forwarded from dnaugsuz
YAML 是用了布局(layout),类似 Python 缩进带语义,那是为了好写,不信你看 Swagger,同样的东西 JSON 简直能让人改得无从下手。
布局是一种语法设计的技术,Haskell、Python、ML 语言都用到了布局。
布局是一种语法设计的技术,Haskell、Python、ML 语言都用到了布局。
Swaggerhub
Build, Collaborate & Integrate APIs | SwaggerHub
Join thousands of developers who use SwaggerHub to build and design great APIs. Signup or login today.