Log in

View Full Version : Multiple statements on a single line


fvisagie
26th March 2013, 09:13
This is probably old hat to the old-timers here, but I stumbled across something quite exciting. Avisynth does support multiple statements on a single line, in contradiction to Multiple Avisynth statements on a single line can only be achieved in the context of OOP notation or embedding filters as parameters of another function (http://avisynth.org/mediawiki/Grammar).

This seems to be supported for normal statements, by Eval() etc. and opens up a whole new world (for me at least ;)) of things like simple conditional block statements. This is with 2.6.0, I haven't tested with earlier versions.

Here's an example of a trivial function returning multiple values

#-------------------------------------------
# ColourCoefficients 1.0.0
# Generates specified colour matrix coefficient values
#
# Useful when
#
# Doing YUV<->RGB colourspace calculations or conversions
# Doing colour coefficient calculations or conversions
#
# ColourCoefficients(string "matrix")
#
# <matrix> Colour coefficient matrix which to generate coefficients for - "Rec601" / "Rec709" / "FCC", default "Rec601"
#
# Usage
#
# coeffs = ColourCoefficients("Rec709") # ColourCoefficients returns a multi-statement string with matrix coefficient value assignments
# Eval(coeffs) # This defines Kr containing Red channel coefficient, Kg with Green channel coefficient and Kb for Blue channel
# y = Kr*r + Kg*g + Kb*b
# ...
#
# References
#
# http://avisynth.org/mediawiki/Color_conversions
#
# Version history
#
# 1.0.0 Francois Visagie
#

function ColourCoefficients(string "matrix") {
matrix = Default(matrix, "Rec601")
matrixnum = (matrix == "Rec601") ? 0 : \
(matrix == "Rec709") ? 1 : \
(matrix == "FCC" ) ? 2 : 3
Assert(matrixnum < 3, """'matrix' value """" + matrix + """" is invalid""")
# Channel coefficients Rec.601 Rec.709 FCC
Kr = Select(matrixnum, 0.299, 0.2125, 0.3 )
Kg = Select(matrixnum, 0.587, 0.7154, 0.59)
Kb = Select(matrixnum, 0.114, 0.0721, 0.11)
return("Kr=" + string(Kr) + " Kg=" + string(Kg) + " Kb=" + string(Kb))
}

To what extent has anyone else played with this, and what gotchas have been discovered so far?

Gavino
26th March 2013, 12:09
Yes, that's right.
Newline (unless accompanied by a '\') always terminates the current statement, but it is not strictly necessary.
The Avisynth parser recognises it has reached the end of a statement when the next symbol is not a valid continuation of what it already has. So
x = 1 y = 2 z = 3
is parsed as three separate (assignment) statements.

Although it is conventional to use newlines to separate statements (and good practice for readability), the syntax is such that it is only strictly necessary if the following statement starts with a unary minus (or plus) operator - not very common, but can occur in cases like (silly example!):
function f(int x, int y) {
z = x + y
- z # meaning return -z
}
Here '- z' must appear on a separate line, since the previous statement could validly be continued with a '-'.

fvisagie
26th March 2013, 13:55
Thanks for the explanation, Gavino.

TheFluff
26th March 2013, 18:32
You could just have put newlines in the returned string, you know. There are also several better ways to "return" multiple values from a function. Using a callback function immediately comes to mind, but I'd say even global variables is cleaner than this solution.

fvisagie
27th March 2013, 08:36
You could just have put newlines in the returned string, you know.

I also thought so, but in this case I've found no way of writing the multi-line return string in a natural way that doesn't cause Eval() to fail. I've tried with literal "\n", variables by that value, triple quotes etc.

The only other syntax I found that works is return("Kr=" + string(Kr) + Chr(10) + "Kg=" + string(Kg) + Chr(10) + "Kb=" + string(Kb))
# or Chr(13)although that defeats the purpose even further, so to speak.

fvisagie
27th March 2013, 09:25
Using a callback function immediately comes to mind

How is this done in Avisynth (without using globals)?

StainlessS
27th March 2013, 09:26
I see nothing wrong with either space or Chr(10) string concatenation on a 'once in a while' usage, eg
clipwise return string, but not too good an idea on framewise or pixelwise usage, mainly due to fact that
there is no dead string garbage collection and freeing of memory.
The Gavino noted ' - z' thing would not come into it.

EDIT:
How is this done in Avisynth (without using globals)?

No Idea (In script).

Gavino
27th March 2013, 10:40
I've found no way of writing the multi-line return string in a natural way
You can use newlines directly inside a string literal, eg
multiline = "first line
second line"

TheFluff
27th March 2013, 10:45
How is this done in Avisynth (without using globals)?


function foo(int x, string callback_name) {
apply(callback_name, x)
}

function bar(int z) {
# do something with z
}

y = 5
foo(y, 'bar')

fvisagie
9th April 2013, 10:19
things like simple conditional block statements

For the record, it seems this is a bit of a moot point (as you guys probably knew all along ;)). As far as I can determine the only expressions accepted by the ternary operator are function calls, be it internal, plugin or script functions. It does not seem to accept assignment statements, unless wrapped in Eval(), which kind of defeats the purpose from this point of view ;).

StainlessS
9th April 2013, 11:56
x = (z == true) ? Q * 17 : Q * 21 # assignment

(z == false) ? Do_somthing(q) : Do_something_else(q) # select one of two funcs

(z == true) ? Do_anything(q) : Nop # conditional do something

Gavino
9th April 2013, 14:17
As far as I can determine the only expressions accepted by the ternary operator are function calls, be it internal, plugin or script functions. It does not seem to accept assignment statements...
From http://avisynth.org/mediawiki/Grammar:
All basic AviSynth scripting statements have one of these forms:
1. variable_name = expression
2. expression
3. return expression
...
An expression can have one of these forms:
1. numeric_constant, string_constant or boolean_constant
2. variable_name or clip_property
3. Function(args)
4. expression.Function(args)
5. expression1 operator expression2
6. bool_expression ? expression1 : expression2
The expressions accepted by the ternary operator (ie in expression form 6) are any of the forms 1-6, so are not limited to function calls (forms 3 and 4).
However, an assignment is not an expression, so can appear only at the start of a statement (statement form 1).

fvisagie
9th April 2013, 14:46
Thanks, guys. Now to read and apply documentation as attentively as you do... ;)

ChiDragon
23rd January 2014, 01:37
Avisynth does support multiple statements on a single line, in contradiction to Multiple Avisynth statements on a single line can only be achieved in the context of OOP notation or embedding filters as parameters of another function (http://avisynth.org/mediawiki/Grammar).

Could someone who understands this issue in-depth update the Wiki to be more accurate? I was recently led astray.

I would change the line myself but I don't want to make it wrong in a different way...