The same piece of demo script is submitted for 4 separately reported bugs.
Within a function block, ARGC behaves as you would intuitively expect .. returning the number of arguments passed.
ARG0 returns the filename of the script rather than the name given to the function block.
ARG1 .. ARG9 cannot be used to access string representations of ARGV[1] .. ARGV[9]
Again, consider this more of a feature request than a bug.
It would be desirable that the usage of these special variables be the same as for the CALL command.
## Some bugs related to function blocks and/or data blocks
## (gnuplot v6 rc1 on Windows 11)
##
## Given that function blocks are still experiemental I hesitate to call these "bugs" however,
## they are definitely not intuitive/expeceted behaviour.
## To experience each bug uncomment that/those script line(s) that has/have just a single hash '#'.
##
##(1) using the backslash "\" to break a (very long) plot command across multiple lines (within a function block) throws an error: "invalid character \"
##(2) datablock definition within an if or else compound statement throws error: "attempt to define data block from invalid context"
##(3) "function block" usage of the special string variables, ARGC, ARG0, ARG1..ARG9 is not consistent with "call" usage
##(3a) cannot access ARGV[1] as the string, ARG1;
##(3b) cannot access function block name as ARG0; (script filename is returned instead)
##(3c) ... but _can_ access argument count for function block as ARGC
##(4) inline data "plot '-'" may not be used within a function block (somewhat akin to the ban on defining a data block within a function block)
##
function $myPlot(strSource,strFont) << _EOFD
set title strSource." - variable color and orientation in plotstyle 'with labels'" offset 0,-2
## within a function block, a backslash throws the error: "invalid character \" .. but not within main script block
#plot @strSource \
# using 1:1:2:3:0 \
# with labels rotate variable tc variable font @strFont
plot @strSource using 1:1:2:3:0 with labels rotate variable tc variable font @strFont
## ARG0 returns script filename (not function block name) .. but ARGC correctly returns a count of arguments passed to function
##return sprintf("function, %s, completed; with %d arguments", "$myPlot", ARGC)
return sprintf("function, %s, completed; with %d arguments", ARG0, ARGC)
_EOFD
function $myInlinePlot << _EOFD
local ARG0 = "$myInlinePlot" # hack
set title "function block INLINE - variable color and orientation in plotstyle 'with labels'" offset 0,-2
## within a function block, attempting to use inline data as the data source causes script execution to hang without any error message
## ... Ctrl+C will not terminate script execution from this point
## ... the only remedy I have found is to locate the hung gnuplot.exe process and terminate it
plot '-' using 1:1:2:3:0 with labels rotate variable tc variable font ",8"
1 one -30
2 two -60
3 three -90
4 four -120
5 five -150
6 six -180
7 seven -210
8 eight -240
9 nine -270
10 ten -300
11 eleven -330
12 twelve -360
EOD
## it seems that inline data may not be used within a function block
## (somewhat akin to the ban on defining a data block within a function block)
## however, the script hangs without any error message
return sprintf("function, %s, completed; with %d arguments", ARG0, ARGC)
_EOFD
##
## Additional data columns can be used to hold text rotation or color
## for plot style "with labels"
##
debug = 1
#if (debug) { ## defining a datablock inside an if/else throws: "attempt to define data block from invalid context"
$Data1 <<EOD
1 one -30
2 two -60
3 three -90
4 four -120
5 five -150
6 six -180
7 seven -210
8 eight -240
9 nine -270
10 ten -300
11 eleven -330
12 twelve -360
EOD
## leading whitespace before the above EOD _does_ throw an error: "no datablock named $Data2"
## ... fair enough since $Data1 definition never correctly ends if EOD not found at start of line.
# }
#else {
$Data2 <<EOD
1 one -30
2 two -60
3 three -90
4 four -120
5 five -150
6 six -180
7 seven -210
8 eight -240
9 nine -270
10 ten -300
11 eleven -330
12 twelve -360
EOD
# }
$Data3 <<EOD
1 one -30
2 two -60
3 three -90
4 four -120
5 five -150
6 six -180
7 seven -210
8 eight -240
9 nine -270
10 ten -300
11 eleven -330
12 twelve -360
EOD
set angle degrees
unset key
set title "variable color and orientation in plotstyle 'with labels'" offset 0,-2
set xrange [0:13]
set yrange [0:13]
set xtics 1,1,12 nomirror
set ytics 1,1,12 nomirror
set border 3
stringFont = "\"Times,10\"" ## exercising care to escape double quotes is necessary (and appropriate)
##plot $Data3 using 1:1:2:3:0 with labels rotate variable tc variable font ",20"
## no error from using backslash to break the above plot command over multiple lines
plot $Data3 \
using 1:1:2:3:0 \
with labels rotate variable tc variable font @stringFont
pause mouse close
printerr $myPlot("$Data1","\"Times,12\"")
pause mouse close
printerr $myPlot("$Data2","\"Times,16\"")
pause mouse close
printerr $myPlot("$Data3","\"Times,20\"")
pause mouse close
set title "INLINE - variable color and orientation in plotstyle 'with labels'" offset 0,-2
plot '-' using 1:1:2:3:0 with labels rotate variable tc variable font ",24"
1 one -30
2 two -60
3 three -90
4 four -120
5 five -150
6 six -180
7 seven -210
8 eight -240
9 nine -270
10 ten -300
11 eleven -330
12 twelve -360
EOD
# EOD
## leading whitespace before EOD, above, does not _seem_ to matter however,
## for the inline data example within a function block this leading whitspace was avoided just to remove any possible doubt
pause mouse close
## to demonstrate bug (4) (and this script hanging without any error message) uncomment the following function call
#printerr $myInlinePlot()
#pause mouse close
Function blocks are documented to use the convention
It is true that the
callmechanism supports both ARGV[] as an array and the older ARGV1, ARGV2, .... convention. To implement the older convention for function blocks would add substantial overhead to every function block call, since those variables would have to be individually converted-to-string, stored, restored, shadowed, etc. I see no gain to balance the penalty in overhead, not to mention the loss of precision in converting all parameters to strings.I grant that ARGV0 could be considered a special case since there is no array element ARGV[0]. The name of the function block is known internally and used in printing error messages. But why would the user ever need to access it in a round-about fashion from inside the block? The name of the block is part of its definition, so if you want print it or pass it to another routine you can do so explicitly. Am I missing a use case where having the name stored in a fixed-name variable would be advantageous?
Yes, of the 10 string variables, ARG0 is definitely the most valuable and the common use case is Error handling. viz.
I do agree that it is a trivial enough burden for a user to make the very first line of the function block a string assignment:
local ARG0 = "$myfunction"and then pretend that the interpreter did this when using ARG0 in any error handling code.
Without meaning to sound persnickety and wrt the gnuplot manual:
ARGCis not explicitly documented for the Function Block.ARGCis casually used in a script example however, the equally casual reference to "a call command" (see below) might just as implicitly suggest thatARG0, ..,ARG9are also features of Function Block .. i.e. just asARGCevidently is.I reckon the least ambiguous remedy would be to make it clear in the manual section for Function Blocks that
ARG0..ARG9are not available whileARGCis available.Having said all that, please do consider making
ARG0(but notARG1..ARG9) available!Cheers!
Sure. Thanks for the comment on documentation. Getting feedback on unclear documentation is rare; people suffer in silence.
As for your example of use for ARG0, doesn't the program itself already generate exactly that error information? I grant you that it doesn't say anything if there are too many arguments rather than too few. Do you think it should?
Ah, yes! ... you see I start with the assumption that the function block may receive a variable number of arguments.
See my example above wherein 4 arguments are expected but 6 arguments are accommodated. Those optional arguments are for special cases. In this situation it is for when the dataset is VERY large and so individual data point labels are not meaningful or the dataset size is so large that output to a GUI terminal (e.g. qt) causes an "insufficient resources" error.
So because I do not pre-define the expected variables (as you have done using parentheses above) I rely on error handling written by me to tell me when I've supplied too few or too many arguments.
If a desirable/intended use case of the gnuplot function block feature is to generate a plot based on some set of parameters passed to it (thereby avoiding repetitive scripting) then a reasonable return string might also benefit from the use of
ARG0as follows.Such output to stderror is especially helpful when time consuming plots are running and monitoring of progress is desirable.
Still on-topic viz-a-viz
ARG0use cases ... in another situation I have used (either within a function block or within the main script block) ...when handling an error. This tends to be helpful during development while I am still unfamiliar with the way gnuplot will handle my scripting.
I'm reasonably sure that if I can rattle off three use cases then other users could quickly do the same with only a little repetition.
ARG0visibility) is effectively asking the gnuplot team to blur the line between a specialized plotting tool and a generalized coding tool. It is truly little effort on the (fussy!) script-writer's part to explicitly defineARG0within a function block.Prioritizing clarity in the manual section is "lower hanging fruit" than burdening the interpreter code with extra string manipulation.
I added the ARG0 code and benchmarked it. The additional overhead from creating and shadowing a new variable on every call to a functionblock added 5% to the runtime of the test case in function_block.dem. Shadowing ARG0...ARG9 would thus impose a hit of up to 50% in runtime. I just can't see the cost being worth it.
I had originally thought that your concern was converting existing code that used the
callmechanism to new code that used function blocks. Having to change ARGn everywhere to ARGV[n] would have made that slightly more work. As I understand it now, that isn't relevant to your development of new code. You want to have access to the function block name programmatically, but it need not be via a variable named ARG0. Would it be sufficient to provide the name via a new function instead? That way there would be no additional cost unless/until you actually call that function. You example above would become something likeLast edit: Ethan Merritt 2023-09-29
I agree that a 5% hit to runtime is not a reasonable price to pay for something that is so trivial for a motivated script writer to implement with a simple string assignment. Not every script writer expects to access ARG0 for a function block they themselves have named!
The suggestion of a new function is not something I would use ... or remember exists.
Honestly, when the gnuplot manual section for Function Blocks makes it explicitly clear that ARG0 .. ARG9 are not available within a function block then I do not think that anything more need be done.
I had another thought. Maybe there could be a way to safely trigger a warning message. The program already knows how to include the current filename/block name + line number with the message. I will file a feature request for such a command. It might be useful in general, not just from inside a function block.