Проблема с контекстом и имуществом

Скажем, я хочу сгенерировать этот вывод:

  public  String toString() {
         return this.getFirstName() + "," + this.getLastName() + "," + this.getAge();
  }

из шаблона ниже и настраиваемой рекурсивной функции разметки сборки:

  template-toString: {this.get<%property%>() <%either not context.build-markup/EOB [{+ "," +}][""]%> }

  build-markup/vars template-toString [property] ["FirstName" "LastName" "Age"]

Моя проблема состоит в том, чтобы избежать объединения последнего элемента с {+ "," +}

Моя идея состояла в том, чтобы использовать разметку context.build со свойством EOB (End Of Block), которому будет присвоено значение true при обработке последнего элемента. Тогда я мог бы использовать в шаблоне-toString выше либо не context.build-markup / EOB [{+ "," +}] [""], чтобы объединить или нет с {+ "," +}:

context.build-markup: context [

  EOB: false

  set 'build-markup func [
      {Return markup text replacing <%tags%> with their evaluated results.} 
      content [string! file! url!] 
      /vars block-fields block-values
      /quiet "Do not show errors in the output." 
      /local out eval value n max i
  ][

    out: make string! 126 

    either not vars [
        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)
            ]
        ]
      ][          


          n: length? block-fields

          self/EOB: false

          actions: copy []

          repeat i n [



            append actions compose/only [

              ;set in self 'EOB (i = n)
              set in system/words (to-lit-word pick (block-fields) (i)) get pick (block-fields) (i)
            ]

          ]
          append actions compose/only [            
              append out build-markup content            
          ]
          foreach :block-fields block-values actions



          if any [(back tail out) = "^/" (back tail out) = " " (back tail out) = "," (back tail out) = ";" (back tail out) = "/" (back tail out) = "\"] [
            remove back tail out
          ]        
      ] 
      out
  ]

]

Но моя попытка не удалась (так я прокомментировал; установил self 'EOB (i = n), потому что он не работает). Как исправить код, чтобы получить то, что я хочу?


person Rebol Tutorial    schedule 02.08.2010    source источник


Ответы (2)


Я совершенно уверен, что вы могли бы достичь своей цели более чистым способом, чем этот. Тем не менее, я могу рассказать вам, почему то, что вы делаете, не работает!

Ваш n - это выражение length? block-fields, а ваш repeat цикл поднимается до n. Но block-fields содержит единственный параметр [property]! Следовательно, он переходит от 1 к 1.

Вы предположительно хотели протестировать что-то, перечисляющее более block-values (в этом примере диапазон от 1 до 3), а затем обработать его однозначно, если индекс достиг 3. Другими словами, ваше set in self 'EOB выражение должно быть частью вашего перечисления более block-values, а НЕ block-fields.

Это дало бы вам желаемое поведение:

n: length? block-values
i: 1
foreach :block-fields block-values compose/only [
    set in self 'EOB equal? i n
    do (actions)
    ++ i
]

Это абсолютно не сработает:

append actions compose/only [
    set in self 'EOB (i = n)
    set in system/words (to-lit-word pick (block-fields) (i)) get pick (block-fields) (i)
]

... потому что вы имеете дело с ситуацией, когда i и n равны 1 для одной итерации этого цикла. Это означает, что (i = n) верно. Итак, метакод, который вы получаете для «действий», таков:

[
    set in self 'EOB true 
    set in system/words 'property get pick [property] 1
]

Затем вы запускаете код с лишним составом (так как PAREN! S нет, вы можете просто опустить COMPOSE / ONLY):

append actions compose/only [
    append out build-markup content
]

Что, очевидно, добавляет строку в ваш метакод actions:

[
    set in self 'EOB true 
    set in system/words 'property get pick [property] 1 
    append out build-markup content
]

Как обычно, я предлагаю вам научиться использовать ЗОНД и ПЕЧАТЬ, чтобы смотреть и проверять свои ожидания на каждом этапе. Rebol хорош в сбросе переменных и тому подобном ...

person HostileFork says dont trust SE    schedule 05.09.2010

Кажется, вы делаете что-то простое очень сложным:

>> a: make object! [                           
[    b: false                
[    set 'c func[i n] [b: i = n]
[    ]
>> a/b
== false
>> c 1 4
== false
>> a/b 
== false
>> c 1 1
== true
>> a/b
== true
person Peter W A Wood    schedule 03.08.2010
comment
Насколько сложно установить в себе EOB (i = n)? - person Rebol Tutorial; 03.08.2010
comment
Но ваше решение не работает, я его тестировал. Проблема в том, чтобы заставить этот материал работать в контексте compose / only и build-markup, чтобы он не работал автономно. - person Rebol Tutorial; 03.08.2010