What's your favorite language feature? - Page 1
Forum section: electronics / general

author: mrflibble
author_rank: Super Contributor
timestamp: March 05, 2020, 11:16:59 am
content: Thought it would be fun to hear from other people what cool language features are out there. What feature in your programming language of choice do you like the most? Can be anything about any language.My choice would have to be ... mmmhh, list comprehension in python. Maybe generators in general. Oh and itertools, and, and... But to keep it specific, yes, list comprehension.So what's yours?

author: jfiresto
author_rank: Frequent Contributor
timestamp: March 05, 2020, 11:27:52 am
content: Associative arrays (dictionaries), named arguments and coroutines

author: tggzzz
author_rank: Super Contributor
timestamp: March 05, 2020, 11:37:09 am
content: Hardrealtime performance guaranteed by the IDE not measurement (combination of hardware and software), output to be executed at specified clock cycle, input received at a specified clock cycle. All found in xC running on xCORE processorsBuilt-in primitives (not libraries) for multiprocessor systems and inter-processor communication. Found in CSP, Occam, xC and to a lesser extent Rust and Go.

author: Mechatrommer
author_rank: Super Contributor
timestamp: March 05, 2020, 11:51:12 am
content: pointer, pointer to pointer, type casting, OOP, operator overloading. keen coder should already know what is this, only one language can provide this at humanly friendly language/syntax. the rest? list of <insert whatever here>, dictionary <insert your fav here> etc all can be made later on as a class or whatever (higher level function), but once the pointer feature is not available directly, it feels like sitting on a wheelchair losing both legs.

author: AndyC_772
author_rank: Super Contributor
timestamp: March 05, 2020, 01:27:27 pm
content: Conditional execution, especially as applied to branch instructions.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 05, 2020, 05:27:26 pm
content: Swearing and cursing.

author: jfiresto
author_rank: Frequent Contributor
timestamp: March 05, 2020, 05:40:32 pm
content: Quote from: SiliconWizard on March 05, 2020, 05:27:26 pmAh, but in what language?

author: boffin
author_rank: Unknown
timestamp: March 05, 2020, 05:56:40 pm
content: Associative Arrays/Dictionaries (most modern languages)Sets (Pascal). Just wait until you use a set to represent an output register. It's a thing of beauty....

author: dferyance
author_rank: Regular Contributor
timestamp: March 05, 2020, 06:10:13 pm
content: Separate compilation / linker.So many "modern" programming languages don't bother with it (Java, .Net, Python, NodeJS). So you end up with Docker hell trying to manage all your dependencies.A programming language ought to be able to produce a single executable without additional runtime libraries or installs. That isn't to say all applications should be a single executable, but they all ought to be able to use a linker to include dependencies (as well as exclude) at compile time.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 05, 2020, 06:37:47 pm
content: Quote from: jfiresto on March 05, 2020, 05:40:32 pmAny that supports it. The OP said: "Can be anything about any language."

author: ve7xen
author_rank: Super Contributor
timestamp: March 05, 2020, 08:01:04 pm
content: I'm going to go with type inference as my favourite 'general' feature. It makes strongly typed languages so much nicer to use.As for the 'coolest' feature, I'm going to go with Golang's goroutines and channels.

author: tggzzz
author_rank: Super Contributor
timestamp: March 05, 2020, 08:51:11 pm
content: Quote from: ve7xen on March 05, 2020, 08:01:04 pmActually Communication Sequential Processes' channels and execution semantics. From 1976, from CAR Hoare. Look him up on wackypedia etc.First implementation : Occam in the early 80s. Current variant: xC, as per my previous post

author: Nominal Animal
author_rank: Super Contributor
timestamp: March 05, 2020, 10:03:55 pm
content: Aggressiveandwords of power.External language bindings in various programming languages, and extended inline assembly in GNU C and C++.

author: bsudbrink
author_rank: Frequent Contributor
timestamp: March 05, 2020, 11:26:43 pm
content: I like languages that allow direct access to hardware, including the CPU and its registers. And the operations are represented by simple numeric codes in consecutive memory locations.

author: David Hess
author_rank: Super Contributor
timestamp: March 06, 2020, 12:59:09 am
content: Sane casting of integer multiplies and divides would be my favorite language feature if it existed.

author: I wanted a rude username
author_rank: Frequent Contributor
timestamp: March 06, 2020, 03:17:42 am
content: The ternary operator.

author: golden_labels
author_rank: Super Contributor
timestamp: March 06, 2020, 04:02:01 am
content: Prototype-based programming. Easy to abuse, but great for compatibility layers and modifying method behaviour. Unfortunately also quite inefficient.Any type of sane multiline string literals, possibly coupled with indentation removal.Template metaprogramming in C++. Too bad the error messages are unreadable.Null coalescing and Elvis operators, in various shapes and forms.Quote from: dferyance on March 05, 2020, 06:10:13 pmJava has a separate compiler (javac) and “linker” (java).Since Java has no executables, it also means the second paragraph would not apply. However: the closest it has to executables, JARs, allow you to pack anything you want — including all the dependencies. This is a horribly bad practice that will bite you just like any other failure at using modularity, but there is nothing that prevents you from doing so.

author: ivaylo
author_rank: Frequent Contributor
timestamp: March 06, 2020, 05:56:14 am
content: functions as first class citizensin any language...

author: emece67
author_rank: Frequent Contributor
timestamp: March 06, 2020, 08:37:24 am
content: .

author: jfiresto
author_rank: Frequent Contributor
timestamp: March 06, 2020, 01:45:18 pm
content: Closures

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 06, 2020, 04:02:02 pm
content: Quote from: golden_labels on March 06, 2020, 04:02:01 amI would cite metaprogramming in general as well. Unfortunately, this is so badly implemented in most languages I know of that I can't really associate this sanely with any.C++ templates were a nice attempt at first, but they became horrible, and yes the diagnostic messages are usually unusable, so you better get it right first or you will cry.Quote from: golden_labels on March 06, 2020, 04:02:01 amJava itself is a horribly bad practice.

author: dferyance
author_rank: Regular Contributor
timestamp: March 06, 2020, 07:46:55 pm
content: Quote from: golden_labels link=topic=232434.msg2950470#msg2950470I intended to mean static or compile-time linker. Most languages and operating systems have some sort of dynamic linker.Yeah, JAR is essentially a work-around, similar to Docker. It still is dynamic linking, slows down program startup, can fail for things that ought to be caught at compile time, doesn't eliminate dead-code or do link-time optimizations. But it is better than having a ton of files all over the place.

author: TerminalJack505
author_rank: Super Contributor
timestamp: March 06, 2020, 09:03:32 pm
content: I would say that, in general, my favorite language feature is "being modern." That is, a language that evolves to meet the demands of modern software engineering and doesn't rest on its laurels and live in the past. A language that helps the developer apply best practices as they are understood here-and-now. (I'm basically calling-out languages like 'C', here.)Specifically, I'd say one of the most interesting language features to come (back) around recently is coroutines.

author: IDEngineer
author_rank: Super Contributor
timestamp: March 23, 2020, 02:50:45 am
content: Saw this thread and had to comment, since I just had to learn Python for a small side project....You'll never realize how much you appreciate braces surrounding (read: clearly, unmistakably delimited) code blocks in C/C++, until you work in a language like Python where (invisible) (whitespace) indent levels attempt to substitute for them.Whomever dreamt that up should be professionally embarrassed for eternity. No other accomplishment can possibly offset the lunacy of that decision.EDIT: If we can take visible code block delimiters for granted, then my favorite language feature is pointers. Can't think of a single other feature that is as powerful and flexible. Can pointers be misused? Sure, just like any other powerful tool in any context. It's the wrong approach to cripple a language so you can better tolerate poor software authors. Hint: Poor software authors willalwaysfind ways to leave bugs in their code.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 23, 2020, 02:45:04 pm
content: Quote from: IDEngineer on March 23, 2020, 02:50:45 amAhah, I fully agree. This is wrong on so many levels, but one that's definitely worse than others is maintainability and code sharing.More generally speaking, this is a pet peeve of mine actually: many people seem to be in the quest for minimizing the number of characters they have to type when writing code, and blame overly "verbose" languages. C is already pretty lean, but some people find it still too verbose and want to get rid of more signs like braces and parentheses.I think this is completely dumb, and often say that if the number of characters you have to type to write a given piece of code really matters to you compared to all other design and implementation tasks, then the code you write must be either really simple or really lame.Just my 2 cents.

author: jfiresto
author_rank: Frequent Contributor
timestamp: March 23, 2020, 04:17:01 pm
content: Almost always when I found something annoying about Python, it was because I was slavishly following a design pattern, necessary in a prior language I had internalized, but now redundant in Python and agreeably forgotten.I think the missing delimiters and significance of whitespace bit me once or twice the first couple days I used Python. That ended after I banished tabs and turned on Python mode: in the same old editor I have been using for the last forty years. The pretty printing I had always done, then mapped one-to-one to Python's indentation, and I promptly forgot about it.I bet you are fighting the language in some way if its indentation is causing you grief, If you could post some examples (perhaps starting another thread), I would be happy to try to smooth things out.

