Function objects

From Avisynth wiki
Revision as of 09:43, 11 February 2021 by Pinterf (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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. </div>

Personal tools