I need to declare a variable as constant, the variable is generated while the program is running, I tried this way:
foo(var) := declare(''var, constant)$
foo(x)$
facts();
But that doesn't work and I get:
[kind(var, constant)]
everytime.
instead:
[kind(x, constant)]
When I write code without a function, everything works fine:
var: x$
declare(''var, constant)$
facts();
I get:
[kind(x, constant)]
Does anyone know how to do this dynamically via a function?
The conventional way to ensure that arguments are evaluated, even for functions which otherwise quote their arguments, is to apply the function to the arguments. E.g.:
apply (declare, [var, 'constant]);
Or, in a function:
foo(var) := apply (declare, [var, 'constant]);
apply evaluates its arguments, so the arguments are evaluated by the time the function sees them.
The quote-quote ''var doesn't have the expected effect in a function because quote-quote is applied only at the time the expression is parsed. So any later assignment to var has no effect.
I recommend against eval_string. There is almost always a better way to do anything than string processing; in this case that better way is apply.
Related
I have a command with six lines that I want to use several times. Therfore, I want to assign a name to this command and use it as a procedure instead of writing the whole command lines over and over.
In this case it is a <-rbind() command, but the issue is also more general.
modelcoeff<-rbind(modelcoeff,c(as.character((summary(mymodel)$terms[[2]])[[3]]),
as.character((((((summary(mymodel)$terms[[2]])[[2]])[[3]])[[3]])[[2]])[[3]]),
summary(mymodel)$coefficients[2,1],
summary(mymodel)$coefficients[2,4],
summary(mymodel)$coefficients[2,2],
summary(mymodel)$r.squared*100))
I would like to call something like rbindmodelcoeff and execute these command lines. How can I achieve this?
I tried to write a function, but it didn't seem to be the right approach.
A literal wrapping of your code into a function:
rbindmodelcoeff <- function(modelcoeff, mymodel) {
rbind(modelcoeff,
c(as.character((summary(mymodel)$terms[[2]])[[3]]),
as.character((((((summary(mymodel)$terms[[2]])[[2]])[[3]])[[3]])[[2]])[[3]]),
summary(mymodel)$coefficients[2,1],
summary(mymodel)$coefficients[2,4],
summary(mymodel)$coefficients[2,2],
summary(mymodel)$r.squared*100))
}
However, there are a couple changes I recommend:
call summary(mymodel) once, then re-use the results
you are using as.character on some of the objects but not all within the enclosing c(.), so everything is being converted to a character; to see what I mean, try c(as.character(1), 2); we can use a list instead to preserve string-vs-number
rbindmodelcoeff <- function(modelcoeff, mymodel) {
summ <- summary(mymodel)
rbind(modelcoeff,
list(as.character((summ$terms[[2]])[[3]]),
as.character((((((summ$terms[[2]])[[2]])[[3]])[[3]])[[2]])[[3]]),
summ$coefficients[2,1],
summ$coefficients[2,4],
summ$coefficients[2,2],
summ$r.squared*100))
}
But there are still some problems with this. I can't get it to work at the moment since I don't know the model parameters you're using, so as.character((summ$terms[[2]])[[3]]) for me will fail. With that, I'm always hesitant to hard-code so many brackets without a firm understanding of what is being used. It's out of scope for this question (which is being converting your basic code into a function), but you might want to find out how to generalize that portion a bit.
I've created my immutable Tensor_field and a function nabla that acts on the tensor (that is nabla(a::Tensor_field) = do something.
I've added a method to function dot for the tensor: Base.dot(a::Tensor_field, b::Tensor_field) = do something....
Now I want to define a new behavior to function dot with nabla as an argument.
Something like Base.dot(nabla::function, a::Tensor_field) = do something different.
I know in Julia we are able to pass functions as arguments to other functions, but I couldn't find in the docs how to define a method for a "functional" argument.
If I type typeof(nabla) the output is My_Module_Name.#nabla, not a real DataType...
If you want it to work for any function, you can do
Base.dot(f::Function, a::Tensor_field) = do something different
If you only want it to work for the nabla function already defined, you can take advantage of what you have discovered, namely that each function has a unique type:
Base.dot(f::typeof(nabla), a::Tensor_field) = do something different
This will match only the function called nabla, which will now be called f inside the function dot.
Note that you can write ∇ as \nabla<TAB> and use it in your code instead of the word nabla. If your tensor field is called e.g. 𝐯 (written as \mbfv<TAB>), you can then write ∇⋅𝐯 in your Julia code! (The centered dot is written as \cdot<TAB>, and is an alias for the dot function.)
I have a function:
func <- function (x)
{
arguments <- match.call()
return(arguments)
}
1) If I call my function with specifying argument in the call:
func("value")
I get:
func(x = "value")
2) If I call my function by passing a variable:
my_variable <-"value"
func(my_variable)
I get:
func(x = my_variable)
Why is the first and the second result different?
Can I somehow get in the second call "func(x = "value")"?
I'm thinking my problem is that the Environment inside a function simply doesn't contain values if they were passed by variables. The Environment contains only names of variables for further lookup. Is there a way to follow such reference and get value from inside a function?
In R, when you pass my_variable as formal argument x into a function, the value of my_variable will only be retrieved when the function tries to read x (if it does not use x, my_variable will not be read at all). The same applies when you pass more complicated arguments, such as func(x = compute_my_variable()) -- the call to compute_my_variable will take place when func tries to read x (this is referred to as lazy evaluation).
Given lazy evaluation, what you are trying to do is not well defined because of side effects - in which order would you like to evaluate the arguments? Which arguments would you like to evaluate at all? (note a function can just take an expression for its argument using substitute, but not evaluate it). As a side effect, compute_my_variable could modify something that would impact the result of another argument of func. This can happen even when you only passed variables and constants as arguments (function func could modify some of the variables that will be later read, or even reading a variable such as my_variable could trigger code that would modify some of the variables that will be read later, e.g. with active bindings or delayed assignment).
So, if all you want to do is to log how a function was called, you can use sys.call (or match.call but that indeed expands argument names, etc). If you wanted a more complete stacktrace, you can use e.g. traceback(1).
If for some reason you really wanted values of all arguments, say as if they were all read in the order of match.call, which is the order in which they are declared, you can do it using eval (returns them as list):
lapply(as.list(match.call())[-1], eval)
can't you simply
return paste('func(x =', x, ')')
I'm trying to package some code I use for data analysis so that other workers can use it. Currently, I'm stuck trying to write a simple function that imports data from a specific file type generated by a datalogger and trims it for use by other functions. Here's the code:
import<-function(filename,type="campbell",nprobes){
if (filename==TRUE){
if (type=="campbell"){
message("File import type is from Campbell CR1000")
flux.data<<-read.table(filename,sep=",",header=T,skip=1)
flux.data<<-flux.data[,-c(1,2)];flux.data<<-flux.data[-c(1,2),]
if (nprobes=="missing"){
nprobes<-32
}
flux.data<<-flux.data[,c(1:nprobes)]
flux.data.names<<-colnames(flux.data) #Saves column names
}
}
}
Ideally, the result would be a dataframe/matrix flux.data and a concomittant vector/list of the preserved column headers flux.data.names. The code runs and the function executes without errors, but the outputs aren't preserved. I usually use <<- to get around the function enclosure but its not working in this case - any suggestions?
I think the real problem is that I don't quite understand how enclosures work, despite a lot of reading... should I be using environment to assign environments within the function?
User joran answered my question in the comments above:
The critical issue was just in how the function was written: the conditional at the start (if filename==TRUE) was intended to see if filename was specified, and instead was checking to see if it literally equaled TRUE. The result was the conditional never being met, and no function output. Here's what fixed it:
import<-function(filename,type="campbell",nprobes){
if (exists(filename){
if (type=="campbell"){
#etc....
Another cool thing he pointed out was that I didn't need the <<- operator to utilize the function output and instead could write return(flux.data). This is a much more flexible approach, and helped me understand function enclosures a lot better.
I'm not that much of an OOP guy, so could someone please explain this simple concept in layman terms.
When I call foo.child from the foo.parent function, it seems to pass the A=7 argument
down into the foo.child object and overrides or takes precedence over the A=3 default argument in foo.child as I would expect.
foo.parent <- function(A=7) foo.child(A)
foo.child <- function(A=3) 2+A
foo.parent(A=7)
#[1] 9
But when I instantiate it inside of foo.parent, the parameter A=7 does pass down or force the instantiated object to use A=7; instead it uses the child object's parameter of A=3
foo.child<-function(A=3) 2+A
foo.parent <- function(A=7){
foo.child(A=3)
}
foo.parent(A=7)
#[1] 5
Why does that happen? And what terminology would I use to describe the differences?
In your second example you do not give a value to A (At least not in such a way as you might thought). Try
foo.child<-function(A=3) 2+A
foo.parent<-function(A=7){
foo.child(A=A)
}
foo.parent(A=7)
foo.parent()
instead. So, you mix here two different As. The =sign within a function call defines, what happens if you do not give a value for that variable in the function call.
I think your problem is you don't quite understand how default arguments work. So
foo.child = function(A=1) 2+A
defines the function foo.child that has a default argument A=1. So,
foo.child()
gives 3. Now in this function
foo.parent = function(A=3){
foo.child(A=4)
}
you are always passing the value A=4 to the function foo.child, hence,
foo.parent(A=7)
# 6
Also, when you are trying to figure out what is happening, it's helpful to have different values of A