author: exe
author_rank: Unknown
timestamp: March 23, 2020, 04:31:34 pm
content: Strong static typing (I'm a python developer).

author: tggzzz
author_rank: Super Contributor
timestamp: March 23, 2020, 04:42:12 pm
content: Quote from: SiliconWizard on March 23, 2020, 02:45:04 pmPrecisely.I'll add "... or you are only coding what somebody else designed".With anydecentlanguage a modern IDE should be able to type many of the characters: in Eclipse it is ctrl-space then a few arrows to select the precise option you want. No, C/C++ cannot (by design) count as decent in this respect.

author: IDEngineer
author_rank: Super Contributor
timestamp: March 23, 2020, 05:32:31 pm
content: Quote from: jfiresto on March 23, 2020, 04:17:01 pmJust to be clear, my Python code works just fine. And I use IDLE, straight out of the Python distribution, so it's not an "editor thing".It's in reading and (especially) debugging, and especially when it's someone else's code, that Python's block delimiter mistake becomes very apparent. There's just no way that the visualabsenceof something is as clear and quick to recognize. This is particularly bad with nested loops. One of the things I had to write in Python recently was some matrix manipulation code, and the nested loops where a pain for everyone on the team. I lost count of the number of times one or more of us was carefully examining a line of code in the wrong loop because the visibility of the indent level was affected by your angle to the screen - if you weren't straight in front of a monitor it became very easy to misjudge which indent level you were tracking by eye. Utter insanity! And so easily avoided, as has been done in other languages for decades. This was a completely avoidable error in language design.It also doesn't help, if you're going to rely on whitespace, that the default indent is just four spaces. I like tight indenting when block delimiters are in use, but when whitespace on the screen is all you've got, four little spaces makes things just that much harder. Particularly in a team environment and it's not YOUR screen so you're off-axis.Finally, Python isn't even consistent in its elimination of block delimiters. It actually has an OPENING delimiter (the colon), which basically substitutes for (say) the open brace in C, C++, Java, etc. But Python's closing delimiter is - wait for it - acorrect number of spacesfrom the left edge. Which is a number that varies depending upon where the associated colon happens to be (or, rather, where the line that contains that colon happens to start). And it's up to theuserto line everything up, visually, through blank white space across potentially many lines on the screen, to avoid (best case) compile errors or (worst case) unintended code behavior.All of which could have been easily eliminated with a closing block delimiter. And that wouldn't have even been a new concept in the world of programming languages. Unbelievable.EDIT: A good related question to this topic is "What problem were they trying to solve by eliminating the closing block delimiter?" Honestly, how many times have programmers pounded their keyboard in frustration and shouted "My life would be so much better if there was a language out there that DIDN'T require a closing block delimiter!!!" I've said, and heard, that complaint precisely zero times.

author: Tepe
author_rank: Frequent Contributor
timestamp: March 23, 2020, 05:33:59 pm
content: Pattern matching (like in SML or Haskell)

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 23, 2020, 06:03:20 pm
content: Quote from: IDEngineer on March 23, 2020, 05:32:31 pmYep!It just looks like a decision from some hugely stubborn person, not completely different from some religious belief. The amount of potential problems it introduces just to save one delimiter is, as you said, unbelievable! But as I said in an earlier thread, I don't think the author of Python ever expected it to become so popular either.This meaningful blank space disaster always makes me think of the Whitespace language:https://en.wikipedia.org/wiki/Whitespace_%28programming_language%29(note that Python is actually cited in this article, which is extra funny.)

author: IDEngineer
author_rank: Super Contributor
timestamp: March 23, 2020, 08:27:44 pm
content: Quote from: SiliconWizard on March 23, 2020, 06:03:20 pmYep! I saw its reference to Python and literally laughed out loud!QuoteAnd ironically, one of the things people say they like about Python is the availability of off-the-shelf libraries. As if those are a whole new Python invention.I don' t know Python's history but it feels very much like a weekend joke similar to the Whitespace language that got taken WAY too seriously. What unique value does it deliver? Let's see... interpreted language? Yep, those existed before. Importable libraries? Check. Some degree of object orientedness? Bingo. Copies C just enough to shorten the learning curve? Yep, been done. Limits flexibility in an attempt to "protect bad programmers from themselves"? Everywhere these days.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 23, 2020, 09:24:26 pm
content: The history is summed up here:https://en.wikipedia.org/wiki/Python_(programming_language)it's largely influenced by ABC:https://en.wikipedia.org/wiki/ABC_(programming_language)

author: IDEngineer
author_rank: Super Contributor
timestamp: March 23, 2020, 10:29:22 pm
content: Quote from: SiliconWizard on March 23, 2020, 09:24:26 pmWhoa. From TFA:"Python 3.0, released in 2008, was a major revision of the language that is not completely backward-compatible, and much Python 2 code does not run unmodified on Python 3."Just throw most existing code under the bus?!? Yessir, THAT's a "professionally managed platform" that I'd want to use as the basis for commercial projects.NOT.Thanks for citing that article. Every time I think I've encountered the worst aspect of Python, something else surfaces to take the award.EDIT: "Python 2.7's end-of-life date was initially set at 2015 then postponed to 2020 out of concern that a large body of existing code could not easily be forward-ported to Python 3." Darned considerate of 'em, eh?

author: Nominal Animal
author_rank: Super Contributor
timestamp: March 23, 2020, 10:59:28 pm
content: Quote from: IDEngineer on March 23, 2020, 02:50:45 amThere is a difference in using a tool as a hammer, and using it effectively, though.I've seen tons of code written in a language as if it was originally written in another programming language, then filtered through the equivalent of Google Translate. The results are.. well, best deleted.To me, the complaints about Python using indentation for code blocks is similar to complaining about Perl's variable type prefixes ("sigils":$,@,%, and&).I do not believe one has truly understood a programming language until they see the beauty in at least some of its expressions. Even Brainfuck has such beauty; you just need to swivel your brain and viewpoint enough to see it. It is onlythenthat things become truly interesting.

author: ivaylo
author_rank: Frequent Contributor
timestamp: March 24, 2020, 05:12:40 am
content: Yeah, I liked this thread until it turned into a Python bashing party.

author: jfiresto
author_rank: Frequent Contributor
timestamp: March 24, 2020, 02:35:41 pm
content: The bashing has, however, made me better appreciate languages that follow theoff-side rule.So, another favorite: syntax that makes a language look like executable pseudo-code.

author: rstofer
author_rank: Super Contributor
timestamp: March 25, 2020, 03:47:09 pm
content: I kind of like the nested block structure of a language like Pascal where functions or procedures can be local to surrounding functions or procedures.I also like 'sets' as provided by Pascal.Pascal code is simply elegant. Everything else is less elegant.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 25, 2020, 04:10:51 pm
content: Quote from: rstofer on March 25, 2020, 03:47:09 pmMany Pascal derivatives are also just as elegant, like Modula, Oberon... (but those are even more of niche languages than Pascal, so...)Of course we can mention ADA, which also is a niche language (although still used and still evolving) Many find it too intimatiding or something, but it can be pretty elegant too.

author: mrflibble
author_rank: Super Contributor
timestamp: April 01, 2020, 03:12:24 pm
content: Quote from: rstofer on March 25, 2020, 03:47:09 pmI kind of like the nested block structure of a language like Python where functions can be local to surrounding functions.I also like 'sets' as provided by Python, including the various operators acting upon them such as union, intersection, set difference, etc.Quake II Chaos Deathmatch is simply elegant. Everything else is less elegant.<--(*)On a more serious note ... another reason for using sets (in python) as opposed to say lists, is that membership tests are pretty fast (read: hash table).And along the lines of nested functions, parameterized functions are also pretty handy.Code:def parameterized_multiplier(param):def multiply_this(x):return param * xreturn multiply_thismul7 = parameterized_multiplier(7)print(f"Answer to the Ultimate Question of Life, the Universe, and Everything: {mul7(6)}")(*)I would have used bouncy proximity mine emoticons, but for some strange reason this forum does not have them.Oh oh oh! I just thought of a solution for this horrible lack of emoticon problem! Just migrate the forum to Discourse. That should surely solve any and all problems.Not only that, but it should also"improve engagement with younger audiences (???)". Not entirely sure about the requirements for that particular phrase, but as a first order approximation I'll go with.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 01, 2020, 04:01:47 pm
content: Quote from: mrflibble on April 01, 2020, 03:12:24 pmI personally think nested functions/procedures are a bad idea both for code readability and code structure. Wirth himself (the author of Pascal) got rid of them in later derivatives of Pascal, like Oberon.I admit I liked them back when I used Pascal, but I changed my mind over time, just like Wirth did.Modules are a much better way of structuring code and hiding/making things local than nested functions IMO. Unfortunately, modules are still supported only in a very small number of languages, but you can more or less emulate them with almost any language. In C, just declare functions you would otherwise like to nest, static and partition your code in as many source files as required to make code clearer and isolate "helper" functions.One obvious downside of nesting functions is that it makes functions including other functions way too long overall, which hinders readablity. They initially look like a good idea, but you end up realizing they're not.

author: mrflibble
author_rank: Super Contributor
timestamp: April 01, 2020, 05:06:37 pm
content: Quote from: SiliconWizard on April 01, 2020, 04:01:47 pmHeh, I tend to use nested functions precisely where (I think) it will improve code readability. Typically it will be where you have a function that contains doing roughly the same thing a few times. Okay, DRY, so make a separate function out of it. But wait, this new separate function does need an aweful lot of information that is only available within the scope of our existing function (the one we are refactoring). No problem, lets just all pass them as arguments. Sure, you can do that. But it does mean that you now have lines like this:Code:result = nice_non_nested_function(central_bit_of_information_for_this_particular_operation,always_the_same_for_entire_scope_of_original_large_function1,always_the_same_for_entire_scope_of_original_large_function2,always_the_same_for_entire_scope_of_original_large_function3,always_the_same_for_entire_scope_of_original_large_function4,always_the_same_for_entire_scope_of_original_large_function5)I would rather have:Code:result = evil_nested_function(central_bit_of_information_for_this_particular_operation)Because with the latter it is fairly obvious what the central bit of information is for this particular operation.As for modules ... yes, no, maybe. As with everything, it depends. There's a fair chunk of functionality vs code complexity where separating it and stuffing it in a module is overkill IMO. As a general rule, the main thing I use to determine nested vs separate is readibility. If all went well, after refactoring the resulting function containing the nested function should be 1) less lines total, 2) less visually cluttered, 3) have clearer intent.

author: guenthert
author_rank: Frequent Contributor
timestamp: April 21, 2020, 11:37:48 pm
content: Quote from: I wanted a rude username on March 06, 2020, 03:17:42 amI prefer a language which doesn't make the distinction between statement and expression and consequently doesn't need crutches like the ternary operator.

author: SilverSolder
author_rank: Super Contributor
timestamp: April 22, 2020, 12:01:59 am
content: Quote from: SiliconWizard on April 01, 2020, 04:01:47 pmIMHO nested functions look good if the functions are relatively short (a handful of lines), there are not many of them, and they clearly belong only to the scope of the parent. With long functions, the overview disappears and it feels better to encapsulate it some other way.

author: Tepe
author_rank: Frequent Contributor
timestamp: April 22, 2020, 02:08:17 pm
content: Quote from: SiliconWizard on April 01, 2020, 04:01:47 pmFrom the Oberon report: "Since procedures may be declared as local objects too, procedure declarations may be nested."

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 22, 2020, 03:33:53 pm
content: Quote from: Tepe on April 22, 2020, 02:08:17 pmHad to re-read it (latest Oberon-07) and that's right. I can't remember exactly now when Wirth talked about that, but I'm pretty sure I remember him saying they were not a good idea.But I've studied Oberon a while ago and I don't think I've ever run into nested procedures in any code example I've seen, including the Oberon OS itself.Anyway, as I said above, I can't see much benefit for them - they just clutter up functions/procedures, would possibly mess up classic code metrics, and just make your functions too long, which hinders readability.Helper functions can always be declared non-nested in most current languages without having to resort to nesting them. All you need is modularize your code in the best way you can with the features of your language. Even in C, just declare your helper functions static. I do consider that any function that is not "exported" (in C meaning: static, not visible to other compilation units) is an "helper" function anyway. It has no other purpose. The only thing nesting would give you is make said function invisible to the rest of the code in the same compilation unit (from its declaration down to the end of the source file), which is really not that much of an advantage in real life IME.Another point "against" nesting is that it may look like it makes sense to nest some helper function when you write it, but later on said helper function may actually be useful for something else. That's very likely to happen if you write your code as "reusable" as possible, and is actually not "risky" (which nesting would mitigate) if your functions are well documented and well written. So in a way, function nesting would be likely to somehow favor non-reusable code IMHO.Yet another point is the following: the possibility (like with local variables) to "hide" declarations with a similar name, which could lead to confusion, or bugs. I think this is more likely to happen, as if using nested functions, you're likely to give them a shortened name (identifier), with more possibilities of name "clashing" in a larger project.Of course this is very much a coding style question, and there will be as many opinions as there are people, or almost. This was just mine.

author: SilverSolder
author_rank: Super Contributor
timestamp: April 23, 2020, 01:48:09 am
content: You could use a naming scheme for local variables, e.g. lv_Count, lv_Index, etc. etc. to avoid confusion. Nested/local functions could also have a naming scheme. As long as you're consistent, you'll never be confused with variable scope again.

author: boffin
author_rank: Unknown
timestamp: June 18, 2020, 05:48:54 pm
content: Quote from: IDEngineer on March 23, 2020, 10:29:22 pmPretty much like Java which every 18 months comes out with a new revision that breaks all the existing code. This forces enterprise developers to include their own copy of Java in their product so it doesn't happen, but that has security vunl etc etc.DEATH TO JAVA

author: SiliconWizard
author_rank: Super Contributor
timestamp: June 18, 2020, 06:24:57 pm
content: This is one of the reasons for using standardized languages only. You at least get some minimal consistency.

author: tggzzz
author_rank: Super Contributor
timestamp: June 18, 2020, 06:28:49 pm
content: Quote from: boffin on June 18, 2020, 05:48:54 pmExample please. N.B. you wroteJava, so we presume you aren't confusing that with libraries or JVMs.QuoteThey do that for other reasons.It is exactly the same with C/C++; you have to create your code in a VM with a specific compiler version and library version, and always use those forevermore. Why? Because new optimisations and flags are prone to breaking programs that were previously OK.

author: tggzzz
author_rank: Super Contributor
timestamp: June 18, 2020, 06:30:06 pm
content: Quote from: SiliconWizard on June 18, 2020, 06:24:57 pmLike C/C++? Snort!Or at least the "minimal" istoominimal to be trustworthy or of use.

author: SilverSolder
author_rank: Super Contributor
timestamp: June 18, 2020, 06:37:43 pm
content: Quote from: boffin on June 18, 2020, 05:48:54 pmI'm so happy I managed to avoid "falling for" the Java hype originally. I always thought it was too slow, and I had already seen a similar approach fail in the past (the UCSD P-system).

author: IDEngineer
author_rank: Super Contributor
timestamp: June 18, 2020, 07:07:42 pm
content: Quote from: SilverSolder on June 18, 2020, 06:37:43 pmI managed to avoid it until I had to write code for the Android platform. Tablets make incredibly convenient control panels for all sorts of things, and (at the time, maybe still) Apple would not give you access to the communication port without a license that I seem to recall cost $25K. Plus Android tablets use standard USB which was a big plus. So I started working with Java to write human interfaces on Android tablets. Worked fine, but having to navigate Java's various minefields was a nightmare. Like C++, it felt like someone just covered a language with a layer of Object Orientedness because it was fashionable.As a side note, Java was NOT the worst part of that experience. I discovered a bug in the Android OS associated with USB connections. Briefly, the OS didn't properly handle physical disconnects and didn't report them to the application. It was impossible to authoritatively know if the remote device had simply stopped communicating or had physically decoupled. I brought it to the attention of the core devs, and it got lots of upvotes by others to be corrected ASAP. I and many others even added comments showing the (literally) one line of code necessary to clean it up. Yet to my knowledge it's still unfixed to this day. This was back in ~2014! Grrrrr.

author: tggzzz
author_rank: Super Contributor
timestamp: June 18, 2020, 07:31:35 pm
content: Quote from: SilverSolder on June 18, 2020, 06:37:43 pmThat's a common misapprehension for those that don't realise the progress that has been made in the past decades. Of course, the easiest course of (in)action is usually to avoid learning how to use a tool effectively.When I last used Java to replace a telecoms C/C++ application, onlookers were gobsmacked at how much faster my Java code executed. All that was needed was imagination, and the understanding that comes from an enquiring mind plus experience. Example... They struggle to comprehend why a C/C++ program running in anemulatedprocessor can run as fast as the same program running on theunemulatedprocessor. Those same techniques are used in HotSpot. That was only published 21 years ago, so it is a little too recent for people to have noticed. Isn't it?! FFIhttps://www.hpl.hp.com/techreports/1999/HPL-1999-78.html

author: IDEngineer
author_rank: Super Contributor
timestamp: June 18, 2020, 07:55:18 pm
content: Quote from: tggzzz on June 18, 2020, 07:31:35 pmThat's what I've told my 18YO sophomore son at CalPoly. Architecture iscruciallyimportant. A good environment can be crippled by bad architecture, but good architecture can often compensate for a poor environment. True in hardware AND software.

author: Siwastaja
author_rank: Super Contributor
timestamp: June 18, 2020, 08:22:59 pm
content: Quote from: tggzzz on June 18, 2020, 06:28:49 pmSeeing you "have" to do that using such absolute terms is a sign you are likely working either in very incompetent teams, or doing something out of ordinary with external requirements for such practices. Or just have no idea how the C/C++ software development world actually runs.After all, I'm quite certain 99% of the "the different compiler version broke my C program" problems are caused by very actual and real bugs in the code, relying on undefined or implementation-defined behavior the programmer didn't understand or even consider when writing it. Which is completely understandable, we all make mistakes, but the key to reducing mistakes is to look for the root cause and learn from it, not to hide it by preventing the detection of said bug.Portable (across compilers and exact standard library versions; even across CPU architectures) POSIX C code is being written and maintained every day. Bugs that are being hidden with one (standard-compliant) compiler, then revealed with another (standard-compliant) compiler do happen, we are humans after all, but they are almost meaningless, minuscule portion of total bugs the developers need to deal with, and definitely no absolute showstoppers. Even bugs caused by abuggy compilerdo happen, although much more rarely than an average developer wants to believe.Yes, I agree such total version lockdowns and virtual machines to prevent such breakage aresometimesneeded, but that is really a very sucky way to do it, and claiming that you absolutelyneedto lock to exact versionsforeveronly shows you have no idea what you are talking about, and are just screaming "I can't do this, I give up!" Extraordinary claims require extraordinary evidence; clearly most of the world being run on C code being compiled on varying compiler and C standard library versions is "the wrong way to do it". Yet this is how it works, and majority of bugs that cause actual damage could not have been prevented by locking down to specific tool versions.Bugs willalwayshappen, and sidestepping the issues caused by different compiler versions will only help with those types of bugs, which are a stunningly small percentage of total bugs. Quite the opposite; if you test your software (using proper automated test suites, yeah?) in different environments, with different compilers, you are likely to catchmorebugs, instead of hiding them by limiting to one compiler.After all, porting to a new environment, or reusing part of your code in another project, compiled on a different compiler, will likely eventually happen. Your code isworth morewhen it's portable, reusable, and relatively bug-free, not some write-once kludge for one forever-locked environment.And think about this: what if you have a difficult-to-reproduce bug that appears with 1% probability with compiler A, but with 100% probability with compiler B? Was locking down to compiler A the right thing? Was this choice really adding robustness to your project, or was it just an excuse to keep producing buggy code?

author: tggzzz
author_rank: Super Contributor
timestamp: June 18, 2020, 08:29:43 pm
content: Quote from: IDEngineer on June 18, 2020, 07:55:18 pmYes, precisely.The question then becomes whether one core technology helps or hinders radically different architectures.Even as late as 2005, Hans Boehm (he of the "usually gets it right" C/C++ GC) found it necessary to point out that in C "Threads Cannot be Implemented as a Library". Remarkably many practitioners were ignorant of that, despite it being the case since K&R days! FFIhttp://www.hpl.hp.com/techreports/2004/HPL-2004-209.pdf

author: tggzzz
author_rank: Super Contributor
timestamp: June 18, 2020, 08:52:00 pm
content: Quote from: Siwastaja on June 18, 2020, 08:22:59 pmHaving been programming in C since 1982, I have a good idea of how it runs - and falls flat on its face.QuoteIn one sense, that used by language lawyers, that is a correct answer - but to an unimportant question.The important questions arehow many and what proportion of C programmers understand the language well enough to avoidallnasal dæmons. The answer to that is simple: only a vanishingly small proportionhow many programs in production contain UB, and could therefore "rm -rf /" when used with the next version of the compiler. Again, the answer is simple: too many and far more than people believeFor examples, nip over to the usenet group comp.arch and have a look at the ongoing "UB and C" thread. There you will seeextremelycompetent and experienced people discussing the difficulties.QuoteAnd there you gloss over the problem you are attempting to address. It isn't just "another compiler", the problems can appear with the nextversionof thesamecompiler, classically when the next version contains new optimisations.And that is why it is prudent to nail down the compiler and library in a VM.Please don't make claims to the effect that "testing will uncover problems", or "if it passes the tests then it is working". Or rather, if you do then please provide a test suite thatprovesan in-memory database has ACID properties given multiple processors accessing it simultaneously.Quote"Most of the world doesn't do it" proves nothing, of course. Most of the world doesn't have access to decent sanitation and drinking water!QuoteWriting a good test suite ismoredifficult than writing the program itself.At best a test shows that a bug exists; so what! The next bug will be due to something you didn't test, recursively!Too many of the test suites I've come across are incompetent, and are little more than fig-leaves to make itlooklike the code is being tested. That's language independent, unfortunately.QuoteI'm not sure what point you are trying to make there.

author: SilverSolder
author_rank: Super Contributor
timestamp: June 18, 2020, 08:54:45 pm
content: Quote from: tggzzz on June 18, 2020, 07:31:35 pmMy bad experiences might have been bad code / older Java implementations, fair enough. I had the team re-write everything in C++ and all the problems disappeared... only to be replaced by new problems, obviously, but that's life!

author: tggzzz
author_rank: Super Contributor
timestamp: June 18, 2020, 09:04:51 pm
content: Quote from: SilverSolder on June 18, 2020, 08:54:45 pmAs they say, you can write Fortran in any language! My attitude to C/C++ is that the tools (and many applications!) have become castles built on sand, and hence become part of the problem, rather than part of the solution.Java has its own set of problems, to be sure. But it avoids many of the problems found in C/C++, and allows me to concentrate on finding interesting problems that are related to my application.It will be interesting to see whether Go and Rust have similar benefits.

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: June 18, 2020, 09:51:11 pm
content: I like:-closures-dynamic typing-nested functions-async/await-event loops-the (function () {})(); form-the C syntax-JSON-impure functional=> I like JavaScriptThere's a problem though: it lets you build objects in a zillion different ways => there's no easy way for an IDE to keep track (static analysis) of what objects there are, what properties and methods they have (or not), the hierarchy, and makes it difficult to interoperate with other peoples' code/libraries. Most of which is solved by TypeScript. => I like TypeScript better (a superset that compiles to JS).

author: SilverSolder
author_rank: Super Contributor
timestamp: June 18, 2020, 11:03:48 pm
content: Quote from: GeorgeOfTheJungle on June 18, 2020, 09:51:11 pmIs TypeScript the one that was designed by Anders Hejlsberg? - he has done a lot of good work in the software industry (e.g. Delphi, C Sharp)

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: June 18, 2020, 11:21:08 pm
content: Quote from: SilverSolder on June 18, 2020, 11:03:48 pmYes..https://channel9.msdn.com/Events/Build/2017/B8088/

author: tggzzz
author_rank: Super Contributor
timestamp: June 19, 2020, 12:07:42 pm
content: Quote from: tggzzz on June 18, 2020, 08:52:00 pmHere's today's examples from a different thread in comp.arch; you may recognise the authorI'veveryheavily snipped it to highlight the relevance to the above point; don't complain to David! For full context, have a look at the original.Re:  Anton Ertl has been proven rightOn 19/06/20 12:16, David Brown wrote:> Here are a couple of references that could be of interest here:>> <https://devblogs.microsoft.com/cppblog/new-code-optimizer/>>> That is an MSVC developer blog saying that their new (in 2016) optimiser> "takes advantage of signed integer overflow being undefined". It> mentions an /undocumented/ compiler flag "d2UndefIntOverflow" to disable> this behaviour (undocumented means you can try it, but it is not> guaranteed to work as you think or to remain available in later compilers).Now, what action do you suggest ispracticaland sufficient to defend against that kind of thing?> Here is a feature request from an MSVC user for type-based alias> analysis to give more efficient code:>> <https://developercommunity.visualstudio.com/idea/513950/structure-usage-is-not-optimized-by-compiler.html>>> The second last comment, by an MSVC developer (AFAICS) says:>> """.......> This is a feature we might consider implementing if there is enough> support in the community for it.> """>> Read that last line. Read it again, and then a third time.......> From the final comment in that post, you can see that people are> sceptical that introducing strict aliasing will cause trouble for> existing C and C++ code written for MSVC, and thus such a change should> require explicit enabling.Again, given that we live on planet earth (not in nirvana), what is your recommendedpracticalcourse of action?

author: Siwastaja
author_rank: Super Contributor
timestamp: June 19, 2020, 12:27:28 pm
content: Practical course of action is accepting that the world isn't perfect, bugs happen, theyneedto be dealt with properly; and that the fact C standard leaves some thingsimplementation-definedprobably wasn't the best idea, but all in all, we can deal with this, and very few will find this a showstopper.Going even more practical, this means: treat the bugs caused by C UB or implementation-defined behaviorlike any other bugs: analyze for root cause, fix your code not to rely on nasal daemons. Learn, and write better code in the future. In very rare cases of compiler bugs, communicate with the compiler team.This is wildly related to the SiliconWizard's original remark of getting "at least some minimal consistency" with "standardized languages". C fits that bill just right: bugs caused by problems in standardization and hence differences in (all standard-compliant) compiler versions happen and are widely documented, but arerare enough, and OTOH,well documented enoughnot to matter too much.Perfect is the enemy of good.The very practical thingyoucan do is to learn these pitfalls and start writing code that does not rely on undefined or implementation-defined behavior. Your bug-free, portable, reusable code ismore valuablethan your locked-down kludge that was verified to work once in 1985.See linux kernel for example, it's being compiled with new GCC versionsall the time. In it's history, there have been a handful of problems due to this, but the linux kernel is fairly reliable and staying modern, is powering most of this modern world (like it or not), handling very critical and important tasks as well.Even if we lived in a magical world where this issue wouldn't exist, the number of bugs would be approximately the same, maybe 1% less.The processfor dealing with bugs would beexactlythe same.OTOH, you propose a solution where there exists two processes for bugs, the "normal" process for most bugs, and then the "lock down development environment to hide some UB bugs by preventing them popping up" version regarding the bugs caused by writing non-standard-compliant code. Call this strawman if you want to, but this isessentiallywhat you propose, and it sounds so bad because it is so bad.This is analogous to the comment I remember seeing from Linus Torvalds regarding the stupidity of handling "normal bugs" and "security bugs" so differently, while in reality, it's a made-up line. You can have higher-priority and lower-priority bugs, but you deal with them the same way.Lockdown to a particular compiler version and toolset environment could be warranted for a life support device, for example. Even then, I wouldn't suggest doing that choice prematurely. And in such projects, writing unambiguous and standard-compliant code to begin with becomes increasingly important! But such projects must be verified to be safe on the binary level, and you just don't go and make small changes to the codebase without verifying the binaries.We all can probably agree we would like to have something that completely fixes problems of the C language, but giving up and requiring silly coping methods like "always lock down your development tool versions totally" is making thingsworse, not better.

author: tggzzz
author_rank: Super Contributor
timestamp: June 19, 2020, 01:25:20 pm
content: Quote from: Siwastaja on June 19, 2020, 12:27:28 pmHow precisely do you achieve that in the real world with reasonable quality programmers. Assume there is no unexpected behaviour withtoday'scompiler. Butnext yearscompiler, with the new and undocumented work-around flags, causes the behaviour tobecomeunexpected.That's an example of why people "archive" the build environment in a VM or, deity help them, in Rational Clearcase.QuoteAs illustrated above, a standardised language is insufficient.If correctness doesn't matter "too much" then I can develop code arbitrarily fastQuoteIn the real world, that is nirvana. If you listen to those with a lot of experience and knowledge of the subject, you will find them saying how difficult that is - to the point of them presuming that any arbitrary program will have UB somewhere.QuoteIt is the practical solution to having code continue to work. It isn't nice, it isn't good, but it is practical and it works.I'm still waiting for someone to suggest something else that can bepredictedtoworkinreal-worldsituations.QuoteI have written code that could kill people, even if it is worklng correctly and to specification!The phrase "verifying the binaries" is a red flag statement. Example: do please tell us how to verify that a multithread/multicore/multicomputer database application doesn't violate ACID guarantees.QuoteHow is it making things worse?

author: SilverSolder
author_rank: Super Contributor
timestamp: June 19, 2020, 01:53:27 pm
content: Quote from: Siwastaja on June 19, 2020, 12:27:28 pmIf you think about it, this feeds back to the compiler writers too, i.e. the toolchain makers respond to how the tools are used, so we end up with both better products and better tools.It is never a good idea to let things stagnate - software, hardware, or even life in general.

author: rstofer
author_rank: Super Contributor
timestamp: June 19, 2020, 10:43:25 pm
content: It always seemed to me that nested functions fit cleanly into Wirth's Syntax Diagrams and the recursive descent approach of the Pascal compiler. The code looked a lot like the diagram.Another language feature I like(d) is from COBOLMOVE CORRESPONDING identifier-1 TO identifier-2Moves identically named fields of record identifier-1 to the fields of record identifier-2

author: golden_labels
author_rank: Super Contributor
timestamp: June 20, 2020, 04:17:11 am
content: I wonder, why are people so often choosing to depict the interaction between UBs and optimization in C in a manner that suggests compiler designers are intentionally breaking programs. It’s ridiculous. :/It’s basically like not reading a datasheet, not knowing maximum ratings, applying 300V to a 3.3V chip and crying that the IC designers are stupid, because they should’ve made their device working up to 1000V and making it PITA for everyone else.While there are cases in which it goes another way, most often the reasoning is not: find potential UB → use it to remove some code. It is: find a possible optimization → check if it works for all cases → if there are any UB cases, ignore them. What else do you people expect? That optimizations will be ruined for everyone just because there are people, who don’t care enough to learn and understand the language? Or that compiler creators will spend their time identifying each UB, determining what’s the “sane behaviour” for what is meaningless in the first place, and spending resources of maintaining the code? And making it more complex, as if it wasn’t a monstrum yet? Sure, putting guards like that everywhere is not insane, but it’s not free and I do not see people lining up to pay for it.

author: SilverSolder
author_rank: Super Contributor
timestamp: June 20, 2020, 04:44:35 am
content: Quote from: rstofer on June 19, 2020, 10:43:25 pmIf you think about the alternative... placing the nested sub-function outside the scope of the function that actually uses it... that is a less "clean" solution (less encapsulation) and doesn't convey the design intent in the same way. Of course, nested functions can be overdone and if they get too long, it's time to reconsider what's going on.

author: tggzzz
author_rank: Super Contributor
timestamp: June 20, 2020, 07:16:47 am
content: Quote from: golden_labels on June 20, 2020, 04:17:11 amThat would indeed be a ridiculous depiction!However, in order continue to have competitive products (as permicrobenchmarks), theyareinterpreting the language specsmore aggressively and, when a problem happens to be noticed, saying "tough, we know the language, you don't, your problem".Actually the users problem should not be the language, it is understanding the application domain and creating a program that solves the problem in that domain. If you add (new) problems in the tool then you have increased the users problems: the language has become part of the problem rather than part of the solution.QuoteAnalogies are always dangerousA better analogy (which hits people in practice) would be trying to find a replacement for an old deceased 2N3055 power transistor, only to find that the circuit now oscillates. Why? Because the modern device's ftis much higher.QuoteIn many cases it is not evenpossibleto uniquely define "sane behaviour"!The point is that it is sufficient that the behaviour doesn't radically change over time. The practical way toensurethat is to preserve the toolchain in a VM, or similar.

author: ozcar
author_rank: Frequent Contributor
timestamp: June 20, 2020, 07:33:56 am
content: Quote from: rstofer on June 19, 2020, 10:43:25 pmOne language feature I will never forget is Cobol OCCURS DEPENDING ON.But I remember it only because because of a bug that IBM had in around 1997, which caused us a fair bit of angst, so it was not a favourite of mine at that time.

author: Feynman
author_rank: Regular Contributor
timestamp: June 22, 2020, 10:05:29 pm
content: The first things that came to my mind were operator overloading (e.g. C++) and negative array indexing (e.g. python).

author: Mattjd
author_rank: Regular Contributor
timestamp: June 25, 2020, 11:49:46 pm
content: Quote from: jfiresto on March 23, 2020, 04:17:01 pmMy biggest grief with python is that the interpreter seems to have a hard time with closing parenthesis. Many, many times I've missed a closing parenthesis, only for the interpreter to throw a fit at the next line under, saying that is invalid. When in fact that line is completely valid, its just getting picked up as an argument being passing in those un-closed parenthesis. I've scratched my head at that many times, not realizing the issue. Finally resolving it after a few minutes.My favorite has to be comprehensions and duck typing.So yeah, python.Negative indexing is nice too.Other than that, one of my all time favorites is broadcasting (as in numpy vector broadcasting) or implicit binary singleton expansion (as matlab calls it). Used to be called bsxfun() now you can just do A.*B' where A is a row vector and B is a transposed row vector (aka column) this creates a matrix.https://blogs.mathworks.com/loren/2016/10/24/matlab-arithmetic-expands-in-r2016b/edit: Oh I forgot, modules. Modules and nested modules are amazing as is aliasing of imports. #include and header macro guards are evil.We've been fucked over at work a few times because of include-guard namespaces being taken up at some earlier time of compilation and then left wondering why this other header file (with unfortunately the SAME include-guard name) isn't being included. This isn't some small program either. Its simulation code for a system thats going to be used on a naval ship. Lots of cogwheels.

author: Mattjd
author_rank: Regular Contributor
timestamp: June 26, 2020, 12:02:30 am
content: Quote from: IDEngineer on March 23, 2020, 05:32:31 pmGuess Guido and the team are just a bunch of idiots that most of FAANG and the world fell for.Ironically, the case for eliminating block delimiters, to my understanding, is the one you thing you are griping about - readability of others code. The idea was to remove the fuss of the nine different brace indentation variants found herehttps://en.wikipedia.org/wiki/Indentation_styleIn my opinion, they succeeded. You go onto any repo and everything looks practically the same.As far as one developer using tabs vs 3 spaces vs 2 spaces. Is replacing tabs with spaces really that difficult? Literally in vim command modeCode:%s/\t/ /g

author: westfw
author_rank: Super Contributor
timestamp: July 07, 2020, 06:45:04 am
content: In general, I'm against using "cute" but relatively rare language features...I did like the assembler macros that could:recurse.define other assembler macros.repeat sections per character of the argument.(You know, in general I miss the sort of advanced macro capabilities that most assemblers had, in higher-level languages...)

author: brucehoult
author_rank: Super Contributor
timestamp: July 07, 2020, 07:20:02 am
content: Generic Functions aka Multiple DispatchPresent in Common LISP, Dylan. Has been talked about for a long time in Python, but never implemented :-(Lets you do OO (i.e. runtime selection of the operation based on the data type) programming without either having functions "inside" classes (C++/Java/most others) or having type switch/case/match statements inside functions (Haskell/ML/Caml).

author: Chris42
author_rank: Contributor
timestamp: July 09, 2020, 04:42:55 pm
content: By language:Python:Portability. I can write a program and it will run on any machine that can run python interpreter. This is the best feature of this language. No more recompiling for some fancy new architecture!C:Very simple and elegant. You can learn all syntaxes in 2 weeks. The rest is standard library.C++:Smart pointers. They really simplify resource management.Java:Garbage collector.VBA:It has IP protection built in. Your code will be so horrible that no one will want to steal it.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 09, 2020, 04:58:14 pm
content: Note that you can replace the standard allocator with a garbage collector in C and C++ if you like that. A well known, and relatively well-behaved one is the Boehm GC:https://www.hboehm.info/gc/

author: tggzzz
author_rank: Super Contributor
timestamp: July 09, 2020, 05:05:59 pm
content: Quote from: SiliconWizard on July 09, 2020, 04:58:14 pmIt makes a good attempt at reclaiming most garbage in programs that match its limitations.Scarcely general purpose.

author: tggzzz
author_rank: Super Contributor
timestamp: July 09, 2020, 05:11:48 pm
content: Quote from: Chris42 on July 09, 2020, 04:42:55 pmDitto Java, of course.QuoteFor some definition of "learn" and "weeks". The latter can be compared with the earth being created in 7 days.QuoteThey get you halfway towards the equivalent features in modern languages.QuotePlural. Choose the right GC for your application.QuoteAgreed

author: brucehoult
author_rank: Super Contributor
timestamp: July 10, 2020, 08:06:54 am
content: Quote from: tggzzz on July 09, 2020, 05:05:59 pmI've not seen it fail in any significant way. A number of programming languages use Boehm as their GC -- and many others *should*. For example Mono (open source C#) did for a long time -- they eventually wrote their own GC and it is the only example I know of where replacing Boehm by a custom GC improved performance.On many or most C/C++ programs you can improve performance significantly (at the cost of a relatively minor increase in RAM usage) by compiling Boehm so that malloc becomes GC_malloc() and free() becomes a no-op and using LD_PRELOAD to replace the malloc() and free() in glibc.

author: tggzzz
author_rank: Super Contributor
timestamp: July 10, 2020, 08:45:18 am
content: Quote from: brucehoult on July 10, 2020, 08:06:54 amI'm more interested in correctness than performance. After all, if it is permissible that my code can contain faults, I can increase performance by orders of magnitudeIt can be the devil's own job demonstrating that a GC is at fault.I have no idea how closely Mono took account of Boehm's GC's limitations.QuotePresumably until garbage is collected!I haven't looked at the topic for alongtime. What are the Boehm's GC's characteristics on SMP systems and/or with highly threaded code?

author: brucehoult
author_rank: Super Contributor
timestamp: July 11, 2020, 01:22:59 am
content: Quote from: tggzzz on July 10, 2020, 08:45:18 amIt's amazing how many programs have use-after-free bugs. They just get lucky because the same memory chunk hasn't been reallocated yet. GC makes that impossible -- indeed Boehm can help you find those.Even more programs simply stop using objects (and nothing points to them) without freeing them. That is probably *the* major reason why you have to restart your web browser, Windows, your WIFI router etc on a regular basis. GC prevents that.Note that while in theory conservative GC can fail to collect some objects, Hans Boehm has a paper that shows that this effect is bounded -- it's extremely unlikely to cause OOM in the way that memory leaks with malloc/free do."Smart" pointers in C++ are just a PITFA to use. They clutter the code and drastically reduce its clarity -- and then people *still* make mistakes.QuoteIncluding GCs of course. I'm talking about 10% to 100% more memory use than with the original malloc/free library. A big benefit of GC is you can tune your program to get the speed/memory use tradeoff you want (e.g. using the GC_FREE_SPACE_DIVISOR environment variable in Boehm)If you simply disable free() while keeping standard malloc() then programs will work and will run fast, right up until they run out of memory. I've tried this in a professional setting. For example disabling free() during one LLVM optimization pass on one function and then releasing all the memory at the end in one hit can make sense -- it will probably use 5 MB. Disabling free() entirely in LLVM (or gcc, I've tried both) works OK for very small programs but for anything non-trivial you quickly find the compiler using tens or hundreds of GB of RAM.Simply disabling free() on long running programs such as servers is completely impossible, of course.QuoteIt's excellent for throughput-oriented tasks i.e. "how long does the program take to finish?" Each thread gets its own pool of space for new objects, so there is essentially no allocation contention between threads. When a GC is needed all threads are stopped during marking -- but all CPU cores are used for the marking. To whatever extent app threads were allocating private objects there is no contention between marker threads, but they are free to follow pointers to "other threads" object graphs as needed.This "world stopped" marking is usually very fast. A few ms or even less.Boehm always does the sweep phase incrementally. Each page of objects of a particular size (normally the same as a VM page) is swept at the moment that the first new object is about to be allocated from that page. That is, the mark bits for that page are scanned and any unmarked objects are added to the start of the free list for objects of that size (and the first one will be allocated immediately). Succeeding objects of that size allocated by the same app thread will be from that same memory page until the page is full.All these features have been in Boehm since .. at least around 1995-2000 when I started to learn its deep innards and use it extensively. (I'm probably ranked pretty close after Hans Boehm and the long time official maintainer Ivan Maidansky in knowledge of the current innards of Boehm -- Ivan hired me to work with him at Samsung R&D Institute Russia in 2015 based largely on my GC knowledge and experience)In 2005-2008 I worked for a tiny company writing a Java native compiler for BREW mobile phones. One of my main tasks was modifying Boehm GC to run well on 1 MHz ARM machines with as little as 400 K of RAM (though 1 to 2 MB was more common). The vast majority of the users were porting games from Java phones to BREW, though there was the occasional medical or industrial app. We ported the same system to iPhone (before there was an SDK and you had to jailbreak and hack everything yourself) and a number of games and other apps early in the AppStore were actually written in (native compiled) Java. Apple never noticed and some e.g. Virtual Villagers were in the top 20 iPhone games for ages.

