2016년 12월 22일 목요일

클로저로 단순한 GUI 프로그램을 만들어보았다.

아주아주 단순한 클로저 프로그래밍을 해보았다. 이전에 웹으로 연결도 해보고 클로저스크립트도 한번 경험해보았지만 아직도 클로저 라는 언어에 확신이 없다. (왜냐하면 내가 제대로 모르기 때문...ㅠㅜ)
그래서 하나를 짬내서 만들어 보았다. 처음에는 swing을 썼다. 참으로 고통이었다. seesaw라는 라이브러리가 있는 걸 확인하고 seesaw를 살짝 사용했다.
저녁에 짬내서 만들면서 느낀 점은 참으로 힘들었다는 점이다.
나의 능력이 문제인지, 내 뇌가 아직 클로저라는 리스프계열에 적응을 못하고 있는 것인지 잘 모르겠다.
막연히 Swing을 쓰면 되겠지라고 생각했었는데... 정말 자바로 그냥 짰으면 순식간에 만들었을 것이라는 생각이 들었다.
아직 내가 클로저를 짬내서 3개월 정도 해봤는데 어렵다는 것은 내가 아직 클로저가 가지는 개념을 모르고 있다는 생각이 든다.

하지만 확실한 것은 리스프 프로그래밍은 정말 어렵다. 처음으로 하는 GUI를 다루는 것이라 버튼 하나 넣는 것에도 애를 먹었다. 내가 고작 만든 것은 이메일만 필터링해서 나열하는 것이다.
대량메일을 보내기 위해서!
그래서 만약
AAA@AAA
BBB@BBB.com
CCC@CCC.net
뭐 이런게 있으면
BBB@BBB.com, CCC@CCC.net
뭐 이렇게 만들어 주는 것이다. 정말 별거 아닌 것을 만들었다. REPL에서 그냥 치면 바로 나오는 걸 만든 것이다.


그런데 참으로 느낀 점은...
재미있었다.
내 앞에 있는 무언가 보이지 않는 큰 힘이 꿈틀거리는데 잡을 수 없는... 그런 느낌?
잡으려고 마구 휘저었지만
잡지 못했고 별거아닌 노력의 산물만 남았지만
정말 재미있었다.
뭔가 쌓아올리는 느낌?

어쨋든 github로 관리하면서 더 손봐야겠다. (과연 할런지...)
https://github.com/ssisksl77/sman

2016년 12월 21일 수요일

[jvm]04 - Instruction Set Summary

Instruction Set Summary

JVM명령은 1바이트 연산코드(opcode)로 구성되어있다.뒤에 딸려오는 제로(zero) 또는 다른 피연산자(operands)는 연산에 쓰인다.많은 명령어들은 피연산자가 없고 그냥 연산코드만 가지고 있다.
예외는 무시하고, JVM인터프리터의 내부 loop는
이렇게 생겼다고 한다. 피연산자의 수와 사이즈는 연산코드에 의해 결정된다. 만약 피연산자의 사이즈가 1바이트보다 크다면?

그것들은 빅엔디안(big-endian order : 데이터의 최상위 비트가 가장 높은 주소에 저장되므로 그냥 보기에는 역으로 보인다.)방식으로 저장된다.

예를들어, 로컬변수 unsigned 16비트 인덱스는 두개의 unsigned 바이트로 저장된다.(byte1 과 byte2).
값은

 이다.


Types and the Java Virtual Machine

JVM 명령어 셋의 대부분은 명령의 타입정보를 인코드한다.
예를들어 iload명령은 로컬 변수(int값이어야만 한다)의 내용을 피연산자 스택에 로딩한다.
floadiload와 똑같이 행동한다.(물론 float값을 사용한다.)
두 명령은 똑같은 구현을 가지고 있지만 서로 다른 연산부호(opcode)다.
  • i : int operation
  • l for long
  • c for char
  • f for float
  • d for double
  • a for reference
어떤 것들은 타입문자(type letter)가 없다. 예를들어 arraylength는 항상 object를 실행하지만 배열이다. goto를 보자. 무조건적인 제어 전환(control transfer), 타입이 있는 피연산자를 실행하지 않는다.

[jvm]03 Special Method

