Function objects
Contents |
Function object basics
Concept of function objects was introduced in Avisynth Neo and was backported to Avisynth+ (avaliable from v3.6). Function object is a new variable type. Once declared, they can be assigned to a variable, and use as function arguments. Internal functions can be casted to function objects, helpes a cleaner syntax for some existing internal function (e.g. ScriptClip).
A user defined function or an external plugin can even take such type as an argument in the parameter list.
Basic example
a = function(int x, int y) { return x + y } MessageClip(String(a)) #Function b = a MessageClip(String(b)) #Function MessageClip(String(a == b)) # true
Take as an argument
function MyFunc(func f) { return f(2, 3) } a = MyFunc(function(x, y) { return x + y }) MessageClip(String(a)) # 5
return as a return value
function MyFunc() { return function(x, y) { return x + y } } a = MyFunc()(2, 3) MessageClip(String(a)) # 5
Capture the variable at that point with '[]' before the formal argument
Capture example
function MyFunc() { x = 2 y = 3 return function[x, y]() { return x + y } } a = MyFunc()() MessageClip(String(a)) # 5
Specification details
Function objects are functions defined with the new syntax.
function [] () {...}
It looks like an unnamed function compared to the usual function definitions so far. '[]' Does not have to be optional.
Functions defined in the normal function format are not function objects (for compatibility).
function MyFunc() {return 123} a = MyFunc MessageClip(String(a)) # 123 (Not Function)
Similarly, built-in functions and plug-in functions are not function objects.
a = Invert # Error: I don't know what 'Invert' means.
Functions that are not function objects can be made into function objects by using the func function.
a = func(Invert) Version().a() # Invert a clip
A new 'func' has been added to the value type.
function MyFunc(func x, func y, int z) { return x () + y () + z } a = MyFunc(function(){1}, function(){2}, 3) MessageClip(String(a)) # 6 (= 1 + 2 + 3)
The IsFunction function that determines the function object has been added.
a = function() {} MessageClip(String(IsFunction(a))) # true
Compare with GRunT
Let's compare function objects with GRunT, a plugin that makes ScriptClip easier to write.
The following code on the GRunT introduction page
function bracket_luma(clip c, float th1, float th2) { Assert (0 <= th1 && th1 <th2 && th2 <= 255, "Invalid thresholds!") ScriptClip (c, "" " avl = AverageLuma () avl <= th1? Last.BlankClip (): avl> = th2? last.BlankClip (color = color_white): last "" ", args =" th1, th2 ", local = true) }
It is a sample to appeal the goodness of GRunT, but with Neo it can be written as follows.
function bracket_luma(clip c, float th1, float th2) { Assert (0 <= th1 && th1 <th2 && th2 <= 255, "Invalid thresholds!") ScriptClip(c, function [th1, th2] () { avl = AverageLuma() avl <= th1? Last.BlankClip() : avl> = th2? last.BlankClip(color = color_white) : last }) }
There are the following differences compared to GRunT.
- There is no need to pass the processing content as a character string - Variables to be used can be written in a special syntax, so the amount of description is reduced.
Supports 'function' type of input of built-in functions
A version that can pass the function has been added to the function that passed the processing content as a script string.
ScriptClip
ScriptClip(clip clip, func filter [, bool show, bool after_frame])
Example 1
Version() ScriptClip (function [] (clip c) { c.Subtitle(String(current_frame)) })
Example 2: Comparison with string input
ScriptClip with text script input
SSS2=""" p=(current_frame)*pow(framecount(last)-1,-1)*100 q=ceil(0.0625*((framecount(last))-(current_frame+1))) Subtitle(String(q,"%.0f")+String(" - ")+String(p,"%.2f")+String("% - ")+String(current_frame,"%.0f")) """ clip1 = Input.Scriptclip(SSS2,After_Frame=True)
With function object (declared inline)
clip1 = Input.Scriptclip(function[](clip c) { p=(current_frame)*pow(framecount(last)-1,-1)*100 \ q=ceil(0.0625*((framecount(last))-(current_frame+1))) \ Subtitle(String(q,"%.0f")+String(" - ")+String(p,"%.2f")+String("% - ")+String(current_frame,"%.0f")) \ }, After_Frame=True)
ConditionalFilter
ConditionalFilter(clip testclip, clip source1, clip source2, func condition [, bool show])
Example
a = Version() b = a.Invert() ConditionalFilter(a, a, b, function [] (clip c) { current_frame<30 # if true return a else b })
ConditionalSelect
ConditionalSelect(clip testclip, func get_index, clip source0 [, clip source1 ...] [, bool show])
Example
Version () ConditionalSelect(function [] (clip c) { current_frame / 100 }, subtitle("0"), subtitle("1"), subtitle("2"))
WriteFile system
- WriteFile(clip clip, string filename, func expression1 [, func expression2 [, ...]] [, bool append, bool flush])
- WriteFileIf(clip clip, string filename, func expression1 [, func expression2 [, ...]] [, bool append, bool flush])
- WriteFileStart (clip clip, string filename, func expression1 [, func expression2 [, ...]] [, bool append])
- WriteFileEnd (clip clip, string filename, func expression1 [, func expression2 [, ...]] [, bool append])
Example
Version().ConvertToY() WriteFile("out.txt", function() { string(current_frame) + ":" + string(YPlaneMedian()) })
Back to AviSynth Syntax.