author: tggzzz
author_rank: Super Contributor
timestamp: July 11, 2020, 08:21:18 am
content: Quote from: brucehoult on July 11, 2020, 01:22:59 amYes to all of that, especially the smart pointers and "lost" objects.However, the effects of lost objects are also be found in GC environments - but those are due to unwittingly retaining a handle to the objects. Many people refer to those as "memory leaks", but I think "data cancer" is a better characterisation.QuoteUnderstood and accepted.My primary interests have been in server applications and long-running desktop applications. The short-duration embarassingly-parallel compilation you mention is an important use case, but uninteresting to me.QuoteTo be picky, that is multithreaded. Does it also apply when the threads are spread over multiple cores?QuoteNiceCompiled Java has sufficient and well-defined information about the objects available at runtime. I could regard that as an application which can fit in with Boehm's limitations. It isn't an arbitrary C/C+ program with unconstrained (and probably UB) access to random bytes.

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 11, 2020, 03:10:12 pm
content: For long-lived processes, I like to use a pooled allocator.(The locality of the allocations is not important at all. The simplest implementation is one that adds a single pointer to each allocation, so that allocations within a "pool" form a singly-linked list. Some use cases can benefit from having the "pools" form a tree as well, so that if an error occurs at a higher conceptual level, all dependent pools can be destroyed at once. Instead of freeing individual allocations, you free an entire pool (including its sub-pools). This is surprisingly robust, and the only "problem" is that you sometimes need to extract or copy individual allocations from one pool to another, when they need to outlive the pool.)I've written some BLAS/LAPACK style code in C for linear algebra (matrices), using reference counting for the actual data in the matrices (so that all matrices are "views" to data, and multiple matrices can refer to the same data, for example transposed, or say a row or column vector, or even a diagonal vector), but that still relies on users explicitly destroying the matrices when they're done. Using a pool-based allocator, a large numerical task could simply use a local pool (under the pool for the overarching task at hand), and simply move the final result matrices to the parent pool, and free all others in the local pool. Much simpler, especially in error conditions.What I've often wondered about, is the lack of native pool allocation facilities -- and even good pool allocator libraries. I don't particularly likeAPR; while it works well for Apache, I don't think it is a good match for general service-type cases.Garbage collection has been investigated very deeply (the articles, proofs, and implementations are actually quite impressive, even though I don't like to use GC myself), but I don't think I've seen pool allocators used outside of Apache and maybe a couple of other projects I've already forgotten about.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 11, 2020, 04:28:56 pm
content: Quote from: brucehoult on July 10, 2020, 08:06:54 amI mostly agree with that. If someone is claiming the Boehm GC is flawed, please at least give details, and accurate facts and figures about it. It has been widely used indeed.Note that I was merely pointing out an option for those that would be dead sure you can't have a GC with C or C++. I was not particularly advocating using one, as GCs have specific issues (however good they are) that you don't necessarily want to have to deal with, such as non-predictable execution times. I am also not 100% convinced about garbage collecting in general - it naturally leads to sloppy resource management. You may argue that it will almost always do a better job than even careful "manual" resource management, and I wouldn't necessarily disagree in the general case, but I'm still not sure it promotes completely healthy programming habits, or that it's even the best way of dealing with "automatic" resource (memory) management.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 11, 2020, 04:37:15 pm
content: Quote from: Nominal Animal on July 11, 2020, 03:10:12 pmI've used this approach quite a bit as well. I like it.Quote from: Nominal Animal on July 11, 2020, 03:10:12 pmThat may be a bit off-topic here, but related. That makes me think of the implementation of linked lists, and trees in general.Except back when I was studying, because it was textbook stuff, I have rarely implemented those with a lot of small (thus very fragmented) allocations linked with pointers. Even with good allocators, it eventually tends to fragment memory a lot and have bad locality properties, which is pretty bad for caches. I usually allocate largish chunks of memory and handle objects in it with indexing. In many cases, this is quite effective and the resulting performance is often very largely better. This is a form of pooling. Then when the pool becomes full, I reallocate a larger one (with a large increment depending on the application). Of course in some very specific cases, it would not be that good, but overall it has proven very effective.

