-1

我之前的问题之后,让我对我到底想要什么更准确,更少混淆。我写了一个化学包,我决定所有化学物质和反应的名称都大写,例如“ATP”、“腺苷”、“脱氧胞苷”等。这让我可以写例如:

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

现在如果使用 ATP 磷酸化 GDP,使用具有催化常数的酶 NDPK

NDPK_constant = 0.6

,我想写成:

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

我可以写:

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

但对我来说它似乎太湿了。看看如何reactant_1reactant_2重复两次,同时ATPGDP记住。简单的解决方案是:

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

以及将和定义为 、 的浓度的上下文中instance_eval的速率查找块。这非常接近,但不完全是我想要的东西,这让我很生气。我什至可以用来查找块内使用了哪些化学物质,例如。_ATP_GDPATPGDPRubyVM

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 irb_binding@(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或者也许[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 irb_binding@(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出现在第 7 行、第 10 行的:ATP, :GDP。在块外,ATP常量GDP包含ChemicalSpecies实例,但在块内,我希望它们引用 ATP 和 GDP浓度。在常量本身具有不同含义的环境中,我没有找到任何方法来评估块(也就是说,除非我想在运行时使用肮脏的技巧临时重写常量,这是我不想要的)。我渴望的是能够getconstant :ATP用例如替换这个 RubyVM 代码指令。send :_ATP, 0, nil, 24, <ic:0>,然后例如。instance_eval在一个环境中关闭_ATP意味着ATP.concentration......我知道我在问一些棘手的问题,再次抱歉......

至于第二个选项[ATP][GDP]那只需要在块内激活某种新的数组创建钩子,这样如果只有一个元素,即 a ChemicalSpecies,则将返回其浓度而不是数组对象。我认为这同样是困难的,即使不是不可能的任务。

4

1 回答 1

1
于 2013-02-03T04:54:43.610 回答