4

I am trying to figure out how to have my if statement do multiple tasks, but only return one thing, if that makes sense. Also, I have no clue how to print a string along with a variable in the same line.

for example, how would you do something like this in scheme (the following is java)

if(num < x){
  num++;
  x = 0;
  System.out.println("The value of x is " + x " and num is now" + num);
}

else System.out.println("error");

Here is what I tried:

(if (< num x) 
( (define num (+ 1 num))
   (define x 0)
   ;idk how to print it
   )
"error";else
)
mr nooby noob
  • 1,860
  • 5
  • 33
  • 56

6 Answers6

3

You can use begin to evaluate a series of expressions for effect, and return the last one. Also you can use printf to print:

(if (< num x)
    (begin
      (set! num (add1 num))
      (set! x 0)
      (printf "The value of x is ~a and num is now ~a\n" x num))
    "error")

However keep in mind that using set! to clobber (mutate) variables is discouraged in Racket. It's better to return new values. It's hard to show you how to do that, here, without a slightly bigger example and more context. Anyway if you're intersted that should probably be its own, new question here.

Greg Hendershott
  • 16,100
  • 6
  • 36
  • 53
1

I'll start off by saying I'm not exactly certain what you want your code to do because I don't know java.

Something I can say though is that the internal define expressions are definitely tripping you up. In racket you generally cannot define a global variable within an expression, but would rather create a local binding with a form like:

(let ([identifier expression]
        ...
        [id-n expression-n])
    body-expressions)

by which the body expressions are evaluated with the specified bindings, the last of which is returned as the result of the entire let expression. This is one way to do multiple things and return one result. Within the context of an (if test consequent alternative)

statement you could group multiple expressions together (eg as a consequent) using the (begin expression...)form, which executes all expressions and returns the result of the last expression. An alternative would be to use a cond expression, which has the form:

(cond [test conequents]
        ...
        [test-n cons-n]
        [else expression])

Each such test can have multiple consequents, so this might be clearer than using several begins.

Also, if you really want to mutate the value of num and x you would use the (set! id value) procedure, but this is unidiomatic for racket as a functionally recursive form would be preferred.

Going beyond these points requires some guesswork on my part but it looks like you are working within a function that takes two arguments, x and num, and want to increment num until it reaches the value of x, printing the values of x and num along the way, and if given an x value larger than num, you want to return an error

In racket you could do this recursively like so:

(define inc-print ;defining inc-print
  (lambda (x num) ;a function of two arguments
    (cond [(> num x) "error"]
          [(< num x)
           ;the printf command takes a string and prints it.
           ;you can add values to the string by inserting ~a's followed by as many
           ;expressions as ~a's
           ;\n is shorthand for (newline) so that subsequent calls to printf print on a newline
           (printf "The value of x is ~a and num is now ~a\n" x num)
           ;a recursive call to inc-print with num incremented by 1 and x the same
           (inc-print x (+ num 1))]
          [else num])))

example:

> (inc-print 5 2)
The value of x is 5 and num is now 2
The value of x is 5 and num is now 3
The value of x is 5 and num is now 4
5

Let me know if this answered your question!

inordirection
  • 959
  • 6
  • 16
0

I have no experience in java but i guess this i what you are looking for

class IfElseDemo {
public static void main(String[] args) {

    int testscore = 76;
    char grade;

    if (testscore >= 90) {
        grade = 'A';
    } else if (testscore >= 80) {
        grade = 'B';
    } else if (testscore >= 70) {
        grade = 'C';
    } else if (testscore >= 60) {
        grade = 'D';
    } else {
        grade = 'F';
    }
    System.out.println("Grade = " + grade);
}

}

more details here:

https://docs.oracle.com/javase/tutorial/java/nutsandbolts/if.html

Why does this code not work as intended?

Community
  • 1
  • 1
user2983686
  • 131
  • 1
  • 2
  • 11
0

You can use let if you want to combine if and define. It is very common, so cond makes the whole thing easier:

(if (< num x) 
    (let () ; use let in order to use define in an expression context
      (define num (+ 1 num))
      (define x 0)
      (displayln (list 'num num 'x x))
      x)
    (displayln "error"))

(cond
  [(< num x) (define num (+ 1 num))
             (define x 0)
             (displayln (list 'num num 'x x))
             x]
  [else     (displayln "error")])
soegaard
  • 30,661
  • 4
  • 57
  • 106
0

First off. You display texts to terminal with display in Scheme and in #!racket you can use displayln as well a lot of other more specialized procedures.

In java (and many other C descendants/dialects) the format of if is almost the same as in Scheme:

if ( x < 3 )
    return 0;
else
    return 10;

In Scheme it looks very similar:

(if (< x 3)
    0
    10)

If you need to do more things where one statement is needed you need to group them. In Java (and all C descendants) we group many statements into one by surrounding them with {}. Eg.:

{
    System.out.println("Side effect " + localVar);
    return 10;
}

That above is a valid block in any place a statement is allowed. In Scheme you denote blocks with begin

(begin (display "Side effect\n")
       10)

The body of procedures and let forms are said to have explicit begin. It means it allows for more than one expression. Only the tail expression is considered the "return" though.

Many special forms have explicit begin in Scheme. You don't have that in Java because you are required to use curlies in those circumstances. Examples are body of a procedure:

(lambda (arg)
  (define test 10) ; one expression
  (+ test arg))    ; another expression

let, let*, letrec, ... are just anonynous procedure calls and thus their bodies inherit the explicit begin of lambda. In cond consequences and alternatives you have them:

(cond ((hash-ref hash test) #f)
      ((> test 10) (hash-set! hash test #t) #t)    ; two expressions consequent
      (else        (hash-set! hash test #t) test)) ; two expressions alternative

cond are usually a macro that transform into if. The difference between them is the implicit begin and that it supports more than one term. Thus its nice to use cond where you need explicit begin or instead of nested ìf. The result is more readable code that is more flat. The cond above can be written like this with if:

(if (hash-ref hash test) 
    #f
    (if (> test 10)
        (begin  
          (hash-set! hash test #t) ; one expression
          #t)                      ; another expression (tail)
        (begin 
          (hash-set! hash test #t) ; one expression
          test)))                  ; another expression (tail)

As you can see cond is more compact and if you familiar with Scheme it's easier to read. It's very important to have the proper identation so using an IDE that does that would help you write code other schemers can read. Since you tagged racket you can use DrRacket and press CTRL + i often.

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

I realize I'm 7 years late, but just came across this question since I had the same struggle. I am using Guile, I looked through the manual and found this:

When you go to write an ‘if’ without an alternate (a “one-armed ‘if’”), part of what you are expressing is that you don’t care about the return value (or values) of the expression. As such, you are more interested in the effect of evaluating the consequent expression. (By convention, we use the word “statement” to refer to an expression that is evaluated for effect, not for value).

In such a case, it is considered more clear to express these intentions with these special forms, ‘when’ and ‘unless’. As an added bonus, these forms accept multiple statements to evaluate, which are implicitly wrapped in a ‘begin’.

So instead of using if or cond as other answers suggest, you can do

(when (< num x)          ;; if (num < x) {
  (set! num (+ num 1))   ;;   num++;
  (set! x 0)             ;;   x = 0;
  (display "..."))       ;;   print("...");
                         ;; }
Daniel Garcia
  • 462
  • 3
  • 8