0

I'm having some complications with a piece of code I'm working on. I need the procedure to take number (list-of-numbers) and return the minimum value between the two. So far I have this

(define (mini y lon)
 (cond
  [(empty? lon) y]
  [else (min (first (foldr cons lon (list y))) (mini y (rest lon)))]))

and I can't figure out the reason why it's not working. Thanks in advance.

2 Answers2

3

The solution is overly complicated, why using foldr and min, when a simple min together with apply will do all the work? try this:

(define (mini y lon)
  (apply min y lon))

... Or you can build a single list with y and lon, but once again you don't need foldr for this, a simple cons is all you want:

(define (mini y lon)
  (apply min (cons y lon)))

... But if you really, really need to use foldl (or foldr), then it's not required to use min, the trick is to pass the right function:

(define (mini y lon)
  (foldl (lambda (e a) (if (< e a) e a)) ; foldr will also work
         y
         lon))

... Or you could use min after all, for a shorter solution. There are so many ways to solve this problem!

(define (mini y lon)
  (foldl min y lon)) ; foldr will also work
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • I thought of this as well but sadly we are required to use foldr or foldl. – Nikolai Naidenov Nov 15 '13 at 14:42
  • You should state that in the question, otherwise it doesn't make sense to use a fold here – Óscar López Nov 15 '13 at 14:43
  • Thank you, I did a workaround, implementing your solution and came up with this: `(define (mini y lon)` `(cond` `[(empty? lon) y]` `[else (apply min (foldr cons lon (list y)))])) ` Edit: Wow, that's an even better and proper way to do this. Thank you! – Nikolai Naidenov Nov 15 '13 at 14:47
  • @user2969733 might work, but that's not the idea. When you're using a fold, it takes care of iteration, you don't have to traverse the list explicitly. See my updated answer. – Óscar López Nov 15 '13 at 14:50
  • 1
    I love fold, but I really wished it would handle multiple values, so that I could rewrite [a min-max function](http://stackoverflow.com/a/19993142/13) using fold. (No, not particularly liking the idea of packing the min and max into a cons, as you'll soon see when you look at the code.) – C. K. Young Nov 15 '13 at 15:26
  • 1
    There's at least one good reason for @user2969733 to use `fold[lr]` in preference to `(apply n-ary-function ...)`; implementations probably have a limit on the length of an argument list that can be used with a function, and `apply` with a long list could run afoul of it. `(fold[lr] n-ary-function ...)` won't have that issue. There's a bit about it (for Common Lisp) in [this answer](http://stackoverflow.com/a/19937184/1281433), but similar considerations probably hold for Schemes. – Joshua Taylor Nov 15 '13 at 16:40
  • 1
    @JoshuaTaylor Racket doesn't have that limitation, so there you can use `apply` with reckless abandon. :-) – C. K. Young Nov 15 '13 at 18:49
3

I think Óscar nailed it for a racket solution, but since you tagged the cmpletely different languages Scheme and Lisp I made som solutions to fit those tags as well.

A R6RS-solution using the native fold-left from (rnrs lists)

#!r6rs ; #!r7rs
(import (rnrs base) (rnrs lists)) ; (import (scheme base))

(define (mini x xs)
  (fold-left min x xs))

;; without fold
(define (mini-simple x xs)
  (apply min x xs))

Since you tagged lisp, here is a Common Lisp version. CL doesn't have foldl/foldr, but reduce which replaces both and more:

(defun mini (x xs)
  (reduce #'min xs :initial-value x))
Community
  • 1
  • 1
Sylwester
  • 47,942
  • 4
  • 47
  • 79