어떻게 자바 스 크 립 트 로 배열 타성 값 라 이브 러 리 를 실현 합 니까?
프로 그래 밍 언어 이론 에서 타성 구 치(영어:Lazy Evaluation)는 타성 계산,게 으 름 구 치 로 번역 되 고 전기 수요 호출(call-by-need)이 라 고도 부 르 며 컴퓨터 프로 그래 밍 의 개념 으로 컴퓨터 가 해 야 할 일 을 최소 화 하 는 것 이 목적 이다.이 는 두 가지 관련 되 고 차이 가 있 는 의 미 를 가지 는데'지연 구 치'와'최소 화 구 치'라 고 할 수 있다.성능 향상 을 얻 을 수 있 는 것 을 제외 하고 타성 컴 퓨 팅 의 가장 중요 한 장점 은 무한 한 데이터 유형 을 구성 할 수 있다 는 것 이다.
함수 식 언어 에서 의 타성 구 치 를 보고 자바 스 크 립 트 로 가장 간단 한 실현 을 쓰 고 타성 구 치 를 깊이 이해 하려 고 합 니 다.두 가지 방법 을 사 용 했 는데 모두 80 줄 도 안 되 어 기본 적 인 배열 의 타성 구 치 를 실현 했다.
어떻게
타성 구 치 는 매번 값 을 구 할 때 수 치 를 되 돌려 주 는 것 이 아니 라 계산 파 라 메 터 를 포함 한 구 치 함 수 를 되 돌려 주 고 가치 있 는 것 을 사용 해 야 계산 할 수 있 습 니 다.
여러 개의 타성 조작 이 있 을 때 하나의 값 함수 체인 을 구성 하고 값 을 구 할 때마다 모든 값 함수 가 이전 값 함수 에 값 을 구 해서 값 을 되 돌려 줍 니 다.마지막 으로 계산 함수 가 종 료 될 때 종료 값 을 되 돌려 줍 니 다.
구체 적 실현
판단 값 함수 종료
매번 값 을 구 하 는 함수 가 각종 데 이 터 를 되 돌려 주기 때문에 유일무이한 값 을 사용 하여 흐름 의 완성 여 부 를 판단 하 는 표지 로 삼 아야 한다.마침 Symbol()은 새로운 symbol 을 만 들 수 있 습 니 다.값 은 다른 값 과 같 지 않 습 니 다.
const over = Symbol();
const isOver = function (_over) {
return _over === over;
}
생 성 함수 범위range 함 수 는 시작 과 종료 파 라 메 터 를 받 아들 여 값 을 구 하 는 함 수 를 되 돌려 주 고 값 을 구 하 는 함 수 를 실행 하여 값 을 되 돌려 주 며 종료 할 때 종료 값 을 되 돌려 줍 니 다.
const range = function (from, to) {
let i = from;
return function () {
if (i < to) {
i++
console.log('range\t', i);
return i
}
return over;
}
}
변환 함수 map값 함수 와 처리 함 수 를 받 아들 여 값 함수 flow 의 데 이 터 를 가 져 와 데 이 터 를 처리 하고 흐름 을 되 돌려 줍 니 다.
const map = function (flow, transform) {
return function () {
const data = flow();
console.log('map\t', data);
return isOver(data) ? data : transform(data);
}
}
필터 함수 필터값 을 구 하 는 함 수 를 받 아들 여 값 을 구 하 는 함수 flow 의 데 이 터 를 걸 러 내 고 일치 하 는 데 이 터 를 찾 아 되 돌려 줍 니 다.
const filter = function (flow, condition) {
return function () {
while(true) {
const data = flow();
if (isOver(data)) {
return data;
}
if(condition(data)) {
console.log('filter\t', data);
return data;
}
}
}
}
인 터 럽 트 함수 stop값 을 구 하 는 함 수 를 받 아들 이 고 특정한 조건 에 이 르 렀 을 때 중단 하면 패 킷 함수 에 stop 함 수 를 더 해서 take 함 수 를 실현 할 수 있 습 니 다.
const stop = function (flow, condition) {
let _stop = false;
return function () {
if (_stop) return over;
const data = flow();
if (isOver(data)) {
return data;
}
_stop = condition(data);
return data;
}
}
const take = function(flow, num) {
let i = 0;
return stop(flow, (data) => {
return ++i >= num;
});
}
수집 함수 join돌아 오 는 것 은 하나의 함수 이기 때문에 마지막 으로 join 함 수 를 사용 하여 모든 값 을 수집 하고 배열 을 되 돌려 야 합 니 다.
const join = function (flow) {
const array = [];
while(true) {
const data = flow();
if (isOver(data)) {
break;
}
array.push(data);
}
return array;
}
테스트:
const nums = join(take(filter(map(range(0, 20), n => n * 10), n => n % 3 === 0), 2));
console.log(nums);
출력:range 1
map 1
range 2
map 2
range 3
map 3
filter 30
range 4
map 4
range 5
map 5
range 6
map 6
filter 60
더욱 우아 한 실현
위 에서 함수+패 키 지 를 사용 하여 타성 구 치 를 실현 하 였 으 나 우아 하지 못 하여 대부분의 코드 는 교체 와 구 치 를 완성 하 는 지 판단 하 는 위 에 놓 여 있 습 니 다.사실 es6 에서 타성 구 치 를 실현 하 는 더 좋 은 방법 이 있다.바로 generator 를 사용 하 는 것 이다.generator 는 우리 에 게 교체 와 흐름 의 완성 여 부 를 판단 해 주 었 기 때문에 우 리 는 논리 에 전념 하여 더욱 간결 하고 알 기 쉬 운 구조 가 뚜렷 한 코드 를 쓸 수 있다.
const range = function* (from, to) {
for(let i = from; i < to; i++) {
console.log('range\t', i);
yield i;
}
}
const map = function* (flow, transform) {
for(const data of flow) {
console.log('map\t', data);
yield(transform(data));
}
}
const filter = function* (flow, condition) {
for(const data of flow) {
console.log('filter\t', data);
if (condition(data)) {
yield data;
}
}
}
const stop = function*(flow, condition) {
for(const data of flow) {
yield data;
if (condition(data)) {
break;
}
}
}
const take = function (flow, number) {
let count = 0;
const _filter = function (data) {
count ++
return count >= number;
}
return stop(flow, _filter);
}
체인 호출 까지 해 야 완 성 된 거 야.
class _Lazy{
constructor() {
this.iterator = null;
}
range(...args) {
this.iterator = range(...args);
return this;
}
map(...args) {
this.iterator = map(this.iterator, ...args);
return this;
}
filter(...args) {
this.iterator = filter(this.iterator, ...args);
return this;
}
take(...args) {
this.iterator = take(this.iterator, ...args);
return this;
}
[Symbol.iterator]() {
return this.iterator;
}
}
function lazy () {
return new _Lazy();
}
마지막 으로 다시 한 번 테스트 해 보 자.
const nums = lazy().range(0, 100).map(n => n * 10).filter(n => n % 3 === 0).take(2);
for(let n of nums) {
console.log('num:\t', n, '
');
}
출력:range 0
map 0
filter 0
num: 0
range 1
map 1
filter 10
range 2
map 2
filter 20
range 3
map 3
filter 30
num: 30
자,큰 성 과 를 거 두 었 습 니 다.
총결산
이렇게 해서 우 리 는 가장 간단 한 배열 의 타성 구 치 를 완성 했다.여 기 는 타성 구 치 를 간단하게 실 현 했 을 뿐 공사 에 넣 으 려 면 많은 세부 사항 을 추가 해 야 한다.코드 가 80 줄 에 불과 하기 때문에 타성 구 치 원 리 를 잘 알 수 있 고 생 성기 에 대한 이 해 를 강화 할 수 있 습 니 다.
이상 은 어떻게 자바 스 크 립 트 로 하나의 배열 타성 구 치 라 이브 러 리 를 실현 하 는 지 에 대한 상세 한 내용 입 니 다.자바 스 크 립 트 가 배열 타성 구 치 라 이브 러 리 를 실현 하 는 지 에 관 한 자 료 는 우리 의 다른 관련 글 에 관심 을 가 져 주 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JS 판단 수조 네 가지 실현 방법 상세그러면 본고는 주로 몇 가지 판단 방식과 방식 판단의 원리를 바탕으로 문제가 있는지 토론하고자 한다. 예를 들어 html에 여러 개의 iframe 대상이 있으면 instanceof의 검증 결과가 기대에 부합되지 않을...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.