2

I'm new to Scheme and I have a background coding mainly in C++/Java, and a bit of Python. I'm doing exercises in Study and Interpretation of Computer Programs, and I've come across this problem:

The book details the structure of the "if" special form as (if (conditional) (consequent clause) (alternative clause)). However, nothing indicates that an alternative clause MUST be included.

In fact, in the exercise I'm currently stuck on (exercise 1.22, for anyone interested), they provide some code that we are supposed to use in creating a procedure that tests for prime numbers within a given range and gives the amount of time taken to find them.

(define (start-prime-test n start-time)
    (if (is-prime n)
        (report-prime (- (runtime) start-time))))

This did not work, so I modified it slightly:

(define (start-prime-test n start-time)
    (if (is-prime n)
        (report-prime (- (runtime) start-time))
        (display ""))) ;prints nothing

The first version results in "SchemeError: too few operands..." I modified it to have an alternative clause that essentially does nothing, and I'm no longer getting the error when testing the procedure.

I just want to know whether requiring an alternative clause is standard for most Scheme interpreters, or if it's unique to the one I'm using. I AM currently using two different interpreters, because the first one I used does not include the built-in procedures detailed in the book, so I have noticed there are some major differences in Scheme interpreters. But that's as far as I know, and it's been very hard finding useful information through googling.

Any help would be greatly appreciated; I don't like including "do-nothing" procedures.

Eggcellentos
  • 1,570
  • 1
  • 18
  • 25

3 Answers3

2

In most Scheme interpreters if allows expressions without the "else" part, and that's what the standard says, as pointed by @codybartfast in his answer.

I'm only aware of Racket enforcing the rule that if must always have both the consequent and alternative parts, and it's for a very good reason: it'll help you catch the kind of mistakes that happen when you forget to write the "else" part.

Although it's valid to have if expressions without the alternative part, that only happens when we are writing procedural code (like displaying a result in your example), and that's the kind of programming style we want to avoid when using Scheme (as we favor functional programming).

Having said that, if you're absolutely certain that you want to write procedural code, then you should use when, which doesn't have an else part and unlike if, it can have several expressions inside because it has an implicit begin. This will work:

(define (start-prime-test n start-time)
  (when (is-prime n)
    (report-prime (- (runtime) start-time))))
Óscar López
  • 232,561
  • 37
  • 312
  • 386
1

I understand R5RS/R6RS are effectively the language standards. They say that the alternate clause is optional:

(if <test> <consequent> <alternate>)‌‌syntax  
(if <test> <consequent>)‌‌syntax  

Syntax: <Test>, <consequent>, and <alternate> must be expressions.

Semantics: An if expression is evaluated as follows: first, <test> is
evaluated. If it yields a true value (see section 5.7), then <consequent> is
evaluated and its values are returned. Otherwise <alternate> is evaluated
and its values are returned. If <test> yields #f and no <alternate> is
specified, then the result of the expression is unspecified.

But in 2009 (quite recently for scheme), the language steering commitee said:

Alas: Scheme has the unhappy distinction of being the world's most unportable programming language. It is almost misleading to call Scheme a "programming language;" it would be more accurate to characterise Scheme as a family of dialects, all loosely related by the common features of lexical scope, dynamic typing, list structure, higher-order functions, proper tail-recursion, garbage collection, macros, and (some form of) s-expression based lexical syntax.

So although a formal stanard may exist there seems little expectation that any given implementaion will adhere to that standard. E.g. By default Racket requires the alternate clause. (Although Racket can also support a R6RS compliant dialet.)

Personally I use Racket with the SICP language pack to be consistent with the book.

codybartfast
  • 7,323
  • 3
  • 21
  • 25
  • `if` without alternative was an addition to R6RS so it is **not a part of R5RS or earlier**. Racket is an implementation. It supports R5RS, R6RS as well a lot of languages that is not Scheme. **`#lang racket` is not Scheme**. It Was a R5RS, but not any longer, but they haven't changed the `if`. You get the R6RS one when you use the R6RS language. When I use `gcc` I don't expect it to support both K&R C, ANSI C and C++ but I don't expect it to allow us to have C++ code in C files and expect it to work just because it can compile both. GCC also has it's own "language". You see the relevance? – Sylwester May 15 '19 at 13:01
  • @Sylwester The R5RS spec for Conditionals that I looked at (https://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html#%_sec_4.1.5) appeared to allow if without alternate. Am I missing something? (I may have missed something as that was the first time I had looked at the reports.) – codybartfast May 15 '19 at 18:10
  • I'm sorry. I should have double checked, but while I am in the wrong I have though for many years that this was a feature in R6RS. Looking at the reports I find it all the way back to the second report which means it is a very old feature. I still think the steering committee is off since Scheme does not have more diversity than C, which is a younger language. – Sylwester May 15 '19 at 23:14
  • 1
    Thanks @Sylwester. It may not be accurate but perhaps, for folk like me who come from C# and Java, their hyperbole is useful to highlight there is a diverse environment. I just took a quick look at R2RS, it was the first time I noticed the acknowledgement: "We also thank Betty Dexter for the extreme effort she put into setting this report in ϒTEX, and Don Knuth for designing the program that caused her troubles" :-) – codybartfast May 16 '19 at 06:48
0

The one-armed if has indeed been standard in Scheme for a while.

Unfortunately the one-armed if allows one to make a mistake - forgetting the second arm is very easy to do. Some implementations added when and unless to reduce the number of mistakes.

See also: Why is one-armed "if" missing from Racket?

soegaard
  • 30,661
  • 4
  • 57
  • 106