author: guenthert
author_rank: Frequent Contributor
timestamp: July 11, 2020, 05:01:22 pm
content: Not necessarily my favorite feature, but one which I occasionally miss dearly in lesser languages:keywords (symbols which evaluate to themselves) as found in Common Lisp.There seem to be only cumbersome and ugly solutions in C/C++ when one wants e.g. string representations of enums. A common recommendation is to maintain a separate file with the definitions from which the C/C++ code is generated using a script ...Comparing C++ with Common Lisp might not be all that fruitful, but C++ is really an unnecessarily ugly duckling. One needs to look only as far as Nim to see, what C++ could have become.

author: Ed.Kloonk
author_rank: Super Contributor
timestamp: July 11, 2020, 05:08:57 pm
content: The feature I like most about Basic is that it just. wont. die.

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 11, 2020, 05:53:41 pm
content: Quote from: SiliconWizard on July 11, 2020, 04:37:15 pmTrue, that's why I said it was just thesimplestimplementation.Memory allocation strategies themselves are a very complex topic, especially when you move from a single continuous heap (Csbrk()style) to obtaining and returning arbitrary pages back to the OS (POSIX C anonymousmmap()style). For pooled allocators, the discontinuous/page approach is not only easier, but when entire pools are discarded, the memory used can immediately be returned to the kernel, too; and fragmentation is much easier to avoid.The main benefit of pooled allocators is that it makes it easier to write code that does not leak memory, because the developer does not need to track each individual allocation, and can instead treat them assets. Using a newsetfor each complex task means the programmer only needs to remember to discard theset, not each and every allocation individually.Quote from: SiliconWizard on July 11, 2020, 04:37:15 pmYes, and that is exactly how and why Python NumPy implements its own array type, for example. I myself also use this in C a lot; so often that I no longer even think about it. (I worry more about the names of the variables/members; I like to useusedfor the number of elements currently in use, andsizefor the number of elements allocated for the area, with oftendataas the pointer to the area.. it soothes my OCD, I guess, but some people have found such names unintuitive.)When I wrote above "the locality of the allocations is not important at all", I tried to express that I am not talking about that form of pooling – which is common, but done on the "user" or "application side", with the application developer managing the pool –, but having dynamic memory management where each allocation always belongs to a pool. For example, in C, you'd havemalloc(pool, size),calloc(pool, size, count),free_all(pool),new_pool(parent_pool), and so on. (Logically, theNULLpool, the default pool, would usually have the same lifetime as the process.)I did not mean that data locality isn't important in general. It is, for efficiency and other reasons. I just wanted to try and highlight the usefulness of the other aspects of pooled memory management.(SiliconWizard, I do believe you know perfectly well all I wrote in this post already; I only wrote this in the hopes that it helps others understand this too.)

