[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[原创] 【震撼发布】VBS函数式编程类库 Brackets

本帖最后由 老刘1号 于 2023-4-30 18:04 编辑
强大、优雅、简洁的 VBS 函数式编程类库,颠覆你对 VBS 编程的理解!
首创 VBS 匿名函数支持,按需添加环境。此外还一并封装了几十个常用、通用、易用的方法。
通过函数的封装和嵌套,将复杂的问题抽丝剥茧,展现其中的变换本质。原来,编程和数学竟能如此相像!
感受函数式编程的魅力吧!


从Github安装

开始

环境要求


  • 视窗操作系统

安装

管理员权限运行以下命令:
  1. git clone https://github.com/OldLiu001/Brackets.vbs.git
  2. cd Brackets.vbs
  3. regsvr32 Brackets.wsc
复制代码
警告:不要使用右键菜单注册 Brackets.wsc

使用下列代码创建类的实例:
  1. Set [] = CreateObject("Brackets")
复制代码
便携

制作便携版本后,其他用户无需进行上述的安装操作即可使用您的脚本。

复制脚本 Brackets.vbsBrackets.js 到您脚本所在的文件夹下。

假设您的脚本的文件名为 MyScript.vbs ,使用如下的代码模板:

Template.wsf
  1. <job id="MyScript">
  2.     <script language="JScript" src="Brackets.js"/>
  3.     <script language="VBScript" src="Brackets.vbs"/>
  4.     <script language="VBScript" src="MyScript.vbs"/>
  5. </job>
复制代码
将其放置到您脚本所在的文件夹下。

或将脚本和类库都嵌入单个 WSF 中:

Template_Embedded.wsf
  1. <job id="MyScript">
  2.     <script language="JScript">
  3.         // 此处写 "Brackets.js" 的内容
  4.     </script>
  5.     <script language="VBScript">
  6.         ' 此处写 "Brackets.vbs" 的内容
  7.     </script>
  8.     <script language="VBScript">
  9.         ' 此处写 "MyScript.vbs" 的内容
  10.     </script>
  11. </job>
复制代码
当然,您可以只将必要的部分嵌入 WSF 中,此处不再赘述。

创建类的实例:
  1. Set [] = New Brackets
复制代码
用法

函数相关方法

[].Function(strParameters, strBody) -> varFunction

受限的匿名函数生成器。

它生成的函数只能引用参数和 VBScript 中的内置函数。
  1. ' 赋值给变量
  2. Set IsBigger = [].Function("i, j", "Return i > j")
  3. Msgbox IsBigger(2001, 1228)
  4. ' 递归
  5. Set Factorial = [].Function("i", "If i > 1 Then : Return i * Callee(i - 1) : Else : Return 1 : End If")
  6. Msgbox Factorial(6)
  7. ' 变长参数
  8. Msgbox [].Function("", "Return ArgumentsCount")(2001, 1228)
  9. Msgbox [].Function("", "Return Arguments(0) + Arguments(1)")(2001, 1228)
  10. Msgbox [].Function("", "Return Join(Arguments, "" "")")(2001, 1228)
复制代码
参数 strParameters 不支持前缀 ByRef 以及 ByVal。你可以把它想象成永远 ByVal

关键字 Return 表示保存返回值,它不会真正返回。
  1. Call [].Function("", "Return Empty : Msgbox ""Fake Return!""")()
复制代码


[].Lambda(strParameters, strBody, strBindings, arrBindings) -> varFunction

[].Function 类似,但可以绑定环境。
  1. ' 给Lambda绑定环境
  2. Set Echo = [].Lambda("strArg", "WSH.Echo strArg", "WSH", Array(WScript))
  3. Echo "Hello, world!"
  4. ' 修改绑定的变量
  5. Set Counter = [].Lambda("", "Return i : i = i + 1", "i", Array(0))
  6. Msgbox Counter() & " " & Counter() & " " & Counter()
  7. Set Fibonacci = [].Lambda("", "Return i + j : i = i + j : j = i - j", "i, j", Array(0,1))
  8. Fibonacci() : Fibonacci() : Fibonacci() ' -> 1 1 2
  9. Msgbox Fibonacci() & " " & Fibonacci() & " " & Fibonacci()
复制代码


[].Times varSubprogram, lngTimes

运行过程若干次。
  1. [].Times [].Function("", "Msgbox ""Say something important three times."""), 3
复制代码


[].Once(varFunction) -> varDisposableFunction

将函数包裹为只可运行一次。
  1. Set varTest = [].Once([].Function("", "Msgbox 1"))
  2. varTest() : varTest() : varTest()
复制代码


[].Curry(varFunction, lngArgumentsCount)

打散参数以支持携带部分参数。

这个过程一般被称作“柯里化”。
  1. ' varFunction(a,b,c), 3 -> varFunction(a)(b)(c)
  2. Set varAdd = [].Curry([].Function("a, b, c","Return a + b + c"), 3)
  3. Msgbox varAdd(1,2,3)
  4. Msgbox varAdd(1,2)(3)
  5. Msgbox varAdd(1)(2)(3)
  6. Msgbox varAdd(1)(2,3)
复制代码


[].Partial(varFunction, arrArguments)

返回携带左半部分参数的函数。

这个过程一般被称作“偏应用”。
  1. ' varFunction(a,b,c,d) , Array(1,2) -> varFunction(1,2,c,d)
  2. Set varAdd = [].Function("a, b, c","Return a + b + c")
  3. Set varAdd3 = [].Partial(varAdd, Array(1, 2))
  4. Msgbox varAdd3(3)
复制代码


[].Compose(varFunc1, varFunc2, ...) -> varPipelineFunction

将若干单参函数打包成流水线函数。
  1. ' varF3(varF2(varF1(1))) -> varPipeline(1)
  2. Set varF1=[].Function("x", "Return x + 10")
  3. Set varF2=[].Function("x", "Return x * 10")
  4. Set varF3=[].Function("x", "Return x - 10")
  5. Msgbox [].Compose(varF1,varF2,varF3)(1)
复制代码
数组相关方法

[].Range(numStart, numStop, numStep) -> arrNumber

返回由若干有序、离散、等距的数组成的数组。
  1. ' Range(1,3,1) -> Array(1,2,3)
  2. ' Range(1,3,2) -> Array(1,3)
  3. ' Range(1,3,3) -> Array(1)
  4. ' Range(1,3,0) -> Error
  5. ' Range(1,3,-1) -> Array()
  6. Msgbox [].Reduce([].Function("i, j", "Return i * j"), [].Range(1,6,1))
复制代码


[].CArray(varSet) -> Array(...)

将类似 FSO.Drives 的集合转换成数组。
  1. Msgbox Join([].CArray(CreateObject("Scripting.FileSystemObject").Drives), " ")
复制代码


[].Append(varSet1, varSet2) -> arrAppended

合并两个数组/集合。
  1. ' Array(a, b), Array(c, d) -> Array(a, b, c, d)
  2. Msgbox Join([].Append(Array(1, 2), Array(3, 4)))
复制代码


[].Flatten(arrNested) -> arrFlattened

将数组打平。
  1. ' Array(a, Array(b), Array(Array(c))) -> Array(a, b, c)
  2. Msgbox Join([].Flatten(Array(1, 2, Array(3, Array(4)), Array(Array(Array(Array(5)))))), " ")
复制代码


[].Zip(varLeft, varRight) -> arrZipped

将两个数组/集合内对应元素打包。
  1. ' Array(a, b, c), Array(d, e, f) ->
  2. ' Array(Array(a, d), Array(b, e), Array(c, f))
  3. [].ForEach [].Function("arrArg", "Msgbox arrArg(0) + arrArg(1)"),
  4.     [].Zip(Array(1, 0, -1), Array(-1, 0, 1))
复制代码


[].Reverse(varSet) -> arrReversed

返回逆序后的数组。
  1. Msgbox Join([].Reverse(Array(1,2,3)), " ") ' -> 3 2 1
复制代码
函数结合数组相关方法

[].Map(varFunction, varSet) -> arrMapped

将象按顺序打包。
  1. 'Func, Array(item1,item2,...) -> Array(Func(item1),Func(item2),...)
  2. Msgbox Join([].Map([].Function("i", "Return i^2"), [].Range(0,9,1)), " ")
复制代码


[].ForEach varSubprogram, varSet

[].Map 类似,但不返回值。
  1. [].ForEach [].Function("strArg", "Msgbox strArg"), [].Range(1,5,1)
复制代码


[].Apply(varFunction, varArguments) -> varReturn

数组元素作为函数参数调用函数。
  1. ' varFunciton, Array(a, b, c, ...) -> varFunction(a, b, c, ...)
  2. ' Msgbox [].Function("i, j", "Return i+j")(12, 28)
  3. Msgbox [].Apply([].Function("i, j", "Return i+j"), Array(12, 28))
复制代码


[].SpreadArguments(varFunction, varArguments) -> varReturn

[].Apply 同。



[].GatherArguments(varFunction) -> varWrappedFunction

将外层函数参数打包成数组传递给内层函数。
  1. ' varFunction(a, b, c, ...) -> varFunciton(Array(a, b, c, ...))
  2. Msgbox [].GatherArguments([].Function("arrArg", "Return arrArg(1)"))(333, 444, 555)
复制代码


[].Filter(varFunction, varSet) -> arrFiltered

将满足条件的数组内元素留下。
  1. Msgbox Join([].Filter([].Function("i", "Return i > 4"), Array(1,3,5,7)), " ")
复制代码


[].Reduce(varFunction, varSet) -> varReduced

[].Reduce(varFunction, [].Append(Array(varInitialValue), varSet)) -> varReduced

使用二元函数归约/累积数组至一个值。
  1. Msgbox [].Reduce([].Function("i, j", "Return i * j"), [].Range(1,6,1))
  2. Msgbox [].Reduce([].Function("i, j", "Return i Or j"), Array(True, True, False))
  3. Msgbox [].Reduce([].Function("i, j", "Return i And j"), Array(True, True, False))
复制代码


[].Accumulate(varFunction, varSet) -> varAccumulated

[].Accumulate(varFunction, [].Append(Array(varInitialValue), varSet)) -> varAccumulated

[].Reduce 同。



[].Every(arrArguments, varFunction) -> boolTested

判断是否所有数组内的元素满足要求。
  1. Msgbox [].Every(Array(1, 2, 3), [].Function("i", "Return i > 0"))
  2. Msgbox [].Every(Array(1, -1), [].Function("i", "Return i > 0"))
复制代码


[].Some(arrArguments, varFunction) -> boolTested

判断是否有数组内的元素满足要求。
  1. Msgbox [].Some(Array(1, -1), [].Function("i", "Return i > 0"))
  2. Msgbox [].Some(Array(0, -1), [].Function("i", "Return i > 0"))
复制代码
其它方法

[].Set varVariable, varValue

统一 VBS 内的赋值方式。
  1. [].Set objFS, CreateObject("Scripting.FileSystemObject")
  2. [].Set PI, Atn(1) * 4
复制代码


[].If(boolCondition, varTrue, varFalse) -> varRet

类似其它语言中的三目运算符,但没有短路求值。
  1. Msgbox [].If(2000 > 3000, "2000¥ > 3000$", "2000¥ <= 3000$")
  2. Msgbox [].If(0.1 + 0.2 = 0.3, "0.1 + 0.2 = 0.3", "0.1 + 0.2 <> 0.3")
复制代码


[].Assert boolCondition, strSource, strDescription

断言条件满足,否则报错。
  1. [].Assert WScript.Arguments.Count = 1, _
  2.     "WScript.Arguments", "Need a command-line argument."
复制代码


[].GetObject(strProgID) -> objCOM

若已存在 COM 对象,则直接得到,否则创建一个。
  1. [].Set objWord, [].GetObject("Word.Application")
复制代码


[].Unless boolPredicate, varSubprogram

若谓词不满足,则执行子程序。
  1. [].Unless True, [].Function("", "Msgbox 1")
  2. [].Unless False, [].Function("", "Msgbox 2")
复制代码


[].Min(numA, numB) -> numMinimum

取双参中的最小值。
  1. Msgbox [].Min(-100, 100)
  2. arrTest =  Array(1, 0, -1, -100)
  3. Msgbox [].Reduce([].Lambda("i, j", "Return [].Min(i, j)", "[]", Array([])), arrTest)
复制代码


[].Max(numA, numB) -> numMaximum

取双参中的最大值。
  1. Msgbox [].Max(-100, 100)
  2. arrTest =  Array(10, 0, -1, -100)
  3. Msgbox [].Reduce([].Lambda("i, j", "Return [].Max(i, j)", "[]", Array([])), arrTest)
复制代码
参考

匈牙利命名:lng Long, str String, obj Object, arr Array, var Variable, num Number.

示例(TODO)

贡献

如果您发现任何 BUG ,请提交一个 Issue

欢迎贡献代码!

记得遵守匈牙利命名规则,然后提交 Pull Request 即可!

参照

1

评分人数

回复 1# 老刘1号


看不到你发的图片,换个图床试试吧:
http://bbs.bathome.net/thread-60985-1-1.html
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 2# Batcher


    好的,我还是放文本吧,方便测试修改,找了好几个markdown -> html -> bbcode的工具,都不大好使,不过好在markdown当纯文本也有较高的可读性
论坛纯文本自动吞缩进,所以塞到code标签里了

TOP

返回列表