UnknownPeach
UnknownPeach

Reputation: 1

Is it possible to use 'append' or 'cons' to create a make-list function in Scheme that repeats values based on a given size parameter?

Is there an alternative way of writing the make-list function in Scheme (R5RS)? I am trying to create a function where the value repeats itself in the list based on the given size.

So my expected output should be:

(print 5 5) --> (5 5 5 5 5)
(print Ana 3) --> (Ana Ana Ana)

If the parameters are switched, return an empty list (print 3 Ana) --> '()

I am doing this through recursion with a helper function and wanted to use either 'append' or 'cons'

(define print-helper (lambda (value size)
                           (if (null? value) 
                               0 ;size is zero
                               (print-helper (append(+ value 1) (cdr size)))
                               )))

(define print (lambda (value size)
                    (if not(number? value))
                        '() ;return
                        (print-helper value size) 
                        ))

Upvotes: 0

Views: 66

Answers (3)

Sylwester
Sylwester

Reputation: 48775

It seems like you are confused about what makes a list. in Scheme a list is a chain of cons. (1 2 4 6) is just fancy printing of the list (1 . (2 . (4 . (6 . ()))) or (cons 1 (cons 2 (cons 4 (cons 6 '())))).

Lists are created from the end to the beginning. The order of execution makes the list (6) before it can make (4 6) because while order of evaluation on the same level is not given, we know that all arguments are evaluated before application and that means that in (cons 1 expr) expr is fully evaluated to (2 3 4 6).

So making a list with the same value, you don't really need to worry about order so I'll show you how to make a list like range does it:

;; unoptimized growing stack way
(define (my-range to)
  (let helper ((from 0))
    (if (>= from to)
        '()
        (cons from 
              (helper (+ 1 from))))))

;; accumulating version with reverse; better
(define (my-range to)
  (let helper ((from 0) (acc '()))
    (if (>= from to)
        (reverse acc)
        (helper (+ 1 from) (cons from acc)))))

;; Best doing it in reverse, the order lists are created
(define (my-range to)
  (let helper ((to (- to 1)) (acc '()))
    (if (< to 0)
        acc
        (helper (- to 1) (cons to acc)))))
                 
;; test
(my-range 10) ; ==> (0 1 2 3 4 5 6 7 8 9)

THat last one can be changed to take a value and use that instead ot the counting and then you can keep the initial value and rather stop at zero instead of below zero. Good luck

Upvotes: 0

Martin Půda
Martin Půda

Reputation: 7576

Aside from the recursive solution, R5RS Scheme already provides make-vector (and then you can use vector->list to get list)- you can use them in your print:

(define (print item times)
  (vector->list (make-vector times item)))

Examples:

> (print 5 5)
(5 5 5 5 5)

> (print "Ana" 3)
("Ana" "Ana" "Ana")

Upvotes: 0

Barmar
Barmar

Reputation: 782488

  • The base case of the recursion should check if size is 0, not value.
  • Use cons to construct a list step by step
  • The recursive call has to be in the argument to cons or append, not around the call.
  • Subtract 1 from size when recursing, don't add 1.
  • You need parentheses around the call to not.
  • You should check whether size is a number, not value.
(define print-helper
  (lambda (value size)
    (if (<= size 0) 
        '()
        (cons value (print-helper value (- size 1))))))

(define print
  (lambda (value size)
    (if (not (number? size))
        '() ;return
        (print-helper value size))))

Upvotes: 0

Related Questions