사전캠프 마지막 주차에 들어섰다. 처음 사전캠프 들어오기 전에 걱정했던 괜히 시간만 허비하면 어쩌지? 라는 고민은 생각보다 알차게 써먹고 즐겨서 좋은 시간이 됐다.
다만 SQL 강의 지급도 됐으면 오랜만에 SQL 작성도 해보고 참 좋았을텐데 지금은 머리가 피로를 호소하는 CS 강의에 실기 문제를 푸느라 4시간도 만만치않게 길게 느껴진다.
이 문제에는 표준 입력으로 두 개의 정수 n과 m이 주어집니다.
별(*) 문자를 이용해 가로의 길이가 n, 세로의 길이가 m인 직사각형 형태를 출력해보세요.
val (a, b) = readLine()!!.split(' ').map(String::toInt)
for (i in 0 until b) {
for (j in 0 until a) {
print("*")
}
println("")
}
학교에서도 단골 손님만큼 자주 보던 별 찍기 문제가 드디어 나왔다.
직사각형이라 이젠 기억도 안나는 골뱅이, 다이아몬드랑 달리 바로 풀긴 했는데 이 답안은 사실 언어를 바꿔도 너무 공통된 풀이가 아닌가 싶어 굳이 다른 방법으로 풀어봤다.
val (a, b) = readLine()!!.split(' ').map(String::toInt)
repeat(b) { println("*".repeat(a)) }
이 방법으론 다이아몬드같은 건 못찍겠지만 repeat
을 써서 코드가 아주 간결해졌다.
실행 속도도 큰 차이가 나는 건 아니고 출력식 문제에서는 for문보다 유연하지도 않겠지만 그냥 자기 만족에 가깝다.
문제가 쉬웠던 만큼 String::toInt
처럼 호출하는 Method reference 방식에 대해 추가로 조사해봤다. 자주 보는 건 아니지만 프로그래머스 기본 탬플릿에서도 사용하는 걸 보면 눈에 익을 필요와 차이도 알아야 할 것 같았다.
핵심은 둘 다 함수형 프로그래밍 언어의 특징을 살리기 위해 사용한다는 점이다. Java의 경우 Java 8부터 지원하기 시작했다고 한다.
val str = "Hello, world!"
val lengthGetter1: (String) -> Int = String::length
val lengthGetter2: (String) -> Int = { it.length }
val length1 = lengthGetter1(str)
val length2 = lengthGetter2(str)
둘 다 문자열의 길이를 구하는 함수지만 참조하는 방식이 다르다 볼 수 있다.
Method reference의 핵심은 String 클래스의 length에 대한 참조를 저장한 것이고
Lambda는 문자열을 입력 받아 그 길이를 반환하는 익명 함수를 만들었다.
Method reference는 length가 이미 존재하기 때문에 문자열 길이를 구하기 위해서 추가적인 연산을 하는게 아니라 String::length
로 참조만 했을 뿐이다.
반면에 Lambda는 이미 존재하는 length를 사용해 자체적으로 연산을 해서 반환한다.
문자열의 길이 구하기 처럼 정말 간단한 작업이 필요하고 이미 필요한 메소드 또한 정의되어 있다면 추가적인 scope를 필요할 것 없이 Method reference를 쓰는게 간결하고 직접적이다.
다만 Lambda를 사용하면 유연한 작업이 가능하고 변수를 추가적으로 사용하기 쉬우니 때에 따라 나눠서 작성해도 되겠다.
사실 실무에선 간단한 작업도 전부 Lambda를 썼던 것 같은데 이후로도 손에 익을지는 잘 모르겠다.