Skip to content

Instantly share code, notes, and snippets.

@kellywoo
Last active April 13, 2021 03:56
Show Gist options
  • Save kellywoo/3ad61b946a32735125f4bce02d7002ed to your computer and use it in GitHub Desktop.
Save kellywoo/3ad61b946a32735125f4bce02d7002ed to your computer and use it in GitHub Desktop.
const {stringify} = (() => {
const separator = () => ',';
const processChar = (char) => {
switch (char) {
case '\\':
return '\\\\';
case '\n':
return '\\n';
case '\t':
return '\\t';
case '\v':
return '\\v';
case '\b':
return '\\b';
case '\r':
return '\\r';
case '"' :
return '\\"';
default:
return char;
}
};
const quote = (str) => {
return `"${str}"`;
};
const processString = (str, i, res) => {
return str.length === i ? res : processString(str, i + 1, res + processChar(str[i]));
}
const processArray = (arr) => {
let str = '[';
for (let i = 0; i < arr.length; i++) {
if(i!==0) {
str += separator();
}
str += stringifyCore(arr[i]);
}
return str + ']';
};
const stringifyCore = (v) => {
const t = typeof v;
switch (t) {
case 'boolean':
return v.toString();
case 'number': {
if (v === 0) {
// -0
return '0';
}
if (isNaN(v)) {
return 'null';
}
if (!isFinite(v)) {
return 'null';
}
return v.toString();
}
case 'object':
if (Array.isArray(v)) {
return processArray(v);
} else {
return 'null';
}
case 'string':
return quote(processString(v, 0, ''));
default:
// unknown
return 'null';
}
};
const stringify = (v) => {
return stringifyCore(v);
}
return {stringify};
})();
// const a = [1, "ab\"c", true, undefined, null, _=>3, Symbol()];
// JSON.stringify(a) === arrayStringify(a);가 되도록 arrayStringify를 구현
// [1,"ab\"c",true,null,null,null,null]
const {stringify} = (() => {
const separator = () => ',';
const processChar = (char) => {
switch (char) {
case '\\':
return '\\\\';
case '\n':
return '\\n';
case '\t':
return '\\t';
case '\v':
return '\\v';
case '\b':
return '\\b';
case '\r':
return '\\r';
case '"' :
return '\\"';
default:
return char;
}
};
const quote = (str) => {
return `"${str}"`;
};
const processString = (str, i, res) => {
return str.length === i ? res : processString(str, i + 1, res + processChar(str[i]));
}
const processArray = (arr, i, str) => {
if (i === 0) str += '['
if (arr.length === i) return str + ']';
return processArray(arr, i + 1, str + (i === 0 ? '' : separator()) + stringifyCore(arr[i]));
};
const stringifyCore = (v) => {
const t = typeof v;
switch (t) {
case 'boolean':
return v.toString();
case 'number': {
if (v === 0) {
// -0
return '0';
}
if (isNaN(v)) {
return 'null';
}
if (!isFinite(v)) {
return 'null';
}
return v.toString();
}
case 'object':
if (Array.isArray(v)) {
return processArray(v, 0, '');
} else {
return 'null';
}
case 'string':
return quote(processString(v, 0, ''));
default:
// unknown
return 'null';
}
};
const stringify = (v) => {
return stringifyCore(v, '');
}
return {stringify};
})();
@hikaMaeng
Copy link

59번째줄을 보시면 아시겠지만 꼬리물기 최적화가 되지 않습니다. + 연산이 있기 때문이죠.

@kellywoo
Copy link
Author

kellywoo commented Apr 12, 2021

그렇군요.. 감사합니다...
말씀하신 부분 수정해서 올렸습니다.
하다보니 제가 꼬리물기 최적화하고 그냥 쌓이는 스택에 대해서 구분을 정확히 못하고 있는것 같아요...
https://gist.github.com/kellywoo/3ad61b946a32735125f4bce02d7002ed#file-recursivetail-L40
아직 이 꼬리물기 최적화에 대한 이해가 낮아서 ..드리는 질문인데...위의 줄에 나오는 + stringifyCore(arr[i]) 도 안에 array가 있다면 문제가 될까요??

@hikaMaeng
Copy link

네. 여전히 그걸 해결하기 위해 스택을 제거할 수 없으니까요. 꼬리재귀는 1강 반복

@kellywoo
Copy link
Author

👍 감사합니다. 이후 시간날때 다시 해보겠습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment