CHAP19 - Modern-Java-in-Action/Online-Study GitHub Wiki

์ฑ•ํ„ฐ19 ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋ฒ•

์ด๋ฒˆ์žฅ์—์„œ ๋‹ค๋ฃฐ ๋‚ด์šฉ๋“ค

  • ๊ณ ์ฐจ์›ํ•จ์ˆ˜, ์ปค๋ง, ์˜๊ตฌ ์ž๋ฃŒ๊ตฌ์กฐ, ๊ฒŒ์œผ๋ฅธ ๋ฆฌ์ŠคํŠธ, ํŒจํ„ด ๋งค์นญ
  • ์ฐธ์กฐ ํˆฌ๋ช…์„ฑ์„ ์ด์šฉํ•œ ์บ์‹ฑ, ์ฝค๋น„๋„ค์ดํ„ฐ

19.1 ํ•จ์ˆ˜๋Š” ๋ชจ๋“ ๊ณณ์—

19.1.1 ๊ณ ์ฐจ์› ํ•จ์ˆ˜ : ํ•จ์ˆ˜๋ฅผ ์ž…๋ ฅ|์ถœ๋ ฅํ•˜๋Š” ํ•จ์ˆ˜

  • ๊ณ ์ฐจ์› ํ•จ์ˆ˜๋ž€, ๋‹ค์Œ ํ•˜๋‚˜ ์ด์ƒ์˜ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜
    • ํ•˜๋‚˜ ์ด์ƒ์˜ ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์Œ
    • ํ•จ์ˆ˜๋ฅผ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜
      • ๋ฏธ๋ถ„์—์„œ f(x)=x^2์„ f(x)=2x๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ
  • ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜์— ๋ถ€์ž‘์šฉ์ด ์—†์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ
    • ๊ณ ์ฐจ ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜์—๋„ ๋ถ€์ž‘์šฉ์ด ์—†์–ด์•ผ ํ•œ๋‹ค
    • ์•„๋‹ˆ๋ฉด ๋ถ€์ •ํ™•ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๊ฑฐ๋‚˜, ๊ฒฝ์Ÿ์ƒํƒœ์— ๋น ์งˆ ์ˆ˜ ์žˆ๋‹ค
    • ์‹ค๋ฌด์—์„œ๋Š” ์–ด๋–ค ๋ถ€์ž‘์šฉ์„ ์ผ์œผํ‚ฌ์ง€ ์ •ํ™•ํ•˜๊ฒŒ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•œ๋‹ค

19.1.2 ์ปค๋ง : ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜

  • ์ปค๋ง์ด๋ž€, x, y ๋‘ ์ธ์ˆ˜๋ฅผ ๋ฐ›๋Š” ํ•จ์ˆ˜ f๋ฅผ, ํ•œ ๊ฐœ ์ธ์ˆ˜๋งŒ ๋ฐ›๋Š” gํ•จ์ˆ˜๋กœ ๋Œ€์ฒด
  • ์ปค๋ง ๊ธฐ๋ฒ•์„ ์ ์šฉํ•œ ์˜ˆ์‹œ
//์ผ๋ฐ˜์ ์ธ ๋ณ€ํ™˜ํ•จ์ˆ˜
static double converter(double x, double f, double b){
  return x * f + b;
}

//์‚ฌ์šฉํ• ๋•Œ๋งˆ๋‹ค ๋ณ€ํ™˜ํ•  ๊ฐ’๊ณผ ํ•จ๊ป˜ ๊ธฐ์ค€๊ฐ’์„ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค
converter(36.5, 9, 32);
//๋ณ€ํ™˜ํ•จ์ˆ˜ ํŒฉํ† ๋ฆฌํ•จ์ˆ˜
static DoubleUnaryOperator curriedConverter(double f, double b){
  return (double x) -> x * f + b;
}

//์›ํ•˜๋Š”๋Œ€๋กœ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
DoubleUnaryOperator convertCtoF = curriedConverter(9.0/5, 32);
DoubleUnaryOperator convertUSDtoGBP = curriedConverter(0.6, 0);
DoubleUnaryOperator convertKmtoMi = curriedConverter(0.6214, 0);

//์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ณ€ํ™˜ํ•  ๊ฐ’๋งŒ applyํ•œ๋‹ค.
convertCtoF.applyAsDouble(1000);

19.2 ์˜์† ์ž๋ฃŒ๊ตฌ์กฐ: ์˜ํ–ฅ๋ฐ›์ง€ ์•Š๋Š” ์ž๋ฃŒ๊ตฌ์กฐ

  • ์˜์†์ด๋ž€, ์ €์žฅ๋œ ๊ฐ’์ด ๋ˆ„๊ตฐ๊ฐ€์— ์˜ํ•ด ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š” ์ƒํƒœ์ด๋‹ค.

    • ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
    • ๊ฒฐ๊ณผ๋กœ ์ „๋‹ฌ๋œ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
      • ํ•„๋“œ๋ฅผ final ์„ ์–ธํ•ด์„œ ์ œ์•ฝ์„ ๊ฑธ ์ˆ˜ ์žˆ๋‹ค.
        • ํ•„๋“œ๋ฅผ ๋‹ค๋ฅธ ๊ฐ์ฒด๋กœ ๋Œ€์ฒดํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ, ํ•„๋“œ ๋‚ด๋ถ€ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜๋Š” ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ์˜. ํ•„์š”ํ•œ ๊ณณ์— final์„ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
  • ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ๋•Œ

    • ๊ธฐ์กด ์ž๋ฃŒ๊ตฌ์กฐ ์ผ๋ถ€๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์ƒˆ๋กœ์šด ์ž๋ฃŒ๊ตฌ์กฐ
      • ๊ฐ’์ด ๋น ๋ฅด๊ฒŒ ๋ณ€๊ฒฝ๋˜๋Š” ๊ณณ
      • ex) ๋ฐ์ดํ„ฐ์ˆ˜์ง‘
    • ๊ธฐ์กด ์ž๋ฃŒ๊ตฌ์กฐ ๊ฐ’๋งŒ ๋ณต์‚ฌ
      • ์—ฐ์‚ฐ์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๊ณณ
      • ex) ๋ฐ์ดํ„ฐ๋ถ„์„

