adamsol / Pyxell

Multi-paradigm programming language compiled to C++, written in Python.
MIT License
54 stars 6 forks source link

break and continue #2

Closed skaller closed 3 years ago

skaller commented 3 years ago

C break and continue have limited utility because in a double loop, you cannot break out of the outer loop. I had these in my language too originally, but replaced them with labelled break and continue. In my language, the label is mandatory if you want to break or continue (or redo) but for compatibility you might allow the default to be the current loop. I think this is not a good idea though, because the absence of a label ensures the loop can only be either normally exited, or exited by a premature function return (which is a problem, it would be better if the assurance was absolute but I don't know how to do that in an imperative language with a return statement).

adamsol commented 3 years ago

Extended break and continue is certainly something that I've been thinking about, though I wanted to implement it with numbers (like break 2) instead of labels. It would be simpler and wouldn't require any additional syntax changes, though it may be not obvious whether indexing should be 0-based or 1-based. BTW, there was already a similar idea in Python: PEP 3136, but it got rejected.

skaller commented 3 years ago

Well you can certainly do that although I'm not sure it is a good idea. I do something vaguely related in my intermediate language for handling recursive types. The usual representation is to use a mu binder, so the recursion point is the name specified in the binder, but in Felix I decided to use a level number instead, the number of levels up the type tree you have to go to find the recursion point. The advantage there is that the representation is unique in that it does not depend on an arbitrary choice of a name which would then require alpha conversion. But the disadvantage is quite serious: if some operation "refactors" the tree structure and introduces an extra level, or removes one, the level number has to be adjusted.

So the question you have to ask is whether the introduction of an extra level of loops should preserve the break target absolutely or relatively: the name will preserve it absolutely and the integer relatively. I think the choice should be driven by use cases. Its hard to think of any! One roughly might be: suppose you have an array of vectors and some loop processing the array and an inner loop for the vector elements, and change the vector into a matrix requiring an extra loop. Where should the break exit go now?

A related example: you have some data consisting of records with N fields, and sort on the first M fields, so you have some iteration over M keys, but decide to split some of the keys in the middle into multiple parts, so you now have extra keys and extra iterating loops. If you use integer level breaks, you may break into the wrong loop now.

In Felix, I hardly ever use break or continue, but then, Felix has goto and I tend to use that for any kind of loop which doesn't fit the simple for or while pattern. All in all its a tough call but if you don't have gotos, then one or the other method (label or integer) seems necessary.

adamsol commented 3 years ago

Thanks for the use-case examples. It seems that breaking a loop absolutely is the more intuitive behaviour for most situations. I've implemented the solution with labels.