---
title: "List Comprehensions in R"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{List comprehensions in R}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

Package provides Python-style list comprehensions for R. List comprehension
expressions use usual loops (`for`, `while` and `repeat`) and usual `if` as
list producers. Syntax is very similar to Python. The difference is that
returned value should be at the end of the loop body.

There are three main functions:

- `to_list` converts usual R loops expressions to list producers. Expression should be started with `for`, `while` or `repeat`. You can iterate over multiple lists if you provide several loop variables in backticks. See examples.
- `to_vec` is the same as `to_list` but return vector. See examples.
- `alter` return the same type as its argument but with modified elements. It is useful for altering existing data.frames or lists. See examples.

Rather unpractical example - squares of even numbers:
```{r}
library(comprehenr)
to_vec(for(i in 1:10) if(i %% 2==0) i*i)
```
Pythagorean triples:
```{r}
to_list(for (x in 1:20) for (y in x:20) for (z in y:20) if (x^2 + y^2 == z^2) c(x, y, z))
```
More examples:
```{r}
colours = c("red", "green", "yellow", "blue")
things = c("house", "car", "tree")
to_vec(for(x in colours) for(y in things) paste(x, y))

# prime numbers
noprimes = to_vec(for (i in 2:7) for (j in seq(i*2, 99, i)) j)
primes = to_vec(for (x in 2:99) if(!x %in% noprimes) x)
primes
```

You can iterate over multiple lists if you provide several loop variables in backticks:
```{r}
to_vec(for(`i, j` in numerate(letters)) if(i %% 2==0) paste(i, j))

set.seed(123)
rand_sequence = runif(20)
# gives only locally increasing values
to_vec(for(`i, j` in lag_list(rand_sequence)) if(j>i) j)

```

`alter` examples:
```{r}
data(iris)
# scale numeric variables
res = alter(for(i in iris) if(is.numeric(i)) scale(i))
str(res)

# convert factors to characters
res = alter(for(i in iris) if(is.factor(i)) as.character(i))
str(res)

# drop factors
res = alter(for(i in iris) if(is.factor(i)) exclude())
str(res)

# 'data' argument example
# specify which columns to map with a numeric vector of positions:
res = alter(
    for(`i, value` in numerate(mtcars)) if(i %in% c(1, 4, 5)) as.character(value),
    data = mtcars
)
str(res)

# or with a vector of names:
res = alter(
    for(`name, value` in mark(mtcars)) if(name %in% c("cyl", "am")) as.character(value),
    data = mtcars
)
str(res)
```
