Skip to content

Commit 81402fa

Browse files
committed
Draft 'modify' - for modification existing object
1 parent 4682121 commit 81402fa

File tree

5 files changed

+69
-12
lines changed

5 files changed

+69
-12
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
export(enumerate)
44
export(lag_list)
55
export(mark)
6+
export(modify)
67
export(numerate)
78
export(to_list)
89
export(to_vec)

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
0.6.5 (09.04.2019)
2+
================
3+
* add for lists/data.frames modification
4+
15
0.6.0 (18.03.2019)
26
================
37
* add iterations over multiple lists: to_vec(for(`i, j` in numerate(letters)) if(i %% 2==0) paste(i, j))

R/to_list.R

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,16 @@ to_vec = function(expr, recursive = TRUE, use.names = FALSE){
5858
}
5959

6060

61-
add_assignment_to_final_loops = function(expr){
61+
add_assignment_to_final_loops = function(expr, result_exists = FALSE){
6262
if(is_loop(expr)){
6363
if(has_loop_inside(expr[-1])){
64-
expr[-1] = as.call(lapply(as.list(expr)[-1], add_assignment_to_final_loops))
64+
expr[-1] = as.call(lapply(as.list(expr)[-1], add_assignment_to_final_loops, result_exists = result_exists))
6565
} else {
66-
expr = add_assignment_to_loop(expr)
66+
expr = add_assignment_to_loop(expr, result_exists = result_exists)
6767
}
6868
} else {
6969
if(has_loop_inside(expr)){
70-
expr = as.call(lapply(as.list(expr), add_assignment_to_final_loops))
70+
expr = as.call(lapply(as.list(expr), add_assignment_to_final_loops, result_exists = result_exists))
7171
}
7272
}
7373
expr
@@ -127,16 +127,46 @@ has_loop_inside = function(expr){
127127
}
128128

129129

130-
add_assignment_to_loop = function(expr){
130+
add_assignment_to_loop = function(expr, result_exists = FALSE){
131131
last_item = length(expr)
132-
expr[[last_item]] = bquote({
133-
134-
.__curr = {.(expr[[last_item]])}
135-
if(!is.null(.__curr)){
132+
if(result_exists){
133+
expr[[last_item]] = bquote({
134+
.__curr = {.(expr[[last_item]])}
136135
.___counter = .___counter + 1
137-
.___res[[.___counter]] = .__curr
138-
}
136+
if(!is.null(.__curr)){
137+
.___res[[.___counter]] = .__curr
138+
}
139+
140+
})
141+
} else {
142+
expr[[last_item]] = bquote({
139143

140-
})
144+
.__curr = {.(expr[[last_item]])}
145+
if(!is.null(.__curr)){
146+
.___counter = .___counter + 1
147+
.___res[[.___counter]] = .__curr
148+
}
149+
150+
})
151+
}
141152
expr
142153
}
154+
155+
#' @rdname to_list
156+
#' @export
157+
modify = function(expr, data = NULL){
158+
expr = substitute(expr)
159+
if(!is_loop(expr)) {
160+
stop(paste("argument should be expression with 'for', 'while' or 'repeat' but we have: ", deparse(expr, width.cutoff = 500)[1]))
161+
}
162+
on.exit(suppressWarnings(rm(list = c(".___res", ".___counter", ".__curr"), envir = parent.frame())))
163+
if(is.null(data)) data = expr[[3]]
164+
eval.parent(substitute(.___res <- data))
165+
expr = expand_loop_variables(expr)
166+
expr = add_assignment_to_final_loops(expr, result_exists = TRUE)
167+
eval.parent(quote(.___counter <- 0)) # initial list length
168+
eval.parent(expr)
169+
res = get(".___res", envir = parent.frame())
170+
res
171+
172+
}

man/to_list.Rd

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test_to_list.R

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,22 @@ index = seq_along(letters)
117117
true_res = expand.grid(paste(seq_along(letters), LETTERS), paste(index[index %% 2==0], letters[index %% 2==0]))
118118
true_res = paste(true_res[[2]], true_res[[1]])
119119
expect_identical(res, true_res)
120+
121+
122+
context("modify")
123+
data(iris)
124+
iris2 = modify(for(i in iris) if(is.numeric(i)) scale(i))
125+
res_iris = iris
126+
res_iris[,-5] = lapply(iris[,-5], scale)
127+
expect_equal(iris2, res_iris)
128+
129+
iris2 = modify(for(`name, value` in mark(iris)) if(grepl("Width", name)) scale(value), data = iris)
130+
131+
res_iris = iris
132+
res_iris[,c("Sepal.Width", "Petal.Width")] = lapply(iris[,c("Sepal.Width", "Petal.Width")], scale)
133+
expect_equal(iris2, res_iris)
134+
135+
136+
# library(data.table)
137+
# dt_iris = as.data.table(iris)
138+
# dt_iris2 = modify(for(i in dt_iris) if(is.numeric(i)) scale(i))

0 commit comments

Comments
 (0)