author: tggzzz
author_rank: Super Contributor
timestamp: July 11, 2020, 07:56:03 pm
content: Quote from: SiliconWizard on July 11, 2020, 04:28:56 pmHans Boehm was completely open about what it couldn't do. Apply those to arbitrary programs composed of components (e.g. libraries!) produced by peoplenotworking together. Then try to ensure correct operation.If there is a strict control of all code in a particular environment (e.g. Apple's) then it becomes less intractible - although still difficult and somewhat limited.QuoteYou sound as if you think people are claiming GC is a silver bullet, which would be stupid.Nonetheless GC removes a whole host of traditional problems, thus enabling more complex systems to be rapidly constructedand work. Naturally people will overuse that capability without exhibiting any "good taste"; such is life.I'll never forget the first time I looked at the Java standard libraries in 1996, and saw that they had effortlessly produced that which had eluded C++ for adecade- and gone far beyond. At that stage there wasn't a C++ string class, and there were endless (well, year-long at least) debates about what "const"oughtto mean.

author: brucehoult
author_rank: Super Contributor
timestamp: July 12, 2020, 02:05:41 am
content: Quote from: guenthert on July 11, 2020, 05:01:22 pmThis seems to be mixing up two distinct things: 1) the concept of "symbol", and 2) converting bidirectionally between symbols and human-readable strings.Many applications of symbols don't require conversion to strings and very very few require conversion from strings to symbols.Lisp symbols are *not* enums. They don't have sequential or even well-defined values. Normally they are simply the memory address of some object. It doesn't even matter what the type of the object is. This easy to do in C and the linker will ensure that non-static objects with the same name used in different compilations will end up with the same address.Make one file...Code:typedef void* Symbol;Symbol square, circle;float area(Symbol shape, float sz) {if (shape == &square) return sz * sz;if (shape == &circle) return 3.14/4 * sz * sz;return 0.0;}... and another ...Code:#include <stdio.h>typedef void* Symbol;Symbol circle;float area(Symbol shape, float sz);void main() {printf("Area = %f\n", area(&circle, 20.0));}Compile them, link them, run, and the output will be "Area = 314.000000"(I've done one very slightly naughty thing here, punning void* and void** but never mind)It's a bit sad that C "switch" won't work with pointers, but that's only syntax.You can somewhere -- anywhere -- in yet another file if you want, put:Code:Symbol square="square", circle="circle";Everything will work just as before.And then you could modify the area function with some debug...Code:float area(Symbol shape, float sz) {float res;if (shape == &square) res = sz * sz;if (shape == &circle) res = 3.14/4 * sz * sz;printf("calculating area(%s, %f) = %f\n", *(char**)shape, sz, res);return res;}Now the output is:Code:calculating area(circle, 20.000000) = 314.000000Area = 314.000000You can of course hide the casting for the SYMBOL->STRING conversion behind a macro or function.This covers about 90% of the rest of the usual Lisp/Scheme use of symbols.To handle runtime uses of STRING->SYMBOL (which is *pretty* unusual in practice) you need to set up some kind of runtime search -- a linked list or binary tree or hash table or something.Common Lisp (and Emacs Lisp) also use symbols to hold property lists. To handle this you just make the Symbol not be a simple void*/char* but a struct holding both a pointer to the name and a pointer to the first item in the property list (which traditionally are actual linked lists).

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: July 12, 2020, 09:42:08 am
content: Quote from: tggzzz on July 11, 2020, 07:56:03 pmStrings alone are enough reason to switch from C to C++, if you ask me. Anybody who's ever had to deal with lots of strings in C will immediately fall in love with automatic String objects.

