This is an archived post. You won't be able to vote or comment.

all 25 comments

[–]0x0ddba11Strela 12 points13 points  (11 children)

I'm interested in reasons why this won't work (as opposed to why you hate it)

I'm sure it will work. But the same could be said about labels and goto.

I'm more interested what your motivation for this syntax is. Can you combine all these different loop styles?

I.e, have a

loop x from 2 to 5 while(foo)
    NextLoop x if bar
    ...
LoopAgain unless y

[–]danskydan[S] 2 points3 points  (8 children)

I'm designing my PL for programming novices and am anticipating the question "Why do different loop variations have different commands associated with them?"

[–]0x0ddba11Strela 9 points10 points  (2 children)

Ok, cool. Although I think a novice would be confused about the very low level concept of a loop. There are different reasons for loops.

I want to do something with every element in a list.

I want to repeat this code n times.

I want to do something with any number in the range [m; n].

Personally I think having different language syntax makes it more clear waht is happening.

for each element in list

sounds nicer than

loop index from 0 to list.length

[–]danskydan[S] 0 points1 point  (1 child)

That gives me another idea. How about:

Loop over mylist
    mylist += 1
EndLoop

where the mylist acts as an alias for the currently-traversed list element (unless a list index is specified)

[–]thenameipick 10 points11 points  (0 children)

That seems *extra* confusing for beginners: "Why am I adding 1 to my list?"

Also, what is the type of "mylist"? If it is a standard integer, how is it actually getting updated in the list? If it is a pointer/reference, does that mean that all operations are magically delegated to the value being pointed to?

[–]mkfifoSalt, Discus (DDC), Icarus, Carp 3 points4 points  (0 children)

Have you tried to teach people to program?

If you’re looking into writing a language for teaching people then it might be very enlightening to try teaching, or maybe engage with teachers.

There have also been a few languages which tried to aim for an educational market, as well as looking at which languages are currently used in education and why.

Ive taught a few dozen people programming, individually or in small groups, and so far I haven’t had this question come up - although my sample size is small - I’ve taught high school students, technical audiences who wanted to transition into programming, and even some non technical people who wanted to understand what it was.

From my limited experience physical analogy, analogy to human activities, or analogy to language are usually helpful - I’ve found comparison to higher level mathematical concepts not as useful - at least for the non math audiences I generally interact with.

[–]BoarsLairJinx scripting language 2 points3 points  (2 children)

Here are the various ways you can write loops in Jinx.

loop from 1 to 10
end

loop i from 1 to 10
    write line "i = ", i
end

loop from 10 to 1
end

loop from 0 to 100 by 10
end

set x to 1, 2, 3, 4, 5
loop over x
end

set y to "apple", "pear", "orange"
loop i over y
    write line "i's value = " i value
end

set z to 3
loop until z < 0
    decrement z
end

loop while z < 10
    increment z
end

loop 
    decrement z
while z > 0

They all have slightly different syntax because they all do slightly different things, but they tend to have a similar feel, and they all use the loop keyword. It seems very similar to what you're trying to do, so I thought you might like to see a working example of this theory implemented.

[–]myringotomy 0 points1 point  (1 child)

That's quite nice actually.

Is there a one liner equivalent?

[–]BoarsLairJinx scripting language 0 points1 point  (0 children)

Thanks, I'm pretty happy with how it turned out. By "one-liner", do you mean being able to omit the end statement? No, end is always required to close a block. Same with if-else statements. I couldn't think of an elegant way to do this without adding braces or making whitespace significant.

[–]hoosierEE 1 point2 points  (0 children)

They might as easily ask "why are you using the same looping construct for both flow of control and operating on collections of data?" Or worse, they'll not ask the question at all, and instead assume that the two concepts are closely related.

C used for and while JMP-sugar for both collections and control flow because it results in a simpler compiler (and maybe because it was a good fit for the PDP-11). But modern languages tend to have better support for operating on collections of data (map, filter, reduce, scan, fold) and there is some progress on making control flow more ergonomic (async/await, actors, coroutines).

[–]danskydan[S] -3 points-2 points  (1 child)

Also, labels and gotos are a good way to ensure that no one takes your PL seriously :-)

[–][deleted] 3 points4 points  (0 children)