19.2.1 ๋ฆฌ์ŠคํŠธ ์˜ˆ์ œ

  • ์—ฐ์‚ฐ๋„์ค‘ ๊ฐ€๋ณ€๊ฐ์ฒด๋ฅผ ๊ฐฑ์‹ ํ•˜๋Š” ๊ฒฝ์šฐ, ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋‹ค๋ฅธ ์—ฐ์‚ฐ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
  • A-B-C ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฐธ์กฐํ•ด์„œ A-C๊นŒ์ง€ ๊ฐ€์ค‘์น˜ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ์—ฐ์‚ฐ
    • ์‹œ๋‚˜๋ฆฌ์˜ค1 : ๊ธฐ์กด ๋ฆฌ์ŠคํŠธ ์ค‘๊ฐ„์— ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ A-B-Z-C
      • ๊ธฐ์กด ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฐธ์กฐํ•˜๋˜ ์—ฐ์‚ฐ์€ ์˜ˆ์ƒํ•˜๋˜ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ›์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์‹œ๋‚˜๋ฆฌ์˜ค2 : ๊ธฐ์กด ๋ฆฌ์ŠคํŠธ์—์„œ A-B๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์ƒˆ๋กœ์šด Z-C ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์—ฐ์‚ฐ
      • ๊ธฐ์กด ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฐธ์กฐํ•˜๋˜ ์—ฐ์‚ฐ๋„ ์˜ˆ์ƒ ๊ฒฐ๊ณผ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

19.2.2 ํŠธ๋ฆฌ ์˜ˆ์ œ

19.3 ์ŠคํŠธ๋ฆผ๊ณผ ๊ฒŒ์œผ๋ฅธ ํ‰๊ฐ€

  • ์ด๋ฒˆ ์žฅ์—์„œ ์•Œ์•„๋ณผ ๊ฒƒ๋“ค
    • ์ŠคํŠธ๋ฆผ์€ ํ•œ ๋ฒˆ๋งŒ ์†Œ๋น„ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์ŠคํŠธ๋ฆผ์€ ์žฌ๊ท€์ ์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์—†๋‹ค.

19.3.1 ์žฌ๊ท€์ ์œผ๋กœ ์ •์˜ํ•˜๋Š” ์ŠคํŠธ๋ฆผ

  • ๊ธฐ์กด ์•Œ๊ณ ๋ฆฌ์ฆ˜

    • ํ›„๋ณด ์ˆ˜ n์„ 2~sqrt(n)์œผ๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€๋Š”์ง€ ํ™•์ธ
  • ์ƒˆ๋กœ์šด ์•Œ๊ณ ๋ฆฌ์ฆ˜

    • 1๋‹จ๊ณ„ ์ŠคํŠธ๋ฆผ ์ˆซ์ž ์–ป๊ธฐ : 2๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ๋ฌดํ•œ ์ˆซ์ž ์ŠคํŠธ๋ฆผ
    • 2๋‹จ๊ณ„ ๋จธ๋ฆฌ ํš๋“ : ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ํš๋“ obj.findFirst()
    • 3๋‹จ๊ณ„ ๊ผฌ๋ฆฌ ํ•„ํ„ฐ๋ง : ๊ผฌ๋ฆฌ๋ฅผ ํš๋“ obj.skip(1), ํ•„ํ„ฐ๋ง ์ง„ํ–‰ obj.filter(n->n%head!=0)
    • 4๋‹จ๊ณ„ ์žฌ๊ท€์ ์œผ๋กœ ์†Œ์ˆ˜ ์ŠคํŠธ๋ฆผ ์ƒ์„ฑ
  • ์‹คํ–‰ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค! ์™œ๋ƒํ•˜๋ฉด..

    • ์ŠคํŠธ๋ฆผ์€ ํ•œ๋ฒˆ๋งŒ ์†Œ๋น„๋  ์ˆ˜ ์žˆ๋‹ค.
      • head()์—์„œ findFirst()๋กœ ์†Œ๋น„๋˜๊ณ 
      • tail()์—์„œ skip()์„ ํ˜ธ์ถœํ•˜๋‹ˆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ
    • ์ŠคํŠธ๋ฆผ์€ '์žฌ๊ท€์  ์ •์˜๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.'
      • ๋Œ€์‹  ์‹ค์ œ๋กœ ํ•„์š”ํ• ๋•Œ ์ŠคํŠธ๋ฆผ์„ '๊ฒŒ์œผ๋ฅด๊ฒŒ ํ‰๊ฐ€'ํ•˜๋ฉด ์œ„ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋Œ€๋กœ ์ž‘๋™์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
        • ์Šค์นผ๋ผ์—์„œ๋Š” #:: ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
        • ์•ž์„œ ๋ฐฐ์šด ๊ฒƒ์ฒ˜๋Ÿผ ()->something ์„œํ”Œ๋ผ์ด์–ด๋กœ ๊ฐ์‹ธ๋„ ๋˜๊ฒ ๋‹ค.
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
	at java.base/java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203)
	at java.base/java.util.stream.IntPipeline.<init>(IntPipeline.java:91)
	at java.base/java.util.stream.IntPipeline$StatefulOp.<init>(IntPipeline.java:655)
	at java.base/java.util.stream.SliceOps$2.<init>(SliceOps.java:231)
	at java.base/java.util.stream.SliceOps.makeInt(SliceOps.java:231)
	at java.base/java.util.stream.IntPipeline.skip(IntPipeline.java:410)
	at CHAPTER19.PrimeNumber.tail(Chapter19Main.java:23)
	at CHAPTER19.PrimeNumber.primes(Chapter19Main.java:30)
	at CHAPTER19.Chapter19Main.main(Chapter19Main.java:7)
