2.1 일급 함수의 특징
- 함수형 프로그래밍의 정의를 간단히 '일급 함수' 와 '편의성'이라는 두 용어로 요약할 수 있다.
- '일급'이라는 용어에는 모든 것을 값으로 취급한다는 의미가 내포되어 있다.
var a = function() {} // 함수를 변수에 저장할 수 있다.
function b(f) { // 함수에 전달인자로 전달 할 수 있다.
f();
}
function c() {
return function() {}; // 함수를 리턴 할 수 있다.
}
- 함수를 인자로 받거나 리턴하는 함수를 고차원 함수라고 부른 다.
var a = function() {} // 함수를 변수에 저장할 수 있다.
function b(f) { // 함수에 전달인자로 전달 할 수 있다.
f();
}
function c() {
return function() {}; // 함수를 리턴 할 수 있다.
}
2.1.1 자바스크립트의 다중 패러다임
- 명령행 프로그래밍
- 동작을 자세히 설명하는 방식에 기반한 프로그래밍.
- 프로토타입 기반 객체 지향 프로그래밍
- 프로토타입형 객체와 인스턴스에 기반한 프로그래밍.
- 메타프로그래밍
- 자바스크립트의 실행 모델의 기반을 변경하는 프로그래밍
- 동작을 자세히 설명하는 방식에 기반한 프로그래밍.
- 프로토타입형 객체와 인스턴스에 기반한 프로그래밍.
- 자바스크립트의 실행 모델의 기반을 변경하는 프로그래밍
명령행 프로그래밍
- 일반적인 for문을 사용하는 프로그래밍을 말한다.
- 알고리즘 세부 구현의 정교함을 특징으로 한다.
- 명령행 코드는 보통 규격명세와 일치하는 수준으로 동작하므로 대부분 일회용 코드이며 재사용하기가 어렵다.
var lyrics = [];
for (var bottles = 99; bottles > 0; bottles--) {
lyrics.push(bottles + " bottles of beer on the wall");
lyrics.push(bottles + " bottles of beer");
lyrics.push("Take one down, pass it around");
if (bottles > 1) {
lyrics.push((bottles - 1) + " bottles of beer on the wall.");
}
else {
lyrics.push("No more bottles of beer on the wall!");
}
}
var lyrics = [];
for (var bottles = 99; bottles > 0; bottles--) {
lyrics.push(bottles + " bottles of beer on the wall");
lyrics.push(bottles + " bottles of beer");
lyrics.push("Take one down, pass it around");
if (bottles > 1) {
lyrics.push((bottles - 1) + " bottles of beer on the wall.");
}
else {
lyrics.push("No more bottles of beer on the wall!");
}
}
함수형 방식
- 추상화된 함수를 이용해서 본래의 기능을 수행하도록 재조립하였다.
function lyricSegment(n) {
return _.chain([])
.push(n + " bottles of beer on the wall")
.push(n + " bottles of beer")
.push("Take one down, pass it around")
.tap(function(lyrics) {
if (n > 1)
lyrics.push((n - 1) + " bottles of beer on the wall.");
else
lyrics.push("No more bottles of beer on the wall!");
})
.value();
}
function song(start, end, lyricGen) {
return _.reduce(_.range(start,end,-1),
function(acc,n) {
return acc.concat(lyricGen(n));
}, []);
}
function lyricSegment(n) {
return _.chain([])
.push(n + " bottles of beer on the wall")
.push(n + " bottles of beer")
.push("Take one down, pass it around")
.tap(function(lyrics) {
if (n > 1)
lyrics.push((n - 1) + " bottles of beer on the wall.");
else
lyrics.push("No more bottles of beer on the wall!");
})
.value();
}
function song(start, end, lyricGen) {
return _.reduce(_.range(start,end,-1),
function(acc,n) {
return acc.concat(lyricGen(n));
}, []);
}
자바8의 명령행과 함수형.. 참고만
public class TheCompanyProcess {
public String cleanNames(List<String> listOfNames) {
StringBuilder result = new StringBuilder();
for(int i = 0; i < listOfNames.size(); i++) {
if (listOfNames.get(i).length() > 1) {
result.append(capitalizeString(listOfNames.get(i))).append(",");
}
}
return result.substring(0, result.length() - 1).toString();
}
public String capitalizeString(String s) {
return s.substring(0, 1).toUpperCase() + s.substring(1, s.length());
}
public String cleanNames(List<String> names) {
if (names == null) return "";
return names
.stream()
.filter(name -> name.length() > 1)
.map(name -> capitalize(name))
.collect(Collectors.joining(","));
}
private String capitalize(String e) {
return e.substring(0, 1).toUpperCase() + e.substring(1, e.length());
}
}
public class TheCompanyProcess {
public String cleanNames(List<String> listOfNames) {
StringBuilder result = new StringBuilder();
for(int i = 0; i < listOfNames.size(); i++) {
if (listOfNames.get(i).length() > 1) {
result.append(capitalizeString(listOfNames.get(i))).append(",");
}
}
return result.substring(0, result.length() - 1).toString();
}
public String capitalizeString(String s) {
return s.substring(0, 1).toUpperCase() + s.substring(1, s.length());
}
public String cleanNames(List<String> names) {
if (names == null) return "";
return names
.stream()
.filter(name -> name.length() > 1)
.map(name -> capitalize(name))
.collect(Collectors.joining(","));
}
private String capitalize(String e) {
return e.substring(0, 1).toUpperCase() + e.substring(1, e.length());
}
}
2.2 응용형 프로그래밍
- 응용형 프로그래밍은 함수 A 내부의 함수 B를 호출하는 방식으로 이루어진다. 이때 함수 A의 결과를 함수 B의 인자로 제공한다.
var nums = [1,2,3,4,5];
function doubleAll(array) {
return _.map(array, function(n) { return n*2 }); // map안에서 *2를 하는 함수가 호출된다.
}
doubleAll(nums);
//-> [2, 4, 6, 8, 10]
function average(array) {
var sum = _.reduce(array, function(a, b) { return a+b });
return sum / _.size(array);
}
average(nums);
//-> 3
function onlyEven(array) {
return _.filter(array, function(n) {
return (n%2) === 0;
});
}
onlyEven(nums);
//-> [2, 4]
var nums = [1,2,3,4,5];
function doubleAll(array) {
return _.map(array, function(n) { return n*2 }); // map안에서 *2를 하는 함수가 호출된다.
}
doubleAll(nums);
//-> [2, 4, 6, 8, 10]
function average(array) {
var sum = _.reduce(array, function(a, b) { return a+b });
return sum / _.size(array);
}
average(nums);
//-> 3
function onlyEven(array) {
return _.filter(array, function(n) {
return (n%2) === 0;
});
}
onlyEven(nums);
//-> [2, 4]
2.2.1 컬렉션 중심 프로그래밍
- 컬렉션 중심 프로그래밍의 핵심은 컬렉션을 처리하는 일반적인 처리 방법을 만들어서 재사용할 수 있는 포괄적인 함수 집합을 구축하는 데 있다.
_.map({a: 1, b: 11}, _.identity);
//-> [1, 11]
_.map({a: 1, b: 11}, _.identity);
//-> [1, 11]
2.2.3 응용형 함수 만들기
- 다른 함수를 인자로 받는 함수를 정의하고 그 다음에 인자로 받은 함수를 호출해서 정의한 함수를 완성한다.
function cat() {
var head = _.first(arguments);
if (existy(head))
return head.concat.apply(head, _.rest(arguments)); // 인자로 배열을 받는 다. 인자로 함수를 받지 않기 때문에 응용형 함수라 할 수 없다.
else
return [];
}
cat([1,2,3], [4,5], [6,7,8]);
//-> [1, 2, 3, 4, 5, 6, 7, 8]
- 인자로 함수를 받을 수 있게 개선한 프로그램
function construct(head, tail) {
return cat([head], _.toArray(tail));
}
construct(42, [1,2,3]);
//-> [42, 1, 2, 3]
function mapcat(fun, coll) {
return cat.apply(null, _.map(coll, fun));
}
mapcat(function(e) {
return construct(e, [","]);
}, [1,2,3]);
//-> [1,",",2,",",3]
function butLast(coll) {
return _.toArray(coll).slice(0, -1);
}
function interpose (inter, coll) {
return butLast(mapcat(function(e) {
return construct(e, [inter]);
},
coll));
}
interpose(",", [1,2,3]);
//-> [1,",",2,",",3]
function cat() {
var head = _.first(arguments);
if (existy(head))
return head.concat.apply(head, _.rest(arguments)); // 인자로 배열을 받는 다. 인자로 함수를 받지 않기 때문에 응용형 함수라 할 수 없다.
else
return [];
}
cat([1,2,3], [4,5], [6,7,8]);
//-> [1, 2, 3, 4, 5, 6, 7, 8]
function construct(head, tail) {
return cat([head], _.toArray(tail));
}
construct(42, [1,2,3]);
//-> [42, 1, 2, 3]
function mapcat(fun, coll) {
return cat.apply(null, _.map(coll, fun));
}
mapcat(function(e) {
return construct(e, [","]);
}, [1,2,3]);
//-> [1,",",2,",",3]
function butLast(coll) {
return _.toArray(coll).slice(0, -1);
}
function interpose (inter, coll) {
return butLast(mapcat(function(e) {
return construct(e, [inter]);
},
coll));
}
interpose(",", [1,2,3]);
//-> [1,",",2,",",3]
'책정리 > 자바스크립트' 카테고리의 다른 글
함수형 자바스크립트 - 7장 순수성, 불변성, 변경 정책 (0) | 2017.02.04 |
---|---|
함수형 자바스크립트 - 4장 고차원 함수 (0) | 2017.02.03 |
함수형 자바스크립트 - 5장 함수로 함수 만들기 (0) | 2017.01.23 |
함수형 자바스크립트 - 3장 변수 스코프와 클로저 (0) | 2017.01.14 |
함수형 자바스크립트 - 1장 함수형 자바스크립트 소개 (0) | 2017.01.09 |
댓글