Home > Back-end >  How do I create a new function that iterates a function I previously made in R?
How do I create a new function that iterates a function I previously made in R?

Time:10-08

I have to create 3 functions that sings The 12 Days of Christmas. The first function makes a phrase.

make_phrase <- function(num, gift) {
  if (!is.character(gift[1])) {
    stop("Gift should be a string of characters") }
    if (!is.numeric(num[1])) {
    stop("Num should be a number") }
  num <- as.character(english(num))
  num <- ifelse(num == "one", "a", num)
  glue("{num} {gift}")
  }

The second function uses the first to create a verse of the song.

sing_verse <- function(num, day, gift) {
  day <- day[num]
  daily_phrase <- make_phrase(num:1, gift[num:1])
  cat("On the", day, "day of Christmas, my true love gave to me, \n")
      glue("{daily_phrase}")
}

Both of these functions seem to work, and I want to create a third function that uses the sing_verse function to sing the entire song.This function needs to have three arguments. Basically doing this:

sing_verse(1, xmas$day_in_words, xmas$gift_item)
sing_verse(2, xmas$day_in_words, xmas$gift_item)
sing_verse(3, xmas$day_in_words, xmas$gift_item)
sing_verse(4, xmas$day_in_words, xmas$gift_item)
sing_verse(5, xmas$day_in_words, xmas$gift_item)
sing_verse(6, xmas$day_in_words, xmas$gift_item)
sing_verse(7, xmas$day_in_words, xmas$gift_item)
sing_verse(8, xmas$day_in_words, xmas$gift_item)
sing_verse(9, xmas$day_in_words, xmas$gift_item)
sing_verse(10, xmas$day_in_words, xmas$gift_item)
sing_verse(11, xmas$day_in_words, xmas$gift_item)
sing_verse(12, xmas$day_in_words, xmas$gift_item)

I tried this:

sing_xmas_song <- function(days, names, gifts) {
verses<- map_chr(days, ~sing_verse(.x, names, gifts)) %>%
  cat(sep = "\n")
return(verses)
}

But I received an error stating "Error: Result 2 must be a single string, not a vector of class glue/character and of length 2"

If I change the second function to include the glue() in the cat() it resolves that issue, but I then get an error that states "Error: Result 1 must be a string, not a NULL of length 0. This change also gives the output in a format I do not want.

CodePudding user response:

Instead of using glue for daily_phrase, it is easier to just print it

make_phrase <- function(num, gift) {
  if (!is.character(gift[1])) {
    stop("Gift should be a string of characters") }
    if (!is.numeric(num[1])) {
    stop("Num should be a number") }
  num <- as.character(english(num))
  num <- ifelse(num == "one", "a", num)
  glue("{num} {gift}")
  }


sing_verse <- function(num, day, gift) {
  day <- day[num]
  daily_phrase <- make_phrase(num:1, gift[num:1]) 
  
  cat(paste("On the", day, "day of Christmas, my true love gave to me, \n"))
    print(daily_phrase)
}

Now, call in a for loop

for(i in 1:3) sing_verse(i, xmas$day_in_words, xmas$gift_item)
On the first day of Christmas, my true love gave to me, 
a partridge in a pear tree
On the second day of Christmas, my true love gave to me, 
two turtle doves
a partridge in a pear tree
On the third day of Christmas, my true love gave to me, 
three french hens
two turtle doves
a partridge in a pear tree

data

xmas <- structure(list(day = 1:6, day_in_words = c("first", "second", 
"third", "fourth", "fifth", "sixth"), gift_item = c("partridge in a pear tree", 
"turtle doves", "french hens", "calling birds", "golden rings", 
"geese a-laying")), row.names = c(NA, 6L), class = "data.frame")
  • Related