package CHAPTER19;

import java.util.stream.IntStream;

public class Chapter19Main {
    public static void main(String[] args){
        PrimeNumber.primes(PrimeNumber.numbers()).forEach(System.out::println);
    }
}

class PrimeNumber{
    static IntStream numbers(){
        return IntStream.iterate(2, n -> n + 1);
    }

    static int head(IntStream numbers){
        return numbers.findFirst().getAsInt();
    }

    static IntStream tail(IntStream numbers){
        return numbers.skip(1);
    }

    static IntStream primes(IntStream numbers){
        int head = head(numbers);
        return IntStream.concat(
                IntStream.of(head),
                primes(tail(numbers).filter(n->n%head!=0))
        );
    }

}

19.3.2 ๊ฒŒ์œผ๋ฅธ ๋ฆฌ์ŠคํŠธ ๋งŒ๋“ค๊ธฐ

  • ๊ฒŒ์œผ๋ฅธ ๋ฆฌ์ŠคํŠธ
    • tail์„ void -> T ์„œํ”Œ๋ผ์ด์–ด๋กœ ๋Œ€์ฒด, tail์„ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ํ‰๊ฐ€ํ•จ
    • ์†Œ์ˆ˜ ํŒ๋ณ„๋„ ํ”„๋ฆฌ๋””์ผ€์ดํŠธ๋กœ, ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ํ‰๊ฐ€ํ•จ
  • ๊ผฌ๋ฆฌํ˜ธ์ถœ ์žฌ๊ท€๊ฐ€ ์ง€์›๋˜์ง€ ์•Š๊ธฐ์—, ์•„๋ž˜ ์˜ˆ์ œ์ฝ”๋“œ๋Š” ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค
  • ๋กœ์ง์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ์–ด๋ ค์› ๋‹ค.
    • ๋‘๋ฒˆ์งธ ์ฝ”๋“œ์˜ ์‹œ์ž‘์ ์€ printall
    • tail์„ ์žฌ๊ท€์ ์œผ๋กœ ํ‰๊ฐ€ํ•ด primes์˜ ์ธ์ˆ˜๋กœ ๋„˜๊ฒจ ์†Œ์ˆ˜๊ฐ€ ์•„๋‹Œ ์ˆ˜๋ฅผ ๊ฑธ๋Ÿฌ๋‚ธ๋‹ค
      • ํ‰๊ฐ€ํ•œ tail์ด head๋กœ filterํ•ด์„œ ๋‚˜๋ˆ„์–ด๋–จ์–ด์ง€์ง€ ์•Š์œผ๋ฉด
        • ์†Œ์ˆ˜์ด๋ฏ€๋กœ ์ƒˆ๋กœ์šด ์„œํ”Œ๋ผ์ด์–ด๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ์ข…๋ฃŒํ•œ๋‹ค

          • โฎ‘ ๋‹ค์‹œ primes๋กœ ๋Œ์•„๊ฐ€ ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ๊ฐ€ ๋‚ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•œ๋‹ค
        • ์†Œ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ tail์„ ๋‹ค์‹œ ํ‰๊ฐ€ํ•˜๊ณ  filter๋ฅผ ์žฌ๊ท€ํ˜ธ์ถœํ•œ๋‹ค

package CHAPTER19;

import java.util.function.Predicate;
import java.util.function.Supplier;

public class MyLinkedListMain{
    public static void main(String args[]){
        /* ๊ฒŒ์œผ๋ฅด๊ฒŒ ์žฌ๊ท€์ ์œผ๋กœ ๋Š˜์–ด๋‚˜๋Š” ์ˆซ์ž ๋ฆฌ์ŠคํŠธ */
        System.out.println("1. ===========================");
        MyLinkedList<Integer> numbers = from(2);
        int two = primes(numbers).head();
        System.out.println(two);
        int three = primes(numbers).tail().head();
        System.out.println(three);
        int five = primes(numbers).tail().tail().head();
        System.out.println(five);

        /* ๊ณ„์† ์ˆ˜ํ–‰ํ•˜๋ฉด ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค */
        System.out.println("2. ===========================");
        try{
            printAll(primes(from(2)));
        } catch(StackOverflowError e){
            //e.printStackTrace();
            System.out.println("stack overflow");
        } catch(IllegalStateException e){
            System.out.println("BREAK");
        }
    }

    public static MyLinkedList<Integer> primes(MyLinkedList<Integer> numbers){
        return new MyLinkedList<Integer>(
                numbers.head(),
                ()->primes(
                        numbers.tail()
                                .filter(n->{
                                            System.out.print("filter "+n+" by "+numbers.head()+"/ ");
                                            return (n%numbers.head()!=0);
                                        }
                                )
                ));
    }

