본문 바로가기
Ios/Swift

축약형에 대한 주저리 주저리 (feat. C#, JS, Swift)

by 잘먹는 개발자 에단 2024. 7. 23.

공부하다가 보니까 자꾸 그런 생각이 든다.

 

그냥 쓰면 되는데, 왜 자꾸 축약형을 만들고 그래가지고

 

축약형을 사용하는 경우에는 원형과 어떤게 다르고, 어떤 걸 주의해야하고... 이런걸 숙지해야하는지 

 

마치 그런 기분이다. 그 뭐라하지.. 그냥 손으로 과일을 먹으면 되는데 그걸 굳이 나무젓가락으로 먹는다고 해서 젓가락 쓰는 법도 배워야하고, 나무젓가락을 쓸 때의 주의점 (예를 들면 손으로 훑다가 가시 박힐 수도 있는 ) 을 숙지해야하는 그런 느낌적인 느낌....

 

 

어쨋든 그런 느낌적인 느낌이 들었다는 것이고 할 건 해야지. 

 

 

여러 언어 ( 물론 그래봤자 내가 아는게 몇가지 안되지만 ) 를 살펴보면서 메서드를 어떤식으로 줄여나가는지 한번 살펴보자.

 

 

먼저 자바스크립트의 map을 한번 볼까. 람다식을 써서 가장 그나마 함수가 깔끔해지는 느낌이 들때가 자바스크립트에서 map을 돌때다. 

 

자바스크립트에서 우리가 어떠한 순회 가능한 객체를 돌면서 작업을 할 때 주로 map을 사용한다.

 

물론 foreach를 사용할 수도 있겠지만, 너무 다양한 키워드는 우리 머리를 복잡하게 할 수 있기 때문에 최대한 한 키워드를 갖다가 변형해서 쓰는 것이 좋다. ( 한가지 키워드의 변형을 여러개 알고 있는 것이 좋다고 개인적으로 생각한다 )

 

 

예를 들어서

const testArr = [1,3,4,5,1,2,3];

가 있다고 하자.

 

다음을 가지고 프론트 단에서는 크게 2가지 동작을 할 수 있다.

 

1. 저걸 가지고 어떠한 처리를 한다.

2. 저걸 가지고 화면에 그리기 위해서 요소를 반환한다.

 

1번의 경우에는 

testArr.map(
	(element) => { 
    	//처리 내용 
        }
);

이 될 것이다.

 

 

2번의 경우에는 

..
..
..
..
return(
	<div>
    	<ul>
        {
        	testArr.map((element, index)=>{
            	// 처리를 막 이것저것한다. 여기서는 x2를 했다고 치면
                const doubledElement = element * 2;
                return <li key={index}>{doubledElement}</li>
            })
        }
        </ul>
    </div>
)

이런식으로 될 것이다.

 

 

 

이번에는 Swift 에서의 몇가지 이런 객체 순환 메서드를 살펴보겠다.

 

1. filter 메서드

- 스위프트도 보면 자바스크립트의 그것과 거의 비슷하게 생겼다. 

- 다만 어떤 언어도 함수를 축약하곤 한다.

 

C# 같은 경우에는 

1. 반환을 한다면 Func이고

Func<int, string, string> testFunc = delegate(string msg1, string msg2){
    return msg1.length + msg2.length;
}


Func<int, string, string> testFunc = (msg1, msg2) => {
	return msg1.length + msg2.length;
}

 

 

2. 반환이 없다면 Action이다. ( delegate는 아래와 같이 람다식을 쓴다면 굳이 쓰지 않아도 되긴한다. 대리자라는 이름이 뭔가 이해를 더 어렵게 만드는 것 같다는 생각이 들었다. )

Action<string, string> act2 = delegate(string msg, string title)
{
	MessageBox.Show(msg, title);
};

// 하지만 이게 편하다.
Action<string, string> act = (msg, title) => 
	{
    	MessageBox.Show(msg,title);
    };

 

 

 

 

JS에서는 

function testFunc(a, b){
	const c = a + b;
    return c;
}


const testFunc = (a,b) => {
	const c = a + b;
    return c;
}

이런식으로 된다.

사실 크게 동작에 차이는 없으나, 아까 말한 그 나무젓가락 뭐시기를 쓸 때 주의해야하는 점 같은게 다음과 같다. 

1. this가 선언할때의 시점인지,  사용할 때의 시점에 묶이는지가 다르다.

2. 익명함수(람다식)의 경우에는 호이스팅이 적용되지 않는다는 점이 다르다. 

 

 

그렇다면 느낌적인 느낌이 오는게 있는데, 강자료형 언어인 경우에는 축약형을 쓰면 오히려 골때린다는 느낌이 든다.

근데, 파고들다보면 강자료형에서는 목적이 코드를 줄이는데에 크게 두고 있지 않다는 것을 알 수 있다. C# 같은 경우에는 저 delegate 때문에 윈도우 cs 프로그램에서 이벤트에 메서드를 묶어주는게 편리해졌다.

 

~~Handler += Method1 이런식으로 가능해졌다는 것이었던 것이었다. 

 

너무 주저리주저리 대고 있긴한데, 원래 목적은 Swift에서 클로저를 줄이고 있는데 왜 그렇게 줄이는지 알아보려고 한 것이기 때문에 한번 보겠다. 

 

Swift 에서의 Filter

let numbers = [1,2,3,4,5,6]

let evenNumbers = number.filter(
	// 내부 클로저
    {
    	(number : Int) -> Bool in
        	// 내부동작
            return number % 2 == 0
    }
)

print(evenNumbers) // [2,4,6]

 

이것을 축약하면

let evenNumbers = numbers.filter{
	$0 % 2 == 0
}

* $0 : 클로저의 첫번째 매개변수

두번째는 $1...... 

 

 

Swift에서의 map

let numbers = [1,2,3,4,5,6]

let doubledNumbers = numbers.map(
	{
    	(number : Int) -> Int in
        return number * 2
    }
)


// 축약한다면
let doubledNumbersShort = numbers.map{ number * 2 }

 

 

 

 

Swift에서의 reduce

let numbers = [1, 2, 3, 4, 5, 6]

let sum = numbers.reduce( 0, 
	// 초기값을 0으로 설정
	{
    	(result : Int, number : Int) -> Int in
        	return result + number
    }
    )
    
 
 // 축약형
 let sum2 = numbers.reduce(0) { $0 + $1 }

 

 

 

C#, JS, 그리고 Swift 까지 원본과 축약형(람다)까지 쭉 봤는데 몇가지 생각이 정리된다.

 

1. 튜닝의 끝은 오리지날이다. -> 원본 써도된다 까짓거. 차라리 그게 가독성이 더 좋을 수 있다.

       ㄴ 그 축약형이 어떻게 생겼는지 읽을 수 있는 사람에게는 그게 좋지만

       ㄴ 아닌 사람은 오히려 읽을 때 힘들기 때문에, 가독성에 문제가 생길 수 있다.

 

2. 모든 축약형의 목적이 코드를 줄이는데에 있지는 않다.