"While" condition test (or otherwise disable an edict)

I have a note named for the current year, that has an edict that creates a new child note named with the current month and year. Works great.

I want it to stop creating notes once the year rolls over. It seems a “While” statement would do it.

Something like:

$MyDate="today";
While ($MyDate.year==$Created.year)
{
$MyString=$MyDate.Format("MM y");
create($MyString);
}

Is there a more efficient way to disable the edict once the year rolls over? I’m not quite sure the how the If conditional test described here might work in this circumstance.

I was feeling quite proud of myself this morning until I realized my 2023 note would happily go on creating notes in the 2023 container indefinitely into the future, so I need a way to tell it to stop. I think this “While” construction would do it, but I don’t want to wait five months to find out, and I’m not sure it’s the best way.

Thanks!

nice - a while statement would be a great addition to TBX.
I would also like to see a case/switch statement instead of nesting if/else…

“Addition”?!
:stuck_out_tongue_winking_eye:

1 Like

Aside, note that operators are case-sensitive in name and start with a lowercase letter, e.g. while() and .format(). No criticism meant there but such small things create silent failures. Also Tinderbox’s parser ignores white space between the operator and its parentheses (for input arguments in any), I think it enlightened self interest to not make the parser have to think and avoid such usage. IOW:

if(condition){...
// not
if (condition) {

though both work. But, to the task at hand…

So your Edict runs and needs to says "is today’s year the same as the $Created-derived year for the current note? If it is, make a new child note using the format month-space-year’ as in “July 2023”.

For other readers, we know from create() documentation that passing a unique note name (not a path) to create() automatically makes the note as a new last child of the current note/container if that note doesn’t already exist).

So, and removing the need for two attribute-stored values in you code above:

if($Created.year == date("today").year){
   var:string vName = date("today").format("MM y");
   var:string vPath = create(vName);
};

The var:string vPath = bit isn’t strictly needed but if used, variable vPath now holds the $Path of the note you just created in case you need to further customise the new note.

So, surfacing an implicit assumption, the note (container?) on which the Edict is run has been created during the current year. What might go wrong with that? It’s now later this year, in December and you need to get back to the party, so thinking ahead you quickly create the ‘2024’ container for your forthcoming New Year’s Day post. Oh dear, as the $Created for the container will still be 2023. Safer might be to have a BlogYear attribute (string or number, here I don’t think it matters) in which you explicitly put the to-be-current (4-digit) year. Now the Edict code becomes:

if($BlogYear.year == date("today").year){
   var:string vName = date("today").format("MM y");
   var:string vPath = create(vName);
};

or without the path bit:

if($BlogYear.year == date("today").year){
   var:string vName = date("today".format("MM y"));
   create(vName);
};

Now the year checked is the one you actually set not the one you possibly didn’t mean to set.

Does that help?

Thanks, Mark!

The Year container resides in the “Archive” container, which has an edict creating a new year container every year. That was easier to do, because I just need the four-digit year as a string. So it will “create” the new 2024 container in 2024 and not before, as near as I can tell.

Also it’s not clear to me that your code is creating month containers with names in the format like: August 2023. Doesn’t .format have to be in there somewhere?

Missing .format("MM y") code? Yes. sorry, copied wrong code test, now fixed in original post above (for later readers!).

Re the yes, that’s fine then. Sorry if I was reading ahead. Partly it’s because I’ve dim memories of being bitten by using $Created in the past. But, based on your description, that edge case shouldn’t happen, so use:

if($Created.year == date("today").year){
   var:string vName = date("today").format("MM y");
   var:string vPath = create(vName);
};

BTW, there really is no harm—and no implied critique— in not using $MyDate, etc. Indeed, for the general reader, the ‘Sandbox’ system attribute group of ‘My’-prefixed attributes are exactly there to give us an attribute of each of the main data-types ready configured for general use. I’ve just acquired the habit, especially now we have data-typed variables, of not saving unneeded in-process data. Meh, as on today’s hardware it make little impact. The ‘data-typed’ part is important as it avoids Tinderbox unwittingly coercing data types. If you put Date-type data in a Date-typed variable, it remains Tinderbox Date-type data.

Glad to see all the consideration and polish going into the Nice Marmot. :slight_smile:

Thanks, it’s not in the marmot yet! I’m testing everything first. But yes, it will be deployed to “production” soon.

I’ll note that I’ve just learned something else new. I’m accustomed to Pascal practice in the dim reaches of my memory, where variable declarations are a kind of separate thing. What I’m seeing here here is a variable declaration, concatenated with an assignment, which actually executes the code that yields the desired result. I had to look twice at that to figure out what was going on. :thinking:

1 Like

Ah, just a bit of concision. You could put:

var:string vName;
vName = date("today").format("MM y");

And as a string is the default data type;

var vName;
vName = date("today").format("MM y");

See var, and the various ways you can declare/assign value to variables. The original design assumption was this:

var vString("Hello");
// this (originally) failed 
var vString = "Hello";
// and you had to do:
var vString;
vString = "Hello";
// now this is OK
var vString = "Hello";
// and now we have optional date-type definition:
var:string vString = "Hello";

As I do some much documentation and example work here I try to avoid the optional omissions to help those less used to code, i.e. so the examples here look closer to the docs (or my docs, anyway!).

Sorry for any confusion. The new fun is we now (‘best practice’) use [1;]2] to define a list vs. older "1;2" (both methods still work) and to use {} similarly for declaring dictionary type data. Plus we’re moving to $MyList[0] over $MyList.at(0) (again both work). But we get cool stuff lie nested lists on the upside. Action code doesn’t stand still—I’ve now a ton of minor stylistic updates to do to my docs as a result. Oof.

1 Like