0

I need to achieve in a cl-loop the following conditional written in pseudocode.

if (flag1) {
  if (flag2) {return ...} 
} else {
  return ...
}

Note that it is equivalent to

if (flag1 && flag2) {return ...} 
if (!flag1) {return ...}

which undesirably repeats flag1 twice.

What I have done is:

(cl-loop ...
  if (flag) do 'nothing and
    if (...) return ... end
  else 
    return ...)

The do 'nothing and looks a bit hacky to me, but I cannot omit it as it's part of the nested if syntax. Are there alternative (and clearer) ways to do this ? Maybe using cl-block or by outsourcing the conditionals to another function ?

EDIT (further clarification):

The use of the keywords and and end could help to disambiguate dangling else (which is the conditional pattern given in this question).

Inspired from @John Kitchin's example, consider the following snippets and note the indentation:

(cl-loop
 with flag1 = nil
 with flag2 = t
 if flag1 return 3
 if flag2 return 1
 else return 2)

returns 1.

On the other hand,

(cl-loop
 with flag1 = nil
 with flag2 = t
 if flag1 return 3 and
   if flag2 return 1 end
 else return 2)

returns 2.

Thus, to accomplish the desired conditional, the keywords and and end are required.

Now, going back to the initial question: how to achieve the latter conditional, without a clause at the return 3 position, ignoring potential infinite loops ?

It seems impossible per se: according to the documentation, the <clause> in if <condition> <clause> should be an accumulation, do, return, if, or unless clause.

My solution is replacing it with do 'nothing or do (ignore) to fulfill the documentation's requirement, or use the equivalent yet repetitive conditional (undesired, see above), but I'm looking for alternatives.

8
  • Your latest edit would never execute the inner if clause at all (it would just return 3), and your original example may be an infinite loop when the first test passes and the second fails? I'm no expert with the loop language, but the question still seems a bit confusing.
    – phils
    Jul 1 at 6:22
  • @phils Do you mean "it would never return 3" ? That's the reason I want to get rid of this clause. Yeah, I'm aware of the potential infinite loop (that's why in my latest edit I assigned those values). In my real-world case, I made sure it doesn't happen at all. Jul 1 at 6:36
  • I mean that return 3 and ... will just return 3 and not do the ....
    – phils
    Jul 1 at 6:58
  • John Kitchin's answer looks good to me, and I can't tell what you want from your edits.
    – phils
    Jul 1 at 7:01
  • (cl-loop if flag1 if flag2 return 1 end else return 2) matches what I thought you wanted (the infinite loop condition notwithstanding).
    – phils
    Jul 1 at 7:07
2

I think this is what you want:

(let ((flag1 nil)
      (flag2 nil))
  (cl-loop
   if flag1
   if flag2 return 1
   else return 0
   else return 2))

if flag1 is nil, you get 2 if flag1 is t, and flag2 is nil you get 0 if flag1 is t, and flag2 is t you get 1


Or to replicate the original pseudo code (complete with its infinite loop scenario):

  (cl-loop
   if flag1
   if flag2 return 1 end
   else return 2)
2
  • Thanks for the answer. It looks perfect until I realized that my question wasn't clear enough. I just edited it. In short, what if I want to remove the else return 0 and keep the if flag1 as it is while keeping the semantics given in the question ? Jul 1 at 4:21
  • Thanks for the edit @phils. I also have the issue to indent nested if or conditional clause in cl-loop: indent-region just align everything as shown in the upper part of this answer. Perhaps, any of you might have an answer or remark for this long-standing question. Jul 1 at 8:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.