How to replace symbols by their value in a R function body - r

This code reveals that f doesn't yet look up q before it's called.
q <- 2
f <- function(x) q + x
f
I want to tell R which symbols in the body to look up right away (in this case list("q")) and have it modify f accordingly. How can it be done?

In Common Lisp this would look like:
CL-USER> (defparameter q 4)
Q
CL-USER> (let ((bar q))
(defmacro f (x)
`(+ ,bar ,x)))
F
CL-USER> (macroexpand-1 `(f 4))
(+ 4 4)
T
In R this could look like:
> q = 2
> f = eval(bquote(function(x) .(q) + x))
> f
function (x)
2 + x
>
Since R is interpreted, eval is par for the course there. With Common Lisp, if you do not want to use eval, you can go with a compile-time macro that carries along with it a hard-coded value for 'q, so that every time it is used in code at that point on it refers to the value of 'q at creation time of the macro.

Actually you are wrong about what happens when you make an assignment for a token of the value of function. Take a look at this:
> environment(f)$q
[1] 2
Some of the base R function keep values hidden away in the environments of the returned objects. The two that come to mind are ecdf and splinefun.

You could use something like this:
f_generator = function(q){
q
function(x){
q + x
}
}
f2 = f_generator(2)
f3 = f_generator(3)
f2(1)
# 3
f3(1)
# 4

Related

[julia]syntax: invalid assignment location "getproperty(f, n)"

My julia version is 1.7.1.
These code can recurrent my problem:
struct Foo1
sixsix
aa
bb
disposion
end
struct Foo2
aa
bb
end
function Base.:+(f1::Foo1, f2 :: Foo2)
newf = f1
for n in fieldnames(typeof(f2))
getproperty(newf, n) += getproperty(f2, n)
end
return newf
end
returned LoadError: syntax: invalid assignment location "getproperty(newf, n)"
same LoadError happened when I try to use getfield:
function Base.:+(f1::Foo1, f2 :: Foo2)
newf = f1
for n in fieldnames(typeof(f2))
getfield(newf, n) += getfield(f2, n)
end
return newf
end
Firstly, you must make your structs mutable for this to work.
Secondly, this:
getproperty(newf, n) += getproperty(f2, n)
is expanded into
getproperty(newf, n) = getproperty(newf, n) + getproperty(f2, n)
In other words you are apparently trying to assign a value into a function call. In Julia you can only assign to variables, not to values. The only thing this syntax is allowed for is function definition. From the manual:
There is a second, more terse syntax for defining a function in Julia.
The traditional function declaration syntax demonstrated above is
equivalent to the following compact "assignment form":
julia> f(x,y) = x + y
f (generic function with 1 method)
So the syntax you are using doesn't do what you want, and what you want to do is not possible anyway, since you can only assign to variables, not to values.
What you are trying to do can be achieved like this (assuming n is a Symbol):
setfield!(newf, n, getfield(newf, n) + getfield(f2, n))
I would rather recommend you to do the following:
Base.:+(f1::Foo1, f2 :: Foo2) =
Foo1(f1.sixsix, f1.aa+f2.aa, f1.bb+f2.bb, f1.disposion)
Your code is wrong for the following reasons:
Foo1 is not mutable, so you cannot change values of its elements
to set a field of mutable struct (which your struct is not) you use setfield!
You mix properties and fields of a struct which are not the same.
fieldnames works on types not on instances of type.
If you wanted to be more fancy and do automatic detection of matching fields you could do:
Base.:+(f1::Foo1, f2 :: Foo2) =
Foo1((n in fieldnames(Foo2) ?
getfield(f1, n) + getfield(f2, n) :
getfield(f1, n) for n in fieldnames(Foo1))...)
However, I would not recommend it, as I feel that it is overly complicated.

Tail recursion in mutually recursive functions

I have the following code:
let rec f n =
if n < 10 then "f" + g (n+1) else "f"
and g n =
if n < 10 then "g" + f (n+1) else "g"
I want to make these mutually recursive functions tail recursive for optimization.
I have tried the following :
let rec fT n =
let rec loop a =
if n < 10 then "f" + gT (a) else "f"
loop (n + 1)
and gT n =
let rec loop a =
if n < 10 then "g" + fT (a) else "g"
loop (n + 1)
Is that a correct tail recursive version? If no, a hint in the right direction would be greatly appreciated.
EDIT (Second take on a solution):
let rec fA n =
let rec loop n a =
if n < 10 then loop (n + 1) ("f" + a) else a
loop n "f"
and gA n =
let rec loop n a =
if n < 10 then loop (n + 1) ("g" + a) else a
loop n "g"
EDIT (Third take on a solution):
let rec fA n a =
if n < 10 then gA (n + 1) (a + "f") else a
and gA n a =
if n < 10 then fA (n + 1) (a + "g") else a
EDIT (The correct solution):
let rec fA n a =
if n < 10 then gA (n + 1) (a + "f") else (a + "f")
and gA n a =
if n < 10 then fA (n + 1) (a + "g") else (a + "g")
Your solution is most definitely not tail-recursive.
"Tail-recursion" is such recursion where every recursive call is the last thing that the function does. This concept is important, because it means that the runtime can opt out of keeping a stack frame between the calls: since the recursive call is the very last thing, and the calling function doesn't need to do anything else after that, the runtime can skip returning control to the calling function, and have the called function return right to the top-level caller. This allows for expressing recursive algorithms of arbitrary depth without fear of running out of stack space.
In your implementation, however, the function fT.loop calls function gT, and then prepends "f" to whatever gT returned. This prepending of "f" happens after gT has returned, and therefore the call to gT is not the last thing that fT.loop does. Ergo, it is not tail-recursive.
In order to convert "regular" recursion into the "tail" kind, you have to "turn the logic inside out", so to speak. Let's look at the function f: it calls g and then prepends "f" to whatever g returned. This "f" prefix is the whole "contribution" of function f in the total computation. Now, if we want tail recursion, it means we can't make the "contribution" after the recursive call. This means that the contribution has to happen before. But if we do the contribution before the call and don't do anything after, then how do we avoid losing that contribution? The only way is to pass the contribution into the recursive call as argument.
This is the general idea behind tail-recursive computation: instead of waiting for the nested call to complete and then adding something to the output, we do the adding first and pass what has been "added so far" into the recursive call.
Going back to your specific example: since the contribution of f is the "f" character, it needs to add this character to what has been computed "so far" and pass that into the recursive call, which will then do the same, and so on. The "so far" argument should have the semantics of "compute whatever you were going to compute, and then prepend my 'so far' to that".
Since you've only asked for a "hint", and this is obviously homework (forgive me if I'm wrong), I am not going to post the actual code. Let me know if you'd rather I did.
I second the observation that your attempt definitely does not put the recursion in tail position
How I would handle moving the recursion into tail position would be using a continuation. To do so, we'd have to implement fk and gk variants which have a continuation parameter, then f and g can be implemented using fk and gk respectively
I'm not an F# expert, but I can illustrate this quite simply with JavaScript. I wouldn't ordinarily post an answer using a different language, but since the syntax is so similar, I think it will be helpful to you. It also has the added benefit that you can run this answer in the browser to see it working
// f helper
let fk = (n, k) => {
if (n < 10)
return gk(n + 1, g => k("f" + g))
else
return k("f")
}
// g helper
let gk = (n, k) => {
if (n < 10)
return fk(n + 1, f => k("g" + f))
else
return k("g")
}
let f = n =>
fk(n, x => x)
let g = n =>
gk(n, x => x)
console.log(f(0)) // fgfgfgfgfgf
console.log(g(0)) // gfgfgfgfgfg
console.log(f(5)) // fgfgfg
console.log(g(5)) // gfgfgf
console.log(f(11)) // f
console.log(g(11)) // g