    public static MyLinkedList<Integer> from(int n){
        System.out.print("from@"+n+"/ ");
        return new MyLinkedList<Integer>(n, ()->from(n+1));
    }

    public static void printAll(MyLinkedList<Integer> list){
        if(list.isEmpty()) return;
        System.out.println(list.head());
        printAll(primes(list.tail()));
    }
}

class MyLinkedList<T> implements MyList<T> {
    public static int cnt = 0;
    private final T head;
    private final Supplier<MyLinkedList<T>> tail;

    public MyLinkedList(T head, Supplier<MyLinkedList<T>> tail){
        this.head = head;
        this.tail = tail;
    }

    @Override
    public T head() {
        return head;
    }

    @Override
    public MyLinkedList<T> tail() {
        //์ œํ•œ์„ ๋‘ 
        if((int)head>=50) throw new IllegalStateException("BREAK");
        return tail.get();
    }

    @Override
    public boolean isEmpty(){
        return false;
    }

    public MyLinkedList<T> filter(Predicate<T> p){
        return isEmpty() ?
                this :
                p.test(head()) ? //ํ‰๊ฐ€ํ•œ tail์ด head๋กœ filterํ•ด์„œ ๋‚˜๋ˆ„์–ด๋–จ์–ด์ง€์ง€ ์•Š์œผ๋ฉด
                        new MyLinkedList<T>(head(), ()->tail().filter(p)) : //์ฐธ์ด๋ฉด ์†Œ์ˆ˜์ด๋ฏ€๋กœ, ์ƒˆ๋กœ์šด ์„œํ”Œ๋ผ์ด์–ด๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ์ข…๋ฃŒ
                        tail().filter(p); //๊ฑฐ์ง“์ด๋ฉด ์†Œ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ, tail์„ ๋‹ค์‹œ ํ‰๊ฐ€ํ•˜๊ณ  filter๋ฅผ ์žฌ๊ท€ํ˜ธ์ถœ
    }
}

interface MyList<T>{
    T head();
    MyList<T> tail();
    default boolean isEmpty(){
        return true;
    }
}

class Empty<T> implements MyList<T>{
    @Override
    public T head(){
        throw new UnsupportedOperationException();
    }

    @Override
    public MyList<T> tail(){
        throw new UnsupportedOperationException();
    }
}
  • ๊ทธ๋Ÿฐ๋ฐ ์‚ฌ์‹ค ์œ„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์—๋ผํ† ์Šคํ…Œ๋„ค์Šค์˜ ์ฒด๊ฐ€ ์•„๋‹ˆ๋‹ค. ๋œ ํšจ์œจ์ ์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.

    • ์—๋ผํ† ์Šคํ…Œ๋„ค์Šค์˜ ์ฒด : ์†Œ์ˆ˜๋ฅผ ์ฐพ๊ณ , ๊ทธ ์†Œ์ˆ˜์˜ ๋ฐฐ์ˆ˜๋ฅผ ๋ชฉ๋ก์—์„œ ๋ชจ๋‘ ์ง€์šด๋‹ค. ๋ฐ˜๋ณตํ•œ๋‹ค.

      • 2 -> 4, 6, 8, 10์ด ๋ชจ๋‘ ์—†์–ด์ง„๋‹ค.
    • 19.3์ ˆ์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ : n++๋ณด๋‹ค ์ž‘์€ ์†Œ์ˆ˜๋กœ n์„ ๋‚˜๋ˆ ๋ณธ๋‹ค. ๋‚˜๋ˆ ์ง€์ง€ ์•Š์œผ๋ฉด ์†Œ์ˆ˜๋กœ ํŒ๋‹จํ•˜๊ณ  ์†Œ์ˆ˜ ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ•œ๋‹ค. ๋ฐ˜๋ณตํ•œ๋‹ค.

      • 2, 3, 4 ์ˆœ์„œ๋Œ€๋กœ ํ‰๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ ํ™”๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค.
      • ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋ฌดํ•œํ•œ ์ˆ˜์— ๋Œ€ํ•˜์—ฌ ์—ฐ์‚ฐ์„ ๊ณ„์†ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

19.4 ํŒจํ„ด ๋งค์นญ: ๊ฐ•๋ ฅํ•œ switch๋กœ ๋‹ค์ค‘ ์กฐ๊ฑด๊ฒ€์‚ฌ ์ถ”์ƒํ™”

  • ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์„ ์ž๋ฐ”์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

    • f(0) = 1, f(n) = n * f(n-1)
    • ๋‹ค์ด๋‚˜๋ฏน ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œํ’€์ด๋ฅผ ํ•  ๋•Œ, ์ด๋Ÿฐ ๊ฒฝ์šฐ dp[0]=1๋‚˜ if(n==0) return 1;๋“ฑ ์ง์ ‘ ์ฒ˜๋ฆฌํ•ด์ค˜์•ผํ–ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ์—†์„๊นŒ?
  • ๋ณด๋‹ค ๊ตฌ์ฒด์ ์ธ ์˜ˆ๋ฅผ ๋“ค๋ฉด

    • new BiOperation("+", new Number(5), new Number(0))๋ฅผ new Number(5)๋กœ ๋‹จ์ˆœํ™”ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
    • ๋ฉ”์„œ๋“œ ์ธ์ˆ˜์˜ ํ˜•์‹๊ณผ ๊ฐ’์œผ๋กœ, ๋ง์…ˆ ๊ทธ๋ฆฌ๊ณ  ๋”ํ•˜๋Š” ์ˆซ์ž๊ฐ€ 0์ธ์ง€ ํ™•์ธํ•œ๋‹ค.
    • ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ์ง์ ‘ ๊ฒ€์‚ฌํ•  ์ˆ˜๋Š” ์—†์œผ๋ฏ€๋กœ, ์ธ์ˆ˜๋ฅผ ๊ฐ๊ฐ ๊ฒ€์‚ฌํ•œ๋‹ค.
