From: mayayana on
> > I understood that, but as I posted before it's
> > a superfluous function that makes no sense.
>
> You miss the point: Eval and Execute take *Strings* (runtime data)
> as input.
>

I'm not talking about Execute. I'm just
looking at Eval. It will handle variables
or strings:

a = 1
b = 2
MsgBox Eval(a + b)


> You could use InputBox here to fill sExpr.

Ah. That's something I hadn't thought of. I can
see how that could *maybe* be useful as
an alternative to parsing the string. But I doubt
I would ever do that because it would prevent
me from error-checking the string. That would
be like a function that accepts an email address
or phone number but doesn't check that the entry
is valid. Eval would be easier, of course, but
far more error-prone than parsing the string to
check for valid content.


From: ekkehard.horner on
mayayana schrieb:
>>> I understood that, but as I posted before it's
>>> a superfluous function that makes no sense.
>> You miss the point: Eval and Execute take *Strings* (runtime data)
>> as input.
>>
>
> I'm not talking about Execute. I'm just
> looking at Eval. It will handle variables
> or strings:
>
> a = 1
> b = 2
> MsgBox Eval(a + b)

The Docs clearly state:

Eval(expression)
Arguments
expression
Required. String containing any legal VBScript expression.

Code:

' To prove that Eval takes strings

Option Explicit

Dim sExpr, vRes
sExpr = "Sin( 1 )"
vRes = Eval( sExpr )
WScript.Echo "A string works:"
WScript.Echo sExpr, "=>", vRes
WScript.Echo

vRes = Eval( Sin( 1 ) )
WScript.Echo "A function seems to work, if the return value can be stringified:"
WScript.Echo sExpr, "=>", vRes
WScript.Echo

WScript.Echo "A function returning a non stringifiable value does not work:"
On Error Resume Next
Set vRes = Eval( CreateObject( "Scripting.Dictionary" ) )
If 0 <> Err.Number Then
WScript.Echo Err.Number, Err.Description
Else
WScript.Echo TypeName( vRes )
End If
On Error GoTo 0
WScript.Echo

WScript.Echo "A string containing a call to a function returning a non stringifiable value
works:"
Set vRes = Eval( "CreateObject(""Scripting.Dictionary"")" )
WScript.Echo TypeName( vRes )

output:

A string works:
Sin( 1 ) => 0,841470984807897

A function seems to work, if the return value can be stringified:
Sin( 1 ) => 0,841470984807897

A function returning a non stringifiable value does not work:
450 Falsche Anzahl an Argumenten oder ungültige Eigenschaftszuweisung

A string containing a call to a function returning a non stringifiable value works:
Dictionary

>> You could use InputBox here to fill sExpr.
>
> Ah. That's something I hadn't thought of. I can
> see how that could *maybe* be useful as
> an alternative to parsing the string. But I doubt
> I would ever do that because it would prevent
> me from error-checking the string. That would
> be like a function that accepts an email address
> or phone number but doesn't check that the entry
> is valid. Eval would be easier, of course, but
> far more error-prone than parsing the string to
> check for valid content.
>

Why feeding a string to Eval would prevent you from checking
it for syntactical correctness is beyond me. Your examples
(simple strings that *are* their values and need not to be
evaluated at all) again miss the point. Eval *computes* the
value of the passed expression using - if necessary - the entire
VBScript interpreter and all the functions in your script.
From: ekkehard.horner on
axtens schrieb:
> G'day everyone
>
> Is this an example of a closure or just a trick with Eval?

[...]

I think it's an example of a function composition and of a usage
of Eval as it is meant to be used.

This is my attempt at demonstrating a closure in VBScript:

' fake a closure

Option Explicit

' A 'normal' VBScript function returning a value; it can be called
' by writing its name followed by parameter () around its
' parameter(s) literally in the code, or treated/accessed as data
' ('pointer' to function) by using the GetRef() function with its name
' (without ()) as parameter.
' The function is created at 'compile time' (=just before the
' program starts to execute).
Function addSeven( nNum )
addSeven = 7 + nNum
End Function

' Function that builds a context (nSummand1) from its parameter
' and returns the newly created 'function object'. The returned
' objects are created at runtime (you could use user input/runtime
' data to influence their creation/behavior).
Function makeAdder( nParm )
Dim nSummand1 : nSummand1 = nParm + 1
Set makeAdder = New cAdder.init( nSummand1 )
End Function

' A Adder class (based on ideas/code of Bruce Axtens and Justin Piper)
Class cAdder
Private m_nSummand1
Public Function init( nSummand1 )
Set init = Me
m_nSummand1 = nSummand1
End Function
Public Default Function addit( nSummand2 )
addit = m_nSummand1 + nSummand2
End Function
End Class ' cAdder

