Question

I am new to Racket and I want to write a function spellNum which does this:

(spellNum 467) ---> '(four six seven)

I don't know how to start. I have started programming by seeing the online documentation, but I don't know how to declare a variable in Dr Racket. I am basically a Python guy. can somebody give me a push to program this function?

(define (spellNum n)
  (if (number? n)
    (what should I do ?)
      null))
Was it helpful?

Solution

EDITED:

A complete solution has been posted, so I guess it's ok for me to show you how to write an idiomatic procedure. Notice that number->list uses a technique called tail recursion for efficiently expressing a loop. Although (coming from a Python background) it might be tempting to use an explicit looping construct (as shown in @uselpa's answer), to really get in the spirit of Scheme you should learn how to write a loop using recursion, it's the standard way to express iteration in this language (When in Rome, do as the Romans do):

(define (digit->symbol n)
  (case n
    ((0) 'zero)
    ((1) 'one)
    ((2) 'two)
    ((3) 'three)
    ((4) 'four)
    ((5) 'five)
    ((6) 'six)
    ((7) 'seven)
    ((8) 'eight)
    ((9) 'nine)
    (else (error "unknown digit:" n))))

(define (number->list n)
  (let loop ((acc '()) (n n))
    (if (< n 10)
        (cons n acc)
        (loop (cons (remainder n 10) acc) (quotient n 10)))))

(define (spellNum n)
  (map digit->symbol (number->list n)))

The trick is to split the problem in different parts, digit->symbol converts a single digit into a symbol. Similarly, number->list transforms a number into a list of numbers. After writing those helper procedures it's easy to write spellNum, which works as expected:

(spellNum 467)
=> '(four six seven)

OTHER TIPS

As Oscar says, you should really learn the Scheme-specific idioms.

But, coming from Python, you might find it easier at first to use classical loops, and Racket provides those as well. Let's build a Racket-specific solution:

First, for/list goes over a sequence (such as a list, a string, same as Python's for ... in construct) and builds a list:

(define (spellNum n)
  (for/list [(c (number->string n))] 
    c))

(spellNum 467)
=> '(#\4 #\6 #\7)

This builds a list of chars. Let's convert those to strings again:

(define (spellNum n)
  (for/list [(c (number->string n))] 
    (string c)))

(spellNum 467)
=> '("4" "6" "7")

Now, we can convert those to numbers using string->number:

(define (spellNum n)
  (for/list [(c (number->string n))] 
    (string->number (string c))))

(spellNum 467)
=> '(4 6 7)

And finally, convert those to symbols:

(define (spellNum n)
  (for/list [(c (number->string n))] 
    (list-ref '(zero one two three four five six seven eight nine)
              (string->number (string c)))))

(spellNum 467)
=> '(four six seven)

So, the complete procedure can be expressed in 3-4 lines of code, but again this is Racket-specific. I'd strongly encourage you to learn the Scheme way of doing things, which is more general and very enlightening ;-)

(require srfi/26)

(define (spell-number n)
  (if (number? n)
      (let ([h (hash #\1 "one"
                      #\2 "two"
                      #\3 "three"
                      #\4 "four"
                      #\5 "five"
                      #\6 "six"
                      #\7 "seven"
                      #\8 "eight"
                      #\9 "nine"
                      #\0 "zero"
                      #\. "point" )])
             (string-join (map (cut hash-ref h <>) (string->list (number->string n))) " "))
             ;; else
             "not a number"))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top