27 comments

[ 4.6 ms ] story [ 73.3 ms ] thread
compare the card with the ordered card in sequence

find the position to be inserted

shift the card to make space

put in the card

This is horribly imprecise and vague. If you understand it, it's only because you can guess a lot from your experience.

If it was talking about versoring introns and translucing gerns to make invo you wouldn't know what's that all about.

Recently I was trying to understand how CRISPR/CAS works and I can't guess much about it.

Btw. there is a vocabulary based programming language, it's called Forth. Not much grammar though.

Natural language is imprecise and vague. And it is relying on a lot of your experience. However, this is why natural language is so much more effective than the programming language counterpart -- it leverages on people's experience, or I would refer as context.

The idea is to differentiate the two layers of programming. The top layer is the syntax layer, and it should follow the path of natural language which takes in human context (the human interface). The lower layer is the rigorous part (but still human readable), mostly context free and emphasizes the machine (optimization) interface.

Just like we get the daily work done, we use the top layer to express and think, then verify at the lower layer.

Forth is a great language, totally fits the concept. But the article is trying to show that we can program in any language with vocabulary leading style (with the help of meta-layer perhaps) in which you do not lose any benefits of language (if you consider them benefits).

How precisely do you expect to be able to map from something imprecise to something precise? The idea of giving the author complete control over the higher level terms they use sounds like a nightmare in the making honestly :) Being able to understand somebody elses code requires that it be written in a way that is at least familiar in terms of syntax.

To say that natural language is "effective" does not, honestly, ring a bell with me. I guess we think about effective on totally different terms. Math is effective. Spoken language is not in my opinion. On a general level this sounds more like somebody feeling frustrated that the computer didn't "understand them".

How do you map from something imprecise to something precise in daily life? For example, you tell the kids "go to school", very vague (walk or bus or wait for you to drive), and each detailed steps require even detailed actions (composability). So how did you reach the efficiency with only "go to school"?

First of all, we have mechanisms to establish conventions -- which is the user maintainable dictionary I was referring to. Second, we have direct feed back -- if the kids didn't move or the school called, we know something went wrong, (then we strengthen or correct the conventions). In the two layer programming structure, both layers are within programmer's access. Programmer try to work at the top layer as we do in our daily life, but we will get signals from lower level compiler, and we can verify the lower level code directly (which is as readable as what you do today -- you are only working at the lower level language today). It is not one or the other, that is how we manage the daily efficiency.

