Log in

View Full Version : Discrepancy between Defined()'s documentation and its behaviour with variables


fvisagie
12th July 2014, 14:48
The Defined() documentation (http://avisynth.nl/index.php/Internal_functions/Boolean_functions) indicates that it returns true or false for both function arguments and variables. When given the name of a defined variable it does return true, but an undeclared variable name causes the script to fail. Is this a bug or a documentation error?

false with function argument
function testfunc (int "testvar") {
return Defined(testvar) ? true : false
}
MessageClip(String(testfunc()))

true with defined variable
function testfunc () {
testvar = 0
return Defined(testvar) ? true : false
}
MessageClip(String(testfunc()))

Script error with undefined variable
function testfunc () {
#~ testvar = 0
return Defined(testvar) ? true : false
}
MessageClip(String(testfunc()))
I don't know what "testvar" means
(New File (2), line 3)
(New File (2), line 5)

Gavino
12th July 2014, 16:01
Script error with undefined variable
function testfunc () {
#~ testvar = 0
return Defined(testvar) ? true : false
}
MessageClip(String(testfunc()))
Here, testvar is not an 'undefined' variable (ie a variable with a value of 'undefined') - it simply does not exist.

Defined(), like all Avisynth functions, works on values, not variables.
As the documentation (http://avisynth.nl/index.php/Internal_functions/Boolean_functions) says, "the function returns false if its argument (normally a function argument or variable) has the void ('undefined') type, otherwise it returns true". See also the decription of the void or 'undefined' type here (http://avisynth.nl/index.php/Script_variables).

fvisagie
12th July 2014, 16:24
Thanks, Gavino. I'm reminded now of what stickboy does in his Undefined() function (which is built-in from 2.6.0).

StainlessS
13th July 2014, 09:09
RT_VarExist().
RT_Undefined() {useful on 2.58}
Also RT_FunctionExist() might be useful, plugins only (dont know how to do it for script functions although a dummy call might work).

EDIT: Eg,


myName="SC_SceneSelect: "
Assert(RT_FunctionExist("GScriptClip"),myName+"Essential GRunT plugin installed, http://forum.doom9.org/showthread.php?t=139337")


EDIT: So far as I'm aware, there is no way to tell if a variable is Global or Local from within a plugin, you can set either
Local or Global variables but only inquire if a variable exists, where Local is checked first and if fails then searches for a Global variable.
EDIT: Although using both PushContext and PopContext, you might be able to inquire directly the Global status.

fvisagie
14th July 2014, 09:40
This is what StickBoy did:
# JDL_FunctionDefined
#
# Determines whether a function is defined.
#
# PARAMETERS:
# functionName : The name of the function.
# Can be the name of a built-in function, a plug-in
# function, or a user-defined function.
# "err_msg" : If specified, JDL_FunctionDefined will throw an
# exception with that error message if the function is
# not defined.
# If not specified, JDL_FunctionDefined will return true
# if the function is defined, false otherwise.
#
# USAGE:
# # JDL_FunctionDefined can be used to check for script dependencies. If
# # a script requires a plug-in or function that isn't found, you can
# # present a meaningful error message explaining where to download the
# # necessary files.
# #
# JDL_FunctionDefined("Trim2",
# \ "This script requires Trim2. Download it from ...")
#
function JDL_FunctionDefined(string functionName, string "err_msg")
{
try
{
Eval(functionName + "()")

# If we made it this far, we called the function without any
# problem; therefore it exists.
return true
}
catch (s)
{
# Dependent on AviSynth generating an exception with the message:
# "Script error: there is no function named ..."
# Basic idea from mf.
isDefined = FindStr(s, "there is no function named "
\ + Quote() + functionName + Quote())
\ == 0

Assert(isDefined || !Defined(err_msg), err_msg)
return isDefined
}
}


The dummy call you referred to.

StainlessS
14th July 2014, 12:12
Yes, about the same as I was suggesting(but as a plugin).

foxyshadis
14th July 2014, 22:49
RT_VarExist().
RT_Undefined() {useful on 2.58}
Also RT_FunctionExist() might be useful, plugins only (dont know how to do it for script functions although a dummy call might work).

EDIT: Eg,


myName="SC_SceneSelect: "
Assert(RT_FunctionExist("GScriptClip"),myName+"Essential GRunT plugin installed, http://forum.doom9.org/showthread.php?t=139337")


EDIT: So far as I'm aware, there is no way to tell if a variable is Global or Local from within a plugin, you can set either
Local or Global variables but only inquire if a variable exists, where Local is checked first and if fails then searches for a Global variable.
EDIT: Although using both PushContext and PopContext, you might be able to inquire directly the Global status.

There's one direct way: Edit avisynth.h to add the first few private members of ScriptEnvironment to IScriptEnvironment as public (along with defining all of the new classes that brings in), then access var_table and global_var_table. It will only work for specific versions of Avisynth, and everyone will hate you, but it works!

The indirect is much more likely to actually keep working, though.

StainlessS
16th July 2014, 09:28
Dont temp me foxyshadis, I'm easily led astray.

and everyone will hate you
Not a problem, I'm used to it.

I might try the indirect route, thank you for your response.