' Treat functions/'function objects' as data: put two closures and a
' 'normal' function into an array. (You could assign them to variables,
' pass them as parameters to other functions ... )
Dim aFuncs : aFuncs = Array( New cAdder.init( 4 + 1 ), makeAdder( 5 ), GetRef( "addSeven" ) )
' Using them repeatedly
Dim nNum
For nNum = 1 To 3
WScript.Echo "fncAddFive(", nNum, ") =>", aFuncs( 0 )( nNum )
WScript.Echo " fncAddSix(", nNum, ") =>", aFuncs( 1 )( nNum )
WScript.Echo " addSeven(", nNum, ") =>", aFuncs( 2 )( nNum )
WScript.Echo " addSeven(", nNum, ") =>", addSeven( nNum )
WScript.Echo()
Next

output:

cscript closurefake.vbs
fncAddFive( 1 ) => 6
fncAddSix( 1 ) => 7
addSeven( 1 ) => 8
addSeven( 1 ) => 8

fncAddFive( 2 ) => 7
fncAddSix( 2 ) => 8
addSeven( 2 ) => 9
addSeven( 2 ) => 9

fncAddFive( 3 ) => 8
fncAddSix( 3 ) => 9
addSeven( 3 ) => 10
addSeven( 3 ) => 10

As there is no equivalent of the Javascript/JScript 'on the fly' function
definition:

function( ... ) { return ... };

in VBScript and closures are like objects in that they combine data and
functionality, I decided to use a class (based on your ideas/code; the
init function approach is (c) Justin Piper)


From: Al Dunbar on


"ekkehard.horner" <ekkehard.horner(a)arcor.de> wrote in message
news:4b859f98$0$6585$9b4e6d93(a)newsspool3.arcor-online.net...
> mayayana schrieb:
>>>> I understood that, but as I posted before it's
>>>> a superfluous function that makes no sense.
>>> You miss the point: Eval and Execute take *Strings* (runtime data)
>>> as input.
>>>
>>
>> I'm not talking about Execute. I'm just
>> looking at Eval. It will handle variables
>> or strings:
>>
>> a = 1
>> b = 2
>> MsgBox Eval(a + b)
>
> The Docs clearly state:
>
> Eval(expression)
> Arguments
> expression
> Required. String containing any legal VBScript expression.

This might lead one to assume that a non-string parameter must throw an
error. But in the VBScript way of things a non-string when a string is
expected is just interpreted as an equivalent string.

In other words this means that when eval is passed an arithmetic expression
instead of a string (eval(a + b)), the result of that expression (a + b) or
(3) is cast or interpreted as a string ("3") by eval.

So mayayana is correct to say that it also handles strings, if by "handles"
he means "doesn't choke on". But in this case eval is not evaluating the
arithmetic expression, as that was done before the result is passed to eval.

/Al

>
> Code:
>
> ' To prove that Eval takes strings
>
> Option Explicit
>
> Dim sExpr, vRes
> sExpr = "Sin( 1 )"
> vRes = Eval( sExpr )
> WScript.Echo "A string works:"
> WScript.Echo sExpr, "=>", vRes
> WScript.Echo
>
> vRes = Eval( Sin( 1 ) )
> WScript.Echo "A function seems to work, if the return value can be
> stringified:"
> WScript.Echo sExpr, "=>", vRes
> WScript.Echo
>
> WScript.Echo "A function returning a non stringifiable value does not
> work:"
> On Error Resume Next
> Set vRes = Eval( CreateObject( "Scripting.Dictionary" ) )
> If 0 <> Err.Number Then
> WScript.Echo Err.Number, Err.Description
> Else
> WScript.Echo TypeName( vRes )
> End If
> On Error GoTo 0
> WScript.Echo
>
> WScript.Echo "A string containing a call to a function returning a non
> stringifiable value works:"
> Set vRes = Eval( "CreateObject(""Scripting.Dictionary"")" )
> WScript.Echo TypeName( vRes )
>
> output:
>
> A string works:
> Sin( 1 ) => 0,841470984807897
>
> A function seems to work, if the return value can be stringified:
> Sin( 1 ) => 0,841470984807897
>
> A function returning a non stringifiable value does not work:
> 450 Falsche Anzahl an Argumenten oder ung�ltige Eigenschaftszuweisung
>
> A string containing a call to a function returning a non stringifiable
> value works:
> Dictionary
>
>>> You could use InputBox here to fill sExpr.
>>
>> Ah. That's something I hadn't thought of. I can
>> see how that could *maybe* be useful as
>> an alternative to parsing the string. But I doubt
>> I would ever do that because it would prevent
>> me from error-checking the string. That would
>> be like a function that accepts an email address
>> or phone number but doesn't check that the entry
>> is valid. Eval would be easier, of course, but
>> far more error-prone than parsing the string to
>> check for valid content.
>>
>
> Why feeding a string to Eval would prevent you from checking
> it for syntactical correctness is beyond me. Your examples
> (simple strings that *are* their values and need not to be
> evaluated at all) again miss the point. Eval *computes* the
> value of the passed expression using - if necessary - the entire
> VBScript interpreter and all the functions in your script.