The Forum for Discussion about The Third Manifesto and Related Matters

Please or Register to create posts and topics.

Life after D with Safe Java

PreviousPage 5 of 11Next

Of those that are left, I tried to find the five principles: safer-higher-shorter, meta and fits in (meaning interoperable with existing code/libraries).

  • words for safer are very common, nominating the areas of type inference, memory, concurrency
  • words for shorter appear often eg 'concise'
  • words suggesting higher do not (except in the OCaml family)
  • Crystal, Elixir, Groovy, Nim, Rust have meta-programming/macros
  • There is a mix of native and VM, with words like 'interoperable' and 'performance'. Only Kotlin and Groovy target the JVM, but most offer some way of interacting with native code.

So this research tells me that most (4 of 5) of the principles I've been plugging are out there driving language development. Of this list, the only ones suitable for general app development right now are probably Groovy and Nim, with Crystal as an outsider. The principles of safe and meta are well-served, but any attempt to find higher is doomed to failure.

Did you look at the Raku language yet?  I recommend it.  May very well outdo some of the other newer and niche languages on your final list.

We wrote quite a bit of Perl back in the day, to analyse log files from our test suites. We were getting files of 50m lines, on Windows and several flavours of Unix, we outgrew awk and Perl handled them well. I wondered what had happened to Perl 6. Thanks for the pointer.

This is a language with a heritage going back over 30  years, seeking to evolve so as to 'fix Perl' and 'remove warts'. That would place it outside my survey.

There seems to be no particular intent to make the language safer at compile time, because dynamic typing is always a fallback. I'm not sure whether the classes and roles in Raku would equate to the TTM type system, or permit type inference. It still reads like a scripting language (Python-ish) rather than a novel general application development language of the kind I've been looking for. But that could be my lack of familiarity

Andl - A New Database Language - andl.org

I don't recall if I've mentioned it here before, but maybe we're going about this "programming language" thing all wrong. Gerry Rzeppa (and son) seem to think so: See https://osmosianplainenglishprogramming.blog and http://www.osmosian.com

It's batty, he's batty, and yet...

It kind of works.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org

It wasn't meant to be an analysis. Just pointing out that your bullet points are vague enough to mean anything from cutting-edge future advancements to crude legacy languages. E.g., "getting rid of ... type declarations" could mean type inference per modern languages, or literally no type declarations and "type inference" of a handful of primitive types per vintage BASIC.

I think you're trying to read them backwards, as a list of inclusions rather than a list of exclusions. Assume you start with the latest Java/C#/etc: this is what we try to take out. There is another list of things we might want to add, including getting things back from C++ (meta, unions, type aliases, value types) and elsewhere.

Often the problem here isn't so much your ideas but your tendency to write descriptions which leave out more than they include, and thus raise more questions than they answer. In particular, your use of terminology often implies long discarded (for good reason) approaches, though that doesn't appear to be the intent.

For example, if your bullet list actually means sophisticated (e.g., algebraic types / dependent typing) type systems, type inference (with optional annotations or obligatory ones for, say, function parameters), value semantics (with references where needed), pattern-matching dispatch, then it's fine. But as written, not so much. E.g., do you really want to get rid of all type declarations? Do you really mean one numeric type, or do you mean the specific numeric type is inferred? Etc.

I was giving a list of stuff to take out, so we can think higher and leave more of the details to the compiler. Yes (obviously) a type system as capable as TTM requires, which means (obviously) the ability to define new types. By all means add union types, I was only doing the subtractions.

Why do you need type declarations? Why do you need to declare which type of number to use? If the compiler can track every value from the point where it was created, why does it need our help?

It doesn't need our help, we need its help, so to speak.

No, the whole point is leave it to the compiler and stop worrying about it, so we can think about other things.

What we sometimes want is the explicit readability provided by annotations, particularly on function/method/procedure declarations. This is both to improve readability (if dispatch is disambiguated by name) and to drive dispatch (if the name is overloaded.)

It's also a nice option for variable declarations. It's not just for readability; it allows us to explicitly specify a supertype/generic to allow assignment of any value belonging to a set of specified substitutable types (usually by explicitly specifying a supertype.)

Java from the outset has had to be both the producer of API implementations and the  consumer in application development. If you design for an API you will need to tell the compiler what it should enforce on a subsequent user. This implies that the only proper place for type declaration is in the construction of APIs.

Yes, there are some issues with value ambiguity aka overloading, but that's all I can think of and that looks solvable.

If so, does that mean pure inference?  That can be hard to read.

Do you have examples?

