While loop inside procedure returns infinite loop

0 votes
asked Jan 9, 2021 in Question / help by pasza (180 points)

While loop works like this:

@startuml
!unquoted function Service($name, $index)
!return 'component "'+$name+'_'+$index+'"'
!endfunction

!$i = 5

!while $i!=0
    Service(svc,$i)
    !$i = $i - 1
!endwhile
@enduml

But when I put it inside a procedure it always outputs "infinite loop?"

@startuml
!unquoted function Service($name, $index)
!return 'component "'+$name+'_'+$index+'"'
!endfunction

!unquoted procedure ScaleService($i)
    !while $i!=0
        Service(svc,$i)
        !$i = $i - 1
    !endwhile
!endprocedure

ScaleService(2)
@enduml

What am I doing wrong?

commented Jan 9, 2021 by kirchsth (4,980 points)

Hi,
the $i is converted to a string (I don't know why) and therefore each -1 adds a "1". You can test it with

@startuml
!unquoted function Service($name, $index)
    !return 'component "'+$name+'_'+$index+'"'
    !endfunction

    !unquoted procedure ScaleService($i)
'        !while $i!=0
            Service(svc,$i)
            !$i = $i - 1
            Service(svc,$i)
            !$i = $i - 1
'        !endwhile
    !endprocedure

    ScaleService(2)
@enduml

 As workaround you could explicite convert it to a integer with %intval() like

@startuml
!unquoted function Service($name, $index)
    !return 'component "'+$name+'_'+$index+'"'
    !endfunction

    !unquoted procedure ScaleService($count)
        !$i=%intval($count)
        !while $i!=0
            Service(svc,$i)
            !$i = $i - 1
        !endwhile
    !endprocedure

    ScaleService(2)
@enduml

Best regards
Helmut

commented Jan 9, 2021 by pasza (180 points)

Yes, also found this problem.

We need static type systemlaugh

2 Answers

0 votes
answered Jan 9, 2021 by pasza (180 points)

found the solution:

@startuml

!unquoted procedure ScaleService($replicas)

    !local $i = %intval($replicas)

    !while $i!=0

        component svc##$i

        !$i = $i - 1

    !endwhile

!endprocedure

ScaleService(2)

@enduml

0 votes
answered Jan 9, 2021 by Martin

I can't tell if there's a bug here, but it is certainly unintuitive. The problem seems to be that by defining the procedure as "unquoted" it assumes the parameter is a string and not a numeric.  And so !$i = $i -1 actually does a string concat rather than an integer subtraction (I could understand + doing this, but - probably should give a syntax error!).  So you can get it working as intended by either removing the "unquoted" from your procedure definition, or by using "!$i = %intval($i) - 1".

Here's your example with the %intval fix, but also a couple of extra lines to show that $i starts as a string and "-" acts as a concat but then $i turns in to a numeric and "-" acts as a minus.

@startuml
!unquoted function Service($name, $index)
!return 'component "'+$name+'_'+$index+'"'
!endfunction

!unquoted procedure ScaleService($i)
    !while $i!=0
        !$j = $i - 1
        component %string("X" + $j)
        Service(svc,$i)
        !$i = %intval($i) - 1
    !endwhile
!endprocedure

ScaleService(3)
@enduml

...