2013-02-02 3 views
1

Ruby에 자체 수정 코드를 작성하는 것에 대해 우려하고 있습니다. 자체 수정을 통해 코드 블록을 입력 값으로 사용하는 함수를 작성하고이를 기반으로 다른 코드 블록을 출력 할 수 있음을 의미합니다. (I는 런타임에 메서드를 재정의 등의 기본에 대한 요구 하진 않았어.)Ruby의 자체 수정 코드

_x_ = lambda { |a, b, c, d| b + c } 

하나

가 알 수있는 것 I는 다음과 같은 블록을 가지고, 예를 들어, 수행 할 수 있습니다, 그 인수 ad 본문에 전혀 사용되지 않으므로 예를 들어 기능을 원합니다. 그들을 제거하기 #strip 서면으로 동일한 결과를 생성한다

x = _x_.strip 

: 리스프 코드가 쉽게 조작 가능한 데이터이기 때문에

x = lambda { |b, c| b + c } 

지금 리스프에,이, 쉽게 될 것입니다. 하지만 루비 코드를 조작하는 방법을 모르겠습니다. 나는 그것을 파싱 할 수있다. by

RubyVM::InstructionSequence.disassemble(x) 

그러나 어떻게 이것을 기반으로 수정 된 블록을 작성합니까? 내가하고 싶은 다른 예는 예입니다.

y = lambda { A + B } 
y.deconstantize 
# should give block same as saying 
lambda { |_A, _B| _A + _B } 

지금까지 루비에서 나는 뭔가를 할 수 없다고 인정해야만했던 상황을 경험하지 못했습니다. 그러나 이번에는, 감각적 인 느낌은 아름답게 구조화 된 코드 대 약한 구문 (Lisp이 될 수있는)을 가진 코드의 근본적인 약점을 만났을 수도 있다는 것을 나에게 말해줍니다. 제발 저를 계몽하십시오.

+0

구체적인 사용 사례가 있습니까? – Nevir

+0

사용하지 않은 병을 감지하려면 AST 레벨로 내려야합니다. 아마도 [melbourne gem]을 통해 (https://github.com/simplabs/melbourne). 하지만 유스 케이스를 커버하기 위해 취할 수있는 다른 /보다 편리한 접근 방법이 있습니다. – Nevir

+0

@Nevir :하지만 분명히하고 있습니다. 나는 관광객이 아니다, 나는 내가 할 일이없는 곳으로 가지 않는다 :-). 다음 코드를 상상해보십시오 :'ChemicalReaction.new (name : "A_and_B_assembly", rate : proc {A * B * 0.189})'. 나는 사용자가 쉽게 가고 싶어하므로,'proc {| _A, _B | _A * _B * 0.189}'이는 다음과 같은 의미 일 것입니다. (0.189는 속도 상수 임) ... –

답변

1

Boris 여기에서 시작하려면 반드시 Boris에 의존해야합니까?

화학자가 자신의 수식을 가장 편리한 방식으로 표현하기 위해 사용할 수있는 자신 만의 상황 별 언어를 만드는 것이 왜 그럴까요? 그런 다음이 "화학 표현 언어"에 대한 간단한 파서 및 컴파일러를 만듭니다.

이 파서와 컴파일러는 화학자가 Ruby 코드에 작성한 표현식을 구문 분석하고 컴파일합니다. 그렇다면 다음을 가질 수 있습니다 :

ChemicalReaction.new(..., "[ATP] * [GDP] * NDPK_constant") 

Voila : 궁극의 유연성.

사용 편의성이 주요 관심사 인 경우이를 수행하는 방식입니다.이미 "람다 (lambda)"를 작성하는 것은 불필요하게 성가신 일로 생각됩니다. 원하는 모든 작업은 가능한 가장 컴팩트 한 방법으로 도메인 특정 수식을 표현하는 것입니다.

+0

답장을 보내 주시면 매우 감사하겠습니다. 상인이 상자 밖에서 생각하는 문구를 보여줍니다. 하지만 Casper, Ruby DSL이 내가 원하는 것을 충분히 보았습니다. Dan Bernstain의 말은 파싱하지 말라는 것입니다. 나는 해석하고 싶지 않다. Ruby 파서를 사용하고 싶습니다.보시다시피, 나는 이미 불완전한 해법을 가지고 있습니다. 화학 이름의 상수 이름과 관련된 변수 이름을 사용하십시오. 블록 외부의 종,'instance_eval' 올바른 환경의 블록. 그러나 이것은 완벽하지 않습니다. 그래서 전능하신 분에게 질문하여 더 많은 것을 배우기를 바랍니다. –

+0

@BorisStitnicky 좋습니다. 좋습니다. 댓글 주셔서 감사합니다. 나는 당신의 강점에 감탄합니다. 이런 상황에서 파서를 쓰는 것을 좋아하지만, 루비에서 아름답게 작동하게 할 수 있다면, 나는 더 나아 졌다고 인정합니다. – Casper

+0

편집 후에 답변을 다시 읽으십시오. 아무도 더 나은 답변을 제공하지 않으면 귀하의 답변을 수락합니다. 거기에있는 문자열에 대해 당신이 맞습니다. 나는 어쨌든 ... 나는 Lisp에 대한 부러움으로 고통 받고 있다고 생각한다 :-) –

2

블록 변수를 사용하는지 여부를 감지하는 것은 복잡한 작업이므로 RubyVM을 사용하여이를 수행 할 수 있습니다. 그래서 질문은 코드의 형식을 바꾸는 방법을 묻는 것 같습니다.

당신은 할 경우

_x_ = ->a, b, c, d{b + c} 

을하고 ad 사용하지 않는 것을 알고 RubyVM을 사용하고 올 수있었습니다 가정, 그래서 당신은 _x_

x = ->b, c{b + c} 

을 만들려면 . 그러면 간단합니다 :

x = ->b, c{_x_.call(nil, b, c, nil)} 
+0

O.K., 내가 아리따운 변화를 포함하는 나의 예가 '# curry' 방법을 사용하여 때때로 해결 될 수 있기 때문에 최선의 것이 아니라고 말해야 만한다. 나는 솔직히 말해서 자기 수정과 같은 리스프입니다. –

+0

잠깐, 이제 내가 대답을 읽었을 때 ... 알다시피, 나는 온라인으로 말할 때 모든 자본을 자주 사용하지 않지만, 과정 중에는 엄격한 코드를 사용하여 코드를 수정할 수있다. 내가 묻는 것은 자기 수정 코드입니다. "자필"은 프로그램이 아니라 "본"이라는 말입니다. 지금 나는 2 + 2가 5가 아니라 4라는 오토 마트에 대해서 설명하려고하는 스탠리 노트의 새 소식을 들었습니다. –

+1

Boris, 귀하의 질문을 흥미롭고 유용하게 생각합니다.하지만 대문자로 쓰지 마십시오. 어쨌든 대화를 돕지 않습니다. – sunnyrjuneja

관련 문제