Sure. This (made-up code) is hard to read:

var criteria = document.getApplicationCriteria();
var fuzzFactor = document.getInsertionFuzzFactor();
var range = document.performSelection(fuzzFactor, criteria);
var success = document.activateSelection(range, criteria);

This is more verbose, but easier to read:

Filter criteria = document.getApplicationCriteria(); 
double fuzzFactor = document.getInsertionFuzzFactor(); 
Pair<int, int> range = document.performSelection(fuzzFactor, criteria); 
boolean success = document.activateSelection(range, criteria);

I would argue that this is wrong. It adds unwanted cruft to readers who just don't care, and if you need to know the types, the proper place to look for them is in the API. It also gets in the way of refactoring: if a decision is made to change the API this physical source code has to be altered and appear as a change in repo when in truth this code did not change.

My emphasis is on readability, rather than terseness or being shorter above all else.

This is easy to read, and easy to visually verify against specifications/contracts:

fn DeepSearch(Tree<TreeNode<CustomNode>> struct, Filter criteria) -> TreeNode<CustomNode> { ... }
fn DeepSearch(Tree<TreeNode<CustomNode>> struct, Filter criteria) -> TreeNode<CustomNode> { ... }

I'm more inclined to agree here: this is an API.

But this is not a concrete proposal, it's a theme. Given there are compilers out there offering this, I plan to do more research. But I guess the broad rules would be:

  • If there is a design, contract, formal API, persistent data format etc it should explicitly declare types as needed: single source of truth.
  • the compiler should import those types from whatever source, and enforce them
  • there should be no need to declare types in application code that merely consumes APIs provided by others.

 

Andl - A New Database Language - andl.org
Quote from Dave Voorhis on April 20, 2021, 8:21 pm

I don't recall if I've mentioned it here before, but maybe we're going about this "programming language" thing all wrong. Gerry Rzeppa (and son) seem to think so: See https://osmosianplainenglishprogramming.blog and http://www.osmosian.com

 

"I often find myself thinking in English pseudo-code, then I translate my thoughts into whatever artificial syntax ..."

No. I first write in some algebra/math notation. Then (for a procedural language) translate into the flow-of-control steps and assignments and condition-tests. The advantage of coding in Haskell is that it's much closer to algebra/math.

"have you considered the fact that most of the code in most programs does simple stuff like “move this over there” and “show that on the screen” — things that can be most conveniently and most naturally expressed in a natural language?"

MOVE A TO RESULT. ADD B TO RESULT. PRINT RESULT ON SCREEN.

If most of my code were like that, I'd be writing in COBOL. But it isn't; and I don't any more.

(Somewhere there's a quote critiquing those who say COBOL can be read by any business analyst. To the effect there's a difference between reading vs understanding all the implications of moving A TO RESULT and thereby overwriting whatever was in result, and how that interacts with flow-of-control -- were you intending to accumulate to RESULT, for example?)

These guys are not thinking in plain-English. They're thinking in machine operations, then back-translating to English.

 

It's batty, he's batty, and yet...

It kind of works.

INTERCAL kind of works. Has a compiler and all. No. Rzeppa is no more than batty. Is that even a real name?

Quote from AntC on April 21, 2021, 1:12 am
Quote from Dave Voorhis on April 20, 2021, 8:21 pm

I don't recall if I've mentioned it here before, but maybe we're going about this "programming language" thing all wrong. Gerry Rzeppa (and son) seem to think so: See https://osmosianplainenglishprogramming.blog and http://www.osmosian.com

"I often find myself thinking in English pseudo-code, then I translate my thoughts into whatever artificial syntax ..."

No. I first write in some algebra/math notation. Then (for a procedural language) translate into the flow-of-control steps and assignments and condition-tests. The advantage of coding in Haskell is that it's much closer to algebra/math.

I think in abstract code, then translate/write that in the target language.

If you ask ten developers how they program, you'll get at least ten answers, and more likely twelve.

"have you considered the fact that most of the code in most programs does simple stuff like “move this over there” and “show that on the screen” — things that can be most conveniently and most naturally expressed in a natural language?"

MOVE A TO RESULT. ADD B TO RESULT. PRINT RESULT ON SCREEN.

If most of my code were like that, I'd be writing in COBOL. But it isn't; and I don't any more.

(Somewhere there's a quote critiquing those who say COBOL can be read by any business analyst. To the effect there's a difference between reading vs understanding all the implications of moving A TO RESULT and thereby overwriting whatever was in result, and how that interacts with flow-of-control -- were you intending to accumulate to RESULT, for example?)