Expression simplyfyExpression(Expression expr){
	if(expr instanceof BiOperation
		&& ((BiOperation)expr).opname.equals("+")
		&& ((BiOperation)expr).right intanceof Number
		&& ((Number)((BiOperation)expr).right).value.equals(0))
			return (BiOperation)expr.left;
}

19.4.1 ๋ฐฉ๋ฌธ์ž ๋””์ž์ธ ํŒจํ„ด: ๊ฐ์ฒด ์ฒ˜๋ฆฌ๋กœ์ง์„ ์œ„์ž„ํ•œ๋‹ค๋ฉด

  • ๋ฐฉ๋ฌธ์ž ๋””์ž์ธ ํŒจํ„ด์œผ๋กœ ์ฒ˜๋ฆฌ๋กœ์ง์„ '์œ„์ž„'ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๋ฐฉ๋ฌธ์ž ๋””์ž์ธ ํŒจํ„ด์ด๋ž€?
    • ์–ด๋–ค ์ ์ด ๋‚˜์•„์ง„๊ฑธ๊นŒ?
      • ์ฒ˜๋ฆฌ๋กœ์ง์„ ์œ„์ž„
        • ๊ธฐ์กด ๊ฐ์ฒด์˜ ๋ฉค๋ฒ„๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์—ฐ์‚ฐ์„ ์ถ”๊ฐ€
        • ์–ด๋””์„œ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ๋ถ„๋ช…ํ•˜๊ฒŒ ํ‘œํ˜„
public class SimplifyVisitor{
	public Expr visit(BinOp e){
		if("+".equals(e.opname) && e.right.instanceof Number && ...){
			return e.left;
		}
		return e;
	}
}

class BinOp extends Expr{
	public Expr accept(SimplifyExprVisitor v){
		return v.visit(this);
	}
}
  • ๋ฐฉ๋ฌธ์ž ๋””์ž์ธ ํŒจํ„ด์€

  • ์œ„ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ ์–ด๋–ค ์ ์ด ๋‚˜์•„์ง„๊ฑธ๊นŒ...

    • ์žฅ์ 
      • ์ดํ•ญ์—ฐ์‚ฐ ๊ฐ์ฒด ์ž๊ธฐ์ž์‹ ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง์„ ๋‹ค๋ฅธ ๊ฐ์ฒด๋กœ ์œ„์ž„ํ•œ๋‹ค.
    • ๋‹จ์ 
      • ์ดํ•ญ์—ฐ์‚ฐ์ด ์•„๋‹ˆ๋ผ ์‚ผํ•ญ์—ฐ์‚ฐ์„ ๊ฐ„๋žตํ•˜๊ฒŒ ํ‘œํ˜„ํ•˜๋ ค๋ฉด, visit์„ ์ƒˆ๋กœ ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค. ํ˜น์€ ์ดํ•ญ์—ฐ์‚ฐ ๋ฉค๋ฒ„๊ฐ€ ๋ฐ”๋€Œ๋ฉด visit์„ ์ƒˆ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.
      • ์—ฐ์‚ฐ ๊ฐ์ฒด์™€ ๊ฐ„๋žตํ•˜๊ฒŒ ํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์„œ๋กœ ๋งŽ์ด ์˜์กดํ•˜๊ฒŒ ๋œ๋‹ค.
    • ๋‚ด ์ƒ๊ฐ
      • ์ฃผ์ฒด.๋ฉ”์„œ๋“œ(๋Œ€์ƒ)์™€ ๋Œ€์ƒ.๋ฉ”์„œ๋“œ(์ฃผ์ฒด)์˜ ๊ฒฐ๊ณผ๋Š” ๊ฐ™๋‹ค.
      • ๊ทธ๋Ÿฌ๋‚˜ ๋Œ€์ƒ.๋ฉ”์„œ๋“œ(์ฃผ์ฒด) ํŒจํ„ด์€, ๋Œ€์ƒ์„ ์ฒ˜๋ฆฌํ•  ๋กœ์ง์„ ์ฃผ์ฒด๋กœ ์œ„์ž„ํ•œ๋‹ค๋Š” ์ ์„ ๋” ๋ถ„๋ช…ํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
      • ์œ„์™€ ๊ฐ™์€ ํŒจํ„ด์„ ๊ณ„์†ํ•ด์„œ ์ด์–ด์„œ ์‚ฌ์šฉํ•˜๋ฉด, ๊ธฐ์กด ํด๋ž˜์Šค ๋ฉค๋ฒ„๋Š” ์œ ์ง€ํ•œ์ฑ„๋กœ ์ƒˆ๋กœ์šด ์—ฐ์‚ฐ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