author: tggzzz
author_rank: Super Contributor
timestamp: July 12, 2020, 02:43:24 pm
content: Quote from: GeorgeOfTheJungle on July 12, 2020, 09:42:08 amStrings are relatively simple and low-hanging fruit, useful only to illustrate the snail-like progress in C++.I'd been using plain-vanilla generic containers (sets, bags, dictionaries, linked lists) in multiple languages since the mid 80s. The lack of those in C++ was a major impediment to programming quickly and correctly.The continual hacked-together erzatz variations of containers in every C++ project reminded me of the 1970s, when new recruits were told to develop the power supply for a project. The PSU wasalwaysa problem area in such projects, ditto crap containers in C++.Also C/C++ finally decided that it needed new language features for multicore processors,decadesafter other languages had known thatandimplemented it successfully.

author: guenthert
author_rank: Frequent Contributor
timestamp: July 12, 2020, 05:44:41 pm
content: Quote from: brucehoult on July 12, 2020, 02:05:41 amWell, pretty much all which maintain a log file do. That might very well be the majority of them.Quote from: brucehoult on July 12, 2020, 02:05:41 amHow about parsing config files? Might not be what the majority is doing, but hardly an exotic application.Quote from: brucehoult on July 12, 2020, 02:05:41 amI made no such claim and I don't think I implied as much.Quote from: brucehoult on July 12, 2020, 02:05:41 amThe value of keyword symbols are themselves. Can't get much more well-defined imho.