These guys are not thinking in plain-English. They're thinking in machine operations, then back-translating to English.

I think it's an interesting idea to create a programming language that "understands" English like a 1970's era text adventure game, but I've no doubt the resulting looseness is inviable for any kind of production programming. Aside from whatever might have been its original (and perhaps idealistic) intent, Rzeppa & Co. primarily appear to position their system as being a teaching tool that allows programming learners to focus on semantics without getting tripped-up by syntax. Rzeppa peddles it as perfect for teaching wee noobs -- as kind of a modern alternative to Logo, I guess -- but I don't know anyone who's ever used it for teaching.

It's batty, he's batty, and yet...

It kind of works.

INTERCAL kind of works. Has a compiler and all. No. Rzeppa is no more than batty. Is that even a real name?

It's a real name, as far as I know. I dimly recall seeing a short biography for him (he's active on Quora, as am I) that gave some (if I recall correctly) reasonably mundane IT industry history, but I don't recall the details. His subsequent (in retirement, I presume) work like Plain English, his religious activities and whatnot, are considerably more, er, colourful.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org
Quote from Dave Voorhis on April 20, 2021, 8:21 pm

I don't recall if I've mentioned it here before, but maybe we're going about this "programming language" thing all wrong. Gerry Rzeppa (and son) seem to think so: See https://osmosianplainenglishprogramming.blog and http://www.osmosian.com

It's batty, he's batty, and yet...

It kind of works.

Yeah, maybe. The premise has usually been that we need to be more precise when it comes to programming, but maybe not.

I've looked at it very briefly and suspect it works very similarly to Rockstar

Quote from dandl on April 21, 2021, 12:44 am

It wasn't meant to be an analysis. Just pointing out that your bullet points are vague enough to mean anything from cutting-edge future advancements to crude legacy languages. E.g., "getting rid of ... type declarations" could mean type inference per modern languages, or literally no type declarations and "type inference" of a handful of primitive types per vintage BASIC.

I think you're trying to read them backwards, as a list of inclusions rather than a list of exclusions. Assume you start with the latest Java/C#/etc: this is what we try to take out. There is another list of things we might want to add, including getting things back from C++ (meta, unions, type aliases, value types) and elsewhere.

I just mean they're vague, and subject to very broad interpretation.

Please, please, please do not bring back C++-style "meta", unions (if you mean what I think you mean), and type aliases. Java not having these is one of its strengths.

But I mention that not to get into a debate about what should/shouldn't be included, but to point out that it's almost inevitable that everyone you ask will have a different vision of what should/shouldn't be included in some C++/C#/Java successor. What I think should/shouldn't be there will differ from what you think should/shouldn't be there, and likewise for Ant, Erwin, Tobega, etc., etc.

I think the best you can do here is write something that scratches your own personal itches, and hope that enough other developers share the same itches to appreciate your, er, itch-scratcher.

Often the problem here isn't so much your ideas but your tendency to write descriptions which leave out more than they include, and thus raise more questions than they answer. In particular, your use of terminology often implies long discarded (for good reason) approaches, though that doesn't appear to be the intent.

For example, if your bullet list actually means sophisticated (e.g., algebraic types / dependent typing) type systems, type inference (with optional annotations or obligatory ones for, say, function parameters), value semantics (with references where needed), pattern-matching dispatch, then it's fine. But as written, not so much. E.g., do you really want to get rid of all type declarations? Do you really mean one numeric type, or do you mean the specific numeric type is inferred? Etc.

I was giving a list of stuff to take out, so we can think higher and leave more of the details to the compiler. Yes (obviously) a type system as capable as TTM requires, which means (obviously) the ability to define new types. By all means add union types, I was only doing the subtractions.

Why do you need type declarations? Why do you need to declare which type of number to use? If the compiler can track every value from the point where it was created, why does it need our help?

It doesn't need our help, we need its help, so to speak.

No, the whole point is leave it to the compiler and stop worrying about it, so we can think about other things.

My point is simply that we sometimes want to be able to specify type annotations, and sometimes use type inference.

What we sometimes want is the explicit readability provided by annotations, particularly on function/method/procedure declarations. This is both to improve readability (if dispatch is disambiguated by name) and to drive dispatch (if the name is overloaded.)

It's also a nice option for variable declarations. It's not just for readability; it allows us to explicitly specify a supertype/generic to allow assignment of any value belonging to a set of specified substitutable types (usually by explicitly specifying a supertype.)

Java from the outset has had to be both the producer of API implementations and the  consumer in application development. If you design for an API you will need to tell the compiler what it should enforce on a subsequent user. This implies that the only proper place for type declaration is in the construction of APIs.