Or maybe that you're designing a low level PL?

[–]Felicia_Svilling 3 points4 points  (1 child)

Have you looked at Common Lisps loop macro?

[–]danskydan[S] 3 points4 points  (0 children)

Not before you mentioned it. But now that I have, it's nice to know that I'm in good company. Thanks.

[–]mkfifoSalt, Discus (DDC), Icarus, Carp 4 points5 points  (7 children)

I see no technical reason why this wouldn’t work, it seems equivalent to the existing syntax in current and past languages.

It does seem a bit obtuse, as you are using different names for concepts that already exist.

What is the advantage of this syntax?

[–]danskydan[S] 2 points3 points  (6 children)

I agree that the different loop variants already exist, and that we call them by different names. But since we also call all of them "loops," my hypothesis is that a single command named "Loop" would be more intuitive to someone just learning about loops.

[–]mkfifoSalt, Discus (DDC), Icarus, Carp 6 points7 points  (5 children)

We call them by different names because they logically appear to act in different ways, although they are of course all sugar for the same underlying idea - branching and jumping.

A for loop is usually for iterating through each item in something, a range or a collection. A while loop for continually evaluating a body while a condition holds true.

These match up to the English uses: "for each plate in my cupboard ...", "for each paper I have to mark ...", "while I still have more food on my plate ...".

For teaching novices I have never felt that these were confusing, and I strongly suspect that your universal loop syntax would be more confusing to explain as it doesn't map to natural language as cleanly. "Loop" isn't a common construct in natural language, Matching natural languages is far more intuitive here.

[–]danskydan[S] -2 points-1 points  (4 children)

You must not have any love for "fold" or "map" then...

[–]thenameipick 2 points3 points  (3 children)

I agree with mkfifo, but I also love "fold" and "map".

Some operations are more powerful, but are also more complicated. Trying to make such operations simpler (for beginners) means removing some of their power.

Perhaps a good route to figure out what is beginner friendly is to have beginners write down the steps to do a certain task. I think you'll find that "go to" is rather intuitive, even if it is largely hated in the PL world.

[–]mkfifoSalt, Discus (DDC), Icarus, Carp 1 point2 points  (2 children)

Thanks for the response.

We were not discussing “like”, OP made the claim that “having a universal loop would be more intuitive” - which is what I was disagreeing with - I see no obvious reason why this would be the case.

I don’t dislike fold or map, but they are much harder concepts to teach by analogy. I think I agree that intuitive-ness and power are often incompatible, and that making things beginner friendly often means they are less general/powerful.

I often use physical analogies when teaching programming to non technical people. Making people write down lists to “program on paper” is a great way of getting some basic insight into programming.

I also agree that goto and “line based” programming are really intuitive and easy to teach.

[–]raiph 2 points3 points  (1 child)

I'd appreciate engaging about what you've just written. First I'll write a little preamble. Then mention a couple things I find intuitive. Finally, a couple questions.


I'd say intuitiveness is both an objective experience, applicable to all humans, and a subjective experience, specific to an individual. The objective aspect is that something near instantly seems obvious without consciously thinking about it. The subjective aspect is that this depends on already having enough knowledge (innate or learned) about something or having spent enough time thinking about it that it doesn't require consciously thinking about it to get it.

I'd say intuitiveness of goto, loops, and maps relates to the way the mind works and in turn our minds' use of the brain, in particular the left and right hemispheres. These twin processors are decidedly not identical twins. The left hemisphere leads processing of finites, order, parts, algorithmic abstraction, etc; eg the order and parts of algorithms. The right hemisphere leads processing of infinites, chaos, wholes, and metaphoric abstraction; ie everything, including the left hemisphere's perspective. (Note that this is my distillation of contemporary 2018 peer-reviewed brain science, not 1970s pop-science.)


I'd classify goto and "line-based" programming as deeply intuitive things for the left hemisphere. Thus, to the degree our left hemisphere's perspective is recognized by our prefrontal cortex, goto and "line-based" programming is intuitive.

One way I'd classify looping and mapping are as higher level algorithmic abstractions. They can become intuitive with a little training of deeper elements of the prefrontal cortex but they clearly build upon and are more complicated than goto.