author: brucehoult
author_rank: Super Contributor
timestamp: July 12, 2020, 11:51:05 pm
content: Quote from: guenthert on July 12, 2020, 05:44:41 pmNope. Symbols are *not* self-evaluating. If you write the bare name of a symbol then it is looked up in the current context and you get whatever it is bound to, not the symbol itself. That's equally true in Lisps and in the C implementation I gave. If you want to refer to a symbol by name -- as a symbol -- then you *have* to quote it by variously putting a ' or a : after it, or perhaps various other things e.g. a # in front if it in Dylan or a * in front of it in Perl or a \ in front of it in PostScript.

author: guenthert
author_rank: Frequent Contributor
timestamp: July 13, 2020, 12:00:41 am
content: Quote from: brucehoult on July 12, 2020, 11:51:05 pmKeywordsymbols are bound to themselves. You might want to peruse the standard:http://www.lispworks.com/documentation/HyperSpec/Body/t_kwd.htm

author: brucehoult
author_rank: Super Contributor
timestamp: July 13, 2020, 01:37:16 am
content: Quote from: guenthert on July 13, 2020, 12:00:41 amKeyword symbols and symbols are different things -- or at least keyword symbols are a subset of symbols. Keyword symbols are a particular Common Lisp feature while I'm talking about a symbol concept that is common across quite a number of programming languages.To quote from the page you reference:Quotei.e. any symbol that has *not* been interned into the KEYWORD package is *not* bound to itself, and that is most symbols.