1. Special Method

자바로 만들어진 모든 생성자는 instance initialization method로 나타내어진다. (그놈의 이름은 ) 이 이름은 컴파일러에서 볼 수 있다. (왜 컴파일러에서?) 왜냐하면 은 유효한 식별자(identifier)가 아니기 때문이다. 이것은 자바 언어로 바로 씌여질 수 없다. 인스턴스 초기화 메소드(Instance initialization methods)는 오로지 JVM안에서 invokespecial명령어로 호출된다. 그리고 이것들은 오로지 초기화안된 클래스 인스턴스에서 호출될 것이다. 인스턴스 초기화 메소드(instance initialization method)는 생성자의 엑세스 권한을 가진다.

클래스 또는 인터페이스는 최소한 한나의 초기화 메소드가 있다. 그리고 그 메소드를 호출해서 초기화가 진행된다. 그 초기화 메소드는 아규먼트가 없으며 void이다. 이라는 특별한 이름을 가진다. class 파일의 version number 가 51이상이면, 추가로 ACC_STATIC 세팅값이 있어야 한다. 은 컴파일러에서 제공한다. 이유는 은 유효한 식별자(identifier)가 아니기 때문(init과 마찬가지) Class and interface initialization methods는 JVM에 의해 내부적으로 호출되어진다. 이것들(methods)은 어떤 JVM명령어로도 직접적으로 호출될 수 없다. 하지만 간접적으로는 호출될 수 있다.(class initialization process에서)

2. Exception

JVM에서 예외(exception) 단순히 Throwable, 아님 Throwable의 subclass의 클래스 인스턴스이다. 예외를 던지는 것은 예외가 던져진 곳(point)에서 즉각적 로컬 외(nonlocal) 컨트롤의 이전이 된다. 대부분의 예외는 동기적으로 일어난다. 비동기적인 예외 또한 프로그램 실쟁 중에 일어날 수도 있다.

2016년 12월 15일 목요일

[jvm]02 Run-Time Data Areas

JVM은 다양한 런타임 데이타 지역을 정의한다. 그리고 이것들은 프로그램 실행중이 사용된다. 몇몇 data area는 JVM이 시작할 때 만들어지고 JVM이 꺼질 때 파괴된다. 다른 data area는 thread 별로 있다. thread별 data area는 thread가 시작되고 죽을 때 그 삶을 같이 한다.

1. pc register

JVM은 다수의 스레드의 동시(at once) 실행을 지원한다. JVM의 스레드 각각은 자기 고유의 pc (program counter) register를 가진다. 어떤 시점에서든, 각각의 JVM스레드는 하나의 메소드 코드를 실행하고 있을 것이다. 즉 해당 스레드의 현재 메소드(current method)를 말이다. 만약 method가 native(native의 뜻은 뭐지? -> native method를 말하는 듯)하지 않다면, pc register는 현재 실행되고 있는 JVM명령어의 주소를 포함한다. 만약 메소드가 현재 스레드에 의해 실행되고 있는게 native라면, JVM의 pc register의 값은 undefined다. JVM의 pc register는 returnAddress 또는 native pointer(on specific platform)를 담기에 충분하다.

2. Java Virtual Machine Stacks

JVM Thread는 각각 private JVM stack을 가진다.(thread가 생성될 때 같이 만들어진다.) JVM stack은 frame을 저장한다.(frame은 나중에 나온다.) JVM stack은 C언어에서 만든거랑 유사하다. JVM stack은 push, pop frames를 제외하고 절대로 직접적으로 수정되지 않는다. frames는 힙에 할당되어진다. JVM stack을 위한 memory는 인접해 있을 필요없다.

3. heap

JVM은 JVM Thread가 공유하는 heap이라는 공간을 가지고 있다. heap은 모든 클래스 인스턴스와 배열이 할당되는 런타입 데이터 공간(run-time data area)이다. heap은 JVM이 시작될 때 만들어진다. 오브젝트를 위한 힙 저장소는 storage managerment system(가비지컬렉션)에 의해 되돌려 받는다. heap은 고정된 사이즈 또는 확장되도록 할 수도 있다.

4. Method Area

