2013-02-02 6 views
-1

my previous question에 이어 정확히 정확하게 내가 원하는 것을 덜 어둡게 만듭니다. 나는 화학 약품을 썼다. 화학 약품과 반응의 이름이 'ATP', '아데노신', '데 옥시 시티 딘'등으로 대문자로 표기 될 것이라는 결정을 내렸다. 예를 들면 :Ruby의 자체 수정 코드가 다시로드되었습니다

ATP = ChemicalSpecies.new initial_concentration: 225.0  # in micromolars 
GDP = ChemicalSpecies.new initial_concentration: 75.0  # in micromolars 

ChemicalReaction.new name: ATP_GDP_phosphate_exchange, 
        rate: lambda { ATP * GDP * NDPK_constant } 

난 그냥 쓸 수있다 : 촉매 일정

NDPK_constant = 0.6 

와 효소 NDPK를 사용하여 ATP가 GDP를 인산화하는 데 사용되는 경우 이제

는, 내가 원하는이로 기록 될

ChemicalReaction.new name: ATP_GDP_phosphate_exchange, 
        reactants: [ ATP, GDP ], 
        rate: lambda { |reactant_1, reactant_2| reactant_1 * reactant_2 * NDPK_constant } 

하지만 너무 젖어 보인다. reactant_1, reactant_2이 두 번 반복되는 방법을 확인하고 ATP, GDP을 염두에 두십시오. 쉬운 해결책은 다음과 같습니다

ChemicalReaction.new name: ATP_GDP_phosphate_exchange, 
        rate: lambda { _ATP * _GDP * NDPK_constant } 

그리고 instance_evalATP, GDP의 농도로 _ATP_GDP을 정의하는 맥락에서 속도-찾는 블록. 이것은 매우 가깝지만, 은 정확히이 아니고, 나는 천국에서 나에게 화를냅니다. 심지어 어떤 화학 물질이 블록 내부에서 사용되는지 찾기 위해 RubyVM을 사용할 수도 있습니다. _ATP_GDP을이 구문 분석하여

require 'ap' # (awesome_print, like pretty_print but fancier, install if you don't have) 
ap RubyVM::InstructionSequence.disassemble(lambda { _ATP * _GDP * NDPK_constant }).split("\n") 
#=> [ 0] "== disasm: <RubyVM::InstructionSequence:block in [email protected](irb)>=====", 
    [ 1] "== catch table", 
    [ 2] "| catch type: redo st: 0000 ed: 0027 sp: 0000 cont: 0000", 
    [ 3] "| catch type: next st: 0000 ed: 0027 sp: 0000 cont: 0027", 
    [ 4] "|------------------------------------------------------------------------", 
    [ 5] "0000 trace   1            ( 22)", 
    [ 6] "0002 putself   ", 
    [ 7] "0003 send    :_ATP, 0, nil, 24, <ic:0>", 
    [ 8] "0009 putself   ", 
    [ 9] "0010 send    :_GDP, 0, nil, 24, <ic:1>", 
    [10] "0016 opt_mult   <ic:5>", 
    [11] "0018 getinlinecache 25, <ic:3>", 
    [12] "0021 getconstant  :NDPK_constant", 
    [13] "0023 setinlinecache <ic:3>", 
    [14] "0025 opt_mult   <ic:6>", 
    [15] "0027 leave 

, 하나는 내부에 어떤 이름을 배운다. 하지만 내가 말했듯이, 고집에서, 나는 _ATP, _GDP을 찾는다. 화학자들이 농도에 대괄호를 사용하기 때문에 ATP, GDP 또는 [ATP], [GDP]이라고 말하고 싶습니다. 나는 Yusuke Endoh가 제약 코딩이라고 부르는 것을 알고 있습니다. 내 질문은,이 두 가지 바람직한 구문 중 하나가 맞을 수 있습니까? 예를 들어, 폐쇄 lambda { ATP * GDP * NDPK_constant }을 가진이 제공 분해 :

ap RubyVM::InstructionSequence.disassemble(lambda { ATP * GDP * NDPK_constant }).split("\n") 
#=> [ 0] "== disasm: <RubyVM::InstructionSequence:block in [email protected](irb)>=====", 
    [ 1] "== catch table", 
    [ 2] "| catch type: redo st: 0000 ed: 0027 sp: 0000 cont: 0000", 
    [ 3] "| catch type: next st: 0000 ed: 0027 sp: 0000 cont: 0027", 
    [ 4] "|------------------------------------------------------------------------", 
    [ 5] "0000 trace   1            ( 23)", 
    [ 6] "0002 getinlinecache 9, <ic:0>", 
    [ 7] "0005 getconstant  :ATP", 
    [ 8] "0007 setinlinecache <ic:0>", 
    [ 9] "0009 getinlinecache 16, <ic:1>", 
    [10] "0012 getconstant  :GDP", 
    [11] "0014 setinlinecache <ic:1>", 
    [12] "0016 opt_mult   <ic:5>", 
    [13] "0018 getinlinecache 25, <ic:3>", 
    [14] "0021 getconstant  :NDPK_constant", 
    [15] "0023 setinlinecache <ic:3>", 
    [16] "0025 opt_mult   <ic:6>", 
    [17] "0027 leave 