author: 0db
author_rank: Frequent Contributor
timestamp: July 13, 2020, 10:40:07 am
content: All the features offered by ucPython on my graphing calculator.Scripting in ucPython is more productive than CASIO-basic.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 14, 2020, 04:58:13 pm
content: Quote from: tggzzz on July 11, 2020, 07:56:03 pmSo you're basically saying that all projects in which it has worked well must fall into this category. Maybe so. As Nominal Animal suggested, there are still many cases (obviously not ALL) in which just using it as a drop-in for malloc() mostly gives benefits without noticeable problems. It should certainly be tested with care, though. Another point, which may be part of what you are saying, is that ideally you must have access to ALL source code and recompile everything using the Boehm GC. I know there are ways to just kind of redirect malloc() calls at the executable level, but I would certainly suggest NOT doing this. Way too slippery.But with your claims, it would have been nice to have more details on the exact limitations and how "difficult" it is to use properly. As it is, it's like we'll have to take your word for it. I absolutely don't think it's perfect, but it would have been interesting to have more detailed information if anyone is interested in possibly using a GC with C or C++. (All the more that there are other options, just the this one is one of the most popular.)Now in the general sense, any allocator that is an integral part of a given language, rather than a third-party addition, is more likely to be more robust, easier to use, and more consistent. No real doubt about that, and if this is what you implied beyond the very case of the Boehm GC, then that's something to consider.Quote from: tggzzz on July 11, 2020, 07:56:03 pmI don't know how you get that from what I said. If it was not clear, all I was saying is that there are actual options for a GC in C and C++, and then I additionally expressed my own (short) opinion on the potential benefits and drawbacks of GC in general.We can also note that depending on the language you use, you may not have a choice. Some languages rely on GC and don't give you alternatives for dynamic allocation. For people using such a language, whether they consider GC a silver bullet or not doesn't matter - they just have to do with it.

author: tggzzz
author_rank: Super Contributor
timestamp: July 14, 2020, 05:50:15 pm
content: Quote from: SiliconWizard on July 14, 2020, 04:58:13 pmNo I'm not saying that. If I say that all crows are black birds, it does not mean I say all black birds are crows.QuoteThe keywords there are "mostly" and "noticeable".As Tony Hoare memorably put it "There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult."It is obvious which category a product made with Boehm's GC falls into.QuoteRemember the old engineering adage: "you can't test/inspect quality into a product". Why is it that too much of the software industry doesn't comprehend that tests cannot show the absence of bugs, they can only show the presence of specific bugs?QuoteAbsolutely. That is not practical for many reasons.QuoteDo not take my word for it! Read the literature to understand what the creator (and others more knowledgeable than me) have said. I'm not going to repeat it poorly!QuotePopularity is irrelevant.If I'm allowed to create a product that doesn't work, I can do it in 10 minutes flat.QuoteI will try to stop people using inappropriate tools when more appropriate tools are available. Familiarity with an inappropriate tool is not a valid reason for using it.For example, I've seen people open tin cans with scissorsQuoteThat doesn't mean it is sensible, nor appropriate, nor correct.Example. I've seen somebody that needed to get a value from one unix process to another running on a different processor. Since he only knew SQL he just had to use that. Yes, his solution was the first process updated a database table, and the second process polled the database table (using SQL SELECT) to spot changes.Sane people would just have started with TCP/IP, not SQL!

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: July 14, 2020, 06:00:51 pm
content: Quote from: tggzzz on July 14, 2020, 05:50:15 pmOr a pipe.

author: brucehoult
author_rank: Super Contributor
timestamp: July 15, 2020, 12:20:42 am
content: Quote from: tggzzz on July 14, 2020, 05:50:15 pmAny program which uses explicit malloc() and free() which are not in the same control flow block (and which could therefore just as well use alloca() or even a local variable) has already exited from the first category.It is an enormous simplification and contribution to reliability to debug the GC once, not debug every malloc() and free() in every program.GC is a huge aid in making separately developed libraries work together. As are exceptions.Very simple libraries can work ok without those, but as soon as you have anything that uses callbacks (or calls methods on an object you pass it, which can be of a derived class of the class the library was written for) then you need both.It's very hard to see how substituting GC for free() in a C program that is bug-free can produce a buggy program. Some objects that would be free()d may never be collected if pointers to them are not zeroed after free() or overwritten with a new pointer sometime after. This effect is strictly limited and can not lead to a continuous leak that does not exist in the malloc/free version.In C++ making delete a no-op results in destructors not being called. The vast majority of destructors do nothing more than delete other objects, in which case it doesn't matter.The case that matters is if a destructor deallocates or closes some external resource such as a file or network port or sends a message to another process etc. However this is a rare style of programming. Usually such things are done by explicit function calls controlled by program logic, by nested control structures, or by RAII.

author: tggzzz
author_rank: Super Contributor
timestamp: July 15, 2020, 10:57:21 am
content: Quote from: brucehoult on July 15, 2020, 12:20:42 amAgreed on all counts.QuoteHere we are diving into discussing the characteristics of some programs plus libraries plus a/one GC retrofitted to a language that was not designed to allow GCs. At this point things are becoming complicated to the point of being intractable. It would be too easy to miss a particular case that does turn out to cause infrequent subtle problems, possibly only when more aggressive optimisations are enabled and/or when third party libraries are linked in.Given the demonstrable inability of most C/C++ programmers to understandallthe language and implementation "gotchas", it looks like building castles on sand. N.B. I'm quite prepared to believe that a relatively few experts could build a useful castle on sand.Overall, if you need GC then:if you are starting from a clean sheet, then best to use a language designed with GC in mind. If desirable, it should then be possible to adopt programming styles that don't generate much (if any) garbage. At that point any "GC overhead" becomes moot. Some fintech Java libraries/products do that.if you can't start from a clean sheet but have to use pre-existing components, then predicting and ensuring there aren't subtle infrequent problems related to GC seems a tall order. Best to avoid GC altogetherSummary of the summary... We have enoughinterestingproblems to solve in our various application domains. Life is too short to spend debugging additional uninteresting problems that are avoidably added by a tool. Let's concentrate on the application, not on the tools.

author: brucehoult
author_rank: Super Contributor
timestamp: July 15, 2020, 01:27:00 pm
content: The first paper on BDW GC was published in 1988:https://hboehm.info/spe_gc_paper/preprint.pdfThat's over 30 years of experience with this software. on many CPU architectures, dozens of compilers, who knows how many thousands of programs. My own experience with Boehm GC is around 22 years.If there were significant problems with the overall approach, in the face of C programmer habits or compiler optimizations, I think we'd know by now.There *have* been problems found over the years, and they have been fixed or mitigated.If you're going to write a program using dynamic memory allocation at all, I firmly believe if you use Boehm GC then it and its interaction with arbitrary C or C++ code is the LEAST LIKELY place you will encounter bugs, and using it instead of malloc/free or new/delete will VERY significantly decrease the overall probability of your having memory bugs.

author: tggzzz
author_rank: Super Contributor
timestamp: July 15, 2020, 02:19:32 pm
content: Quote from: brucehoult on July 15, 2020, 01:27:00 pmI thought it was a 90s invention rather than 88, and I'm sure your experience is valid. I'm not surprised there have been problems found (and fixed); I certainly haven't been following the subject. I'm mildly curious (in a rather prurient way) as to the way the bugs were found, reported, believed, and fixed. I don't expect you to set them out, though!I also have no difficulty believing that it is less error prone than "traditional" malloc/free/new/delete. But that's an unacceptably low bar to set!But overall the balance of probabilities is that if you are starting a new application with significant dynamic memory allocation, then there have long been better tools available. The existence of Boehm's GC highlights that - but doesn't change that.

author: AntiProtonBoy
author_rank: Frequent Contributor
timestamp: August 10, 2020, 03:43:42 pm
content: Bit late to the party, but C++ destructors is easily the most favourite language feature. Literally a game changer in how you think about writing code.

author: K8Philip
author_rank: Newbie
timestamp: October 30, 2020, 02:51:52 pm
content: Associative Arrays

author: SiliconWizard
author_rank: Super Contributor
timestamp: October 30, 2020, 03:16:21 pm
content: Quote from: K8Philip on October 30, 2020, 02:51:52 pmIs that what we also call "dictionaries"? Such as tables as implemented in LUA.If that's what you mean, then I definitely agree. Of course there are numerous libraries available to implement them in various languages, but having the feature "built-in" sounds nice. More generally speaking, having "dynamic tables" as a built-in feature is an extremely useful feature. You can emulate that in various ways when not available, but it's always more or less clunky.Ideally, I'd like a general "dynamic table" data structure built in the language, where you could declare a given table to be either an ordered table, an unordered table (could lead to more efficient handling if order doesn't matter), or a dictionary (or associative array.) And yes, again you can find libraries for this in almost any language, but having that built-in could have a number of benefits (such as better optimization opportunities.)

author: bd139
author_rank: Super Contributor
timestamp: October 30, 2020, 06:05:39 pm
content: Go channels is a winner for me. Nice concurrency primitive.

author: tggzzz
author_rank: Super Contributor
timestamp: October 30, 2020, 07:33:00 pm
content: Quote from: bd139 on October 30, 2020, 06:05:39 pm...particularly when coupled with the select statement.We have a lot to thank Tony Hoare for, since his CSP introduced the concepts 45 years ago. They then lead to Occam / xC / Go, and a few others.