JVM이 공유하는 method area는 class의 구조 (such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods used in class and instance initialization and interface initialization.)를 담는다. method area는 JVM이 시작할 때 만들어진다. 비록 논리적으로 heap의 부분이다.

5. Run-Time Constant Pool

class파일 안에 per-class, per-interface의 런타임 constant_pool테이블을 보여주는 곳. (constant,ranging from numeric literals known at compile-time to method and field references that must be resolved at run-time이 들어있음) The run-time constant pool은 일반적인 프로그래밍 언어에 심볼테이블(symbol table)과 유사한 것이라 생각하면 된다. 물론 이건 그것보다 더 많은 범위를 가지고 있다. 각각 run-time constant pool은 JVM의 method area에 할당되어 있다. class나 interface의 run-time constant는 걔네들이 만들어질때 JVM이 구성해준다.

5. Native Method Stacks

JVM은 일반적인 stack을 이용한다. 구어체로 "C tacks"라 부른다. 왜 stack을 사용하냐면 네이티브 메소드(native methods)를 지원하기 위해서다.(자바가 아닌 언어로 씌여진 메소드) 네이티브 메소드 스택은 JVM 명령어 모음의 인터프리터 구현(C언어로)으로 사용된다.

6. frames

프레임(frame)은 데이터와 부분 결과를 저장하려고 사용한다. 뿐만 아니라 dynamic linking, return values for methods, and dispatch exceptions. 이럴 때 사용된다. 새로운 프레임은 메소드가 호출될 때마다 각각 만들어진다. 그리고 메소드 호출이 완료되면 죽는다.(그것이 성공이건 익셉션이건...) 프레임은 각자 로컬변수 배열이 있고, 피연산자 스택 그리고 현재 메소드의 클래스의 런타임 constant pool의 참조.. 가 있다.

7. Local Variables

frame은 각각 local variables 배열을 가짐. 길이는 컴파일 타임에 결정 single local variable은 boolean, byte, char, short, int, float, reference, or returnAddress. A pair of local variables은 long or double. 타입을 가진다.

8. Operand Stacks

각각 frame은 last-in-first-out(LIFO)stack 을 가진다(known as its operand stack). 한가지 알아야 할 점은 double, long은 스택이 두개가 하나다. 그래서 스택에 쌓일 때 두개씩 쌓인다.

[jvm]01 Type and Values

1. Integral Types and Values The values

The values of the integral types of the Java Virtual Machine are:

  • For byte, from -128 to 127 (-27 to 27 - 1), inclusive
  • For short, from -32768 to 32767 (-215 to 215 - 1), inclusive
  • For int, from -2147483648 to 2147483647 (-231 to 231 - 1), inclusive
  • For long, from -9223372036854775808 to 9223372036854775807 (-263 to 263 - 1), inclusive
  • For char, from 0 to 65535 inclusive

2. Floating-Point Types, Value Sets, and Values

부동소수점 타입(floating-point types)은 float과 double이 있다. 둘은 각각 개념적으로는 'IEEE 754 표준'에서 규정하는 32-bit single-precision과 64-bit double-precision 포맷이다.

IEEE 754 standard는 +/- 수만 포함하지 않고 +/- 0(제로값), +/-무한값, 그리고 Special Not-a-Number(NaN)값. NaN값은 0/0같은 유효하지 않은 연산의 결과를 표현할 때 쓰인다. 모든 JVM의 구현은 두개의 표준 집합을 지원하는 것이 요구된다. (float value set과 double value set)

returnAddress Type and Values

returnAddress type은 JVM의 jsr, ret 그리고 jsr_w 명령어에서 사용한다. returnAddress의 값은 JVM명령어들의 연산부호의 포인터들이다. 숫자 원시 타입(numeric primitive types)와 달리 returnAddress타입은 어느 자바 프로그래밍 언어 타입과 들어맞지 않고 running program에 수정될 수 없다.

3. boolean Type