Yes, there are some issues with value ambiguity aka overloading, but that's all I can think of and that looks solvable.

If so, does that mean pure inference?  That can be hard to read.

Do you have examples?

Sure. This (made-up code) is hard to read:

var criteria = document.getApplicationCriteria();
var fuzzFactor = document.getInsertionFuzzFactor();
var range = document.performSelection(fuzzFactor, criteria);
var success = document.activateSelection(range, criteria);

This is more verbose, but easier to read:

Filter criteria = document.getApplicationCriteria(); 
double fuzzFactor = document.getInsertionFuzzFactor(); 
Pair<int, int> range = document.performSelection(fuzzFactor, criteria); 
boolean success = document.activateSelection(range, criteria);

I would argue that this is wrong. It adds unwanted cruft to readers who just don't care, and if you need to know the types, the proper place to look for them is in the API.

That compels the reader to look in the API, which turns what could be simple code-reading into a painful festival of API lookups. Speaking as someone who spends a significant amount of time reading/maintaining legacy code, judicious use of explicit type annotations in this context is really, really, really helpful.

I wouldn't want to lose the ability to provide such annotations, when I feel they're appropriate to enhance readability.

It also gets in the way of refactoring: if a decision is made to change the API this physical source code has to be altered and appear as a change in repo when in truth this code did not change.

My emphasis is on readability, rather than terseness or being shorter above all else.

This is easy to read, and easy to visually verify against specifications/contracts:

fn DeepSearch(Tree<TreeNode<CustomNode>> struct, Filter criteria) -> TreeNode<CustomNode> { ... }
fn DeepSearch(Tree<TreeNode<CustomNode>> struct, Filter criteria) -> TreeNode<CustomNode> { ... }

I'm more inclined to agree here: this is an API.

But this is not a concrete proposal, it's a theme. Given there are compilers out there offering this, I plan to do more research. But I guess the broad rules would be:

  • If there is a design, contract, formal API, persistent data format etc it should explicitly declare types as needed: single source of truth.
  • the compiler should import those types from whatever source, and enforce them
  • there should be no need to declare types in application code that merely consumes APIs provided by others.

All reasonable. Note that sometimes we do want to declare types in application code that merely consumes APIs provided by others, in order to be warned and/or forced to update when the APIs change.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org
Quote from dandl on April 20, 2021, 2:22 pm

Did you look at the Raku language yet?  I recommend it.  May very well outdo some of the other newer and niche languages on your final list.

We wrote quite a bit of Perl back in the day, to analyse log files from our test suites. We were getting files of 50m lines, on Windows and several flavours of Unix, we outgrew awk and Perl handled them well. I wondered what had happened to Perl 6. Thanks for the pointer.

This is a language with a heritage going back over 30  years, seeking to evolve so as to 'fix Perl' and 'remove warts'. That would place it outside my survey.

There seems to be no particular intent to make the language safer at compile time, because dynamic typing is always a fallback. I'm not sure whether the classes and roles in Raku would equate to the TTM type system, or permit type inference. It still reads like a scripting language (Python-ish) rather than a novel general application development language of the kind I've been looking for. But that could be my lack of familiarity

While early on Raku was a modest evolution of Perl, they dropped that pretence long ago, and Raku is in fact a whole new programming language rewritten from the ground up with huge influences from multiple other languages as well as many novel things never done in other languages.

So you should be thinking of Raku as around 15 years old in practice, and as its own thing rather than as a continuation of anything else.  Calling Raku a continuation of Perl is like calling Java a continuation of C++.

Raku is a full featured novel general application development language that lacks no features in any other such language, and has all the more modern advanced features, it is not "just" a scripting language.

The fact that Raku, unlike Perl, supports declared types of variables/parameters/etc, means it is making the language safer at compile time.

 

Quote from AntC on April 21, 2021, 1:12 am
Quote from Dave Voorhis on April 20, 2021, 8:21 pm

I don't recall if I've mentioned it here before, but maybe we're going about this "programming language" thing all wrong. Gerry Rzeppa (and son) seem to think so: See https://osmosianplainenglishprogramming.blog and http://www.osmosian.com

 

"I often find myself thinking in English pseudo-code, then I translate my thoughts into whatever artificial syntax ..."

No. I first write in some algebra/math notation. Then (for a procedural language) translate into the flow-of-control steps and assignments and condition-tests. The advantage of coding in Haskell is that it's much closer to algebra/math.

And I think visually: a data model, state transitions, data flows. English pseudo-code and arcane symbols get in the way.

