Search code examples
racketabstraction

Using Racket ISL to define function using list abstractions


I am trying to create a function that accepts a number and then produces text they can temporarily copy into their paper as a space saver. Here are a few examples below:

(define
  CITATION-SPACE-2
  (string-append
   "[1] author information\n"
   "title information\n"
   "venue information\n"
   "year & page information\n"
   "[2] author information\n"
   "title information\n"
   "venue information\n"
   "year & page information"))

(define
  CITATION-SPACE-3
  (string-append
   "[1] author information\n"
   "title information\n"
   "venue information\n"
   "year & page information\n"
   "[2] author information\n"
   "title information\n"
   "venue information\n"
   "year & page information\n"
   "[3] author information\n"
   "title information\n"
   "venue information\n"
   "year & page information"))

(check-expect (citation-space 2) CITATION-SPACE-2)
(check-expect (citation-space 3) CITATION-SPACE-3)

I have been able to define the function using cond and string-append but can't figure out how to have a \n between each line of the result (though not after the last line). Also, I am unsure how to define and simplify the function using the foldr list abstraction.

This is what I have tried so far:

(define (citation-space num)
  (local [; data-string : Nat -> String
          ; produces a space saver
          ; for a supplied number
          (define (data-string num)
            (foldl (λ (s1 s2)
                     (string-append s2 "\n" s1))
                   (string-append
                    "[" (number->string num) "]"
                    " author information")
                   (list "title information"
                         "venue information"
                         "year & page information")))]
    (cond
      [(zero? num) ""]
      [(= num 1) (data-string 1)]
      [else (string-append
             (citation-space (sub1 num))
             "\n"
             (data-string num))])))

Solution

  • If you didn't have to do this exercise in ISL, you could use string-join provided by racket/string.

    If you didn't have to use foldl or foldr, you could write something like this:

    (define (my-join strs sep)
      (cond ((null? strs) "")
            ((= (length strs) 1) (first strs))
            (else (string-append (first strs)
                                 sep
                                 (my-join (rest strs) sep)))))
    

    But I think it's possible to solve this problem also with pair of foldl. Used language is Intermediate Student with Lambda:

    (define
      CITATION-SPACE-2
      (string-append
       "[1] author information\n"
       "title information\n"
       "venue information\n"
       "year & page information\n"
       "[2] author information\n"
       "title information\n"
       "venue information\n"
       "year & page information"))
    
    (define
      CITATION-SPACE-3
      (string-append
       "[1] author information\n"
       "title information\n"
       "venue information\n"
       "year & page information\n"
       "[2] author information\n"
       "title information\n"
       "venue information\n"
       "year & page information\n"
       "[3] author information\n"
       "title information\n"
       "venue information\n"
       "year & page information"))
    
    (define (data-string number)
      (foldl (lambda (s result)
               (string-append result "\n" s))
             (format "[~a] author information" number)
             (list "title information"
                   "venue information"
                   "year & page information")))
    
    (define (citation-space number)
      (if (zero? number) ""
          (let ((strs (map data-string (range 1 (add1 number) 1))))
            (foldl (lambda (s result) (string-append result "\n" s))
                   (first strs)
                   (rest strs)))))
    
    (check-expect (citation-space 2) CITATION-SPACE-2)
    (check-expect (citation-space 3) CITATION-SPACE-3)
    

    EDIT: Solution with one foldl:

    (define (data-string number)
      (foldl (lambda (s result)
               (string-append result "\n" s))
             (format "[~a] author information" number)
             (list "title information"
                   "venue information"
                   "year & page information")))
    
    (define (citation-space num)
      (cond
        [(zero? num) ""]
        [(= num 1) (data-string 1)]
        [else (string-append
               (citation-space (sub1 num))
               "\n"
               (data-string num))]))