Joshua Cranmer says, Honestly (and I mean no disrespect), this doesn't feel
procedural programming language" but "C or maybe Java."
Gerry replies, All I meant by "practical" was "sufficient to write,
conveniently and efficiently, the kind of programs we typically write".
Those include advanced user interfaces, simplified file managers, elegant
text editors, hex dumpers, native-code-generating compilers, wysiwyg
page-layout facilities, and many more.
Joshua Cranmer says, Personally,
I've never felt that distinguishing between procedural, imperative,
object-oriented, functional, etc. is terribly useful because the major
modern languages end up being a complex mismatch of everything. I mean
C++ and Java both now have lambdas, and C++ is even talking about
coroutines the other day.
Gerry replies, I have to disagree; the mental models one forms when using
different kinds of languages are significantly different and thus affect
both how one thinks and how one codes. With a procedural langauge, for
example, one pictures oneself commanding the machine to do things; with an
object-oriented approach, one pictures semi-autonomous objects interacting
with one another. The resulting systems are typically significantly
Joshua Cranmer says, Essentially, I find your categorization troubling
assuming a particular, very specific way of looking at
programming--and a model that's not necessarily reflective of most
large-scale programs (where object-oriented code rules the day).
Gerry replies, Yes, I am assuming a particular, very specific way of looking
at programming, because that's the model that we find works best for us. If
others prefer different ways of thinking, that's fine for them. And yes, our
model is "not necessarily reflective of most large-scale programs (where
object-oriented code rules the day)" -- intentionally so. I'm an old man and
I come from an era where we could send men to the moon and back with a slide
rule. Judging by more recent attempts at space travel, I suspect something
important in the way of simplicity and reliability got lost along the way.
Joshua Cranmer says, A good example of where things really break down is in
introduction of parallelism. Many (all?) languages these days have put
some emphasis on trying to decide good parallelism and concurrency
models at increasingly fundamental positions in the language. I
believe there's a widespread consensus that shared multithreading
isn't good enough, but while there are models of more structured
constructs (e.g., OpenMP, which does explict task parallelism), I
can't speak to how often those get used in practice in major systems.
Certainly, I think the academic community heavily desires the use of
"structured" parallelism instead of "unstructured" (much as we prefer
structured control flow over the goto statement), but industry best
practices can lag a bit or a lot.
Gerry replies, It is our belief that in many cases, parallelism of any kind
is simply overkill.
Joshua Cranmer says, What you have done is not used English as a programming
you did was start with a semantic definition of your language and work
out a syntax for it that happens to be a subset of the English
Gerry replies, Yes, we've coded for a subset of English. But a subset that
can be grown both by improving the compiler, and -- more importantly -- by
programmers simply adding to the collection of available libraries.
Joshua Cranmer says, Clearly, anything that's not expressible in your
language definition isn't expressible in the English-language-version
of your syntax--even if that thought is expressible as a reasonable,
simple English sentence. Since there's a bit of a cooking theme in the
examples, here's an example of such a sentence from a cooking article
in a recent newspaper:
Once it has slowed to one or two seconds between pops, take it out of
Gerry replies, In the current version of our compiler, you'd have to express
that thought more like this:
If it has slowed to one or two seconds between pops, take the popcorn out of
But I hope you can see that it's not a big deal to extend our compiler to
recognize "once" as a synonym for "if" in such cases. Our program is, after
all, a mere prototype, a "proof of concept".
Joshua Cranmer says, In other words, now you have an example of event-driven
programming! Well, kind of (there are better example sentences).
Gerry replies: Yeah, I'm not quite sure why you call that "event driven"
programming; placing that statement in a strictly procedural loop would
work. But we do support the "event driven" paradigm in Plain English; in
fact, our sample program in our instruction manual is event driven. See page
Where the main event loop is defined as follows:
To handle any events:
Deque an event.
If the event is nil, exit.
Handle the event.
Joshua Cranmer says, The way you've
defined your language, though, you can't express this. And it could be
that you don't want to--that's a design decision, and design decisions
are basically subjective opinions.
Gerry replies: But we can express that thought, as above. Or like this:
To make some popcorn:
Put the popcorn into the microwave oven.
Turn on the oven.
Loop. If it not has slowed to one or two seconds between pops, repeat.
Take the popcorn out of the microwave.
And obviously, it won't require much of an extension to our prototype to
support a variety of "loop" expressions, including, for example:
Repeat until it slows to one or two seconds between pops.
When it slows to one or two seconds between pops, stop.
Etc. Like any natural language, we expect Plain English to grow. At this
stage we've only answered our initial questions (enumerated and discussed,
quite fully, in a related thread here):
Joshua Cranmer says, The reason I bring this all up, though, is that you
make a conceit in
your Indiegogo page that the importance of what you're doing is that
you want "scientists, engineers, programmers and many others [ ... ]
to simply write down what they're thinking, in the way that's most
natural." And the way that's most natural is not necessarily
procedural programming--sometimes you can express stuff most naturally
in an event-driven model, perhaps a functional model, or maybe an
actor model. And that's why the major programming languages of today
are all multi-paradigm languages (and even continually expanding their
paradigms)--because, in the end, sometimes it's better to structure
portions of a program in different paradigms.
Gerry: We fully agree: that's the whole point of Hybrid programming; you use
the mode of expression that's most natural for each part of a program. But
the whole is contained in the most natural framework, specifically, a
natural language (in our case, English) -- like a math book, or a physics
book, or a technical (or non-technical) paper. Think Plain English with
sub-compilers for whatever other syntaxes seem generally (or specifically!)
Joshua Cranmer says, Now, to some degree, a Turing-complete language can
emulate any other
Turing-complete language, even if the two are completely different,
incompatible paradigms. That doesn't mean it's a wise idea though, and
you can lose a lot of expressiveness and simplicity in such a
Gerry: We're not thinking "conversion" -- we're thinking "sub-compilers", as
Joshua Cranmer says, Using a parser generator like bison allows for you to
more clearly use the code as documentation for the syntax of the
language--writing the code in a recursive-descent parser loses that
clarity, and it requires substantial commenting to recover what is
going on. You can also use the more abstract description to gain more
features: e.g., a LALR parser basically boils down to
for (each token):
... all code inline here ...
-- and that form is easier to convert into one that gets its tokens
streaming than a recursive descent parser. (On the other hand, parser
generators tend to suffer in their ability to print good diagnostics.)
Gerry: We use recursive descent only where convenient; in our prototype, for
example, we use it to (1) locate and (2) parse certain different statement
types, typically at later time. We also use a variety of ad hoc methods. And
we're convinced that in future versions, a more general "statement locator
and classifier" algorithm would serve us better. Specifically, our plan is
to scan the source, dividing it into blocks where each block contains some
recognizable syntax -- and then sub-compile each block with an appropriate
Joshua Cranmer says, TO sum it up, from my perspective, you have a rather
underwhelming language, semantically speaking (actually some of the
semantic decisions you make some of us mightily disagree with, but
those are quibbles compared to what I discussed in this post). The
syntax seems to be what you are most proud of, but I rather suspect
that most of the people in this group don't care too much about
Gerry: Actually, what we're most proud of is not the syntax per se, but (1)
the fact that we were able to do so much with so little: that we were able
to conveniently and efficiently write a complete, non-trivial and
iconoclastic development environment with a unique native-code-generating
compiler/linker for a subset of English (with a wysiwyg page-layout
documentation facility, to boot) entirely in that very subset of English;
and (2) that our system can be used, educationally, with everyone from
primary school children to college students writing compilers -- the very
same development environment and language being suitable for both. But our
works does indeed strike different people in different ways. Unsolicited
reviews have ranged from "utter rubbish" to "a minor work of genius"; from
"banal and underwhelming" to "nothing short of impressive". Different
strokes for different folks.
Thanks for taking the time to comment.
[I think you're missing the point he was making about "once ...".
Event driven languages have a different model, you tell it what
the triggers are, it figures how how and when to call them,
typically from an implicit event loop. But you don't have
to write the loop. -John]