19.4.2 ํŒจํ„ด๋งค์นญ: switch/case๊ฐ€ ๋” ๋งŽ์€ ํ˜•์‹์„ ์ง€์›ํ•œ๋‹ค๋ฉด

  • ๋งŒ์•ฝ, switch/case์—์„œ ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋” ๊ฐ„๋‹จํžˆ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.
    • ์Šค์นผ๋ผ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ํŒจํ„ด๋งค์นญ์„ ์ง€์›ํ•œ๋‹ค.
    • ์ž๋ฐ”๋Š” ์ง€์›์•ˆํ•œ๋‹ค.
      • ๊ธฐ๋ณธํ˜•, ์—ด๊ฑฐํ˜•, ์ผ๋ถ€ ๊ธฐ๋ณธํ˜• ๋ž˜ํผํด๋ž˜์Šค, ๋ฌธ์ž์—ด ๋“ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
def simplifyExpression(expr: Expr): Expr = expr match{
	case BinOp("+", e, Number(0)) => e
	case BinOp("*", e, Number(1)) => e
	case BinOp("/", e, Number(1)) => e
	case _ => expr
}
  • ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ์—๊ฒ ๋žŒ๋‹ค๊ฐ€ ์žˆ๋‹ค. ๋žŒ๋‹ค๋กœ ํŒจํ„ด๋งค์นญ์„ ํ‰๋‚ด๋‚ด๋ณด์ž.
    • ์Šค์นผ๋ผ์˜ ๊ฒฝ์šฐ ๋‹ค์ค‘ switch๋ฌธ์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
      • ๋จผ์ € BinOp ๋ฉ”์„œ๋“œ์ธ์ง€ ํ™•์ธํ•˜๊ณ 
      • ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ํ™•์ธํ•œ๋‹ค
    • ์ž๋ฐ”์˜ ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์€ ์ฝ”๋“œ๋กœ ๋ณด๋‹ค ๋ฒ”์šฉ์ ์ธ switch๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
//์‚ฌ์šฉ
myIf(n%2==0, ()->42์–ต*42์–ต, ()->42์–ต);
myIf(do(something).IsSucceed(), ()->successHandler, ()->failHandler);

//๊ตฌํ˜„
static <T> T myIf(boolean b, Supplier<T> truecase, Supplier<T> falsecase){
	return b ? truecase.get() : falsecase.get();
}

์—ฐ์‚ฐ์„ ๊ฐ„๋‹จํžˆํ•˜๋Š” ๊ธฐ์กด์˜ˆ์ œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

  • ๊ทธ๋Ÿฌ๋ฉด ์–ด๋–ค ์ ์ด ๋” ๋‚˜์•„์ง€๋‚˜?
    • ์ถ”์ƒํ™”: ์กฐ๊ฑด๋ฌธ์„ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€๋กœ ๋ชจ๋‘ ๊ฐ์ท„๋‹ค.
    • ๋‹คํ˜•์„ฑ: TriFunction, ๊ทธ๋ฆฌ๊ณ  ์„œํ”Œ๋ผ์ด์–ด๋ฅผ ๋‹ค์‹œ ์ •์˜ํ•˜๋ฉด, ์ˆซ์ž๋ฟ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ํ˜•์‹์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
      • ์ด๋ฅผํ…Œ๋ฉด ์„œํ”Œ๋ผ์ด์–ด๋ฅผ ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ฌธ์ž์—ด ๊ฐ’์„ ์ฝ๋Š” ๊ฒƒ์œผ๋กœ ๋ฐ”๊พธ๊ณ 
      • TriFunction์—์„œ๋Š” ๋ฌธ์ž์—ด ๋ง์…ˆ์—์„œ ๋’ค์— ๋นˆ ๋ฌธ์ž์—ด์ด ์˜ค๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์™ผ์ชฝ ์ธ์ˆ˜๋งŒ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋“ ์ง€
    • ์ฝ”๋“œ์˜ ์–‘์€ ๋ณ€ํ•จ์—†๋‹ค.
//์‚ฌ์šฉ
simplify(new BiOperation("+", new Number(5), new Number(0)));

//๊ตฌํ˜„
interface TriFunction<S, T, U, R>{
  R apply(S s, T t, U u);
}

static <T> T patternMatchExpr(
	Expr e,
  TriFunction<String, Expr, Expr, T> binopcase,
  Function<Integer, T> numcase,
  Supplier<T> defaultcase){
  
  return
    (e instanceof BinOp) ?
    	binopcase.apply(((BinOp)e).opname, ((BinOp)e).left,
                      									 ((BinOp)e).right) :
  	(e instanceof Number) ?
      numcase.apply(((Number)e).val) :
  		defaultcase.get();
}

public static Expr simplify(Expr e){
  TriFunction<String, Expr, Expr, Expr> binopcase = 
    (opname, left, right) -> {
  		if("+".equals(opname)){
        if(left instanceof Number && ((Number)left).val==0){
          return right;
        }
        if(right instanceof Number && ((Number)right).val==0){
          return left;
        }
      } 
    	if("*".equals(opname)){
        //do something;
      }
    	return new BinOp(opname, left, right);
  };
  Function<Integer, Expr> numcase = val -> new Number(val);
  Supplier<Expr> defaultcase = () -> new Number(0);
  
  return patternMatchExpr(e, binopcase, numcase, defaultcase);
}

