Extending Build-markup with repeat refinement

后端 未结 2 414
夕颜
夕颜 2021-01-17 02:23

I tried to add a repeat refinement to build-markup function using the previous answer: How to bind to foreach context?

build-markup: func [
    {Return marku         


        
相关标签:
2条回答
  • 2021-01-17 03:09

    seems to work:

    build-markup: func [
        {Return markup text replacing <%tags%> with their evaluated results.} 
        content [string! file! url!] 
        /repeat block-fields block-values
        /quiet "Do not show errors in the output." 
        /local out eval value
    ][
    
      out: make string! 126 
    
      either not repeat [
          content: either string? content [copy content] [read content] 
    
          eval: func [val /local tmp] [
              either error? set/any 'tmp try [do val] [
                  if not quiet [
                      tmp: disarm :tmp 
                      append out reform ["***ERROR" tmp/id "in:" val]
                  ]
              ] [
                  if not unset? get/any 'tmp [append out :tmp]
              ]
          ] 
          parse/all content [
              any [
                  end break 
                  | "<%" [copy value to "%>" 2 skip | copy value to end] (eval value) 
                  | copy value [to "<%" | to end] (append out value)
              ]
          ]
        ][        
    
            actions: compose/only [
                set in system/words (to-lit-word pick (block-fields) 1) get pick (block-fields) 1
                set in system/words (to-lit-word pick (block-fields) 2) get pick (block-fields) 2
                probe get in system/words (to-lit-word pick (block-fields) 1)
                probe get in system/words (to-lit-word pick (block-fields) 2)
                append out build-markup content
    
            ]
            foreach :block-fields block-values actions        
        ] 
        out
    ]
    
    template1: {    <td><%a%></td><td><%b%></td>
    }
    template2: {  <tr>
    <%build-markup/repeat template1 [a b] [1 2 3 4]%>
      </tr>
    }
    template3: {<table>
    <%build-markup/repeat template2 [a b] [1 2 3 4 5 6]%>
    </table>}
    build-markup template3
    

    output:

    == {<table>
      <tr>
        <td>1</td><td>2</td>
        <td>3</td><td>4</td>
    
      </tr>
      <tr>
        <td>1</td><td>2</td>
        <td>3</td><td>4</...
    >
    

    >

    0 讨论(0)
  • 2021-01-17 03:17

    For:

    words: [num]
    vals: [1 2 3]
    

    When you use foreach :words, you are creating a new context for which the repeat block will be bound to. The word! contents of :words are not actually bound to this new context. The values you are getting suggest 'a is globally set to 1 and 'b is set to [a b]. To illustrate:

    >> num: 9                 
    == 9
    >> words: [num]           
    == [num]
    >> foreach :words vals [
    [    probe get 'num         
    [    probe get first :words 
    [    ]                      
    1
    9
    2
    9
    3
    9
    == 9
    

    To work around this, try to picture that for each iteration of the loop, the block that is executed is 'bind-ed to the loop context. You can preempt the bind like this:

    foreach :words vals probe compose/only [
        probe get first (words)
    ]
    

    (probe left in for illustrative purposes)

    0 讨论(0)
提交回复
热议问题