247 |
247 |
248 // Source.fromURL(url)(encoding) |
248 // Source.fromURL(url)(encoding) |
249 // Source.fromFile(name)(encoding) |
249 // Source.fromFile(name)(encoding) |
250 |
250 |
251 |
251 |
|
252 // Tail recursion |
|
253 //================ |
|
254 |
|
255 @tailrec |
|
256 def fact(n: BigInt): BigInt = |
|
257 if (n == 0) 1 else n * fact(n - 1) |
|
258 |
|
259 |
|
260 fact(10) |
|
261 fact(1000) |
|
262 fact(100000) |
|
263 |
|
264 def factB(n: BigInt): BigInt = |
|
265 if (n == 0) 1 else n * factB(n - 1) |
|
266 |
|
267 def factT(n: BigInt, acc: BigInt): BigInt = |
|
268 if (n == 0) acc else factT(n - 1, n * acc) |
|
269 |
|
270 |
|
271 factB(1000) |
|
272 |
|
273 |
|
274 factT(10, 1) |
|
275 println(factT(500000, 1)) |
|
276 |
|
277 |
|
278 // there is a flag for ensuring a function is tail recursive |
|
279 import scala.annotation.tailrec |
|
280 |
|
281 @tailrec |
|
282 def factT(n: BigInt, acc: BigInt): BigInt = |
|
283 if (n == 0) acc else factT(n - 1, n * acc) |
|
284 |
|
285 factT(100000, 1) |
|
286 |
|
287 // for tail-recursive functions the Scala compiler |
|
288 // generates loop-like code, which does not need |
|
289 // to allocate stack-space in each recursive |
|
290 // call; Scala can do this only for tail-recursive |
|
291 // functions |
|
292 |
|
293 // Moral: Whenever a recursive function is resource-critical |
|
294 // (i.e. works with a large recursion depth), then you need to |
|
295 // write it in tail-recursive fashion. |
|
296 // |
|
297 // Unfortuantely, Scala because of current limitations in |
|
298 // the JVM is not as clever as other functional languages. It can |
|
299 // only optimise "self-tail calls". This excludes the cases of |
|
300 // multiple functions making tail calls to each other. Well, |
|
301 // nothing is perfect. |
|
302 |
252 |
303 |
253 |
304 |
254 |
305 |
255 |
306 |
256 // Sudoku |
307 // Sudoku |
389 |
440 |
390 time_needed(1, search(game2)) |
441 time_needed(1, search(game2)) |
391 |
442 |
392 |
443 |
393 |
444 |
394 // Tail recursion |
|
395 //================ |
|
396 |
|
397 @tailrec |
|
398 def fact(n: BigInt): BigInt = |
|
399 if (n == 0) 1 else n * fact(n - 1) |
|
400 |
|
401 |
|
402 fact(10) |
|
403 fact(1000) |
|
404 fact(100000) |
|
405 |
|
406 def factB(n: BigInt): BigInt = |
|
407 if (n == 0) 1 else n * factB(n - 1) |
|
408 |
|
409 def factT(n: BigInt, acc: BigInt): BigInt = |
|
410 if (n == 0) acc else factT(n - 1, n * acc) |
|
411 |
|
412 |
|
413 factB(1000) |
|
414 |
|
415 |
|
416 |
|
417 |
|
418 factT(10, 1) |
|
419 println(factT(500000, 1)) |
|
420 |
|
421 |
|
422 |
|
423 |
|
424 |
|
425 // there is a flag for ensuring a function is tail recursive |
|
426 import scala.annotation.tailrec |
|
427 |
|
428 @tailrec |
|
429 def factT(n: BigInt, acc: BigInt): BigInt = |
|
430 if (n == 0) acc else factT(n - 1, n * acc) |
|
431 |
|
432 factT(100000, 1) |
|
433 |
|
434 // for tail-recursive functions the Scala compiler |
|
435 // generates loop-like code, which does not need |
|
436 // to allocate stack-space in each recursive |
|
437 // call; Scala can do this only for tail-recursive |
|
438 // functions |
|
439 |
|
440 // tail recursive version that searches |
445 // tail recursive version that searches |
441 // for all Sudoku solutions |
446 // for all Sudoku solutions |
|
447 import scala.annotation.tailrec |
442 |
448 |
443 @tailrec |
449 @tailrec |
444 def searchT(games: List[String], sols: List[String]): List[String] = games match { |
450 def searchT(games: List[String], sols: List[String]): List[String] = |
445 case Nil => sols |
451 games match { |
446 case game::rest => { |
452 case Nil => sols |
447 if (isDone(game)) searchT(rest, game::sols) |
453 case game::rest => { |
448 else { |
454 if (isDone(game)) searchT(rest, game::sols) |
449 val cs = candidates(game, emptyPosition(game)) |
455 else { |
450 searchT(cs.map(c => update(game, empty(game), c)) ::: rest, sols) |
456 val cs = candidates(game, emptyPosition(game)) |
451 } |
457 searchT(cs.map(c => update(game, empty(game), c)) ::: rest, sols) |
452 } |
458 } |
453 } |
459 } |
|
460 } |
454 |
461 |
455 searchT(List(game3), List()).map(pretty) |
462 searchT(List(game3), List()).map(pretty) |
456 |
463 |
457 |
464 |
458 // tail recursive version that searches |
465 // tail recursive version that searches |
485 |9724...5.""".stripMargin.replaceAll("\\n", "") |
492 |9724...5.""".stripMargin.replaceAll("\\n", "") |
486 |
493 |
487 searchT(List(game3), Nil).map(pretty) |
494 searchT(List(game3), Nil).map(pretty) |
488 search1T(List(game3)).map(pretty) |
495 search1T(List(game3)).map(pretty) |
489 |
496 |
490 // Moral: Whenever a recursive function is resource-critical |
|
491 // (i.e. works with a large recursion depth), then you need to |
|
492 // write it in tail-recursive fashion. |
|
493 // |
|
494 // Unfortuantely, Scala because of current limitations in |
|
495 // the JVM is not as clever as other functional languages. It can |
|
496 // only optimise "self-tail calls". This excludes the cases of |
|
497 // multiple functions making tail calls to each other. Well, |
|
498 // nothing is perfect. |
|
499 |
|
500 |
|
501 |
497 |
502 |
498 |
503 |
499 |
504 |
500 |
505 |
501 |