Are you a mathematician? How much math do you speak anyway? Even my fellow mathematician convey most of the mathematical meaning in English. Can you imagine mathematicians only write in math (as today's programmer do)? Theorem, at least from the math books on my shelf, are mostly composed in English (more words than math). And even in pure math equations, we make up new symbols (with special meanings under special context, not just operators, what do you think the concept of algebra is) all the time, which is along the same line of vocabulary based programming.

If you think I am saying that math can work with English only, then you misunderstood me.

Of course math works across all languages and I didn't think you were implying that, but using a word in a mathematical context carries a lot of precision with it. It isn't simply a layman's usage. The words don't make the description work, but the math behind it does. This applies to programming languages as well.
> Natural language is imprecise and vague. And it is relying on a lot of your experience.

Yes. That's because if you need to be precise you remove yourself farther and farther from natural language towards professional jargon where words have more specified meanings and towards math and computer languages that you can call precise.

> The top layer is the syntax layer, and it should follow the path of natural language which takes in human context (the human interface).

It would be nice to keep at least some part familiar but more often than not you can't because some 'top layer' constructs you need to express have very cumbersome expression, if any, in natural language.

For example natural languages lacks constructs for deep composability or indirection. Natural language is perfectly fine in daily work, like deciding what's for dinner, but trying to explain any non-trivial concept with natural language quickly becomes too cumbersome and person trying to convey the message moves onto more expressive and precise tools like math or drawings or pseudocode.

Please look at how theorems and proofs looked before invention of math symbolism. That's natural language stretched to extremes.

Also please read any modern code of law. That's what we get when people go out of their way to express concepts in natural language instead of creating some explicit domain symbolism.

I'll take math or even cobol any day instead of that.

Para 33 should read "functions" in the plural?
"For function(s), we need worry about ..." ?

Corrected.

As a card carrying condescending know it all, I am obligated to point out that Lisp allows extending the programming language with new vocabulary easily and with new syntax relatively easily. Whew...now that that's out of the way, I can get on with what I really wanted to say.

From a natural language standpoint, I have found J [1] particularly interesting. Kenneth "not Alan" Iverson [2] extended and refined the the ideas he developed for APL [3] and mapped it onto the ASCII character set. Like APL, J is built on a grammar of nouns, verbs, adverbs, etc. with the idea that the labels for the language's parts map reasonably to their counterparts in natural language (for some definition of "reasonably").

One of the great things about J is it's documentation. Originally a commercial product, J's documentation includes great tutorials and primers that someone was paid to write (as opposed to produced instead of doing the coding they love).

[1]: http://www.jsoftware.com/

[2]: https://en.wikipedia.org/wiki/Kenneth_E._Iverson

[3]: https://en.wikipedia.org/wiki/APL_%28programming_language%29

When I tried out both J and APL a while back, I found the J symbols to be unintuitive compared to APL's, mainly because APL had balanced parens, brackets, and curlies, whereas J didn't but instead used them unpaired as part of multi-symbol operators. APL operators were always single-symbol which also helped readability compared to J, but of course entering APL symbols was far more difficult than J's ASCII ones.

One of my favorite possibilities for a syntax that's terse but still readable as well as easily enterable is one using Chinese/Japanese Kanji. IME's like Cangjie or Wubizixing mean they can be entered easily without using unintuitive operators like (= or /] or {%

I think learning J is a project that will take more than 24 hours, not something that where naive intuition is going to produce significant progress...the documentation implies as much. It's Emacs not gedit.

Then again, I don't think any powerful programming language is going to be easy to learn. Turing machines or lambda calculus, take your pick, are hard concepts when it comes to navigating all their implications. That's what allows them to capture all of computation. Python or Ruby or whatever may push the point where the power to complexity curve goes asymptoticly vertical a bit to the right, but it's still there and steep as a wall.

J doesn't pretend to be English. It tries however to have a logical grammar that reflects the grammar of natural language rather than a vocabulary that does.

Many functions in k (see http://kparc.com/k.txt, also in the APL family), are shorter than the 'readable' name that would be attached to it in another language. Rather than deciphering a long name and then reading the code, why not just read the code and find out what is really happening?

Also interesting to note is that k's grammar is defined in terms of nouns, verbs, and adverbs.

I am not familiar with APL or J (only viewed some presentations).

>> Like APL, J is built on a grammar of nouns, verbs, adverbs, etc.

I think this is counter the true nature of natural language. In English at least, the word is in the root and it is not really being bounded by the grammar usage. Noun or verbs, adverbs are a description of the usage, just like dictionary definition, is an aftermath organization, but should not be a prescription. I guess I am arguing on a linguistic aspect, but I think natural language is not built on a grammar, rather they are built on meanings (with patterns automatically emerge).

This is complete nonsense. After finally making it to the end of the article, it became clear that the author is simply advocating for a top-down programming style. However, this fact is completely hidden by some very fundamental misunderstandings about how any of the referenced languages work. "Fold" is not a "keyword" in Haskell, not by a long shot. The author doesn't seem to understand how the programmer can himself implement functions such as fold.
Thanks for reading to the end; I appreciate it.

I quoted "fold" because it is essentially a vocabulary word (which is the whole reason I quote it), it only feels like a language keyword because it is designed and programmer typically learned it.

Sorry, still nonsense. All functions are "designed" and "learned"—that's the whole point of a function, a unit of code reuse. You're positing magic, uh, how did you call them... "elite programmers" in the sky who bestow upon us all the magic functions. Now, I understand that when you first see packages such as Kmett's lens package, it can certainly feel that way, but there's no real truth to the idea.

There's no difference between what you call "vocabulary" and library-supplied functions like fold.

> A vocabulary based programming need give ordinary user the ability to create new words and the ability to expand its usage

That's just called implementing a new function, or maybe writing a new API.

Anecdotal Comment: No matter how magical someone has made a library, I have never worked on a project that did not find an oversight, or some weird edge case where the abstraction dies in a horrible fire and you end up having to understand all the of the libraries internals anyway. Its just kind of the nature of programming in the end.

I'd much rather understand how to write a fold than to "know what it is." There is always something that just has to be done "the hard way."

I understand, and this is kind of today's programming wisdom. But I think we can change it, unless you take the "hard way" as benefit.

In English, I say "go to school", there will be some oversight that end up the kid stray to a game parlor. So in practice, we still do our due diligence to make sure the kid do what we meant. But the important aspect is we do not change "go to school". "go to school" retain its independent meaning even when the implementation is not clear.

Similarly, in programming, the abstract vocabulary will not predict how the actual code will do, but my point is that the implementation is a separate layer from the vocabulary. If the implementation did not do what we meant with the vocabulary (which can be context dependent), we fix the implementation, until to the point that we build the trust (putting into a trust-able library).

Just like we as individual all maintain our own dictionary and trust database, I advocate we each maintain our own macro library (which does not exclude importing from trusted source, sort of like `git`).

By library, I am actually referring to meta(macro) library, (like slang dictionary). Today's binary library does not define the meaning of their names (function/class names), they define the meaning by code, which end up the only way to get the meaning is the hard way. For the macro library, the meaning comes first, (even when the implementation are ambiguous at the time), and therefore it can retain its meaning and further grow its meaning.

It may sound too complicated or too abstract, but in practice, it is just like when we say the kid "goes to school". It is a more of ad hoc practice and, well, natural.

To summarize, current way of programming is more or less code comes first, a vocabulary based programming would be meaning comes first. And for a casual practice, it will provide opportunity for common programmers to only program at the meaning level while trusting the meta-layer (with evolved intelligence) do the right thing, ... until we got feedback otherwise (what? The kid is not at the school? ...)

I'm not even really sure what you are advocating, we all already use libraries, and helper functions, and understand data types, and use generics to map the same function name to multiple types. Fold/reduce are words that are in our vocabulary and if you want to fold a list, array, vector, the result is very well understood by most people. If you want to fold a tree, while conceptually its still the same, the actual "twiddly bits" are very different. And that's not something all of us want or even need abstracted away. It really depends on what level you are working on.

If I'm writing a rest api, abstractions just make everything simpler, but sometimes I'm working with something new or I'm doing something custom and those abstractions are actually bad. I need to talk to the computer not the compiler.

Additionally not everyone thinks about programming the same way, I prefer whole word function names, I know guys that they could care less what things are called, they know what the code does all the same, they might be better developers than me, I'm not sure, but I know that their way of understanding a code base has very few corollaries to my way of understanding it.

Vocabulary about an abstraction is still an abstraction, and abstractions can be immensely useful in certain contexts, but they aren't always useful.

I think your comments are focused at learning side: we learn about the syntax, we learn about the library, we learn about "fold/reduce". At the learning side, abstraction do feel like just one more layer to penetrate, unless, the abstraction is based on your existing experience, which in current programming culture is not really the case.

To understand what I am advocating, think on the writing side, think about when you want to write a program when there is no library and no syntax. What will you have? You'll start with abstract word with meanings based on your past experience. And that abstract word will be able to communicate with your fellow as they often share some of your experience. That is what I mean vocabulary based programming. I guess it is the word "abstraction" confuses. I did not use the word "abstraction" although people with experience in learning tend to see abstraction. Think about how you sort a deck of card, does the word such as pick, find, insert appear abstraction to you? They are the first natural units of meaning, and they appear in our head before any detail implementations. So if we refer abstractions as the steps for our mind to get to, then those vocabulary are not abstractions, the actual implementations are. Anyway, I know I am confusing the hell out of even myself -- natural language and how our mind works are strange :). In the end, I would like you to forget about abstraction or even vocabulary, just go to the most natural way of thinking: whatever comes first should come first in writing (code), and often that is how the most natural way to read as well.

I think you misunderstood me.

Language is an abstraction and its based in symbols. The word rock has literally nothing to do with what a rock is, other than it is the sound we use to refer to rocks. And the concept of rocks is an abstraction, rocks certainly have many similar properties but no single rock is the same as any other rock, they all have differing numbers of atoms, and shapes. But generally speaking rocks are similar enough at the level we work with them at, that you can say things like, big rock, and small rock and there is a general understanding of what is meant. This is a ridiculous example, but its important.

I think what you are looking for here is composition. Let me explain. Java has a TON of natural language, but its much derided for its "verbosity" and boiler-plate centric coding style. But if you sit down and read Java code, its very hard to "miss the point." Classes lend themselves to natural language, and a User object almost certainly contains information like username and password, and first_name, last_name type stuff. It doesn't break the expectations of how we imagine things are grouped together. So in that regard Java is very "natural" but Java is not very composable.

fold add [1,2,3] is a great simple example of composition.

so is

map reverse (zip array_of_arrays)

Natural language, and composable, and the results are fairly easy to guess.

So I get what you are saying, natural language is really nice, but what you are probably advocating is composition. Which is where things like generics stand out.

Writing fold add list is better than. fold add_float list_of_floats and fold add_integer list_of_ints, ideally things which use the + operator should be composable with +, if not it really just makes the whole affair not very fun. Having to basically do taxonomy on your functions, to write the same use of the same operator.

In fact I'd argue this is where a lot of languages really fall on their face where composition is concerned. They have static types, and they might even allow operator overloading, but they don't support generics in a way that allows you to avoid telling the compiler that "yes its really okay to use the operator the way its already been described to be used as".

Generics as in current C++ and Java are still tied to the low level data types. They merely extended from single data type to a collection of data types (that fits certain strict condition).

Now look at our natural language, "eat" for example, you can suddenly say "the sky dog eats the sun" out of the blue and people will start to make that sentence work (which is the ancient Chinese referring to eclipse). Here the vocabulary word "eat" can be defined at any time of history, but not being confined by the definition at any time. The use of words leads definition rather than the other way around.

Let's look at the word "fold", which works on list. Now I have an array or a hash or a matrix, and I am thinking that I need some kind of operation similar to "fold" on a list. Do you just write "fold add array|hash|matrix" then work out the detail implementation (probably at a much later stage)? If you do, you are treating fold as a vocabulary word and you are doing vocabulary lead programing.

Yes, in the case of "fold", it describes a composition type of meaning. How about "pick", "find" or "eat"?

I guess what I am trying to differentiate is meaning and implementation. Larry Wall's favorite idiom is there is more than one way to do it, I think it fits what I mean. it is the meaning, and way is the implementation. In current programming practice, most people only focuses on how it is done, but neglects the meaning. I actually heard many complaints from programmers against Perl exactly because of this "there's more than one way to do it" attitude, how about you?

This is a problem already solved by typeclasses in Haskell; http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Fo...

You can write your own instances of Foldable to add implementations of the "vocabulary" word fold.

How is this different from what you're proposing? It sounds almost like you want the compiler to figure out an instance of Foldable (or, say, Edible) for you, but computers simply don't work that way (then again, GHC can derive Foldable sometimes!).

> Sorry, still nonsense.

No apology necessary.

Unfortunately, sense is individual context dependent.

I agree. I don't see how the author is doing anything differently than the current programming languages.
I'm a few days late to the party but still wanted to add my comment. Contrarily to others in this thread, I get what the author is trying to do with the MyDef library and I share that goal myself.

As I see it, such lightweight scripting (meta-)layer is not intended to replace a programming language in full. Instead, it acts as a general-purpose template language - a wrapper were you put in the ''easy'' parts of the program, which can then be written without the attention to detail that a true programming language forces upon you.

As others have said, the hard parts of a program still benefit from a non-ambiguous, utterly detailed syntax of a full PL. A templating meta-layer is not a good fit for those, that's why you should use them in combination - use something like MyData to write the "general picture" flow, dive in into the hard language to build the details. Then you get the best of both worlds.

It's no different to what it's commonly done with template languages for the web or user interfaces, expect that this library seems to be extendable to other business domains.

Thanks a lot for understanding.

I am puzzled why most readers see MyDef as another language or library. Let's use Javascript for example, Coffee script or other language force you to re-learn and write in the new language, but with MyDef, we still write JavaScript and use the same pattern we acquired. It is not about re-learn, rather it is about growing. For example, `document.getElementById('name')`, which you learned the first time starting Javascript, you don't have to relearn; but in the meantime you don't want to write/think in so much detail, so with MyDef, you start write `$(id:name)` (one of the many ways you can come up). Here, you did not learn the new word, you grew it. Then, you start write `$(type:name)`, `$(value:name)`, `$(show:name)`, `$(hide:name)`, or `$(select:#name)`. Just like the word we use in daily life, when we say "go to school", we understand what we mean and (more importantly) we immediately get feedback on whether the reality (the kids walks to school bus) meets our expectation. In MyDef, we understand where these idioms are defined and the translated output is right there for us to verify (which is not much different from markdown). In comparison, when we use `$("#name)`, we only can learn the meaning; if we guess, there is nowhere to directly get feedback -- which forms a disconnect from your old acquired knowledge. Similar with most library and framework, you are disconnected from you old experience (I don't mean abandon, but a discontinuity) and re-learn a new set. MyDef is about grow, not re-learn, there isn't any barrier.