List comprehensions and tuples in Julia

I am trying to do in Julia what this Python code does. (Find all pairs from the two lists whose combined value is above 7.)
#Python
def sum_is_large(a, b):
return a + b > 7
l1 = [1,2,3]
l2 = [4,5,6]
l3 = [(a,b) for a in l1 for b in l2 if sum_is_large(a, b)]
print(l3)
There is no if for list comprehensions in Julia. And if I use filter(), I'm not sure if I can pass two arguments. So my best suggestion is this:
#Julia
function sum_is_large(pair)
a, b = pair
return a + b > 7
end
l1 = [1,2,3]
l2 = [4,5,6]
l3 = filter(sum_is_large, [(i,j) for i in l1, j in l2])
print(l3)
I don't find this very appealing. So my question is, is there a better way in Julia?
Using the very popular package Iterators.jl, in Julia:
using Iterators # install using Pkg.add("Iterators")
filter(x->sum(x)>7,product(l1,l2))
is an iterator producing the pairs. So to get the same printout as the OP:
l3iter = filter(x->sum(x)>7,product(l1,l2))
for p in l3iter println(p); end
The iterator approach is potentially much more memory efficient. Ofcourse, one could just l3 = collect(l3iter) to get the pair vector.
#user2317519, just curious, is there an equivalent iterator form for python?
Guards (if) are now available in Julia v0.5 (currently in the release-candidate stage):
julia> v1 = [1, 2, 3];
julia> v2 = [4, 5, 6];
julia> v3 = [(a, b) for a in v1, b in v2 if a+b > 7]
3-element Array{Tuple{Int64,Int64},1}:
(3,5)
(2,6)
(3,6)
Note that generators are also now available:
julia> g = ( (a, b) for a in v1, b in v2 if a+b > 7 )
Base.Generator{Filter{##18#20,Base.Prod2{Array{Int64,1},Array{Int64,1}}},##17#19}(#17,Filter{##18#20,Base.Prod2{Array{Int64,1},Array{Int64,1}}}(#18,Base.Prod2{Array{Int64,1},Array{Int64,1}}([1,2,3],[4,5,6])))
Another option similar to the one of #DanGetz using also Iterators.jl:
function expensive_fun(a, b)
return (a + b)
end
Then, if the condition is also complicated, it can be defined as a function:
condition(x) = x > 7
And last, filter the results:
>>> using Iterators
>>> result = filter(condition, imap(expensive_fun, l1, l2))
result is an iterable that is only computed when needed (inexpensive) and can be collected collect(result) if required.
The one-line if the filter condition is simple enough would be:
>>> result = filter(x->(x > 7), imap(expensive_fun, l1, l2))
Note: imap works natively for arbitrary number of parameters.
Perhaps something like this:
julia> filter(pair -> pair[1] + pair[2] > 7, [(i, j) for i in l1, j in l2])
3-element Array{Tuple{Any,Any},1}:
(3,5)
(2,6)
(3,6)
although I'd agree it doesn't look like it ought to be the best way...
I'm surprised nobody mentions the ternary operator to implement the conditional:
julia> l3 = [sum_is_large((i,j)) ? (i,j) : nothing for i in l1, j in l2]
3x3 Array{Tuple,2}:
nothing nothing nothing
nothing nothing (2,6)
nothing (3,5) (3,6)
or even just a normal if block within a compound statement, i.e.
[ (if sum_is_large((x,y)); (x,y); end) for x in l1, y in l2 ]
which gives the same result.
I feel this result makes a lot more sense than filter(), because in julia the a in A, b in B construct is interpreted dimensionally, and therefore the output is in fact an "array comprehension" with appropriate dimensionality, which clearly in many cases would be advantageous and presumably the desired behaviour (whether we include a conditional or not).
Whereas filter will always return a vector. Obviously, if you really want a vector result you can always collect the result; or for a conditional list comprehension like the one here, you can simply remove nothing elements from the array by doing l3 = l3[l3 .!= nothing].
Presumably this is still clearer and no less efficient than the filter() approach.
You can use the #vcomp (vector comprehension) macro in VectorizedRoutines.jl to do Python-like comprehensions:
using VectorizedRoutines
Python.#vcomp Int[i^2 for i in 1:10] when i % 2 == 0 # Int[4, 16, 36, 64, 100]

How to define map fusion in the Pure language?

I'm experimenting with the Pure language based on term rewriting.
I want to define "map fusion" using an equation, like this:
> map f (map g list) = map (f . succ . g) list;
(The succ is there to verify that the rule kicks in.)
However, it doesn't seem to work:
> map id (map id [2,3,4]);
[2,3,4]
The Pure manual says that
expressions are evaluated using the “leftmost-innermost” reduction strategy
So I suppose what's happening is that the innermost map id [2,3,4] expression is reduced first, so my rule never kicks in.
How to make map fusion work, then?
Here's a related experiment. The first rule doesn't kick in:
> a (b x) = "foo";
> b x = "bar";
> a (b 5);
a "bar"
I should have read the manual more closely. What I needed to do is to turn the pattern into a macro using the def keyword. This way it works:
> def map f (map g list) = map (f . succ . g) list;
> map id (map id [2,3,4]);
[3,4,5]

map function if a predicate holds

I feel like this should be fairly obvious, or easy, but I just can't get it. What I want to do is apply a function to a list (using map) but only if a condition is held. Imagine you only wanted to divide the numbers which were even:
map (`div` 2) (even) [1,2,3,4]
And that would give out [1,1,3,2] since only the even numbers would have the function applied to them. Obviously this doesn't work, but is there a way to make this work without having to write a separate function that you can give to map? filter is almost there, except I also want to keep the elements which the condition doesn't hold for, and just not apply the function to them.
If you don't want to define separate function, then use lambda.
map (\x -> if (even x) then (x `div` 2) else x) [1,2,3,4]
Or instead of a map, list comprehension, bit more readable I think.
[if (even x) then (x `div` 2) else x | x <- [1,2,3,4]]
mapIf p f = map (\x -> if p x then f x else x)
In addition to the answer of PiotrLegnica: Often, it's easier to read if you declare a helper function instead of using a lambda. Consider this:
map helper [1..4] where
helper x | even x = x `div` 2
| otherwise = x
([1..4] is sugar for [1,2,3,4])
If you want to remove all the other elements instead, consider using filter. filter removes all elements that don't satisfy the predicate:
filter even [1..4] -> [2,4]
So you can build a pipe of mapand filter than or use list-comprehension instead:
map (`div` 2) $ filter even [1..4]
[x `div` 2 | x <- [1..4], even x]
Choose whatever you like best.
Make your own helper function maker:
ifP pred f x =
if pred x then f x
else x
custom_f = ifP even f
map custom_f [..]
(caveat: I don't have access to a compiler right now. I guess this works OK...)
I like the other, more general solutions, but in your very special case you can get away with
map (\x -> x `div` (2 - x `mod` 2)) [1..4]
Mostly a rip off of existing answers, but according to my biased definition of "readable" (I like guards more than ifs, and where more than let):
mapIf p f = map f'
where f' x | p x = f x | otherwise = x
ghci says it probably works
ghci> let mapIf p f = map f' where f' x | p x = f x | otherwise = x
ghci> mapIf even (+1) [1..10]
[1,3,3,5,5,7,7,9,9,11]

Resources