What good is the NERFIN loop operation in LOLCODE?

2k Views Asked by At

What the spec says on the subject:

Iteration loops have the form:

IM IN YR <label> <operation> YR <variable> [TIL|WILE <expression>]  
  <code block>
IM OUTTA YR <label>

Where <operation> may be UPPIN (increment by one), NERFIN (decrement by one), or any unary function. That operation/function is applied to the <variable>, which is temporary, and local to the loop. The TIL <expression> evaluates the expression as a TROOF: if it evaluates as FAIL, the loop continues once more, if not, then loop execution stops, and continues after the matching IM OUTTA YR <label>. The WILE <expression> is the converse: if the expression is WIN, execution continues, otherwise the loop exits.

Question

My gripe with the spec is the combination of:

  • the lack of a loop variable initializer
  • the fact it's temporary and local to the loop

As I understand it, this means it has to start at 0.

While that's mostly ok for most uses of UPPIN, it's totally off for most (my) intended uses of NERFIN. My most common uses of a decrementing loop variable in other languages are the "repeat n times (n not re-used)" idiom and string operations, which wouldn't be a good idea in LOLCODE anyway.

Is it possible to use NERFIN to get a loop decrement from n to 1 or 0 in a way that's less verbose than the equivalents with UPPIN or the operationless forms of looping?

Alternatives' comparison

Printing 5 4 3 2 1 with the UPPIN variant:

IM IN YR LOOPZ UPPIN YR COWNTR TIL BOTH SAEM COWNTR AN 5
  VISIBLE DIFF OF 5 AN COWNTR
IM OUTTA YR LOOPZ

Pros: concise.
Cons: actual loop variable is not accessible directly.

With the operationless variant:

I HAS A COWNTR ITZ 5
IM IN YR LOOPZ
  VISIBLE COWNTR
  COWNTR R DIFF OF COWNTR AN 1
  BOTH SAEM COWNTR AN 0, O RLY?
  YA RLY, GTFO, OIC
IM OUTTA YR LOOPZ

Pros: loop variable is directly available.
Cons: longer.

Best I can get with NERFIN:

IM IN YR LOOPZ NERFIN YR COWNTR TIL BOTH SAEM COWNTR AN -5
  VISIBLE SUM OF 5 AN COWNTR
IM OUTTA YR LOOPZ

Pros: err... uses NERFIN?
Cons: loop variable isn't directly accessible; less readable (hah!) than the UPPIN variant; no gain in verbosity.

TLDR question, repeated

Is it possible to use NERFIN to get a loop decrement from n to 1 or 0 in a way that's less verbose than the equivalents with UPPIN or the operationless forms of looping?

I'm using the lci interpreter at language specification level 1.2.

1

There are 1 best solutions below

2
On BEST ANSWER

There was design discussion from 2007 on this exact topic. Consensus at the time seemed to suggest adding a FROM as a solution the working group wanted fast-tracked into 1.2:

http://forum.lolcode.com/viewtopic.php?pid=2484

The issue was tabled and didn't make it in to the 1.2 spec. However, it is apparently in the 1.3 specification:

http://lolcode.com/proposals/1.3/loop2

Still in the works, though. I checked and it is not in the "future" branch of the repository yet. We can see this by looking into the loop interpreter code. As of 8/24/2011 (in revision 72c983d0667d4d650657e1b7c5f4c7054096b0dd) it still always initially assigns the loop variable a NUMBR of 0:

https://github.com/justinmeza/lci/blob/72c983d0667d4d650657e1b7c5f4c7054096b0dd/interpreter.c#L3434

However, even with the old spec, it should theoretically be possible to use a TROOF in combination with a test against -1 to allow for a relatively clean form of counting down from 5 to 0:

BTW countdown-test.lol
CAN HAS STDIO?
HAI 1.2

HOW DUZ I COUNTDOWN YR BOWNDZ
    I HAS A FIRSTIES
    FIRSTIES R WIN
    IM IN YR LOOPZ NERFIN YR COWNTR TIL BOTH SAEM COWNTR AN -1
        FIRSTIES
        O RLY?
            YA RLY
                COWNTR R BOWNDZ
                FIRSTIES R FAIL
        OIC

        VISIBLE COWNTR

    IM OUTTA YR LOOPZ
IF U SAY SO

COUNTDOWN 5

KTHXBYE

Unfortunately, there is an "efficiency hack" which prevents code inside a loop from modifying the loop variable using R:

https://github.com/justinmeza/lci/blob/a6ef5811e8eb98935a16600b799bccbe4adffdde/interpreter.c#L3408

Yet as this seems to be a bug in the code as opposed to an omission in the spec, it's more likely to get fixed in advance of the 1.3 release. Patching interpreter.c to say if (0 && stmt->update->type == ET_OP) makes the code for countdown-test.lol run as expected. It may be a suitable interim solution for existing 1.2 LOLCODE deployments if you don't have to share code with unpatched installations.