(sum (range (inc 10)))Clojure:
(reduce + (range (inc 10)))Likely the most common way:
(loop for i from 1 to 10 sum i) Mostly used in Common LispFunky solution that NO ONE IN THE WORLD USES (CommonLisp version):
(defun sum (start end) (prog (counter total) (setq total 0); 10 LET TOTAL = 0 (setq counter start); 20 LET COUNTER = START loop (setq total (+ total counter)); 30 LET TOTAL = TOTAL + COUNTER (if (= counter end) (return total)); 40 IF COUNTER = END THEN RETURN TOTAL (setq counter (+ counter 1)); 50 LET COUNTER = COUNTER + 1 (go loop))); 60 GOTO 30What is that magnificent language on the right! We must to release it to the world.
It is called BASIC -- it is quite nice.
Funky solution that NO ONE IN THE WORLD USES (SchemeLanguage version):
(define (sum start end) (let ((counter #f) (total #f)) (define (line-10) (set! total 0) (line-20)) (define (line-20) (set! counter start) (line-30)) (define (line-30) (set! total (+ total counter)) (line-40)) (define (line-40) (if (= counter end) total (line-50))) (define (line-50) (set! counter (+ counter 1)) (line-60)) (define (line-60) (line-30)) (line-10)))Math nerd version:
(defun sum-integers (n) (* (1+ n) n 1/2))Using a self-evaluating integer:
55Using Series (in response to "Why not (sum (span 1 10))?"):
(collect-sum (scan-range :from 1 :upto 10))(Scheme) Using Eager Comprehensions as in srfi-42:
(sum-ec (: i 11) i)(Scheme) Using named let:
(let sum ((i 1)) (if (> i 10) 0 (+ i (sum (+ i 1)))))(Scheme) Using named let with accumulator:
(let sum ((i 1) (acc 0)) (if (> i 10) acc (sum (+ i 1) (+ acc i))))(Scheme) Using anonymous recursion with accumulator:
((lambda (f) (f f 1 0)) (lambda (f n acc) (if (> n 10) acc (f f (+ n 1) (+ acc n)))))(Scheme) Using do (trying to make it equivalent to the "normal iterative version":
(do ((i 1 (+ i 1)) (total 0)) ((> i 10) total) (set! total (+ total i)))(Scheme) using apply or reduce on a generated list:
(reduce + 0 (iota n 1)) or (apply + (iota n 1))
The reason there are so many options for suming is because Lisp lets you express your solution in whatever way fits the problem best.
In most functional languages, including SchemeLanguage and CommonLisp, you would implement this using REDUCE. For example in SchemeLanguage...
(reduce + 0 <list-of-numbers>)To get the list of numbers from [1..10] then you would use the IOTA function. For example...
(iota 10 1)returns the list
(1 2 3 4 5 6 7 8 9 10)And so to sum a list from 1 to N you would define a new function, call it SUM-INTEGERS. For example in SchemeLanguage...
(define (sum-integers n) (reduce + 0 (iota n 1))) (sum-integers 10)returns the number
It is simpler just to add the numbers:
(apply + (iota 1 10))-- Jens Axel S�gaard
This solution, while elegant, strikes me as rather wasteful: you construct a list of integers just to immediately throw it away. That being said, it is certainly the preferred idiom for languages with call-by-need semantics, where the list would be constructed lazily. Using HaskellLanguage for example your solution would read
sum [1..10]and consecutive elements of the list would only be constructed if needed. CallByNeed semantics makes it really easy to define possibly infinite structures simply by "writing them down".
(define (sum-integers n) (* (+ n 1) (/ n 2)))-- SunnanFenderson
Beautiful. Everyone's arguing over wasteful memory and throwaway lists, and here you go with a little math - a couple integers and three simple operations. An ounce of math is worth a pound of programming expertise...
[I "invented" this independently, although I wasn't 10 when I did it (19, I think). Does this make me as smart as Gauss? -- about 10/19 as smart]
Does this example have a round off error? For example, does (sum-integers 3) equal 4, or 6 (as it should)? Does this code work better?
(define (sum-integers n) (/ (* (+ n 1) n) 2)I don't know about Scheme implementations, but here is a transcript of a CommonLisp session:
? (defun sum-integers (n) (* (1+ n) (/ n 2))) sum-integers ? (sum-integers 3) 6 ? (/ 5 2) 5/2I think that's exactly as it should be. ;) -- PascalCostanza
The Scheme standard allows for rational numbers, but doesn't require them. Implementations have to provide a "coherent subset" (R5RS) of the numeric tower. In Guile, for example, (/ 5 2) returns 2.5.
I'd have started with something like
(loop for i from 1 to 10 ...)or even the prosaic
(dotimes (i 10) ...)
My point is that most lisp, say, >99%, looks just like code in other languages; i.e. you write it the `obvious' way. Sure, we do closures, macros, pass lots of lambdas around, but people who use lambdas to represent integers are just trying to show off and scare you. Don't let them. -- AlainPicard
Well, I just don't get it. If you want to sum anything, why don't you start with
(sum ...)and if you are going to sum the first ten integers, why don't you write
(sum (span 1 10) )? -- NikitaBelenki (who doesn't actually know Lisp, but likes STL)
How about (collect-sum (scan-range :from 1 :upto 10)) - that's possible in Common Lisp with series (and it doesn't waste space building a list!)
I suspect that as often as not when someone says "I hate Lisp!" it also applies to Scheme. And Alain's point about Lisp programs idiomatically using loops just like the C snippet doesn't apply to Scheme's idioms.
I suspect it usually applies to Scheme first and foremost. -- PederTowne?
I think an idiomatic way of writing this function in scheme (ignoring the more efficient accumulator version) would be:
(define (sum-span first last) (cond ((= first last) last) ((< first last) (+ first (sum-span (+ 1 first) last)))))Which is a codified version of the recursive definition: "The sum-span from X to X (i.e. span of one number) is just X; the sum-span from X to Y (where X < Y) is X plus the sum-span of the number after X to Y." To me, and I expect to most people who're used to scheme, this is in fact "the obvious way" (and a purely functional one) to write that function.
If you hate that style and think it's confusing, but want to face your hatred, then the book TheLittleSchemer might help. It's a tutorial on this style of programming. Though if you're easily offended you may find its colourful style objectionable :-)
This ML type would me more inclined to do:
(define (sum-integers n) (define (sum-helper i a) (cond ((= 0 i) a) (else (sum-helper (- i 1) (+ i a))))) (sum-helper n 0))recursively, with an accumulator and a HelperFunction, like in a lot of textbooks.
In Common Lisp, the same function can be written without the outer function, thanks to optional parameters:
(defun sum-integers (i &optional (a 0)) (if (= 0 i) a (sum-integers (- i 1) (+ i a))))However, I would use a more C-like appoach:
(loop for ix from 1 to 10 sum ix)
Moreover, although Scheme lacks the (loop ...) feature, there are iterative constructs in Scheme, namely do, named let, map and for-each, which is more than many "procedural" languages can boast. Moreover, any other looping construct is only a define-syntax away.
Here is sum-span with named let.
(define (sum-span first last) (let loop ((count first) (sum 0)) (if (> count last) sum (loop (+ count 1) (+ sum count)))))And here it is with my for-macro:
(define (sum-span first last) (let ((sum 0)) (for (i first (+ last 1)) (set! sum (+ i sum))) sum))Which is to say: you can program in Scheme in any style you want. You can even write C programs in Scheme if you really want to (yes you can fake pointers in Scheme, so that you can do things like "take a pointer to a local variable").
I hate the Scheme do-loop with a passion: I never could get the strange parentheses right on the first try and/or without thinking. So I came up with a nice macro, too, so I never had to think about this abomination again. It looks a lot like more conventional languages:
(let ((sum 0)) (for i from 1 to 10 (set! sum (+ sum i))) sum)It can count backwards, too. Should be the same. ;)
(let ((sum 0)) (for i from 10 to 1 step -1 (set! sum (+ sum i))) sum)It also works on lists, like for-each:
(let ((sum 0)) (for i in (iota 10) (set! sum (+ sum i))) sum)It uses the define-syntax facility of R5RS, I used PLT-Scheme:
(define-syntax for (syntax-rules (for in to step) ((for i in elements body ...) (for-each (lambda (i) body ...) elements)) ((for i from start to end step is body ...) (let ((condition (lambda (i) (cond ((< is 0) (< i end)) ((> is 0) (> i end)) (else #f))))) (do ((i start (+ i is))) ((condition i) (void)) body ...))) ((for i from start to end body ...) (do ((i start (+ i 1))) ((> i end) (void)) body ...))))Scheme doesn't come with batteries included, it's more like a box of building blocks, so you can make the language you prefer.
Note that the language Scheme (that is, the content of the standards) contains just about the basics. Almost every Scheme environment contains a large set of libraries that come with it. My favorites are PLT, scsh and SLIB.
I have to do everything myself?
(+ 1 2 3 4 5 6 7 8 9 10)No, that's what the computer is for...
(eval ('+ . (iota n 1)))