"have you considered the fact that most of the code in most programs does simple stuff like “move this over there” and “show that on the screen” — things that can be most conveniently and most naturally expressed in a natural language?"

MOVE A TO RESULT. ADD B TO RESULT. PRINT RESULT ON SCREEN.

If most of my code were like that, I'd be writing in COBOL. But it isn't; and I don't any more.

I hated writing Cobol. It took me a long time to actually believe it was as dumb as it really was.

(Somewhere there's a quote critiquing those who say COBOL can be read by any business analyst. To the effect there's a difference between reading vs understanding all the implications of moving A TO RESULT and thereby overwriting whatever was in result, and how that interacts with flow-of-control -- were you intending to accumulate to RESULT, for example?)

These guys are not thinking in plain-English. They're thinking in machine operations, then back-translating to English.

You think so> I'd like to know which language this is better than.

 

It's batty, he's batty, and yet...

It kind of works.

INTERCAL kind of works. Has a compiler and all. No. Rzeppa is no more than batty. Is that even a real name?

 

Andl - A New Database Language - andl.org
Quote from Dave Voorhis on April 21, 2021, 8:22 am
Quote from dandl on April 21, 2021, 12:44 am

It wasn't meant to be an analysis. Just pointing out that your bullet points are vague enough to mean anything from cutting-edge future advancements to crude legacy languages. E.g., "getting rid of ... type declarations" could mean type inference per modern languages, or literally no type declarations and "type inference" of a handful of primitive types per vintage BASIC.

I think you're trying to read them backwards, as a list of inclusions rather than a list of exclusions. Assume you start with the latest Java/C#/etc: this is what we try to take out. There is another list of things we might want to add, including getting things back from C++ (meta, unions, type aliases, value types) and elsewhere.

I just mean they're vague, and subject to very broad interpretation.

Please, please, please do not bring back C++-style "meta", unions (if you mean what I think you mean), and type aliases. Java not having these is one of its strengths.

C++lets you do things (unsafely) that you can't do in Java. I want to be able to do them, but safely.

The meta I want is to solve this problem. I have just spent a couple of hours writing code like this for a large number of named variables:

Console.Writeln($"version="{a.Version}");
b.version = a.Version
Console.Writeln($"version="{b.version}");

This is debugging code, not production, and I don't care if the macro that does this for me offends your sensibilities. Simple text substitution is enough to save a mountain of typing, and we now have the tech that will allow us to do this safely. I want it.

C unions did two things: structural overlays (which is actually undefined behaviour) and simple algebraic types (along with struct). I want the algebraic types: don't  you?

C typedefs allow you to type check usage of primitive types. We used them extensively in Powerflex to manage the various compiler differences (such as signed/unsigned, short/long) but they're also really useful to distinguish (say) between an integer used as a count, one used as an index and one used as a length. There is no downside.

But I mention that not to get into a debate about what should/shouldn't be included, but to point out that it's almost inevitable that everyone you ask will have a different vision of what should/shouldn't be included in some C++/C#/Java successor. What I think should/shouldn't be there will differ from what you think should/shouldn't be there, and likewise for Ant, Erwin, Tobega, etc., etc.

I think the best you can do here is write something that scratches your own personal itches, and hope that enough other developers share the same itches to appreciate your, er, itch-scratcher.

I have very few specific itches: whatever gives me safer-shorter-higher, meta and fits in will be just fine. But it's totally wrong to think about what to add until you know for sure what you're prepared to give up to get it.

No, the whole point is leave it to the compiler and stop worrying about it, so we can think about other things.

My point is simply that we sometimes want to be able to specify type annotations, and sometimes use type inference.

Again, upside down. You start from the preconception that need to know everything and be in total control. If you were designing Java you would include pointers and unsigned because 'sometimes you want to specify this and sometimes that'. Someone with better insight said no, you can't have them. My question is not what you want to add, but what you can allow to be taken away. What do you use routinely, which can be totally removed from 'next J' (because there more important things to think about)?

That compels the reader to look in the API, which turns what could be simple code-reading into a painful festival of API lookups. Speaking as someone who spends a significant amount of time reading/maintaining legacy code, judicious use of explicit type annotations in this context is really, really, really helpful.

I wouldn't want to lose the ability to provide such annotations, when I feel they're appropriate to enhance readability.

So what does the compiler have to do for you give up your insecurity and stop looking? Why do you need to know? What mistakes are happening which a smarter compiler could avoid?

 

Andl - A New Database Language - andl.org
PreviousPage 5 of 11Next