Print Page | Close Window

Code generator skips fields

Printed From: MetaCase
Category:
Forum Name: MetaEdit+
Forum Description: All topics relating to MetaEdit+ or DSM
URL: https://www.metacase.com/forums/forum_posts.asp?TID=942
Printed Date: 27.Mar.2026 at 03:26
Software Version: Web Wiz Forums 12.05 - http://www.webwizforums.com


Topic: Code generator skips fields
Posted By: bram.bolder
Subject: Code generator skips fields
Date Posted: 13.Dec.2021 at 12:35
I have a problem with a code generator. While constructing a line of output from some constant strings and some property values, it stops after the fourth field and skips the last two. Below my (simplified) code:
_ROSLaunch_params( @param_list )
dowhile @param_list
{
      @defaults = __( dowhile :ParameterDefinitions { id } )
      @rosparam_files = __( dowhile @defaults { dowhile :RosParamFiles { id newline } } )
      dowhile @rosparam_files
      {
           '   <rosparam command="load" file="$(find '
            :Package;
           ')/'
            id
            '"/>'
            newline
      }
}
It writes the two constant strings, :Package and id, but always skips the '"/>' and the newline.
This is both for the normal code generation and while debugging (the single step just jumps after processing "id" instead of continuing to the '"/>'. I use similar code elsewhere (also with '"/>', and that seems to work fine).
Does anyone have any idea, why only the first 4 fields of this output string are processed and not the last two?

PS: I use variables for @defaults and @rosparam_files because in the non-simplified version I allow an additional source of content for these lists of strings.



Replies:
Posted By: stevek
Date Posted: 13.Dec.2021 at 13:03
That sounds exactly like how https://www.metacase.com/support/55/manuals/mwb/Mw-6_3_3.html" rel="nofollow - dowhile is meant to behave:
Quote The dowhile clause is a variant of do, differing only in that it skips any trailing literal strings or newlines on its last iteration over a given set of elements. This is useful for avoiding trailing separators such as commas or spaces after the last item to be output, e.g.
      do .Process {id ', '}   produces “1.0, 1.1, 1.2, ”
 dowhile .Process {id ', '}   produces “1.0, 1.1, 1.2”

You could just switch to using do rather than dowhile. Or if you want to omit the last newline but always output the closing tag, you could use dowhile but enclose the tag command in an if statement that is always true - dowhile only skips literal commands directly in the dowhile loop. 


Posted By: bram.bolder
Date Posted: 13.Dec.2021 at 13:26
Side note: I have many lists of strings or objects that I want to process and noticed that it often wanted to process an empty string/object on the last iteration. That's why I switched to using 'dowhile' instead of 'do' and it always solved the problem.

If I replace the 'dowhile' before :RosParamFiles into 'do', then the first iteration prints all 6 fields (string, :Package, string, id, string, newline), and the second prints only four (string, empty-string {as :Package of an empty string does not exist}, string, id (of the empty string) ). That is  just as before but now on an invalid element.

PS: sorry for the strange formatting of the code in my post, it was the forum software that inserted line breaks, even though I used the 'code' BBcode.


Posted By: stevek
Date Posted: 13.Dec.2021 at 13:48
Quote I have many lists of strings or objects that I want to process and noticed that it often wanted to process an empty string/object on the last iteration
That's probably because you built the list to process with something like this:
$list = __(do .Thing { id newline })
do $list { _doSomething(id) }
The first command will make a variable with one line per Thing, but with an extra newline at the end. Iterating over a variable in the second command will execute the loop once per line, including any blank lines like the one at the end. To avoid adding that last newline, use dowhile in the first command (as you did in your example). Or then if you want to exclude all blank lines, use dowhile .Thing; where id {...}.

Sorry if my suggestion above was unclear – so many dowhiles! I meant the last one, dowhile @rosparam_files.  Change the closing tag to:
if 'T' then '"/>' endif   /* protect from dowhile */


Posted By: bram.bolder
Date Posted: 13.Dec.2021 at 14:13
OK. That solved the problem. So dowhile just ignores all stuff that is after the last variable or property in the body. I had understood that is was ignoring the last empty element on the things to iterate over (i.e. before the body). This is in many cases equivalent, but not quite.

So if I understand correctly and the second line in your example would be 'do $list { _doSomething(id)  '/' )' and if .Thing were 2 things A and B, $list would be A, newline, B and the do $list would call _doSomething(A), '/', and _doSomething(B).
I had assumed $list would be A, newline, B, newline and that if the second line would use 'dowhile', it would do "_doSomething(id), '/' " on A and on B and ignore the second newline in $list, i.e. the result would have been: _doSomething(A), '/', doSomething(B), '/'.



Posted By: stevek
Date Posted: 13.Dec.2021 at 14:27
Great, glad that the problem is solved, and your updated understanding is absolutely correct!



Print Page | Close Window

Forum Software by Web Wiz Forums® version 12.05 - http://www.webwizforums.com
Copyright ©2001-2022 Web Wiz Ltd. - https://www.webwiz.net