하나는 getconstant:ATP, :GDP를 들어, 라인 7에서 10을 나타 것으로보고있다. 블록 외부의 ATPGDP 상수는 ChemicalSpecies 인스턴스를 포함하지만 블록 안에는 ATP 및 GDP 의 농도 인을 참조해야합니다. 상수 자체가 다른 의미를 갖는 환경에서 블록을 평가할 방법을 찾지 못했습니다 (즉, 내가 원하지 않는 더러운 트릭을 사용하여 런타임에 상수를 임시로 다시 쓰지 않는 한). 내가 간절히 원했던 것은이 RubyVM 코드 getconstant :ATP 명령어를 예를 들어 대체 할 수 있다는 것이다. send :_ATP, 0, nil, 24, <ic:0> 그리고 나서 예. instance_eval_ATPATP.concentration을 의미 evironment이 폐쇄 ... 난 하나가 새로운 배열의 어떤 종류의 활성화가 필요 것이라고, 내가 두 번째 옵션 [ATP], [GDP]에 관해서는

... 죄송합니다 다시 어려운 질문을 부탁 해요 알고 생성 후크가 블록 내부에만 있으므로, 요소가 하나만있는 경우 (ChemicalSpecies), 배열 객체 대신 해당 집중이 반환됩니다. 나는 이것이 불가능하지는 않더라도 똑같이 어렵다고 생각한다.

+1

모든 화학 대화를 제거하고 일반화하십시오. 우리는 마치 우리가 외계 종소리를 말하는 것처럼 들릴지도 모릅니다.하지만 이것은 그리스어입니다. 또한 해체는 무의미합니다. – Linuxios

+2

이것은 단지 망치를 포크로 구부리려고하는 (또는 다른 영리한 말을 삽입) 것을 확인하는 것입니다. 사용자가 주요 우려 사항이라면 프로그래밍 철학자가 말한 것처럼 지옥에 빠지면됩니다 :) 사용자를 주요 지시어 1로 코딩하십시오. [ATP]가 아무도없는 추악한 스파게티 코드의 똥 더미없이 멋지게 행동하게하는 방법은 없습니다 해독하고 유지할 수있을 것입니다. 뿐만 아니라 Ruby 내부에 의존적 인 취성 코드가 될 것입니다. 자신 만의 도메인 언어를 작성하면 궁극의 통제력을 발휘할 수 있으며 결국에는 더 행복해하는 코더가됩니다 (사용자도 행복합니다). – Casper

+0

[내 이전 답변] (http://stackoverflow.com/a/14658827/823617)도 볼 수 있습니다. 파서를 만들지 않고도 모든 것을 처리 할 수 ​​있습니다. 간단한 문자열 교체와'eval'만으로도이 트릭을 수행 할 수 있습니다. 나는. '[ATP]'를'ATP.concetration'와'eval'로 대체하십시오. – Casper

답변

1

누구나, 특히 캐스퍼에게 감사드립니다. 요약하면, 나는 Sourcify/RubyParser을 가리키며 루비 코드가 아닌 강간을 당했다. Sourcify/RubyParser는 내가 원했던 정확한 대답 이었지만 Casper는 주석에서 언급했다. 어쨌든 - 하늘은 명성을 얻습니다. ⁅ATP⁆가 싫어 일반 솔루션 _ATP보다 보면

ChemicalSpecies = Struct.new :concentration 
ATP, GDP = ChemicalSpecies[ 225.0 ], ChemicalSpecies[ 75.0 ] 
class << (ChemicalSystem = Object.new) 
    def ⁅ATP⁆; ATP.concentration end 
    def ⁅GDP⁆; GDP.concentration end 
end 
rate = lambda { ⁅ATP⁆ + ⁅GDP⁆ * 0.6 } 
ChemicalSystem.instance_exec &rate 
#=> 10125.0 

가짜 괄호 : 가짜 유니 코드 브라켓 - 나는 게시 된 이후, 새로운 아이디어 나에게 방문을 지불했다. 전체 너비 대괄호 [ATP]과 같이 더보기 좋은 옵션은 많지 않지만 입력하는 방법뿐 아니라 사용자가 바닐라와 혼동하지 않도록하는 방법도 있습니다. 나는 전체 유니 코드를 샅샅이 뒤졌고, 내가 싫어하는 유일한 옵션은 「ATP이었다. 물론 이것은 자기 수정 코드와는 아무런 관련이 없습니다. 진짜 대답은 캐스퍼의 말이다.

관련 문제