비록 JVM이 불린타입을 정의한다 하지만, 아주 제한적인 것만을 지원한다. JVM에는 boolean 값을 위해 만들어진 명령어는 없다. 대신 JVM에 불린값을 int로 바꾸는 어구가 따로 있다. JVM은 boolean arrays는 직접적으로 지원한다. newarray 명령어는 불린타입배열를 만들 수 있다. 불린타입배열은 바이트배열(byte array)의 명령어로 접근되고 수정된다.(baload, bastore) *오라클 JVM의 구현에서는, 불린배열은 JVM 바이트배열로 인코딩 되어있다.(불린요소 하나당 8비트) JVM은 1,0을 인코딩해서 불린배열을 사용한다.(1=true, 0=false) 자바의 불린값이 int타입 값으로 매핑된다.(compiler가 함)

4.Reference Types and Values

reference type에는 3가지가 있다. : class type, array type, interface type 이것들의 값은 각각 동적으로 만들어지는 클래스 인스턴스, 배열 또는 인터페이스를 구현한 클래스 인스틴스 / 배열과 연결된다. 배열타입은 1차원 컴포넌트타입을 구성한다.(???) 배열타입의 컴포넌트 타입은 자기 스스로 배열 타입이다.(???) 만약, 어떤 배열타입에서 시작하면, 하나는 컴포넌트 타입을 고려하고, 그 후에 그 타입의 컴포넌트타입(이것도 배열이라면)을 고려한다. 계...속, 마침에(마지막에) 배열타입이 아닌 컴포넌트타입이 발견된다. 이걸 element type of an array type 이라고 한다. 배열의 요소타입이라고 하자. 이 요소타입은 원시 타입, 클래스 타입, 인터페이스 타입건 상관 없지면 이 이중에 있어야 한다. *여담: 컴포넌트타입은 확장이 가능하니 배열을 확장할 때 component type으로 확장되다가 값이 있는 element type으로 가면 거기서 멈추는 듯. 레퍼런스 값은 null reference를 가질 수도 있다. null reference는 오브젝트가 없음과 연결되어 있다. (null이란 말) null reference는 처음에는 run-time type을 가지지 않는다. 하지만 어떤 타입으로도 캐스팅 될 수 있다. 이 타입의 디폴트 값은 null이다. 이 명세는 구체적인 null 값을 강제하지 않는다.

[jvm]00-Class File Format 클래스파일포맷

