Pari/GP: user defined functions - pari-gp

I have defined a couple of functions of arity 1, say func1(-) and func2(-). I have tested them and seen that they actually do what they are supposed to.
I wish to define a third function, say func3(-), that outputs the difference of func1(-) and func2(-). This is what I do
func3(k) = {j=func1(k)-func2(k); print(j)}
Nevertheless, it doesn't return what it ought to. Let us suppose that func1(5) outputs 10 and func2(5) outputs 2. Then, func3(5) ought to output an 8, right? It returns instead the output of func1(5) in one row, the output of func2(2) in another row, and then a zero (even though the difference of the corresponding outputs is not 0).
Do you know what's wrong with the definition of func3(-)?

A GP user function returns the last evaluated value. Here, it's the resut of
the 'print(j)' command, which prints j (side effect) and returns 'void',
which is typecast to 0 when it must be given a value, as here.
f1(x) = 10
f2(x) = 2
f3(x) = f1(x) - f2(x)
correctly returns 8. You didn't give the code for your func1 / func2
functions, but I expect you included a 'print' statement, maybe expecting it
to return a value. That's why you get outputs on different rows, before the 0.
If you don't like this 'return-last-evaluation-result' behaviour, you can use
explicit 'return (result)' statements.

Related

How to solve Argument K missing by default error

I have a function below and I have K to be a range of values and want to set lambda =2.
When I run the code I get an error in R- argument k is missing with no default.
What am I doing wrong?
lnmp <- function(mu, k) {
n <- length(k)
-n*mu + log(mu)*sum(k) - sum(lfactorial(k))
}
k<-c(5,12,10,22,45,67,39,28,45,53,45,41,4,lamhda=2)
lnmp(k)
You set your function lnmp with two inputs, mu and k. However, you only passed one. The important thing is that it doesn't matter what the argument you passed is named, it's going to be the first one. If you name it dog, it's still going to be treated as mu inside the function. Since you didn't pass a second argument, k is not defined (it has no value). Therefore, what you have to do is pass both arguments when you call the function (therefore, lnmp(first, second) or lnmp(mu, k)).

Accessing values in expression using a macro

I'm wondering whether it's possible to define a macro that can modify the values of an expression only if the values are of a specific type?
Here's a minimal example:
type Special
x::Int
end
f1(s, n::Special) = println("f1", s, n)
f2(s, n::Special) = println("f2", s, n)
x1 = Special(3)
x2 = Special(5)
expr = :(
f1("this is f1", x1),
f2("this is f2", x2)
)
Now a macro might be able to examine the values of the arguments to the functions, determine that x1 and x2 are of type Special, run some function to modify their values, say by changing 3 to 4 and 5 to 2 (it might involve comparing two values), then pass the expression back to the caller. The final result would be equivalent to calling:
f1("this is f1", 4)
f2("this is f2", 2)
I found that it's possible to access the values in a macro via:
eval(eval(filter(x -> typeof(eval(x)) == Special, expr.args[1].args))[1]).x
=> 3
but although this works it looks wrong, and I'm might either be doing it wrong or trying to do something too way out...
No, you should never try to check types or values inside macros. Using eval to figure out the type or value of something in a macro may work in very limited situations, but it'll break in almost every real use. Instead, just have the macro insert a call to a generic function — that's where Julia excels at picking apart types (as method dispatch) and values (within the method):
munge_special(x::Special) = Special(x.x + 42)
munge_special(x) = x
macro do_something_special(x)
return :(munge_special($(esc(x))))
end
julia> #do_something_special Special(2)
Special(44)
julia> #do_something_special 3
3

How can I interpret user input as a function in Julia?

I've been using the following function to take in user input for something I'm writing in Julia:
function input(prompt::AbstractString = "")
println(prompt * " ")
chomp(readline())
end
In my particular case, the input that I'm taking in is in the form of equations such as "y = x^2". After the input() function passes it to me as an ASCIIString, I then use the parse() function to convert it to an Expression:
:(y = x^2)
As an Expression, I can use the .args attribute to do things like counting the number of variables and returning the unique variables, all of which has worked fine. Now, I need to be able to evaluate the right side of the expression as the Function f(x) = x^2. To do so, I began writing the following function (which has some pretty major flaws):
function evalExpression()
L = [1,2,3,4]
equation = parse(input("Enter an equation"))
f = equation.args[2].args[2]
for i in L
x = i
value = eval(f)
println(value)
end
end
This function has two problems that I haven't been able to resolve. The first is that it gives me an UndefVarError for x when I try to run it right now; that's more or less expected. The second is that unless I knew that the user would input a function of only x, I would have no way of figuring out what the variables I needed to assign were. I wrote a recursive function that can take in an expression and return all its variables in the form of [:x, :y, etc.], but I cannot assign :x to a number to evaluate the function--I need to assign it just to x, and I cannot figure out how to access that. Is there anything that I can use to access the variables I need? Or a different approach I could take?
Thank you!
When I run the following:
function evalExpression()
L = [1,2,3,4]
equation = parse(input("Enter an equation"))
global x
for i in L
x = i
f = equation.args[2].args[2]
value = eval(f)
println(value)
end
end
and then putting y = x*x I get
evalExpression()
Enter an equation
y = x*x
1
2
3
4
What is missing, at least for x as a variable, is declaring it globally. When you eval parsed statements, these parsed statements only access global variables
So what you probably need to do after you've invented your recursive function to correctly fetch variables, is to create them globally. Maybe
eval(parse("$variable = 0"))
will do

R functions counting elements

I would like to print the element number of the list that is going through a function. For example if there are 10 elements in the list, I would like a counter that will go from 0-10 as the function goes through each element.
a = length(url)
func0 = function(url){
a = a-1
print(a)
}
cc = lapply(url, func0)
However this does not work. Please let me know what I'm doing wrong.
Your function changes the internal copy of variable a, and prints number 9 10 times. To change this behaviour to desired you should change the assignment operator = (btw, why not <-? equal sign is usually used in definitions of functions' parameters) to the global assignment operator <<-.
func0 = function(url){
a <<- a-1
print(a)
}
It will work, but the common recommendation is to avoid the global assignment operator in your code.
As an alternative I can suggest to check the package pbapply, which adds progress bar to the *apply functions.
require(pbapply)
pblapply(url, func1)
Where func1 will stand for the the function you want to apply to each element of the list.

R switch in function [duplicate]

I am trying to write a function which does different things, depending on the second argument. But I am getting an error all the time. Depending on the dimension of the matrix, the function should perform different tasks. Here is an example
x<-cbind(X1,X2,X3)
function<-function(x,hnrstr){
if (hnrstr<-1){
x<-data.frame(X1=x[1],X2=x[2],X3=x[3])
y<-x
y[ ,"X2","X3"]<- gsub(" {2, }"," ",y[ ,"X2","X3"])
}
if (hnrstr<-2){
x<-data.frame(X1=x[1],X2=x[2])
P<-x
}
if (hnrstr<-1){
x<-y
}
if (hnrstr<-2){
x<-P
}
return(x)
}
apply(x,c(3,3), function(x,1))
I am getting the error:
Error in drop && !has.j : invalid 'x' type in 'x && y'
hnrstr<-1 is assigning the value of 1 to hnrstr. You do not want this in an if statement. You either meant "test that hnrstr is less than minus one", in which case add some whitespace. hnrstr < -1, or you meant "test that hnrstr is equal to one", in which case use double equals, hnsstr == 1.
If X1, X2 and X3 are vectors, then x will be a matrix. That is, it has two dimensions. that means that later, after you've assigned y <- x (why do you need to do this?) y[ ,"X2","X3"]) doesn't make much sense because it implies that there are 3 dimensions, not two. This is what is causing the error. Did you mean y[, c("X2","X3")])?
gsub accepts a vector, so after you've changed the previous code, you also need to change the call to that function. Do you want to pass it the second column or the third column or both (one after the other)?
Those second if blocks look pointless. Have a think about how you can remove them.
if (hnrstr<-1){
x<-y
}
if (hnrstr<-2){
x<-P
}
You don't need a return statement at the end of the function. R automatically returns the last value that was calculated in the function.
As Colin said, don't try and call your function "function". That's just asking for trouble. Change the line
function <- function(x,hnrstr){

Resources