19.5 ๊ธฐํƒ€

  • ํ•จ์ˆ˜ํ˜• ๋ถ€์ˆ˜ ํšจ๊ณผ (Side Effect), ์ฐธ์กฐ ํˆฌ๋ช…์„ฑ (Referential Transparency) โ€“ Jinwoo's Blog (wordpress.com)

    • ๋ถ€์ˆ˜ํšจ๊ณผ/๋ถ€์ž‘์šฉ : ํ•จ์ˆ˜๋‚ด ์‹คํ–‰์œผ๋กœ ํ•จ์ˆ˜ ์™ธ๋ถ€๊ฐ€ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๊ฒƒ
    • ์ฐธ์กฐํˆฌ๋ช…์„ฑ : ํ•จ์ˆ˜/๋ฉ”์„œ๋“œ๊ฐ€ ํ•จ์ˆ˜ ์™ธ๋ถ€์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š” ๊ฒƒ
      • ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋Š” ์ž…๋ ฅ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์˜์กดํ•˜๊ณ , ํ•จ์ˆ˜ ์™ธ๋ถ€(๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ)์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ๊ฒƒ.
      • ํŠน์ง•
        • ์ž๊ธฐ์ถฉ์กฑ์ : ํ•จ์ˆ˜ ์™ธ๋ถ€์— ์˜์กดํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์—†๊ณ , ํ•จ์ˆ˜ ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ๋Š” ์œ ํšจํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ ์ „๋‹ฌํ•˜๋ฉด ๋œ๋‹ค.
        • ๊ฒฐ์ •๋ก ์ : ๋™์ผํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•ด์„œ๋Š” ํ•ญ์ƒ ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค.
        • ์˜ˆ์™ธ๋ฅผ ๋˜์ง€์ง€ ์•Š๋Š”๋‹ค. ์˜ˆ์™ธ๋Š” ๋ฒ„๊ทธ์ด๊ณ , ํ•จ์ˆ˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ง€ ์•Š๋Š”๋‹ค.
        • ๋‹ค๋ฅธ ์ฝ”๋“œ๊ฐ€ ์˜ˆ๊ธฐ์น˜ ์•Š๊ฒŒ ์‹คํŒจํ•˜๋Š” ์กฐ๊ฑด์„ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ํ•จ์ˆ˜ ์™ธ๋ถ€์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค.
        • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ํŒŒ์ผ์‹œ์Šคํ…œ, ๋„คํŠธ์›Œํฌ ๋“ฑ ์™ธ๋ถ€ ์š”์ธ์œผ๋กœ ๋™์ž‘์ด ๋ฉˆ์ถ”์ง€ ์•Š๋Š”๋‹ค.
    • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ด๋“
      • ๊ฒฐ์ •๋ก ์ ์ด๋ฏ€๋กœ ํ”„๋กœ๊ทธ๋žจ์„ ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋Œ€์‹  ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€๋งŒ ํ™•์ธํ•˜๋ฉด ์˜ค๋ฅ˜์˜ ์›์ธ์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.
      • ๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ํ…Œ์ŠคํŠธ์šฉ ๊ฐ€์งœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†๋‹ค. (ํ…Œ์ŠคํŠธ ์ค‘์—๋„ ๋Œ€์ƒ ๊ฐ์ฒด๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ)
      • ๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ์—†๊ณ , ์™ธ๋ถ€ ์š”์ธ์—์„œ ์ž์œ ๋กญ๊ณ , ์˜ˆ์™ธ๊ฐ€ ์—†๊ณ , ๊ฐ’์˜ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚˜์ง€ ์•Š๊ณ , ๋™์‹œ์„ฑ ๋ฌธ์ œ์—์„œ ์ž์œ ๋กœ์šฐ๋ฏ€๋กœ, ํ•จ์ˆ˜๋ฅผ ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฝ๋‹ค.
  • ์ฝค๋น„๋„ค์ดํ„ฐ: ๋‘ ๊ฐœ ์ด์ƒ ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ/ํ•จ์ˆ˜

19.5.1 ์บ์‹ฑ ๋˜๋Š” ๊ธฐ์–ตํ•ด์„œ ์“ฐ๊ธฐ: ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ™์œผ๋ฉด ๊ฒฐ๊ณผ๋„ ๊ฐ™์œผ๋ฏ€๋กœ

  • ํŠธ๋ฆฌ ํ˜•์‹์˜ ํ† ํด๋กœ์ง€๋ฅผ ๊ฐ–๋Š” ๋„คํŠธ์›Œํฌ์—์„œ ํŠน์ • ๋ฒ”์œ„ ๋‚ด ๋…ธ๋“œ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ถ€์ž‘์šฉ ์—†๋Š” ๋ฉ”์„œ๋“œ
    • ๋ฐ˜๋ณตํ•ด๋„ ๋„คํŠธ์›Œํฌ์— ๋ณ€๊ฒฝ์€ ๊ฐ€์ง€ ์•Š์ง€๋งŒ, ์—ฐ์‚ฐ ๋น„์šฉ์ด ๋น„์‹ธ๋‹ค.
    • ์ด๋ฏธ ์—ฐ์‚ฐํ•œ ๋ฒ”์œ„๋ฅผ ํ•ด์‹œ๋งต ๋“ฑ์— ๋„ฃ์–ด ์ฐธ์กฐํ•˜๋ฉด ์—ฐ์‚ฐ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.
      • ๋‹ค๋งŒ, ๋ชจ๋‘ ๊ณต์œ ํ•˜๋Š” ๊ฐ€๋ณ€๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ์™„์ „ํžˆ 'ํ•จ์ˆ˜ํ˜•'์ด๋ผ๊ณ  ํ•˜๊ธฐ๋Š” ์–ด๋ ต๋‹ค.
      • ๋˜ํ•œ ํ•ด์‹œ๋งต์€ ์Šค๋ ˆ๋“œ ์„ธ์ดํ”„ํ•˜์ง€ ์•Š๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค.