jvm 개요

  1. Class File Format

  2. 모든 JVM으로 컴파일된 코드는 class라는 파일포맷으로 변환된다.

  3. Data Types

  4. JVM은 두 가지의 타입을 운영한다. primitive typesreference types이다. 그에 부응하여, 이 두 타입은 서로 방식으로 값을 저장하고, 아규먼트로 다뤄지거나, 리턴값으로 사용되고 또 계산된다. JVM은 대부분의 타입체킹type checking을 런타임 이전에 한다. primitive type의 값들은 이름표가 붙여질 필요가 없어서 알기 힘들 수 있지만, run time에는 타입을 볼 수 있고, 레퍼런스타입의 값으로 구별할 수도 있다.

    JVM도 이런 식으로 알아낼까??? JVM은 명령어 집합이 operand(피연산자)타입을 구별한다. (특정 타입 값을 실행하기 위해서 명령어를 보고 확인한다) 예를들어, iadd, ladd, fadd, dadd 는 모두 JVM에서 수를 더하고 결과값을 생성하는 명령어다. 하지만 각각 특정한 operand type에서만 작동한다. 위의 명령어들은 순서대로 int, long, float, double이다.

    JVM은 오브젝트를 지원한다. (여기서 오브젝트는 동적할당 인스턴스 또는 배열 모두를 말한다.) 오브젝트 레퍼런스(a reference to an object)는 Java Virtual Machine type reference로 간주된다. (그냥 reference type이라 간주된다는 말...?) 레퍼런스타입의 값은 오브젝트의 포인터로 생각해도 좋다. 하나의 오브젝트에 여러개의 오브젝트레퍼런스가 존재할 수 있다. (More than one reference to an object may exist.) 오브젝트는 항상 type reference의 값을 통해서 실행되고, 넘겨지고 테스트된다.(Objects are always operated on, passed, and tested via values of type reference.)

  5. Primitive Types and Values

  6. Java Virtual Machine이 지원하는 primitive data type은 숫자 타입(numeric types), 불린 타입(boolean type), 그리고 리턴어드레스 타입이다.(returnAddress type)

    숫자타입(numberic types)는 정수타입(integral type)과 부동소수점 타입(floating-point type)으로 나뉜다.

    정수타입

    • byte, 8-bit 부호붙은 2의보수 정수(8-bit signed two's-complement integers), 디폴트 0
    • short, 16-bit 부호붙은 2의보수 정수, 디폴트 0
    • int, 32-bit 부호붙은 2의보수 정수, 디폴트 0
    • long, 16-bit 부호없는 정수(16-bit unsigned integers), 유니코드 코드포인트(문자의 바이트코드)를 나타내며, UTF-16으로 인코딩되어있다. 디폴트 null code point('\u0000')

    부동소수점 타입은 IEEE754의 표준을 따른다.

    • float, whose values are elements of the float value set or, where supported, the float-extended-exponent value set, and whose default value is positive zero
    • double, whose values are elements of the double value set or, where supported, the double-extended-exponent value set, and whose default value is positive zero
    • 위 내용을 그냥 적은 이유는 아래에 관련 내용이 제대로 설명될 것 같아. 용어를 남겨 놓는다. (적절한 용어도 뭔지 모르겠음, 그냥 float,double 값들이랑, double-extended-exponent는 지수로 표현되는 값들을 말한다. 디폴트는 양수0으로 같다)

    불린타입(boolean type)은 참 거짓을 true, false로 부호화한다. 디폴트 false.

    • The First Edition of The Java® Virtual Machine Specification did not consider boolean to be a Java Virtual Machine type. However, boolean values do have limited support in the Java Virtual Machine. The Second Edition of The Java® Virtual Machine Specification clarified the issue by treating boolean as a type.

    returnAddress타입은 JVM명령어의 연산부호의 포인터다. primitives type에서 유일하게 Java Programming language type과 직접적으로 연관되어 있지 않다.

윈도우 브라우저 호환성 문제




IE는 우리의 주적이다.


여튼 윈도우즈 브라우저의 호환성 문제를 많이 일으키는 것이 IE인데 그 호환성 문제를 없애려는 미봉책 중 하나를 여기에 적어 놓는다.

http-equiv="X-UA-Compatible" content="IE=edge"
매타테그를 하나 만들어서 그 안에 이것을 넣어라. (사실 메타태그를 다 넣어서 보여주고 싶은데 안보여짐... 계속 사라지고... 정말 메타태그로 인식하는 것 같음.방법을 알아봐야겠지만 귀찮아서 이렇게 보여줌)

[javascript patterns][Namespace Pattern] 스터디 19


Namespace Pattern

다른 언어를 공부해 본 적이 있다면 바로 느낌이 왔겠지만 네임스페이스패턴(Namespace Pattern)은 타 언어에서 네임스페이스를 정하는 것과 비슷한 일을 한다. 가장 중요한 차이는 namespace 혹은 package라는 문법적 이름을 사용하지 않고 구현을 해야 한다는 점이다.

[javascript patterns][Object Creation Pattern] 스터디 18

The JavaScript language is simple and straightforward and often there’s no special syntax for features you may be used to in other languages, such as namespaces, modules,packages, private properties, and static members.
자바스크립트에는 namcespace, module, packages, private properties, static members를 만드는 데 새로운 문법이 있지는 않다. 대신 여러가지 방법으로 구현할 수 있다. (우리는 이 패턴들을 알아야 한다. 다른 언어들이 패키지를 가지고 있듯이 자바스크립트에도 패키지를 가지고 있다. 단지 문법이 제공하는 것이 아닌 우리가 직접 구현해야 한다는 점이 다른 점이다. 그러니 익혀야 한다.)

이번 장에서는 객체화에 관련된 패턴들을 배울 것이다.
  • namespacing
  • dependency
  • declaration
  • module pattern
  • sandbox patterns

[javascript patterns][함수] 스터디 17

지금까지 배운 것을 요약해보자

코드를 더욱 깨끗하게 하는 것은 개발자의 의무이다. javascript는 참으로 깨끗한 코드를 짜기가 힘들다. 그래서 서로다른 js를 만들어서 html에서 따로 관리하는 것이 대부분인 듯하다.
하지만 당신이 API를 만든다면? 이름 하나하나에 많은 공을 들일 것이다. 그리고 이름이 없어지길 원할수도 있다. 그 때 우린 익명함수를 사용한다. 즉시실행함수를 사용하여 전역(ex. window)에 수 많은 라벨들을 없애 깔끔한 코드를 만들도록 한다.
하지만 나는 아직 멀었다. 배우면 배울수록 늘어가는 것이 '내가 모르고 있는 것'들의 양인 것 같다.

[javascript patterns][커리(Curry)] 스터디 16

커링(Curring)

function add(x, y) {
  var oldx = x, oldy = y;
  if (typeof oldy === 'undefined') { // 부분적인 적용
    return function (newy) {
      return oldx = newy;
    }
  }
  // 전체 인자를 적용
  return x + y;
}

//테스트
typeof add(5); // "function"
add(3)(4); // 7

// 새로운 함수를 만들어 저장
var add200 = add(200);
add200(10); // 2010
교재의 예제를 그대로 썼다. add가 반환하는 내부 함수에 클로저를 만든다. 클로저는 x,y의 값을 oldx와 oldy에 저장한다. 하지만 더 간단하게 할 수 있다. 다음 예제를 보자.
function add(x, y) {
  if (typeof y === "undefined") {
    return function (y) {
      return x + y;
    }
  }
  // 전체 인자를 적용
  return x + y;
}
여기에는 oldx, oldy가 없는데 원래 x는 암묵적으로 클로저에 저장되어 있고, y는 재사용을 하고 있다.

조금더 범용적인 방식으로 처리할 수 있을까?

어떤 함수라도 부분적인 매개변수를 받는 새로운 함수로 변형할 수 있을까?
function flexible_curry(fn) {
  var slice = Array.prototype.slice,
      stored_args = slice.call(arguments, 1);

  return function () {
    var new_args = slice.call(arguments),
        args = stored_args.concat(new_args);
    return fn.apply(null, args);
  };
}
되게 복잡해 보이는 이유는 단시 arguments가 배열이 아니기 때문이다. slice를 쓰고 싶은데 arguments는 배열처럼 보일 뿐 배열이 아니기 때문에 var slice = Array.prototype.slice로 slice안에 메소드를 넣었다. 그리고는 slice.call(arguments, 1); argument를 배열의 메소드로 배열처럼 사용하는 것이다. 이해가 안된다면
[1, 2, 3, 4, 5].slice(1); // [2, 3, 4, 5]
Array.prototpye.slice.call([1, 2, 3, 4, 5], 1);
이제 테스트를 해보자
function add(x, y) {
  return x + y;
}
function flexible_curry(fn) {
  var slice = Array.prototype.slice,
      stored_args = slice.call(arguments, 1);

  return function () {
    var new_args = slice.call(arguments),
        args = stored_args.concat(new_args);
    return fn.apply(null, args);
  };
}


var newadd = flexible_curry(add, 5);
newadd(5); // 10
add(fn)는 클로저로서 값이 휘발성으로 사라지지 않는다. (객체화도 되지 않았는데 어떻게?) 그것이 클로저다. 나중에 좀 더 공부해보도록 하자. 어쨋든 argument에서 첫번째 것만을 잘라내서(slice) sotred_args에 넣기 위해 Array.prototype.slice.call(arguments, 1)을 사용하였다.
그리고 반쪽자리 add(fn)를 반환한다. 그것을 newadd에 넣었고 newadd(5)를 실행하면 더하기를 수행 할 것이다. 여기서 concat은 배열끼리의 접합을 수행한 후, args에 넣는다. 그 후 fn.apply(null, args); 를 실행한다. (apply는 call과 비슷하게 동작하지만 배열을 받는 다는 것을 기억하라. 이 예제에서 apply는 아주 잘 맞는다.)
function multifly(a, b, c, d, e) { return a * b * c * d * e; }

function flexible_curry(fn) {
  var slice = Array.prototype.slice,
      stored_args = slice.call(arguments, 1);

  return function () {
    var new_args = slice.call(arguments),
        args = stored_args.concat(new_args);
    return fn.apply(null, args);
  };
}

flexible_curry(multifly, 1, 2, 3)(5, 5);


var a = flexible_curry(multifly, 1.534);
a(10, 10, 10, 10);
var b = flexible_curry(a, 2, 3);
b(6, 7);
커링은 엄청난 자유를 준다.

커링을 사용해야 할 경우

어떤 함수를 호출할 때 대부분의 매개변수가 항상 비슷하다면, 커링의 적합한 후보라고 할 수 있다. 매개 변수 일부를 적용하여 새로운 함수를 동적으로 생성하면 이 함수를 반복되는 매개변수를 내부적으로 젖아하여, 매번 인자를 전달하지 않아도 원본 함수가 기대하는 전체 목록을 미리 채워놓을 것이다.

[javascript patterns][커리(Curry)] 스터디 15

부분적인 적용

함수의 호출이 실제로는 인자의 묶음을 함수에 적용하는 것임을 알 수 있다. 그러면 인자를 한 번에 다 적용하는 것이 아니라 부분부분 인자를 가져와서 함수에 적용하는 것은 어떨까? 이것은 수학 함수를 직접 계산할 때 흔히 쓰는 방법이라 한다.
예를 들어보자
funtion add(x, y) {
  return x + y;
}

add(5, 4);
여기서 부분적인 적용을 하는 개념은
function (5, y) {
  return 5 + y;
}
// 이렇게 x를 먼저 적용한 후에
function (5, 4) {
  return 5 + 4;
}
// 이렇게 나머지 인자가 부분적으로 가져와서 적용하는 것이다.
그러니까 첫번째 인자를 적용한 상태에서 다른 인자를 넣어서 함수를 수행하는 것이다.
var add = function (x, y) {
  return x + y;
}

add.apply(null, [5, 4]); // 9

var add_part = add.partialApply(null, [5]); // 첫번째 인자만 먼저 적용 (부분적용)

add_part.apply(null, [4]); // 9
이것은 사실 add(5)(4)와 같다. add(5)가 (4)로 호출할 수 있는 함수를 반환하기 때문이다. 아! partialApply는 현재 없는 메서드이다. 하지만 이제 만들어 볼 것이다.
함수의 부분적인 적용을 처리하도록 하는 과정을 커링(Curring)이라고 한다.

[javascript patterns][설정 객체 패턴] 스터디 13


설정 객체 패턴

설정 객체 패턴은 좀 더 깨끗한 API를 제공하는 방법이다. 라이브러리나 다른 프로그램에서 사용할 코드를 만들 때 특히 유용하다. 소프트웨어를 개발하고 유지보수하는 과정에서 요구사항이 변경되는 것은 어쩔수 없는 현실이다. 변화하는 요구사항에 우리는 어떻게 코드로 대처해야 할까. addPerson()이라는 함수를 가정해보자. 처음에는 이름과 성만 만들어 사람을 추가하라고 요구를 했다.
function addPerson(first, last) {/*...*/}
갑자기 생일, 성별, 주소 도 저장해야 한다고 한다.(게다가 선택적으로) 선택적으로 저장하는 것을 모르겠고 일단 매개변수를 추가해보자.
function addPerson(first, last, dob, gender, address) {/*...*/} //선택적인 매개변수는 일부러 뒤에 적었다.
함수가 좀 길어졌다. 그런데 username은 필수로 저장해야 한다고 전화가 왔다. 이제 함수를 호출할 때는 필수로 써야 하는 것, 선택적인 매개변수, 그리고 매개변수의 순서... 점점 많아지고 복잡해진다.
addPerson("Younghwan", "Nam", new Date(), null, null, "myID");
많은 수의 매개변수는 참 불편하다. 모든 매개변수를 하나의 객체로 만들어 전달하는 것이 더 낫다. 이 객체를 설정(configuration)을 뜻하는 conf라고 해보자.
var conf = { username: "myID", first: "Bruce", last: "Wayne" };
addPerson(conf);
이 패턴은 함수가 DOM 엘리먼트를 생성할 때, 엘리먼트의 CSS스타일을 지정할 때 유용하다. 엘리먼트와 스타일은 많은 수의 어트리뷰트와 프로퍼티를 가지며 대부분은 선택적인 값이기 때문이다.