EmbeddedRelated.com
Forums

Language feature selection

Started by Don Y March 5, 2017
On 3/6/2017 8:15 PM, George Neuner wrote:
> On Mon, 6 Mar 2017 13:36:49 -0700, Don Y <blockedofcourse@foo.invalid> > wrote: > >> On 3/6/2017 11:33 AM, George Neuner wrote: >>> On Sun, 5 Mar 2017 16:03:25 -0700, Don Y <blockedofcourse@foo.invalid> >>> wrote: >>> >>>> A quick/informal/UNSCIENTIFIC poll: >>>> >>>> What *single* (non-traditional) language feature do you find most >>>> valuable in developing code? (and, applicable language if unique >>>> to *a* language or class of languages) >>> >>> Closures. Far more useful than (OO) objects. >> >> But doesn't this complicate the run-time (e.g., drag in GC)? >> Or, can all of this (subsetted) be handled at compile time? > > Not necessarily. Closures don't require GC at all unless they can > persist beyond their definition scope.
But that limits their utility. E.g., I instantiate heaps by allowing the instantiating entity to specify the nominal heap parameters (location, size, granularity, etc.) along with default *policies* (how it selects a piece of itself to allocate, how it handles the release of that allocation, how greedy/stingy it is in satisfying the request, etc.). So, the instantiating entity can (often!) cease to exist before the supplied parameters are ever referenced. The selected allocation algorithm could reside in this "zombie" module... or, in the code space of the "task" using that heap... or, in the heap module "library of algorithms". Of course, it means the instantiated heap needs some way of tracking these parameters (d'uh) and <someone> has to assume responsibility for ensuring that they are in place before the heap is used and disposed of when the heap is torn down. [Making sure they are in place is relatively easy. Disposing of them can also be easy -- as long as you're careful not to attempt to use them after they have "been disappeared".]
> Think about nested functions as in Pascal, but augmented with private > persistent variables (trying to avoid the word "static" to prevent > unwanted associations with C). This form of closure is stack-strict > and does not require any heap allocation[1].
Yes, but that limits the function's scope. It makes it difficult to "import" these from other modules.
> Such closures are confined to the scope in which they are defined, so > a little thought (vs C) has to be given to program structure. But > many programmers successfully used Pascal and modular descendants of > it ... it isn't *that* hard. > <grin>
I don't see it as a case of "difficulty" but, rather, "convenience". It forces code to take a particular form, regardless of how "natural" it may (not) seem. [E.g., consider the heap instantiator example: why does *it* have to persist just so something it provides remains accessible?]
> Nested functions do require a little bit of runtime bookkeeping. A > "display" (static scope array) is generally more performant than scope > links in call frames. The size of the display for the program/module > is fixed at compile time, and because it is accessed frequently (at > every function call/return), it tends to cache quite well. > > If you are providing GC anyway, then IMO there is no reason not to > provide 1st class closures as they are just a small object containing > a pointer to the code and a pointer to a separate heap allocation for > the persistant variables[2]. Closure objects can be handled like any > other data. > > If you want GC to clean up unneeded code as well, that gets a little > more interesting. You need to know the size of the code block to > deallocate it, and it needs a global "name" (like any other data) so > that closures can reference it. When there are no more closure > objects referencing the block, it can be deallocated.
For "run forever" systems, its not an issue. OTOH, if you can load and unload modules (as in my case), then you're faced with more explicit managing of those resources -- I can't kill off a module that has an outstanding reference to some *portion* of itself persisting in another module. [In my case, an "object handle" ensures the OS will keep track of the "thing" for me -- including if it migrates elsewhere]
> [Obviously, there is a race condition: what if GC runs before any > closures referencing the code block are created? Best way to handle > that is deliberate unloading of the containing module. Alternatively > you could use (compiler directed) reference counting and define a > special count value to indicate the block should be retained despite > currently having no references.] > > George > > [1] persistant variables can be heap allocated rather than stack > allocated to reduce/control stack size. In either case the persistant > variables would be defined as a structure (de)allocated by the > *surrounding* scope rather than by the closure function itself. > > [2] if there are no shared persistant variables, then a closure object > can contain them directly rather than having a pointer to a separate > allocation. This saves an indirection at runtime, but at the expense > of more complexity in the compiler (non-uniform handling of shared vs > non-shared variables).
The advantage of having the *language* do this is that it enforces a consistency on the implementation (and, catches careless errors on the developer's part). [In my case, the OS carries most of that burden -- *if* the developer treats these things as "managed objects"] [[Pecan Sandies tonight]]
On 06.3.2017 &#1075;. 22:38, Don Y wrote:
> On 3/6/2017 2:11 AM, Dimiter_Popoff wrote: >> On 06.3.2017 &#1075;. 01:03, Don Y wrote: >>> A quick/informal/UNSCIENTIFIC poll: >>> >>> What *single* (non-traditional) language feature do you find most >>> valuable in developing code? (and, applicable language if unique >>> to *a* language or class of languages) >> >> Flexibility/expandability. In vpa if I miss something for a while >> I can simply implement it rather than work around it every time. > > Are you thinking of superficial/syntactic differences (e.g., things > that could be addressed with a macro preprocessor)? Or, > genuine semantic differences (e.g., adding interprocess communication > operators to a language that doesn't currently support it)?
I suppose both. The macro functionality in vpa is an example how I have proceeded over the years; at first I could just pass arguments (also trough macro within macro, not sure I ever used that but I had made it). At some stage I added partial argument passing, i.e. you can specify <argument>[starting character][character count]. Later I made the variable etc. script infrastructure thing available to vpa (dps shell variables are similar to those in unix shell but more complex in that a variable name can be put together of variables). The interprocess communication is not vpa inherent, it is higher level. That is, at the lowest level your code must make a system call (named "signal" or sort of); at a higher level the code would refer to a dps object and ask it to do something like passing a message, an event etc (e.g. a display_window object contains an ID of a lowest level window descriptor, if you ask the display_window to do a "getevent" it will do what it takes at the lower level and get you an event descriptor which another object can "process" etc.). The variety of what different objects do can grow huge so it is impractical to put that in the language; the language itself is responsible just to provide the macros for "do" (which is a wasted word, was the first I used in a type of call which is useless but legacy supported.... :), I may add some higher level do-likes which would include passing the object quick ID, action initiator plus initiator quick id etc. (now I do the latter with plain operators explicitly, not sure I need to change this though). I think of this higher level thing as of phrases built using the language though. Not sure where to put this re your query, when do phrases become part of a language? When does it become practical to invent a new symbol? In alphabet based language it just does not become practical (the Latin alphabet has been unchanged for a while), in hieroglyph based languages I don't know how it is (my feeling about the latter is they are limiting by nature though). Dimiter ------------------------------------------------------ Dimiter Popoff, TGI http://www.tgi-sci.com ------------------------------------------------------ http://www.flickr.com/photos/didi_tgi/
On 06/03/17 21:44, Don Y wrote:
> On 3/6/2017 1:33 PM, David Brown wrote: >> On 06/03/17 16:47, Don Y wrote: >>> On 3/6/2017 12:40 AM, David Brown wrote: >>>> On 06/03/17 00:03, Don Y wrote: >>>>> A quick/informal/UNSCIENTIFIC poll: >>>>> >>>>> What *single* (non-traditional) language feature do you find most >>>>> valuable in developing code? (and, applicable language if unique >>>>> to *a* language or class of languages) >>>> >>>> What do you mean be "non-traditional"? >>> >>> I suspect we'd all agree that the ability to support "procedures" >>> is highly valuable (imagine writing a complex piece of code *without* >>> being able to invoke one). And, that adding support for functions >>> enhances this capability (though functions without procedures makes >>> little sense) >>> >> >> What about functional programming languages? They don't have >> procedures in the >> same sense as in a procedural programming language like C. You do have >> functions, but they are rather different from C functions. >> >> Or BASIC? I believe some people make embedded software written in BASIC >> without procedures as such. >> >> I believe I understand roughly what you mean, but I think it would >> take quite >> an effort to give a decent rigorous definition. And the way you pose the >> question implies that people regularly use programming languages that >> are have >> "non-traditional" features. Does that mean you think some features of >> C are >> non-traditional (since the majority of embedded programmers use C), or >> that >> some people use C in a non-traditional manner, or that you are >> interested in >> people who use languages other than C? >> >> Perhaps a clearer question would be, "if you use a language other than >> C for >> your embedded programming, what language do you use and what >> feature(s) are >> particularly useful?". > > There's no need to bind the discussion to C -- or any other language. > > I suspect most folks (i.e., damn near everyone) has used more than one > language in their career.
I am not sure you are right about that. A lot of embedded programmers know only C - perhaps with a vague knowledge about assembly from courses they took. Many other programmers have only ever learned one programming language.
> And, formed preferences for particular languages > largely based on what the language allowed them to *do* -- and, at some > fuzzy point in time, they thought to themselves: "<previous_language> > wouldn't > let me *do* things like this!"
Agreed (for people that have learned more than one language). But what people view as "traditional features" is going to be based almost totally on the languages they are most familiar with. If you learned to program using Haskell, then you are going to think in terms of lists, recursion, functions-of-functions, etc. The idea of incrementing a variable or using a pointer would be completely alien - but infinite lists are perfectly normal and "traditional". The opposite is true for someone programming in C.
> > Limbo won't let me use pointers. I consider that a *huge* handicap as > my coding style relies heavily on them in ways that feel "clumsy" to > approximate using the mechanisms that Limbo supports in their stead. > > OTOH, I can type "a few characters" and communicate with another process > (even on a remote node) without all the cruft of having to open a > connection to that process (as well as figuring out *where* it resides). >
On 06/03/17 21:50, Tauno Voipio wrote:
> On 6.3.17 09:40, David Brown wrote: >> On 06/03/17 00:03, Don Y wrote: >>> A quick/informal/UNSCIENTIFIC poll: >>> >>> What *single* (non-traditional) language feature do you find most >>> valuable in developing code? (and, applicable language if unique >>> to *a* language or class of languages) >> >> What do you mean be "non-traditional"? >> >> The two languages I find most useful in developing embedded code are >> English and C, followed by Norwegian, C++ and assembly. >> >> If these count as "traditional", then maybe it would be Python - that's >> the language I use most for scripts, auxiliary programs, test programs, >> etc. >> > > Which Norwegian: Bokmal or Nynorsk?
Bokm&aring;l, when written, but with a spoken dialect from the West of Norway.
> > For non-traditional languages, how about APL - cryptic, for sure? >
APL must be one of the most cryptic languages that is actually used (i.e., excluding languages on this list <https://en.wikipedia.org/wiki/Esoteric_programming_language>).
On 3/7/2017 4:24 AM, David Brown wrote:
>> And, formed preferences for particular languages >> largely based on what the language allowed them to *do* -- and, at some >> fuzzy point in time, they thought to themselves: "<previous_language> >> wouldn't >> let me *do* things like this!" > > Agreed (for people that have learned more than one language). > > But what people view as "traditional features" is going to be based > almost totally on the languages they are most familiar with. If you > learned to program using Haskell, then you are going to think in terms > of lists, recursion, functions-of-functions, etc. The idea of > incrementing a variable or using a pointer would be completely alien - > but infinite lists are perfectly normal and "traditional". The opposite > is true for someone programming in C.
That's entirely my point! Should, instead, we argue over what "traditional" means in the UNIVERSE of "programming" languages? *Then*, individually decide which features "stand out" as "valuable" in our own minds? Or, do you let individuals come to grips with their own, personal notion of "traditional" and, from that, define their own sense of "utility"? ("*THIS* is what I think is really cool about THIS language...") [Overloading operators in C++ to exploit infix notation can be "way cool" to some as a more *expressive* way of writing code. Others look past the syntax and see little changing in the *generated* code -- and yawn.] I like the fact that I can write self-modifying code in languages that support pointers to code (not code whose behavior changes but, rather, CODE that changes -- leaving no sign of its ancestry). *Getting* that ability is an "oh, wow!" event.
On 3/7/2017 3:18 AM, Dimiter_Popoff wrote:
> On 06.3.2017 &#1075;. 22:38, Don Y wrote: >> On 3/6/2017 2:11 AM, Dimiter_Popoff wrote: >>> On 06.3.2017 &#1075;. 01:03, Don Y wrote: >>>> A quick/informal/UNSCIENTIFIC poll: >>>> >>>> What *single* (non-traditional) language feature do you find most >>>> valuable in developing code? (and, applicable language if unique >>>> to *a* language or class of languages) >>> >>> Flexibility/expandability. In vpa if I miss something for a while >>> I can simply implement it rather than work around it every time. >> >> Are you thinking of superficial/syntactic differences (e.g., things >> that could be addressed with a macro preprocessor)? Or, >> genuine semantic differences (e.g., adding interprocess communication >> operators to a language that doesn't currently support it)? > > I suppose both. The macro functionality in vpa is an example how > I have proceeded over the years; at first I could just pass arguments > (also trough macro within macro, not sure I ever used that but > I had made it). At some stage I added partial argument passing, > i.e. you can specify <argument>[starting character][character count]. > Later I made the variable etc. script infrastructure thing available > to vpa (dps shell variables are similar to those in > unix shell but more complex in that a variable name can be put > together of variables).
If the changes you want can be created with a "preprocessor", then I think it has less value -- the same preprocessor (with a different back-end) could be applied to some other language (assuming the syntax you've chosen is compatible to both). E.g., I build state machines "in-line" with my code by letting a preprocessor deal with their (abbreviated) syntax instead of forcing the SYNTAX of the implementation to be compatible with the application's language. OTOH, if you are actually changing the nature of the language by adding some characteristic (e.g., support for infix notation in overloaded arithmetic operators in C++), then I can't see an easy way of doing it -- short of rewriting the compiler and/or runtime, etc. [Or, some intermediary document that *drives* the operation of the compiler]
> The interprocess communication is not vpa inherent, it is higher > level. That is, at the lowest level your code must make a system > call (named "signal" or sort of); at a higher level the code would > refer to a dps object and ask it to do something like passing > a message, an event etc (e.g. a display_window object contains an > ID of a lowest level window descriptor, if you ask the display_window > to do a "getevent" it will do what it takes at the lower level > and get you an event descriptor which another object can "process" > etc.).
In Limbo: // define channel in file scope so visible to producer/consumer // if the producer and consumer exist in different modules, then // the definition must be consistent across them pipe: chan of (...stuff...) init(...) { ... // instantiate channel pipe = chan of (...stuff...) ... spawn producer(someargs, pipe) spawn consumer(otherargs, pipe) ... } producer( args, gozeout: chan of (...stuff...) ) { ... while (...) { ... gozeout <-= (...more_stuff...) ... } ... } consumer( moreargs, cumzin: chan of (...stuff...) ) { ... while (...) { ... (...thatstuff...) =<- cumzin ... } ... } I.e., the compiler needs to know about the syntax for defining, declaring and referencing channels. AND, the means by which the runtime will support those channels. [Here, it is easiest to see the channel "pipe" as a named pipe that passes structs that resemble (...stuff...). Obviously, that "stuff" can degenerate to a simple data type (like "string")] I don't see how to support adding something like this to an "expandable" language without a boatload of effort "behind the scenes".
> The variety of what different objects do can grow huge so it is > impractical to put that in the language; the language itself is > responsible just to provide the macros for "do" (which is a wasted > word, was the first I used in a type of call which is useless but > legacy supported.... :), I may add some higher level do-likes > which would include passing the object quick ID, action initiator > plus initiator quick id etc. (now I do the latter with plain > operators explicitly, not sure I need to change this though). > > I think of this higher level thing as of phrases built using > the language though. Not sure where to put this re your query, > when do phrases become part of a language? When does it become > practical to invent a new symbol? In alphabet based language > it just does not become practical (the Latin alphabet has been > unchanged for a while), in hieroglyph based languages I don't > know how it is (my feeling about the latter is they are > limiting by nature though).
If your "expansion" can be restated as syntactic shorthands (i.e., handled by a preprocessor), then that relies on how much you want to contort the underlying syntax to support the *changed* syntax. E.g., you could replace parens with angle brackets EVERYWHERE -- or, in specific cases -- but that makes the syntax of the exposed "language" significantly (though superficially) different from the underlying language. [However, it could conceivably "make sense" if the additions you were making were more "consistent" in that new representation] In FORTH, for example, "pick a word (identifier), any word" (practically). You're effectively treating (FORTH) "words" as your "alphabet" though subject to the syntax restrictions of FORTH. I guess I don't see how you can make *significant* changes to a language without (the potential risk of) reimplementing that language entirely. Consider the "channel" example above -- through to "running code"... [A pair of machines to build, today -- now that the memory tests have finished...]
On 3/6/2017 12:04 AM, Wouter van Ooijen wrote:
> Op 06-Mar-17 om 00:03 schreef Don Y: >> A quick/informal/UNSCIENTIFIC poll: >> >> What *single* (non-traditional) language feature do you find most >> valuable in developing code? (and, applicable language if unique >> to *a* language or class of languages) > > I can't think of any language feature that is usefull in isolation.
You, of course, wouldn't use *a* "single-feature language" for anything! OTOH, there are certain features of certain languages that are more useful/valuable than other "features". And, unless you're a one-trick pony when it comes to "language exposure", you've undoubtedly had moments when you came to that realization for <some_language> in contrast to <some_other_language>. Else, all languages would be exactly and completely interchangeable with no effect on productivity, reliability, etc.
On 2017-03-05, Don Y <blockedofcourse@foo.invalid> wrote:
> A quick/informal/UNSCIENTIFIC poll: > > What *single* (non-traditional) language feature do you find most > valuable in developing code? (and, applicable language if unique > to *a* language or class of languages)
Non-traditional in today's environment only or non-traditional over the whole of computing history ? You sound like you are asking for language features which would be considered non-traditional in today's world only. As such I would offer you the strong typing as seen in the Wirth languages or (especially) Ada. A person who only knows Javascript and C would probably consider C to be strongly typed. A person with Wirth languages (or especially Ada) in their background would have a different viewpoint. I think we are losing something if we continue the move away from strongly typed languages for various application domains. I really like the discipline that strongly typed languages force upon you as I think you produce better code as a result. Simon. PS: I'll let you decide if you consider Ada to be a Wirth language or not. He didn't design it but it's very strongly based on his language concepts. -- Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP Microsoft: Bringing you 1980s technology to a 21st century world
On 2017-03-07, Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
> On 2017-03-05, Don Y <blockedofcourse@foo.invalid> wrote: >> A quick/informal/UNSCIENTIFIC poll: >> >> What *single* (non-traditional) language feature do you find most >> valuable in developing code? (and, applicable language if unique >> to *a* language or class of languages) > > Non-traditional in today's environment only or non-traditional > over the whole of computing history ?
To me, "traditional" means COBOL, FORTRAN and assembly. -- Grant Edwards grant.b.edwards Yow! Life is a POPULARITY at CONTEST! I'm REFRESHINGLY gmail.com CANDID!!
On 2017-03-07, Grant Edwards <invalid@invalid.invalid> wrote:
> On 2017-03-07, Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote: >> On 2017-03-05, Don Y <blockedofcourse@foo.invalid> wrote: >>> A quick/informal/UNSCIENTIFIC poll: >>> >>> What *single* (non-traditional) language feature do you find most >>> valuable in developing code? (and, applicable language if unique >>> to *a* language or class of languages) >> >> Non-traditional in today's environment only or non-traditional >> over the whole of computing history ? > > To me, "traditional" means COBOL, FORTRAN and assembly.
On punch cards or paper tape. :) -- Grant Edwards grant.b.edwards Yow! I'm ZIPPY the PINHEAD at and I'm totally committed gmail.com to the festive mode.