问题
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))
回答1:
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)
回答2:
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 ;-)
回答3:
(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"))
来源:https://stackoverflow.com/questions/22696615/how-to-spell-a-number-in-racket-spellnum