final Map<Range, Integer> numberOfNodes = new HashMap<>();

//์ง์ ‘๊ตฌํ˜„
Integer computeNumberOfNodesUsingCache(Range range){
	Integer result = numberOfNodes.get(range);
	if(result!=null) return result;
	result = computeNumberOfNodes(range);
	numberOfNodes.put(range, result);
	return result;
}

//computeIfAbsent์‚ฌ์šฉ
Integer computeNumberOfNodesUsingCache(Range range){
	return numberOfNodes.computeIfAbsent(range, this::computeNumberOfNodesUsingCache);
}

19.5.2 '๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•จ'์ด๋ž€, ==์ธ๊ฐ€ equals์ธ๊ฐ€

  • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์ธ์ˆ˜๊ฐ€ ๊ฐ™๋‹ค๋ฉด ๊ฒฐ๊ณผ๋„ ๊ฐ™์•„์•ผ ํ•œ๋‹ค.
  • 19.2.3์ ˆ์˜ ์ด์ง„ํŠธ๋ฆฌ ์˜ˆ์ œ์—์„œ๋Š” ์ผ๋ถ€ ๋…ธ๋“œ๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด์„œ ๋ฐ˜ํ™˜ํ–ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์ฐธ์กฐํˆฌ๋ช…์„ฑ(=์ธ์ˆ˜๊ฐ€ ๊ฐ™๋‹ค๋ฉด ๊ฒฐ๊ณผ๋„ ๊ฐ™๋‹ค)์„ ๊ฐ€์งˆ๊นŒ?
    • ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์ฐธ์กฐํˆฌ๋ช…ํ•˜์ง€ ์•Š๋‹ค.
    • ๊ธฐ์กด๊ฐ์ฒด๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•˜๊ณ  ๊ฐ™์€ ๊ฐ’์„ ๊ฐ€์ง€๋ฏ€๋กœ ์ฐธ์กฐํˆฌ๋ช…ํ•˜๋‹ค.

19.5.3 ์ฝค๋น„๋„ค์ดํ„ฐ: ๋‘ ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜

  • ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ f์— ์—ฐ์†์ ์œผ๋กœ n๋ฒˆ ์ ์šฉํ•˜๋Š” ๋ฃจํ”„ ์—ฐ์‚ฐ์„ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
repeat(3, (Integer x) -> 2*x);

static <A> Function<A,A> repeat(int n, Function<A,A> f){
	return n==0 ? x->x : compose(f, repeat(n-1, f));
}

19.6 ์ •๋ฆฌ

  • ํ•จ์ˆ˜๋ฅผ ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ชจ๋“ˆํ™”ํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ํŽธํ•˜๋‹ค.

    • ์ผ๊ธ‰ํ•จ์ˆ˜๋Š” ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•˜๊ฑฐ๋‚˜, ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜, ์ž๋ฃŒ๊ตฌ์กฐ์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

    • ๊ณ ์ฐจํ•จ์ˆ˜๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋‹ค.

    • ์ปค๋ง์€ ํ•จ์ˆ˜๋ฅผ ๋ชจ๋“ˆํ™”ํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•œ๋‹ค.

    • ์ฝค๋น„๋„ค์ดํ„ฐ๋Š” ๋‘˜ ์ด์ƒ์˜ ํ•จ์ˆ˜๋‚˜ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์กฐํ•ฉํ•˜๋Š” ํ•จ์ˆ˜ํ˜• ๊ฐœ๋…์ด๋‹ค.

  • ๋ถ€์ž‘์šฉ์ด ์—†๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๊ฑฑ์ •์„ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

    • ์˜์† ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ๊ธฐ์กด ๋ฒ„์ „์˜ ์ž์‹ ์„ ๋ณด์กดํ•œ๋‹ค.
  • ์„œํ”Œ๋ผ์ด์–ด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•„์š”์— ๋”ฐ๋ผ '๊ฒŒ์œผ๋ฅด๊ฒŒ' ์ƒ์„ฑ๋˜๋Š” ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

    • ์ž๋ฐ” ์ŠคํŠธ๋ฆผ์€ ์žฌ๊ท€์ ์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์—†๊ธฐ์— ์ ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
    • ์ง์ ‘ ์„œํ”Œ๋ผ์ด์–ด๋ฅผ ์‚ฌ์šฉํ•ด ๊ฒŒ์œผ๋ฅธ ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ํ•จ์ˆ˜ํ˜•์œผ๋กœ ๋™์ž‘์„ ์ถ”์ƒํ™”ํ•˜๊ณ  ์ „๋‹ฌํ•จ์œผ๋กœ์จ switch๋ฅผ ์ผ๋ฐ˜ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ฐธ์กฐํˆฌ๋ช…์„ฑ(=๊ฐ™์€ ํŒŒ๋ผ๋ฏธํ„ฐ, ๊ฐ™์€ ๊ฒฐ๊ณผ)์„ ์œ ์ง€ํ•˜๋Š” ์ƒํ™ฉ์—์„œ๋Š” ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.


The Genuine Sieve of Eratosthenes (hmc.edu)

  • ์ฃผ์ œ: ์—๋ผํ† ์Šคํ…Œ๋„ค์Šค์˜ ์ฒด ์•Œ๊ณ ๋ฆฌ์ฆ˜, ์ŠคํŠธ๋ฆผ ๊ฒŒ์œผ๋ฅธ ์—ฐ์‚ฐ
โš ๏ธ **GitHub.com Fallback** โš ๏ธ