Есть ли способ писать анонимные функции, передавать их другим функциям, в которых они вызывают, в vbscript?Функции более высокого порядка VBScript
ответ
- В VBScript нет анонимных функций/подмножеств/методов.
- Вы можете использовать GetRef() (см. sample1, sample2), чтобы получить что-то вроде указателя функции, который может быть передан в функции/подсистемы, которые будут там вызваны (обратный вызов). Но в VBScript нет замыканий, поэтому в VBScript возможны ошибки в других языках.
- Для конкретные проблемы, которые могут быть решены с помощью функций более высокого порядка в функциональных языках, могут быть (почти) эквивалентные решения VBScript, включающие классы/объекты; но для обсуждения этого подхода вам необходимо подробно описать вашу/такую проблему.
VBScript имеет возможность исполнять арбитражный кодекс.
Выполнение и Eval просто выполняют то, что они говорят строкой, содержащей код.
ExecuteGlobal добавляет код в вашу программу, как новую функцию, новые переменные.
Сценарий управления добавляет скриптовый язык vbscript/jscript в любую программу, включая vbscripts. Он может иметь доступ к данным хоста.
Если вы используете ExecuteGlobal/Execute/Eval, лучше сначала запустить скриптконтроль, чтобы проверить наличие синтаксических ошибок (поскольку вы не можете улавливать синтаксические ошибки, но вы можете уловить ошибку времени выполнения, которую элемент управления скриптом дает синтаксис ошибка).
Таким образом, вы можете создать свою программу во время выполнения.
Set Arg = WScript.Arguments
set WshShell = createObject("Wscript.Shell")
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
Sub VBSCmd
RawScript = LCase(Arg(1))
'Remove^from quoting command line and replace : with vbcrlf so get line number if error
Script = Replace(RawScript, "^", "")
Script = Replace(Script, "'", chr(34))
Script = Replace(Script, ":", vbcrlf)
'Building the script with predefined statements and the user's code
Script = "Dim gU" & vbcrlf & "Dim gdU" & vbcrlf & "Set gdU = CreateObject(" & chr(34) & "Scripting.Dictionary" & chr(34) & ")" & vbcrlf & "Function UF(L, LC)" & vbcrlf & "Set greU = New RegExp" & vbcrlf & "On Error Resume Next" & vbcrlf & Script & vbcrlf & "End Function" & vbcrlf
'Testing the script for syntax errors
On Error Resume Next
set ScriptControl1 = wscript.createObject("MSScriptControl.ScriptControl",SC)
With ScriptControl1
.Language = "VBScript"
.UseSafeSubset = False
.AllowUI = True
.AddCode Script
End With
With ScriptControl1.Error
If .number <> 0 then
Outp.WriteBlankLines(1)
Outp.WriteLine "User function syntax error"
Outp.WriteLine "=========================="
Outp.WriteBlankLines(1)
Outp.Write NumberScript(Script)
Outp.WriteBlankLines(2)
Outp.WriteLine "Error " & .number & " " & .description
Outp.WriteLine "Line " & .line & " " & "Col " & .column
Exit Sub
End If
End With
ExecuteGlobal(Script)
'Remove the first line as the parameters are the first line
'Line=Inp.readline
Do Until Inp.AtEndOfStream
Line=Inp.readline
LineCount = Inp.Line
temp = UF(Line, LineCount)
If err.number <> 0 then
outp.writeline ""
outp.writeline ""
outp.writeline "User function runtime error"
outp.writeline "==========================="
Outp.WriteBlankLines(1)
Outp.Write NumberScript(Script)
Outp.WriteBlankLines(2)
Outp.WriteLine "Error " & err.number & " " & err.description
Outp.WriteLine "Source " & err.source
Outp.WriteLine "Line number and column not available for runtime errors"
wscript.quit
End If
outp.writeline temp
Loop
End Sub
Vbs
filter vbs "text of a vbs script"
filter vb "text of a vbs script"
Используйте двоеточия для того чтобы отделить заявления и линии. Используйте одиночные кавычки вместо двойных кавычек, если вам нужна одна цитата, использующая chr (39). Скопируйте скобки и амперсанд с символом ^. Если вам понадобится использование каретки chr (136).
Эта функция называется UF (для пользовательской функции). Он имеет два параметра: L, который содержит текущую строку и LC, который содержит linecount. Задайте результаты сценария UF. См. Пример.
Доступны три глобальных объекта. Необъявленная глобальная переменная gU для поддержания состояния. Используйте его как массив, если вам нужно больше одной переменной. Объект словаря gdU для сохранения и доступа к предыдущим строкам. И объект RegExp greU готов к использованию.
Пример
Этот VBS скрипт вставляет номер строки и устанавливает линию к функции UF, какой фильтр печатает.
filter vbs "uf=LC ^& ' ' ^& L"<"%systemroot%\win.ini"
Вот как это выглядит в памяти
Dim gU
Set gdU = CreateObject("Scripting.Dictionary")
Set greU = New RegExp
Function UF(L, LC)
---from command line---
uf=LC & " " & L
---end from command line---
End Function
Если будет отображать отладочные детали ошибки фильтра синтаксиса.
User function syntax error
==========================
1 Dim gU
2 Dim gdU
3 Set greU = CreateObject("Scripting.Dictionary")
4 Function UF(L, LC)
5 On Error Resume Next
6 uf=LC dim & " " & L
7 End Function
Error 1025 Expected end of statement
Line 6 Col 6
User function runtime error
===========================
1 Dim gU
2 Dim gdU
3 Set greU = CreateObject("Scripting.Dictionary")
4 Function UF(L, LC)
5 On Error Resume Next
6 uf=LC/0 & " " & L
7 End Function
Error 11 Division by zero
Source Microsoft VBScript runtime error
Line number and column not available for runtime errors
Я думал об этом, но это не очень изящное решение. Поскольку цель заключалась в том, чтобы мой код был более надежным и чистым, eval и co. не очень полезны. Тем не менее, вы правы в том, что если цель моей попытки функции более высокого порядка состояла в том, чтобы просто передавать фрагменты кода для выполнения, это было бы безупречное решение. – DJD
Забавная вещь о функциональных объектах заключается в том, что они по определению являются утечкой памяти. Это означает, что, как только вы создаете объект функции, вам нужно сохранить область, в которой она была создана, неповрежденной, что отбросило меня.
Class VBCompiler
Public leaks
Public Sub Class_Initialize()
leaks = Array()
End Sub
Public Function Compile(code)
Dim compiler, result
Set compiler = CreateObject("MSScriptControl.ScriptControl")
Set portal = CreateObject("Scripting.Dictionary")
Dim name
compiler.Language = "VBScript"
compiler.AddObject "portal", portal, True
compiler.ExecuteStatement code
name = compiler.Procedures(1).Name
compiler.ExecuteStatement "portal.Add ""result"", GetRef(""" & name & """)"
' save the script control because if we go out of scope...
' our function object goes poof!
' leaks.Push compiler
ReDim Preserve leaks(UBound(leaks) + 1)
Set leaks(UBound(leaks)) = compiler
Set Compile = portal("result")
End Function
End Class
Dim z
Set z = New VBCompiler
Set z2 = z.Compile("Function Foo(s):MsgBox s:Foo = 2:End Function")
z2("Hi!")
z2 "Hello Again!"
дает два окна сообщений по желанию
Class VBCompiler
Public Function Compile(code)
Dim compiler, result
Set compiler = CreateObject("MSScriptControl.ScriptControl")
Set portal = CreateObject("Scripting.Dictionary")
Dim name
compiler.Language = "VBScript"
compiler.AddObject "portal", portal, True
compiler.ExecuteStatement code
name = compiler.Procedures(1).Name
compiler.ExecuteStatement "portal.Add ""result"", GetRef(""Foo"") "
Set Compile = portal("result")
End Function
End Class
Dim z
Set z = New VBCompiler
Set z2 = z.Compile("Function Foo():MsgBox ""Well Met!"":Foo = 2:End Function")
z2("Hi!")
z2 "Hello Again!"
выше дает (29, 5) (null): Unspecified error
. Эта ошибка по существу: your object has committed suicide
.
Этот подход может быть улучшен (в частности, проблема расточительного сценария ScriptControl для компиляции без каких-либо планов их выпуска).
- 1. Функции более высокого порядка
- 2. C++ функции более высокого порядка
- 3. Производные функции более высокого порядка
- 4. Уточнение функции более высокого порядка
- 5. Функции javascript более высокого порядка
- 6. Regex более высокого порядка
- 7. Функция более высокого порядка
- 8. Унификация более высокого порядка
- 9. Производные более высокого порядка
- 10. Предикаты более высокого порядка
- 11. Функции более высокого порядка в SML/NJ
- 12. Получение функции более высокого порядка в Scala
- 13. Функции более высокого порядка в haskell Error2
- 14. Пример объяснения функции более высокого порядка scala
- 15. функции более высокого порядка в haskell
- 16. Как эффективно использовать функции более высокого порядка?
- 17. Python: функции более высокого порядка с методами
- 18. Clojure создание более высокого порядка первой функции
- 19. Как работают функции более высокого порядка Kotlin?
- 20. Объясните это поведение функции более высокого порядка
- 21. Лямбда-выражения и функции более высокого порядка
- 22. Функции более высокого порядка в Javascripts
- 23. Функции более высокого порядка в Erlang
- 24. Функции более высокого порядка с шаблонами?
- 25. Задача функции более высокого порядка Scala
- 26. Общая ошибка задания функции более высокого порядка
- 27. Функции более высокого порядка в ошибке haskell
- 28. Функции более высокого порядка в обходе дерева
- 29. Функции более высокого порядка в Python
- 30. о функции более высокого порядка haskell
Спасибо! Тем временем я выяснил путь вокруг него, хотя это было очень специфично, а потому не очень абстрактное решение. Ну что ж. – DJD