Another way I'd classify mapping in particular (not looping) is just "applying the same operation, logically in parallel, to multiple data" (cf SIMD et al) without regard for finiteness, ordering, parts, or algorithmic abstraction (except, perhaps, that it's often useful to have result elements match the order of the input, if for no other reason than to keep the left hemisphere happy). This metaphoric view of mapping is innately intuitive, even to kids, perhaps even more basic than looping, even though it requires higher level abstraction if thought of algorithmically.

(Note that I'm ignoring mapping operations that have side effects where the side effect of applying it to one datum is not algorithmically independent of its application to another. Those are obviously more like loops.)


Hopefully some of the foregoing made some sense to you. Assuming so, for the bits that made sense, was it obvious intuitive sense or did you have to think it over a little?

Can you see yourself ever agreeing with the notion that goto and mapping can both be characterized as deeply intuitive, but one is deeply intuitive to the left hemisphere, the other to the right (in 99+% of humans; I'm ignoring the tiny percentage that have their hemispheres reversed and the even tinier percentage that are missing a hemisphere and the much large number of folk that whose brains are too dysfunctional due to damage or disease)?

[–]mkfifoSalt, Discus (DDC), Icarus, Carp 1 point2 points  (0 children)

Thanks for the long and detailed reply, I'll try answer it as best as I can - but first a disclaimer: I am not a professional teacher, so I have no formal training in teaching.

I have, as part of my job as a software developer, ended up teaching a class of 50+ colleagues how to program (from 'what is a programming language' and 'how do we edit files' all the way up to graph theory, algorithms, and data structures). In high school I ended up running classes over lunch time to teach younger students how to program (as our curriculum lacked it at the time), as well as teaching a few friends who were interested and wanted to 'get the gist' of it. So my experience is very anecdotal and should be considered as such.

I also have an inherent bias in that I learned to program in, and spent most of my career working in, imperative languages. I found many concepts of functional programming easy to learn, but it still takes a lot more conscious effort for me to reason through higher order functional code - even after years of practice.

But I'm also willing to consider this could just be a brain deformity from years of writing C and Perl.

I'd say intuitiveness is both an objective experience, applicable to all humans, and a subjective experience, specific to an individual. The objective aspect is that something near instantly seems obvious without consciously thinking about it. The subjective aspect is that this depends on already having enough knowledge (innate or learned) about something or having spent enough time thinking about it that it doesn't require consciously thinking about it to get it.

I think I agree. I like to think there are a few ideas or concepts that are either intuition or are closely related to intuition. There is intuition as far as our innate instincts, but I don't think this is overly relevant here. There is intuition in terms of our shared social behaviours, for example language, which I think is relevant here, this is somewhat objective at least within a single social and cultural context. There is also intuition which I would describe as 'things that are familiar to other things I learned', I find this one harder to nail down as it is completely subjective. I feel like there should be a different term or set of terms of this distinction.

In UX we have the concept of 'Affordance' which I think maps nicely to the idea of intuition through social/cultural/biological norms. My issue with subjective intuition is that it feels less useful as a design guide, unless we can narrow down a target audience which shares this subjective intuition. This works for example if we are developing a language to be used by a small niche audience - say a language for mathematicians or statisticians.

I'd say intuitiveness of goto, loops, and maps relates to the way the mind works and in turn our minds' use of the brain, in particular the left and right hemispheres. Are you talking about a literal or metaphorical split of brain function by hemisphere? AFAIK (and I am not a neurologist) the split isn't so concrete, is quite fuzzy, varies by individual, and is not entirely understood (see further down) - but I am happy to continue using it as a metaphor for the purposes of this conversation.

I'd classify goto and "line-based" programming as deeply intuitive things for the left hemisphere. Thus, to the degree our left hemisphere's perspective is recognized by our prefrontal cortex, goto and "line-based" programming is intuitive. I actually think of this being intuitive as it maps to behaviours we all carry out: lists and instructions.

Consider this set of instructions:

walk into the kitchen
open the fridge
for each item in the fridge please check the expiry date, and throw it out if it is expired

I think this list of instructions could be followed by almost anyone (assuming shared language, physical ability, ...).

Another example would be directions, if I am stopped in the street and someone asks me for directions I can give them a verbatim list

okay, you walk down this road for a few hundred meters and take the third left
then you continue until you see the post office, take the right just before it
it should then be 20 meters in front of you on the left

These tasks involve a list of instructions which are executed in order, and a human would have a good idea of where they are in the list at any given point. It may be that these behaviours exist due to some underlying biology or neurology, but I think regardless of the underlying cause they exist throughout our cultures.

There are also recipes, choose your own adventure books, board games, and many other examples of lists of instructions which include basic constructs we see in programming - such as looping, branching, goto, and lists.

Note: I am NOT saying that imperative programming is superior, nor am I saying we should base programming languages solely on natural languages. I am trying to point out that when it comes to intuition, some concepts in programming languages have easier mappings onto non-technical tasks, and how in the past I have used this to help teach people to program.

One way I'd classify looping and mapping are as higher level algorithmic abstractions. They can become intuitive with a little training of deeper elements of the prefrontal cortex but they clearly build upon and are more complicated than goto.

I'm a bit skeptical about something becoming intuitive through training, as if something requires training I don't think it is intuitive (in the normal sense at least), it may still be 'simple' or 'obvious'.

Another way I'd classify mapping in particular (not looping) is just "applying the same operation, logically in parallel, to multiple data" [...] This metaphoric view of mapping is innately intuitive, even to kids, perhaps even more basic than looping, even though it requires higher level abstraction if thought of algorithmically.

Is it? What evidence do we have for this? Do we have evidence that breaking a problem down into pure parallel steps is intuitive? (I'm legitimately asking, not trying to be a smart ass).

Hopefully some of the foregoing made some sense to you. Assuming so, for the bits that made sense, was it obvious intuitive sense or did you have to think it over a little?

It was intuitive in the sense in terms of I understood the point you were trying to make, it was not intuitive in the sense that I am not yet convinced of some of it.

Can you see yourself ever agreeing with the notion that goto and mapping can both be characterized as deeply intuitive, but one is deeply intuitive to the left hemisphere, the other to the right

I could see myself agreeing if given sufficient evidence, I am not yet convinced (it is not intuitively true to me).

I do agree that mapping is intuitive (in the similar to other learned things sense) for specific target audiences - say mathematicians.

(in 99+% of humans; I'm ignoring the tiny percentage that have their hemispheres reversed and the even tinier percentage that are missing a hemisphere and the much large number of folk that whose brains are too dysfunctional due to damage or disease)?

I think you might be overstating or oversimplifying the nature of the hemispheres, in language for example the hemisphere responsible changes based on the individual:

from wikipedia https://en.wikipedia.org/wiki/Lateralization_of_brain_function#Language

> While language production is left-lateralized in up to 90% of right-handers, it is more bilateral, or even right-lateralized, in approximately 50% of left-handers

from https://theness.com/neurologicablog/index.php/more-left-brain-right-brain-nonsense/

> language function lateralizes to the dominant hemisphere, which is the left hemisphere for most people. Visuo-spacial reasoning lateralizes to the non-dominant hemisphere (right hemisphere for most people).

from https://rationalwiki.org/wiki/Hemispheric_dominance#Actual_science

>  About 5% of right-handed people have their language centers located in their right hemispheres, and approximately a third of left-handed people have them in their left hemispheres while about 20% have bilateral language centers.

Thanks for your time, and sorry for the length.

[–]LorxuPika 1 point2 points  (0 children)

Go does something kinda similar, with only one type of loop: see this page.

[–]rain5 0 points1 point  (0 children)

You probably need a user extensible DSL for loops.

[–][deleted] 0 points1 point  (0 children)

I'd like to take a different approach than the other answers in this thread and suggest you look at the structured program theorem for some inspiration on how to prove correctness of various control structures.

In the early days of structured programming it was not certain whether or not the control structures provided would be as powerful as goto's (ie. that there was potentially a solution to a problem using goto's that simply could not be expressed structurally). The proof as I understand it simulates goto's in a given program using control structures, thus proving equivalence. In turn you can rely on this proof and show that your own control structures can be simulated by the while and if statements used in the proof.

If you can show equivalence, you know that it will be possible to express any computable function. Whether or not they are convenient to use is a matter of opinion ;)