[Feature Request]: 'else-if' statement

Big Feature: add else-if statement in console

Syntax like that:

# RouterOS 
:if (<condition_1>) do={
    <command>
} else-if (<condition_2>) do={
    <command>
} else-if (<condition_3>) do={
    <command>
} else={
    <command>
};
3 Likes

definitely +1

1 Like

Should it provide

on-error={ ... }

for each do in if, if-else or the only one for the whole statement?

1 Like

There is a separate :onerror handler, so I don’t see any sense in this.

1 Like

@teslasystems
You are right

@BartoszP
It is simple you can use
:do {} on-error={} inside ‘if’ statement, However it does not require adding it besides because it will conflict with ‘else’ and ‘else-if’ (if it is added in the future) or prevent you from using them.

Could you please enlighten me both how the on-error for “if” should be used?

On the other hand, if the own “on-error” for each do is needed to be applied when sth goes wrong in the particular “if” branch. If there would be the only one whole statement catching “on-error” then you have to collect somehow what branch triggered the error … lets welcome try/catch statement :slight_smile:

Whole idea, not only in MT scripting, of “else-if” is wrong for me when there is no obligation for conditions to have anything in common. Pure:

if condition then
   set of statements
else
  another set of statements
endif

takes indisputably one or another execution path.

When you have multiply related or unrelated "if"s and "else if"s then there should be a statement like “switch” or “case of” used:

case of
  condition#1: set of statements for contidion#1
  condition#2: set of statements for contidion#2
  ....
  condition#N: set of statements for contidion#N
end case of

as it’s selfexplaining construction and does not relly on “saved” state of previous checks beeing applied to the following “else-if” parts of a statement what you have to “store in the memory” analyzing the code

if condition#1 then
   set of statements for condition#1
else-if condition#2 then
   set of statements for condition#2
...
else-if condition#N then
   set of statements for condition#N
endif

really means

if condition#1 then
   set of statements for TRUE(condition#1)
else-if condition#2 then
   set of statements for  condition#2 when FALSE(condition#1) .and. TRUE(condition#2)
...
else-if condition#N then
   set of statements for  condition#2 when FALSE(condition#1) .and. FALSE(condition#2) .and. ... FALSE(condition#N-1) .and. TRUE(condition#N) 
endif

comparing it to much obvious

cond#1 = check#1
cond#2 = check#2
...
cond#N = check#N

case of

  TRUE(condition#1) : statements for condition#1
  FALSE(condition#1) .and. TRUE(condition#2) : statements for condition#2
...
  FALSE(condition#1) .and. ... .and. TRUE(condition#N) : statements for condition#N
end case of

however I do open the can of worms now :slight_smile: :slight_smile:

1 Like

There is a difference between else-if and switch-case in most languages, latter allows performing blocks for multiple conditions if condition block is not breaked (in some languages you need to state explicit continue), while else-if is explicit per condition to avoid nesting in else block. RSC even lacks break / continue statements to have proper implementation of switch-case…

1 Like

Worms are getting out :slight_smile:

What does it mean “in most languages”? I could agree to not agree on that.

  • Csomething family: use “break” to break the follow-through evalutaion of the next case. For me it’s just an artifact of being planned as an assembler++ during development and it let optimize code much easier using that particular syntax.

  • D, Java: mimics C, uses “break”

  • Rust: no follow-through evaluation, one statements block per case

  • Python: no follow-through evaluation, one statements block per case

  • Goldies-grandoldies COBOL, FORTRAN: one statement per case

  • Ada: no follow-through evaluation,

  • Pascal family (I should write Algol/Simula families): no-follow no follow-through

I’m aware of these differences. Look that I intentionally assigned results of check#N to variables as evaluating a check could be a non-invariant operation. I wrote it in a quite independend syntax to not imply any language.
I’m also aware that RSC lacks a lot of handy syntax features. It’s not even consisten with “if” syntax, true branch is a do={} statement but else is it’s own entity. It would be more consistent if the syntax is

if (cond) do= {
} else do={
}
1 Like

I do not think there should be an else-if. But agree is a switch is missing, and that be preferable to to a serials of :if. “Modern languages” go beyond a simple switch to use “pattern matching”, so you a provide something to match, and set expressions (vs. C-style only a value) to test against.

Personally, supporting “groups” in regular expressions would go a long way to avoid some long chains of :if (and still helpful in some future “else-if”/“switch”/pattern matching syntax). If you can get a regex to do the work of some chain of if else-if else, that be clear.

Also, the comparisons with “general purpose languages” are difficult… RouterOS is more a “configuration language”, like Cisco TCL, one half-dozen Kubernetes languages, or even Apple boutique pkl language where “if” is relegated to a mere expression.

Finally, the purposed syntax ignores stuff like :if is still just a command (i.e. function) so the :if () do={} being followed by anything let alone multiple do= blocks violates many rules RouterOS parses things today. Meaning it be really hard to add some else-if I suspect – on top of just backwards looking.

TL;DR: –1 on ‘else-if’ statement

1 Like

@BartoszP

you can use on-error inside if statement, as in the following example:

:if (<condition>) do={
    :do {
        <command>
    } on-error={
        <command>
    };
} else={
    :do {
        <command>
    } on-error={
        <command>
    };
}

But really, using a
switch case break default
is best.

Yup.

Sidenote The :if is still a command (builtin function), so the on-error= is an argument to “if” command, just like else={}. The issue with “else-if” in OP is that is NOT an argument & new commands always need a newline or semi-colon (+whitespace). And 2nd, the stack be resolved if else-if was it’s own command — why the else-if is likely harder than some new :switch thing.

1 Like

@BartoszP
@optio
@Amm0
You are right :+1: :heart:
Using switch-case is the best

By most, I meant most modern. Ok, some languages may have different statement for multiple condition or value matching like Rust (match) but there are alot others which support multiple matching with fallthrough (as mentioned some requires explicit statement for it), like: Various C style lang including JS and TS, Swift, Kotlin, Golang… or scripting like Bash, TCL…

Hell with this forum…

Hit wrong reply button, this above post was meant to be for @BartoszP post not @Amm0’s…
I can’t paste same content on Reply post to @BartoszP even if I delete old because is to similar…
Crap

For the whole statement it would be like this:

:local x true

:onerror errMsg {
	:if ($x) do={
		:put "x is true"
	} else={
		:put "x is false"
	}
} do={
	:put "Something is wrong, error: $errMsg"
}

@Moustafa :do {} on-error={} is deprecated (that’s what MikroTik support said) and may not work in some cases, avoid using it, use :onerror err {} do={} instead.


And I would agree, that case or switch would be better. But it such case I would prefer Pascal-like behavior, i. e. it should stop comparing remaining conditions after first match. Or they need to add break command and let it be C-like (less preferrable).

Btw, break as a command is needed anyway! It was requested by users many times even 15 years ago and nothing was done :smiling_face_with_horns:

@teslasystems

  • Where is your source that they said that?

  • Regardless of asking you for sources, I still use :do {} on-error={} on a daily basis until writing this reply, and I don’t have any problems, and I don’t think they will remove it, because it is considered a simple and quick use of the onerror function

  • although they are similar, they differ in the way they work and are implemented

  • I see that each of them has its own method

What source? MikroTik support is the source, I said it.
As an example, snmp-get tool doesn’t work with :do {} on-error={}, only :onerror can handle it.

Anyway, it’s up to you, use it or not, I just warned.