7

I am trying to write a simple program in Racket that prints 1 if the value of a is > 1, prints 0 if the value of a = 0 and -1 if a < 0 . I wrote the following but looks like it is not taking care of the third condition. Actually, I have not included the third condition so I don't know how to check for all three conditions using 'if' clause. A little guidance is appreciated.

I am new to Racket. My program is:

#lang racket
(define a 3);


(if (> a 0)
    0 
    1)
-1

Thanks in advance.

soegaard
  • 30,661
  • 4
  • 57
  • 106
user3400060
  • 299
  • 3
  • 9
  • 23

3 Answers3

12

The function you are looking for is already defined under the name sgn.

The reason your implementation doesn't work is that it is incomplete. You want:

(if (= a 0)
    0
    (if (< a 0)
        -1
        1))

Or just the better looking:

(cond 
    [(negative? n) -1]
    [(positive? n)  1]
    [else 0])
MaiaVictor
  • 51,090
  • 44
  • 144
  • 286
  • 2
    One small note since the question was tagged just `racket` (not also `scheme`): Although not mandatory it's idiomatic in Racket to use square brackets for certain forms like the clauses in `cond`. For example `(cond [cond expr] [else expr])`. – Greg Hendershott May 05 '15 at 00:32
3

So how you describe it you have two consequences and one alternative. I would then have used cond:

(cond ((> a 0) 1)
      ((= a 0) 0)
      (else -1))  ; if it's not greater or equal it has to be less than

With cond each term you can expect all previous to be false, thus the last test is not needed since if it's not greater or equal it has to be less than 0. This is exactly the same as writing:

(if (> a 0)
    1
    (if (= a 0) 
        0
        -1))

The main difference is that it looks slightly better with cond. If you have a need for begin (side effects) then using cond would also be beneficial since it has implicit begin:

(define seen
  (let ((hash (make-hash)))
    (lambda (x) 
      (cond ((hash-ref hash x #f) #t)
            (else (hash-set! hash x #t) #f)))))

The same with if:

(define seen
  (let ((hash (make-hash)))
    (lambda (x) 
      (if (hash-ref hash x #f) 
          #t
          (begin
            (hash-set! hash x #t)
            #f)))))

Its the same but I feel cond wins since it's less indentation and more flat.

Sylwester
  • 47,942
  • 4
  • 47
  • 79
0

I'm a beginner CS student, but we started with Racket and this is how we would make this. Also, I'm just going by exactly what you say in your question "prints 1 if the value of a is > 1, prints 0 if the value of a = 0 and -1 if a < 0"

(cond
[(> a 1) 1]
[(= a 0) 0]
[(< a 0) -1])

Something else that I might add just purely as a CS student going by class standards, when we were writing functions that used intervals we always wrote an appropriate amount of check-expects to see if anything unexpected happens. I noticed that you have something happen when a > 1, a = 0, and everything below 0 would be = -1. So if you wrote a = 1 it would return with -1 if you had put "else" for anything that wasn't >1, = 0, or <0 . I don't know what you would want to happen if a = 1, but I thought I would just throw that out for good measure.

If you were to put in a = 1 with the cond written above it would just return with "cond: all question results were false".. Oki, now I'm done.

Mikey
  • 1
  • 3