here i defined 2 functions and call the second directly:
$ jq -n 'def f1: "here f1" ; def f2: "here f2"; f2'
"here f2"
can i define a variable and call the function name contained in the value of that variable? for example:
$ jq --arg fp f1 -n 'def f1: "here f1" ; def f2: "here f2"; "fp is \($fp)"'
"fp is f1"
I want to call the function that is defined by the fp variable. so the result would be
"fp is here f1"
can i define a variable and call the function name contained in the value of that variable?
No. You’d have to write a dispatcher.
Related
I want to draw an environment diagram for the following code which contains an error to understand how R works exactly when evaluating a function.
# emphasize text
emph <- function(f, style = '**') {
function(...) {
if (length(style) == 1) {
paste(style, f(...), style)
} else {
paste(style[1], f(...), style[2])
}
}
}
# function to be decorated
tmbg <- function() {
'tmbg are okay'
}
# a decorator function with self-referencing name
tmbg <- emph(tmbg)
I got error while evaluating the call expression of the decorator function
tmbg()
> Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
I could understand this is related to the lazy evaluation of function parameter in R. It feels like when evaluating tmbg() in global frame, the name of f used in the returned anonymous function binds again to tmbg in global frame which again returns the anonymous function and calls f, thus leads to infinite recursive calls. But this image is not so clear to me because I don't exactly know what is the evaluation model used in R especially with this "lazy evaluation".
Below I draw the essential parts of the environment diagrams and explain the evaluation rule used in Python for the equivalent code. I hope to get such environment diagrams for R as well, or at least get the same level of clarity for the environmental model used in R.
# This is the equivalent python code
def emph(f, style = ['**']):
def wrapper(*args):
if len(style) == 1:
return style[0] + f(*args) + style[0]
else:
return style[0] + f(*args) + style[1]
return wrapper
def tmbg():
return 'tmbg are okay'
tmbg = emph(tmbg)
tmbg()
When evaluating the assignment statement at line 12 tmbg = emph(tmbg), the call expression emph(tmbg) needs to be evaluated first. When evaluating the operator of the call expression, its formal parameter f binds to name tmbg in global frame which binds to a function we defined in global frame, as shown in the picture below.
Next, after finishing the evaluation of the call expression emph(tmbg), its returned function wrapper binds to the name tmbg in global frame. However the binding of f and the actual function tmbg is still hold in the local frame created by emph (f1 in the diagram below).
Therefore when evaluating tmbg() in global frame, there won't be any confusion about which is the decorator function (tmbg in global) and which is the function to be decorated (f in local frame). This is the different part compared to R.
It looks like what R does is that it changes the binding from f -> function tmbg() to f -> name tmbg in global frame, which again binds to function wrapper(*args) calling f itself and thus leads to this infinite recursion. But it might also be a completely different model that R does not really bind f to any object but a name tmbg and ignores what that name represents. When it starts to evaluate, it looks for name tmbg and it finds the global one which is created by tmbg <- emph(tmbg) and gets infinite recursion. But this sounds really weird as the local scope created by the function call does not count anymore (or partially counts) for the purpose of "lazy evaluation" as soon as we pass an expression as argument of that function. There has to be then a system running parallelly other than the environments created by the function calls managing the namespaces and the scopes.
In either case, it is not clear to me the environmental model and evaluation rule R. I want to be clear on these and draw an environment diagram for the R code as clear as the one below if possible.
The problem is not understanding environments. The problem is understanding lazy evaluation.
Due to lazy evaluation f is just a promise which is not evaluated until the anonymous function is run and by that time tmbg has been redefined. To force f to be evaluated when emph is run add the marked ### force statement to force it. No other lines are changed.
In terms of environments the anonymous function gets f from emph and in emph f is a promise which is not looked up in the caller until the anonymous function is run unless we add the force statement.
emph <- function(f, style = '**') {
force(f) ###
function(...) {
if (length(style) == 1) {
paste(style, f(...), style)
} else {
paste(style[1], f(...), style[2])
}
}
}
# function to be decorated
tmbg <- function() {
'tmbg are okay'
}
# a decorator function with self-referencing name
tmbg <- emph(tmbg)
tmbg()
## [1] "** tmbg are okay **"
We can look at the promise using the pryr package.
library(pryr)
emph <- function(f, style = '**') {
str(promise_info(f))
force(f)
cat("--\n")
str(promise_info(f))
function(...) {
if (length(style) == 1) {
paste(style, f(...), style)
} else {
paste(style[1], f(...), style[2])
}
}
}
# function to be decorated
tmbg <- function() {
'tmbg are okay'
}
tmbg <- emph(tmbg)
which results in this output that shows that f is at first unevaluated but after force is invoked it contains the value of f. Had we not used force the anonymous function would have accessed f in the state shown in the first promise_info() output so all it would know is a symbol tmbg and where to look for it (Global Environment).
List of 4
$ code : symbol tmbg
$ env :<environment: R_GlobalEnv>
$ evaled: logi FALSE
$ value : NULL
--
List of 4
$ code : symbol tmbg
$ env : NULL
$ evaled: logi TRUE
$ value :function ()
..- attr(*, "srcref")= 'srcref' int [1:8] 1 13 3 5 13 5 1 3
.. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x00000000102c3730>
I originally wrote my jq command as
.data.viewer.zones[] | .httpRequests1mGroups[0].sum|with_entries(select(.key|endswith("Map")|not)) + {"zoneTag": .zoneTag}
and got this result:
{
"bytes": 2875120330,
"cachedBytes": 1475518778,
"zoneTag": null
}
{
"bytes": 2875120330,
"cachedBytes": 1475518778,
"zoneTag": null
}
zoneTag is the last attribute in a zones object.
I rewrote the command as
.data.viewer.zones[] | {"zoneTag": .zoneTag} + .httpRequests1mGroups[0].sum|with_entries(select(.key|endswith("Map")|not))
and get what I expected:
{
"zoneTag": "zone 1",
"bytes": 2875120330,
"cachedBytes": 1475518778,
}
{
"zoneTag": "zone 2",
"bytes": 2875120330,
"cachedBytes": 1475518778,
}
My question is why? Is + eager? (I get the same results using *.)
Thanks.
So maybe you're looking for an explanation in terms of operator precedence.
Let:
A represent .data.viewer.zones[]
B represent .httpRequests1mGroups[0].sum
C represent with_entries(select(.key|endswith("Map")|not))
Then your first jq expression is equivalent to
A | B | C + {zoneTag}
whereas your second is equivalent to:
A | {zoneTag} + B | C
So in the first case, {zoneTag} gets its value from B but in the
second case, it comes from A.
In jq, for most purposes, including that of object addition, an explicit null value in the object on the right is not the same as the absence of a key.
Thus if A is {"a": 1} then A + {} is A but A + {"a": null} is {"a": null}.
Thus the "right-most value" rule must be understood to mean "right-most explicit value".
Whether any of this has to do with "eagerness" depends on your understanding of that term.
Non-lazy evaluation
In jq, object addition (and indeed addition in general) proceeds from right to left and is of course non-lazy, as can be seen in the following example, which also illustrates the RHS-dominance mentioned above.
jq -n '{a:(1|debug)} + {b: (2|debug)} + {a:(3|debug)}'
["DEBUG:",3]
["DEBUG:",2]
["DEBUG:",1]
{
"a": 3,
"b": 2
}
So far as I know, though, the right-associativity might not be guaranteed.
I need to auto-complete two parameters of a function, where the second parameter depends on the first one.
An example: the first parameter of a function "foo" can have values of "a" or "b". The second parameter can have values "10" or "11" in case the first parameter is "a", and "20" and "21" in case the first parameter is "b". So the following combinations of the parameters are legal:
foo a 10
foo a 11
foo b 20
foo b 21
The combinations are known upfront (they can be hardcoded).
The zsh completion system doc is quite obscure and the great How To didn't solve my problem neither. The closest would be to use _arguments, possibly with state action, but I didn't manage to make it work.
_arguments would make sense if you've got options mixed in with the arguments that you've described. Otherwise, just look in the $words array for the previous word - something like:
if (( CURRENT == 1 )); then
_wanted letters expl letter compadd a b
else
case $words[1] in
a) numbers=( 10 11 ) ;;
b) numbers=( 20 21 ) ;;
esac
_wanted numbers expl number compadd -a numbers
fi
I solved my case with the following:
IFS='
'
local -a options
_arguments "1:first:->first" "*:next:->next"
case "$state" in
first)
for o in $(_command_to_autocomplete_first); do
options+=("$o")
done
_describe 'values' options
;;
next)
for o in $(_command_to_complete_others $words[2]); do
options+=("$o")
done
_describe 'values' options
;;
esac
I am currently writing a short program to print the global macro variables of the current Stata session.
I cannot understand the outcome of the following piece of code:
macro drop _all
global glob0: all globals
cap program drop print_globals
program define print_globals
args start_globs
di "$glob0"
di "`start_globs'"
end
print_globals $glob0
The outcome of this is:
S_level S_ADO S_StataMP S_StataSE S_FLAVOR S_OS S_OSDTL S_MACH
S_level
Why am I not passing to start globs the entire information contained in glob0?
Your args statement assigns only the first argument supplied to the program to a local macro; if there are other arguments they are ignored.
The essence of the matter is whether double quotes are used to bind what is supplied into one argument.
Whether you supply an argument as a global or a local is immaterial: globals and locals mentioned on the command line are evaluated before the program even runs and are not seen as such; only their contents are passed to the program.
Define this simpler program and run through the possibilities:
program showfirstarg
args first
di "`first'"
end
global G "A B C D E"
local L "A B C D E"
showfirstarg $G
showfirstarg "$G"
showfirstarg `L'
showfirstarg "`L'"
Results in turn:
. showfirstarg $G
A
. showfirstarg "$G"
A B C D E
. showfirstarg `L'
A
. showfirstarg "`L'"
A B C D E
In order to print the content of the program argument as intended, one must use compound quotes:
print_globals `" ${glob0} "'
and not print_globals ${glob0}.
To see this, consider the following example:
local A "a b c d e"
global B "a b c d e"
cap program drop print_prog
program define print_prog
args loc_input
di "print global: $B"
di "print local: `loc_input'"
end
print_prog `A'
print_prog `" `A' "' // prints both A and B as initially intended
The confusion here is given by the fact that B is printed as intended without having to use compound quotes, whereas the same does not apply for the local macro A when it's passed as argument to the program.
In fact, as highligted in the comments below, in the latter case only the first element is passed as program argument (a in the example).
By using compound quotes we supply a b c d e as a single argument and the final result is the one wanted.
I'm trying to figure out how to have a quote block, when evaluated, return a symbol. See the example below.
function func(symbol::Symbol)
quote
z = $symbol
symbol
end
end
a = 1
eval(func(:a)) #this returns :symbol. I would like it to return :a
z
The symbol your function returned where the symbol function, due to the last symbol in your qoute did not have $ in front. The second problem is you would like to return the symbol it self, which requires you make a quote inside the quote similar to this question
Julia: How do I create a macro that returns its argument?
function func(s::Symbol)
quote
z = $s
$(Expr(:quote, s)) # This creates an expresion inside the quote
end
end
a = 1
eval(func(:a)) #this returns :a
z