Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.misc > #2037 > unrolled thread
| Started by | bruce axtens <bugmagnet@outlook.com> |
|---|---|
| First post | 2014-04-28 16:23 +0000 |
| Last post | 2014-04-29 05:37 -0700 |
| Articles | 14 on this page of 34 — 9 participants |
Back to article view | Back to comp.lang.misc
Wirth-ian languages bruce axtens <bugmagnet@outlook.com> - 2014-04-28 16:23 +0000
Re: Wirth-ian languages Joe Hynes <theda@southpark.net> - 2014-04-28 17:31 +0000
Re: Wirth-ian languages Kaz Kylheku <kaz@kylheku.com> - 2014-04-28 18:47 +0000
Re: Wirth-ian languages "BartC" <bc@freeuk.com> - 2014-04-28 20:35 +0100
Re: Wirth-ian languages Kaz Kylheku <kaz@kylheku.com> - 2014-04-28 20:18 +0000
Re: Wirth-ian languages "James Harris" <james.harris.1@gmail.com> - 2014-04-28 22:50 +0100
Re: Wirth-ian languages "BartC" <bc@freeuk.com> - 2014-04-29 00:03 +0100
Re: Wirth-ian languages Kaz Kylheku <kaz@kylheku.com> - 2014-04-28 23:51 +0000
Re: Wirth-ian languages "James Harris" <james.harris.1@gmail.com> - 2014-04-29 07:59 +0100
Re: Wirth-ian languages "BartC" <bc@freeuk.com> - 2014-04-29 10:04 +0100
Re: Wirth-ian languages "James Harris" <james.harris.1@gmail.com> - 2014-04-29 11:33 +0100
Re: Wirth-ian languages "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-04-29 07:41 -0400
Re: Wirth-ian languages "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-04-28 21:46 -0400
Re: Wirth-ian languages "James Harris" <james.harris.1@gmail.com> - 2014-04-29 08:24 +0100
Re: Wirth-ian languages "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-04-29 07:33 -0400
Re: Wirth-ian languages "James Harris" <james.harris.1@gmail.com> - 2014-04-29 14:38 +0100
Re: Wirth-ian languages "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-04-30 21:28 -0400
Re: Wirth-ian languages "James Harris" <james.harris.1@gmail.com> - 2014-05-01 10:44 +0100
Re: Wirth-ian languages "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-04-29 09:59 +0200
Re: Wirth-ian languages Kaz Kylheku <kaz@kylheku.com> - 2014-04-29 15:51 +0000
Re: Wirth-ian languages "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-04-30 10:57 +0200
Re: Wirth-ian languages Kaz Kylheku <kaz@kylheku.com> - 2014-04-30 15:47 +0000
Re: Wirth-ian languages "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-01 10:18 +0200
Re: Wirth-ian languages Kaz Kylheku <kaz@kylheku.com> - 2014-05-01 16:56 +0000
Re: Wirth-ian languages "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-02 10:10 +0200
Re: Wirth-ian languages "BartC" <bc@freeuk.com> - 2014-04-30 18:27 +0100
Re: Wirth-ian languages "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-01 10:18 +0200
Re: Wirth-ian languages Kaz Kylheku <kaz@kylheku.com> - 2014-05-01 17:10 +0000
Re: Wirth-ian languages "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-02 09:22 +0200
Re: Wirth-ian languages "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-04-28 20:59 -0400
Re: Wirth-ian languages "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-04-28 21:10 -0400
Re: Wirth-ian languages Nils M Holm <news2009@t3x.org> - 2014-04-29 07:52 +0000
Re: Wirth-ian languages "BartC" <bc@freeuk.com> - 2014-04-29 09:45 +0100
Re: Wirth-ian languages Jacko <jackokring@gmail.com> - 2014-04-29 05:37 -0700
Page 2 of 2 — ← Prev page 1 [2]
| From | "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> |
|---|---|
| Date | 2014-04-30 10:57 +0200 |
| Message-ID | <1pqfweefeeeee$.1c1g5eqx3n1ph.dlg@40tude.net> |
| In reply to | #2066 |
On Tue, 29 Apr 2014 15:51:17 +0000 (UTC), Kaz Kylheku wrote: > On 2014-04-29, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: >> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote: >> >>> So, let's list some (what I recall right now...) of what I think >>> C gets correct: >>> >>> 1) pointers >> >> Since C did almost everything wrong. I will comment only on pointers, which >> is also an easy game. What is wrong with them: >> >> 1. Pointer types are improperly typed as they are matched by structure. >> Thus you cannot have two distinct pointer types for the same target type. >> The feature extremely important for building sorted containers and custom >> memory pools. > > "Extremely" is a hyperbole, since people have developed these things in C > without even so much a fleeting thought such as "I could use pointer type names > based on name equivalence". It is not about Turing-completeness of C, it is about pointer design. Yes, people don't even aware of a possibility to automatically select the memory pool based on the pointer type. Not possible, per wrong design. > Any decent C compiler has a warnings for uninitialized locals, Record fields, dynamically allocated objects? Anyway, it is a halting problem. Trivially: int x; int * y; if (HALT (p)) y = &x; So any such check must necessarily generate false negatives or false positives. And it is not in C programming culture to pay much attention to silly compiler warnings, anyway. > and any decent > C programmer investigates what diagnostic options are available, and uses > all of them that aren't nuisance stylistic warnings. A little problem is that "decent C programmers" according this definition probably don't exist. It is extremely difficult to hire a good C programmer. Anyway, a precaution that can be done by compiler but left to the programmer is a language design fault, which C pointers are. >> 4. Pointer arithmetic is a low level hack which should not be there, >> because it does not make any sense for variable sized targets or advanced >> structures like graphs and trees. > > Pointer arithmetic is necessary for managing variable-sized targets, > like records that have multiple variant fields, all in the same linear > memory block. These could be stuck into a graph structure. No. If you need a pointer to the next element you don't have to compute it. You just store it. Otherwise, see the position #1. If pointers were properly designed as ADTs, there would be no problem to define arithmetic on *some* of them as needed. Instead of that the language enforces blanket garbage semantics on all of them. Which is a language design fault. >> It also does not make sense on certain >> machine architecture which was and is a huge problem for ones with the >> machine word shorter than the physical memory space. > > The demand for C toolchains killed those architectures, so that's not a problem > any more. So much for being "close to hardware"! > This is not a "huge problem" in the world; on the contrary, it is a > non-problem, now that cheap 64 bit machines are available to consumers. Well, the balance between the cost of a CPU cycle vs. memory byte has shifted towards CPU. It is difficult to say whether that will stay so. When massively parallel architectures will arrive, the model of shared memory will inevitable die. There is no way to share memory between thousands of cores. This might shift the balance back, away from flat, isotropic memory models... >> 5. Confusing pointers with arrays is a huge problem that caused countless >> issues throughout all life time of C. Recent example is OpenSSL. > > No comment there. The tools and choice of tools and methods does deserve blame > here. Ah, but if you need tools on top of the language, that is a language fault again. Tools is an answer to miserable languages we have to program in. > What would constitute sufficient difficulty in the integer-pointer conversion? > Sacrificing a goat for each instance? Making meaningless conversions unnecessary? > The code is not fragile and non-portable at the same time. Conversions between > pointers and integers can be completely solid. > > Example: the traditional return value of the POSIX function to indicate failure: > -1 cast to (void *). (Nowadays hidden behind the symbol MAP_FAILURE). > > Non portable it may be, but there isn't anything "fragile" about it. > Fragility would be demonstrated by breaking, and that would just add up to > non-portability. Fragility is when small changes lead to heavy distributed maintenance overhead in the client code base. >> 7. Each object in C is assumed to be addressable, i.e. the &-operation is >> defined on each object. > > Variables declared "register" cannot have this operation applied to them. > > But even without this, the analysis is very easy for determining whether or not > a declared object is subject to the & operator over its scope. So, the program semantics and legality may depend on the outcome of register optimization? That is again a language design fault. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2014-04-30 15:47 +0000 |
| Message-ID | <20140430055029.933@kylheku.com> |
| In reply to | #2072 |
On 2014-04-30, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
> On Tue, 29 Apr 2014 15:51:17 +0000 (UTC), Kaz Kylheku wrote:
>
>> On 2014-04-29, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
>>> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote:
>>>
>>>> So, let's list some (what I recall right now...) of what I think
>>>> C gets correct:
>>>>
>>>> 1) pointers
>>>
>>> Since C did almost everything wrong. I will comment only on pointers, which
>>> is also an easy game. What is wrong with them:
>>>
>>> 1. Pointer types are improperly typed as they are matched by structure.
>>> Thus you cannot have two distinct pointer types for the same target type.
>>> The feature extremely important for building sorted containers and custom
>>> memory pools.
>>
>> "Extremely" is a hyperbole, since people have developed these things in C
>> without even so much a fleeting thought such as "I could use pointer type names
>> based on name equivalence".
>
> It is not about Turing-completeness of C, it is about pointer design. Yes,
> people don't even aware of a possibility to automatically select the memory
> pool based on the pointer type. Not possible, per wrong design.
Indeed, C has very little compile-time polymorphism.
(The successor language C++ adds considerable compile-time polymorphism, while
maintaining strong backward compatibility. C++ hasn't completely succeeded in
displacing C.)
>> Any decent C compiler has a warnings for uninitialized locals,
>
> Record fields, dynamically allocated objects?
In C, an aggregate or struct field cannot be individually initialized, such
that others are left uninitialized. If the object has an initializer, all
members are initialized.
The problem of partially initialized objects occurs when objects are
left uninitialized and then configured member by member.
(This is, ironically, a big problem in C++, rather than C. In C++, when you
define a constructor, that constructor takes all responsibility for
initializing an object, and an atomic C-like initialization isn't possible.)
Dynamically allocated objects can be produced by a function that returns all
zero memory, like calloc, or your own wrapper for malloc.
struct foo *p_dynamic_foo = calloc(sizeof *pf, 1);
struct foo local_foo = { 0 }; /* all fields are initialized */
Another technique:
static const struct foo blank_foo; /* "blank" static structure */
struct foo *ptr = malloc(sizeof *pf);
*ptr = blank; /* initialize allocated object by copying the blank */
(This two-step approach avoids relying on a pattern of a all-zero bits
producing 0.0 floating-point values and null pointers.)
> Anyway, it is a halting problem. Trivially:
A perfectly accurate diagnostic is not only equivalent to solving the Halting
problem, but it requires access to functions in external compilation units, and
knowledge whether the function in question is ever called, which could depend
on inputs to the program and events. In other words, it is in fact intractable.
The Halting Problem is primarily of academic importance; it requires that we
have a complete description of the entire program that is to be analyzed, and
its complete input.
But we do not need a perfectly accurate diagnostic for uninitialized variables
in the real world; a suspicion is enough.
> int x;
> int * y;
>
> if (HALT (p)) y = &x;
>
> So any such check must necessarily generate false negatives or false
> positives.
If there is any suspicion that the variable is uninitialized, the case
can be made that it needs to be fixed. If a machine finds it hard to tell
whether the variable is uninitialized, a human being will also find it hard to
tell.
Even if HALT(p) (which is in a library somewhere) always returns true today,
so that the assignment always executes whenever this function is called,
someone could change the defnition of HALT so that it no longer always returns
true. When HALT changes, the above code does not get recompiled.
Generating a rational suspicion is easy; it doesn't require solving the Halting
Problem. If it's obvious that the variable is used uninitialized, emit a
confident diagnostic. Otherwise if it is not obvious that the variable is
initialized, emit a "possibly uninitialized" warning. If your compiler is told
to treat warnings as errors, then the build fails.
There is no reason to have false negatives (neglect to identify suspicious cases).
When we fix the false positive with "int *y = NULL", we are at that point no
worse off than a language which forces this automatically, and we can still
leave variables uninitialized in cases that are obviously safe.
> And it is not in C programming culture to pay much attention to silly
> compiler warnings, anyway.
That is neither here nor there. Every language that has ever been popular has
had attracted the goofballs, and always will. It is a social problem.
> Anyway, a precaution that can be done by compiler but left to the
> programmer is a language design fault, which C pointers are.
Not every precaution that can be done by the compiler *should* be done.
Static checking is bane of programming. Ideally, everything should be dynamic,
especially type and dispatch. Binding should always be as late as possible.
Write in a dynamic language, and leave C for the device drivers, codecs,
OS schedulers, etc.
>>> 4. Pointer arithmetic is a low level hack which should not be there,
>>> because it does not make any sense for variable sized targets or advanced
>>> structures like graphs and trees.
>>
>> Pointer arithmetic is necessary for managing variable-sized targets,
>> like records that have multiple variant fields, all in the same linear
>> memory block. These could be stuck into a graph structure.
>
> No. If you need a pointer to the next element you don't have to compute it.
> You just store it. Otherwise, see the position #1.
But then you're dictating to me the memory layout.
Firstly, I don't like that; I'm the designer of my program, I choose the layout.
Now I can live with dictation of memory representations in a nice, high-level
language (e.g. Lisp: I don't care what a cons cell looks like on the heap).
But I still need a language or sub-language for those cases when I do want to
control the layout.
Secondly, what if this is a third-party memory-mapped file where the layout is
imposed?
When the programming language interferes with implementing third-party
requirements, it's a poor language (at least for the problem domain at hand).
> If pointers were
> properly designed as ADTs, there would be no problem to define arithmetic
> on *some* of them as needed. Instead of that the language enforces blanket
> garbage semantics on all of them. Which is a language design fault.
I've never seen pointer arithmetic happen by accident in C code.
This problem Just Doesn't Happen (TM). (Like, "Oops, how did that completely
pointless ++ get onto that ptr variable? I didn't write that!")
I've seen arithmetic wrongly used, of course, but it was used because the
programmer needed and intended it, which is a different problem. If incrementable
pointers were wrapped in an ADT, then the programmer would have used the ADT
in that situation.
That said, there are pointers in C that do not support arithmetic: pointers
to incomplete types. One incomplete type is void: void * pointers do not
support pointer arithmetic. (Arithmetic on void * is a well-known GNU C
extension that is diagnosed if you tell GCC to stick to ISO C).
Other incomplete types beside "void" are incomplete arrays and incomplete
structure, the latter of which are very useful:
struct foo *p; /* no definition of struct foo in scope */
/* arithmetic on p not allowed */
Pointers to incomplete struct types are often used in library or module API's.
The client doesn't know what struct foo is, and cannot perform arithmetic
on pointers to struct foo. The implementation code, of course, can.
(We are sure on a roll. Let's see what utter basics you don't know about C ...)
>> The demand for C toolchains killed those architectures, so that's not a problem
>> any more.
>
> So much for being "close to hardware"!
"C is close to the hardware" is simply the clueless mantra of those who haven't
ever seen the cover of an ISO standard.
C isn't that close to the hardware. There is no standard way to disable interrupts,
or read register R7, or peek at the return address that goes back to the
caller, or test the arithmetic overflow flag of the CPU, if it has one, ...
Now C is close *enough* to the hardware that low-level-ish operating system
code, including device drivers, can be ported between machines. E.g. a UART
driver developed on x86 Linux can work on MIPS, if the same peripheral chip is
available. Furthermore, that driver is not at any serious disadvantage compared
to one written in assembly language for either processor.
>> This is not a "huge problem" in the world; on the contrary, it is a
>> non-problem, now that cheap 64 bit machines are available to consumers.
>
> Well, the balance between the cost of a CPU cycle vs. memory byte has
> shifted towards CPU. It is difficult to say whether that will stay so. When
> massively parallel architectures will arrive, the model of shared memory
> will inevitable die. There is no way to share memory between thousands of
> cores. This might shift the balance back, away from flat, isotropic memory
> models...
There is no way to share memory between millions of machines on an internet,
yet they all use a TCP/IP stack written in C.
A massively parallel machine with many cores will still have local memories,
with some software that uses them conventionally.
>> What would constitute sufficient difficulty in the integer-pointer conversion?
>> Sacrificing a goat for each instance?
>
> Making meaningless conversions unnecessary?
So what then implements the requirements served by those conversions?
Converting a number to a pointer is something which is used because it is needed.
>>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
>>> defined on each object.
>>
>> Variables declared "register" cannot have this operation applied to them.
>>
>> But even without this, the analysis is very easy for determining whether or not
>> a declared object is subject to the & operator over its scope.
>
> So, the program semantics and legality may depend on the outcome of
> register optimization?
The register storage class means that taking the address of the object is a
diagnosable constraint violation.
(It is additionally intended to be an optimization hint at the same time,
that access to the object should be fast.)
[toc] | [prev] | [next] | [standalone]
| From | "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> |
|---|---|
| Date | 2014-05-01 10:18 +0200 |
| Message-ID | <v76gg3ijutby.vdc53emm25e6$.dlg@40tude.net> |
| In reply to | #2078 |
On Wed, 30 Apr 2014 15:47:10 +0000 (UTC), Kaz Kylheku wrote: > If there is any suspicion that the variable is uninitialized, the case > can be made that it needs to be fixed. If a machine finds it hard to tell > whether the variable is uninitialized, a human being will also find it hard to > tell. All this is not needed if the language were properly designed. E.g. using the principle of safest choice (by default, initialized or not?), require everything explicitly initialized without default initialization defined (e.g. for pointers). If the programmer wants to leave a variable not initialized (once in a year), give him a keyword to state this. >> Anyway, a precaution that can be done by compiler but left to the >> programmer is a language design fault, which C pointers are. > > Not every precaution that can be done by the compiler *should* be done. Every, for economical reasons. Debugging is more expensive than design. Maintenance is more expensive than debugging. > Static checking is bane of programming. Ideally, everything should be dynamic, > especially type and dispatch. Binding should always be as late as possible. On the contrary. Late binding convert bugs into faults, e.g. type error into constraint violation/message-not-understood etc. This is intolerable from the software engineering POV. From the CS POV, there no dynamic languages, only poor static languages. You cannot have everything dynamic, you must stop the indirection somewhere. If you put all objects that accept a given operation together, that would constitute a perfectly static type. If that type is anonymous, that is a language fault, the type is semantically there. > Write in a dynamic language, and leave C for the device drivers, codecs, > OS schedulers, etc. Which implies that dynamic languages are incomplete. Why should anybody use such a language. Wouldn't it better to design and use a decent language instead? >>>> 4. Pointer arithmetic is a low level hack which should not be there, >>>> because it does not make any sense for variable sized targets or advanced >>>> structures like graphs and trees. >>> >>> Pointer arithmetic is necessary for managing variable-sized targets, >>> like records that have multiple variant fields, all in the same linear >>> memory block. These could be stuck into a graph structure. >> >> No. If you need a pointer to the next element you don't have to compute it. >> You just store it. Otherwise, see the position #1. > > But then you're dictating to me the memory layout. Why? A pointer can point anywhere. > Secondly, what if this is a third-party memory-mapped file where the layout is > imposed? You will need de-/serialize objects as with any other file. Memory-mapped files is a hack, unless we consider a pure object-oriented OS, without files, where everything is a persistent object. That would not be for C anyway, nor for poor old Windows nor Linux. >>> This is not a "huge problem" in the world; on the contrary, it is a >>> non-problem, now that cheap 64 bit machines are available to consumers. >> >> Well, the balance between the cost of a CPU cycle vs. memory byte has >> shifted towards CPU. It is difficult to say whether that will stay so. When >> massively parallel architectures will arrive, the model of shared memory >> will inevitable die. There is no way to share memory between thousands of >> cores. This might shift the balance back, away from flat, isotropic memory >> models... > > There is no way to share memory between millions of machines on an internet, > yet they all use a TCP/IP stack written in C. So what? You are again confusing completeness in narrow Turing sense with language design. We are talking about structuring the address space. The address space of Internet is *not* flat and *not* isotropic. q.e.d. > A massively parallel machine with many cores will still have local memories, > with some software that uses them conventionally. Yes, but the programmer of such systems will care about local memory barely more than he presently cares about L2-cache. >>> What would constitute sufficient difficulty in the integer-pointer conversion? >>> Sacrificing a goat for each instance? >> >> Making meaningless conversions unnecessary? > > So what then implements the requirements served by those conversions? > Converting a number to a pointer is something which is used because it is needed. It is never needed, because there is no proper method of obtaining such numbers in first place. If the method exist, it is pointer-to-number and back to pointer conversion. Which raises immediate question why number was needed as a middleman? Because the language lacks means of handling pointers as proper types and objects (e.g. in order to serialize them)? All cases where numbers are converted to pointers are at some I/O boundary and even then there always exist better ways. >>>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is >>>> defined on each object. >>> >>> Variables declared "register" cannot have this operation applied to them. >>> >>> But even without this, the analysis is very easy for determining whether or not >>> a declared object is subject to the & operator over its scope. >> >> So, the program semantics and legality may depend on the outcome of >> register optimization? > > The register storage class means that taking the address of the object is a > diagnosable constraint violation. So must have been the class of addressable objects. If the programmer's intent is to access the object via pointer, he should declare this in advance. If he mistakenly takes a pointer to an object that is not intended for aliasing, this is a serious bug, and must be flagged as such. Bugs related to aliasing are extremely hard to debug. The principle of safest choice. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2014-05-01 16:56 +0000 |
| Message-ID | <20140501064151.690@kylheku.com> |
| In reply to | #2092 |
On 2014-05-01, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
> On Wed, 30 Apr 2014 15:47:10 +0000 (UTC), Kaz Kylheku wrote:
>
>> If there is any suspicion that the variable is uninitialized, the case
>> can be made that it needs to be fixed. If a machine finds it hard to tell
>> whether the variable is uninitialized, a human being will also find it hard to
>> tell.
>
> All this is not needed if the language were properly designed. E.g. using
> the principle of safest choice (by default, initialized or not?), require
> everything explicitly initialized without default initialization defined
Before C99, C had "declarations before statements" (like "Wirthian" languages).
If declarations have to follow statements, you sometimes have to write
code like this:
int var;
lock(&obj->lock_var);
var = obj->memb;
I wrote something very similar to this just yesterday, inside
a USB driver.
If var had to be initialized, the compiler would still have to do all
the same analysis in order to optimize that away; it would have to
relize that the initial value has no "next use" in the flow graph.
This particular use goe away if we mix variable definitions with statements:
lock(&obj->lock_var);
int var = obj->memb;
This is supported in C starting with C99, and has been in C++ for a long
time (precisely because C++ objects with constructors do not support
this two-step initialization).
>> Static checking is bane of programming. Ideally, everything should be dynamic,
>> especially type and dispatch. Binding should always be as late as possible.
>
> On the contrary. Late binding convert bugs into faults, e.g. type error
> into constraint violation/message-not-understood etc. This is intolerable
> from the software engineering POV.
If you don't formalize late binding into the language, programmers
will reinvent it anyway, in an ad-hoc way.
Dynamic languages are well known for their productivity and robust
applications.
Whenever something falls down in computing, more often than not, some
statically typed trash is at the root cause.
> From the CS POV, there no dynamic languages, only poor static languages.
Complete nonsense. Languages are dynamic by default. All the pseudo-code
in CS textbooks and papers is essentially dynamic.
Statica analysis is just a way of classifying a certain subset of dynamic
programs: those which have the property that a type can be inferred for
every node in their graph (possibly after expanding that graph in the
face of "static polymorphism"), so that no expression has more than one type in
different run-time situations.
(Languages with explicit declarations for determining what type flows
into every node in the graph are obsolete dinosaurs; the state of the
art in static typing is inference.)
> You cannot have everything dynamic, you must stop the indirection
> somewhere.
Reductio ad 1 et 0.
Dynamic languages are supported by a kernel of run-time code that isn't
itself dynamic, and also by compiler generated code that isn't dynamic
either. It just "knows" that, say, two certain bits of a value are a
type tag: no other meta-tag tells it that.
Ultimately, bits are statically typed; we know that a bit cell has type "bit"
and only contains a 1 or 0; there is no need to check some other information to
verify.
> If you put all objects that accept a given operation together,
> that would constitute a perfectly static type.
Sure, a meaningless static type like "Object" which need not be mentioned int
the language.
>> Write in a dynamic language, and leave C for the device drivers, codecs,
>> OS schedulers, etc.
>
> Which implies that dynamic languages are incomplete. Why should anybody use
> such a language. Wouldn't it better to design and use a decent language
> instead?
They aren't. For instance Lisp machines were written entirely in Lisp,
interrupt-driven device drivers and all. There are nice implementatinos
of Lisp with good compilers. Whereas, say, Python or Ruby users call
C libraries for things like regex, crypto or image processing, Lisp
programmers use libraries written in Lisp for this, because the performance
is decent.
People don't write device drivers in Lisp nowadays though because platforms
dictate the methodology for those (so it is usually done in C).
Millions of programmers choose "incomplete" languages that don't even have
compilers, because they find them to be the right tool for the right job. They
have some ready-made framework, library and possibly "recipes" on how to
structure the major pieces together.
They aren't writing an device driver, so they don't care that they cannot.
However, a dynamic language can certainly be the "be all" system language
from the boostrap loader on up.
>>>>> 4. Pointer arithmetic is a low level hack which should not be there,
>>>>> because it does not make any sense for variable sized targets or advanced
>>>>> structures like graphs and trees.
>>>>
>>>> Pointer arithmetic is necessary for managing variable-sized targets,
>>>> like records that have multiple variant fields, all in the same linear
>>>> memory block. These could be stuck into a graph structure.
>>>
>>> No. If you need a pointer to the next element you don't have to compute it.
>>> You just store it. Otherwise, see the position #1.
>>
>> But then you're dictating to me the memory layout.
>
> Why? A pointer can point anywhere.
You're dictating that the pointer is *there* in the layout, rather than just
the next element itself (whereby we calculate the address of the element
ourselves, outside of the structure) That embedded pointer not even directly
possible if that layout is from a memory mapping that can be placed at any
address, and shared by processes.
>> Secondly, what if this is a third-party memory-mapped file where the layout is
>> imposed?
>
> You will need de-/serialize objects as with any other file.
Screw that; I want memory mapped!
> Memory-mapped files is a hack,
That is neither here nor there; they exist, developers sometimes want them.
They have measurable, demonstrable benefits. (As well as shortcomings.)
>>> Well, the balance between the cost of a CPU cycle vs. memory byte has
>>> shifted towards CPU. It is difficult to say whether that will stay so. When
>>> massively parallel architectures will arrive, the model of shared memory
>>> will inevitable die. There is no way to share memory between thousands of
>>> cores. This might shift the balance back, away from flat, isotropic memory
>>> models...
>>
>> There is no way to share memory between millions of machines on an internet,
>> yet they all use a TCP/IP stack written in C.
>
> So what? You are again confusing completeness in narrow Turing sense with
> language design.
I am not confusing anything. I know all all about Turing equivalence not
being expressivity equivalence. (And have had to hit numerous people on
Usenet over the head with that over twenty years.)
I didn't claim that C is an expressive language for writing an application
for a thousand cores that do not share memory well.
However, I think C will will end up used for programming parts of that system,
and perhaps even parts of the run-time support for whatever language is used
at the high level for harnessing those cores.
That machine will still need to to mundane things like boot up, or
push packets to and from some ethernet controller with DMA and interrupts,
etc.
C you there! :)
> We are talking about structuring the address space. The
> address space of Internet is *not* flat and *not* isotropic. q.e.d.
But you can get 64 kilobyte pieces of thanks to a popular C library! :)
>> A massively parallel machine with many cores will still have local memories,
>> with some software that uses them conventionally.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
See, some software: not all.
> Yes, but the programmer of such systems will care about local memory barely
> more than he presently cares about L2-cache.
The programmers of some kinds of applications already don't care about this
on boxes with just a handful of cores (perhaps one).
>>>> What would constitute sufficient difficulty in the integer-pointer conversion?
>>>> Sacrificing a goat for each instance?
>>>
>>> Making meaningless conversions unnecessary?
>>
>> So what then implements the requirements served by those conversions?
>> Converting a number to a pointer is something which is used because it is needed.
>
> It is never needed, because there is no proper method of obtaining such
> numbers in first place.
Yes there is; system documentation, data sheets.
> If the method exist, it is pointer-to-number and
> back to pointer conversion. Which raises immediate question why number was
> needed as a middleman?
Simply for the pragmatic reason that addresses on digital, binary computers are
numbers.
This can be abstracted away for objects that need not have a concrete,
particular address.
> All cases where numbers are converted to pointers are at some I/O boundary
> and even then there always exist better ways.
No, not all cases have to do with I/O.
Sometimes C programs use "spare bits" in pointers for additional information.
Some concurrent algorithms rely on this (like lock-free linked lists), and also
implementations of dynamic languages that are written in C.
Tn the implementation of the TXR language, every value is a C pointer
of type val, which is a typedef for obj_t *.
Pointers are relied upon to have an alignment of at least four bytes,
which leaves the least significant two bits open for use as a type tag.
So "fixnum" integers can be represented directly inside the pointer
value, as well as characters.
The tag is chosen such that the value 0 (bits 00) denote a heaped object.
That means that the pointer can be dereferenced directly.
>>>>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is
>>>>> defined on each object.
>>>>
>>>> Variables declared "register" cannot have this operation applied to them.
>>>>
>>>> But even without this, the analysis is very easy for determining whether or not
>>>> a declared object is subject to the & operator over its scope.
>>>
>>> So, the program semantics and legality may depend on the outcome of
>>> register optimization?
>>
>> The register storage class means that taking the address of the object is a
>> diagnosable constraint violation.
>
> So must have been the class of addressable objects. If the programmer's
> intent is to access the object via pointer, he should declare this in
> advance. If he mistakenly takes a pointer to an object that is not intended
> for aliasing, this is a serious bug, and must be flagged as such.
The Wirthian language commit a serious offense in this regard compared to C.
In Pascal and its ilk, you can change a procdure's conventional by-value
argument to a VAR argument. When the program is recompiled, calls to that
procedure now silently "steal" references to variables and may modify them.
C++ also has this in the form of references.
In C we at least have a loud and clear syntax that the address is being
taken: the & operator (though it can be hidden behind a macro).
Having to explicitly declare a permission for an address to be taken isn't such
a bad idea, but it can have downsizes. For instance, your program could really
benefit from taking the address of a variable in some third-party library.
Ooops, it is not declared for that!
In C we have the const qualifier whose behavior is such that the address of a
const qualified object is a pointer to a const-qualified type. When this
pointer is dereferenced, the resulting lvalue cannot be assigned; it is not
modifiable. This provides a reasonable middle ground: allow the address, but
one that gives rise to only read-only aliases.
> Bugs
> related to aliasing are extremely hard to debug. The principle of safest
> choice.
If that's the best way to write the program, then it is no harder to debug
than it has to be.
[toc] | [prev] | [next] | [standalone]
| From | "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> |
|---|---|
| Date | 2014-05-02 10:10 +0200 |
| Message-ID | <dpbh4lif541g$.1wok0ymoxov71.dlg@40tude.net> |
| In reply to | #2112 |
On Thu, 1 May 2014 16:56:50 +0000 (UTC), Kaz Kylheku wrote: > On 2014-05-01, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: >> On Wed, 30 Apr 2014 15:47:10 +0000 (UTC), Kaz Kylheku wrote: >> >>> Static checking is bane of programming. Ideally, everything should be dynamic, >>> especially type and dispatch. Binding should always be as late as possible. >> >> On the contrary. Late binding convert bugs into faults, e.g. type error >> into constraint violation/message-not-understood etc. This is intolerable >> from the software engineering POV. > > If you don't formalize late binding into the language, programmers > will reinvent it anyway, in an ad-hoc way. Sure, but that does not change the point: bind as early as you can. If the earliest possible point is run-time, be it so. > Dynamic languages are well known for their productivity and robust > applications. Just wait they arrive in your car's ECU... >> If you put all objects that accept a given operation together, >> that would constitute a perfectly static type. > > Sure, a meaningless static type like "Object" which need not be mentioned int > the language. The Universe as a whole is a meaningless thing. >>> Write in a dynamic language, and leave C for the device drivers, codecs, >>> OS schedulers, etc. >> >> Which implies that dynamic languages are incomplete. Why should anybody use >> such a language. Wouldn't it better to design and use a decent language >> instead? > > They aren't. For instance Lisp machines were written entirely in Lisp, > interrupt-driven device drivers and all. There are nice implementatinos > of Lisp with good compilers. Whereas, say, Python or Ruby users call > C libraries for things like regex, crypto or image processing, Lisp > programmers use libraries written in Lisp for this, because the performance > is decent. > > People don't write device drivers in Lisp nowadays though because platforms > dictate the methodology for those (so it is usually done in C). Thus dynamic language are unsuitable for the existing computational strata. You have a choice, either you change the hardware (where are infamous Lisp-machines?) or you ditch garbage languages. > Millions of programmers choose "incomplete" languages that don't even have > compilers, because they find them to be the right tool for the right job. Millions of programmers are unqualified for the job. And the industry of software design as a whole is a joke, for numerous reasons from economical and legal to the sad fact that software development is not really engineering and CS is not a science. >>>>>> 4. Pointer arithmetic is a low level hack which should not be there, >>>>>> because it does not make any sense for variable sized targets or advanced >>>>>> structures like graphs and trees. >>>>> >>>>> Pointer arithmetic is necessary for managing variable-sized targets, >>>>> like records that have multiple variant fields, all in the same linear >>>>> memory block. These could be stuck into a graph structure. >>>> >>>> No. If you need a pointer to the next element you don't have to compute it. >>>> You just store it. Otherwise, see the position #1. >>> >>> But then you're dictating to me the memory layout. >> >> Why? A pointer can point anywhere. > > You're dictating that the pointer is *there* in the layout, rather than just > the next element itself (whereby we calculate the address of the element > ourselves, outside of the structure) "next element itself" is a much stricter dictate and implementation burden. If it weren't so, and you could always have "the next thing", just as you wanted, you would be no need pointers in first place! >>> Secondly, what if this is a third-party memory-mapped file where the layout is >>> imposed? >> >> You will need de-/serialize objects as with any other file. > > Screw that; I want memory mapped! How do you ensure that object's representation in the memory is same? Deserialization is a process of doing this. Your pointer arithmetic is deserialization of pointer object from some numeric media. What you argue for, is merely performing deserialization each time you access serialized (as a number) pointer. Not always the best strategy. >>>>> What would constitute sufficient difficulty in the integer-pointer conversion? >>>>> Sacrificing a goat for each instance? >>>> >>>> Making meaningless conversions unnecessary? >>> >>> So what then implements the requirements served by those conversions? >>> Converting a number to a pointer is something which is used because it is needed. >> >> It is never needed, because there is no proper method of obtaining such >> numbers in first place. > > Yes there is; system documentation, data sheets. That does not require either pointer or conversions. E.g. in Ada type Processor_Status_Register is record ...; -- Whatever PS : Processor_Status_Register; for PS'Address use 16#FFFF_FFAC#; -- No pointers, no conversions >> If the method exist, it is pointer-to-number and >> back to pointer conversion. Which raises immediate question why number was >> needed as a middleman? > > Simply for the pragmatic reason that addresses on digital, binary computers are > numbers. No, they are not. The proper statement is that there exist mappings address to number and back. Which mapping is not even a bijection, on most machines. Merely fact that finiteness of any computer allows you to map anything there to number does not make anything number. In that sense any program is integer. Does that help? >> All cases where numbers are converted to pointers are at some I/O boundary >> and even then there always exist better ways. > > No, not all cases have to do with I/O. > > Sometimes C programs use "spare bits" in pointers for additional information. But these are not *numbers*. These are records, bit-fields etc. >>>>>> 7. Each object in C is assumed to be addressable, i.e. the &-operation is >>>>>> defined on each object. >>>>> >>>>> Variables declared "register" cannot have this operation applied to them. >>>>> >>>>> But even without this, the analysis is very easy for determining whether or not >>>>> a declared object is subject to the & operator over its scope. >>>> >>>> So, the program semantics and legality may depend on the outcome of >>>> register optimization? >>> >>> The register storage class means that taking the address of the object is a >>> diagnosable constraint violation. >> >> So must have been the class of addressable objects. If the programmer's >> intent is to access the object via pointer, he should declare this in >> advance. If he mistakenly takes a pointer to an object that is not intended >> for aliasing, this is a serious bug, and must be flagged as such. > > The Wirthian language commit a serious offense in this regard compared to C. Nope. C's parameters are broken, you should never be able to update an immutable input parameter. If the parameter is mutable, that must have an effect on the caller. Either this or that, by-copy vs. by-value is irrelevant. But the point stands: pointers introduce aliasing per intent and making all objects capable of being aliased is a language design fault. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-04-30 18:27 +0100 |
| Message-ID | <Coa8v.127640$t%4.123890@fx04.am4> |
| In reply to | #2056 |
"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:1965jbmywu22u$.9o9wv0bq5csu$.dlg@40tude.net... > On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote: > >> So, let's list some (what I recall right now...) of what I think >> C gets correct: >> >> 1) pointers > > Since C did almost everything wrong. Are you taking account of the fact that C is a low-level language? If not, then you can argue that any assembly language does everything 'wrong'. > I will comment only on pointers, which > is also an easy game. What is wrong with them: > > 1. Pointer types are improperly typed as they are matched by structure. > Thus you cannot have two distinct pointer types for the same target type. > The feature extremely important for building sorted containers and custom > memory pools. If you can't trust yourself to not get the two types mixed up, then you can wrap the target in a struct type. > 2. Pointers are not initialized with null, as they must for safety > reasons. > Neither are they checked for null when dereferenced. They often are checked for null (usually by the memory management of the hardware). Doing an explicit runtime check, except during debugging, would defeat the purpose of using C in the first place. And there are many pointer invalid values other than null. > 6. Pointers are easily converted to integers and many C programmers > consider such conversions OK, which leads to extremely fragile and > non-portable code. Conversion of integers /to/ pointers is more of a problem, or would be in the hands of a programmer who had no idea what he or she is doing. But usually there is a reason for it. > 7. Each object in C is assumed to be addressable, i.e. the &-operation is > defined on each object. This was tolerable half century ago, > notwithstanding that K&R were seemingly unaware of Boolean and packed > arrays. But now it is a heavy burden with machines of hundreds of > registers > and many leveled cache. If an object is legally addressable, that why not make that assumption? The implementer can take care of that if someone wants to use & on something (for objects that would otherwise only exist in registers, or not at all). If you mean packed arrays of bit values, then the language has never allowed individual bits to be addressable. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> |
|---|---|
| Date | 2014-05-01 10:18 +0200 |
| Message-ID | <1oz1ou4obfdrc.ihri7rhvc8gt$.dlg@40tude.net> |
| In reply to | #2080 |
On Wed, 30 Apr 2014 18:27:08 +0100, BartC wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:1965jbmywu22u$.9o9wv0bq5csu$.dlg@40tude.net... >> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote: >> >>> So, let's list some (what I recall right now...) of what I think >>> C gets correct: >>> >>> 1) pointers >> >> Since C did almost everything wrong. > > Are you taking account of the fact that C is a low-level language? If not, > then you can argue that any assembly language does everything 'wrong'. Oh, but this is different. Firstly, of course, you should define the "level". Presumably it is a level of abstraction away, but from what? Often repeated proposition that C is close to the hardware = not really abstracts the machine, is plain wrong. Most of C primitives do not really match the hardware architecture. In that sense C is by no means low-level. It is quite high-level in fact. It might have been low-level for PDP, in the time when the myth was established. There is little low-level in C in this sense now. C has an assorted set of abstractions, poorly chosen ones. This alone does make C low level, it does it wrong. Note that an assembly language does not suffer this problem as it indeed matches the hardware. If you consider "level" related to some abstract programming paradigm, yes, C is very low-level because it lacks a lot of things, starting with a decent type system, means of encapsulation etc. This, again, is not really comparable to assembly languages. Some of them have higher level features like macro capacities (AKA generic programming) missing in C. E.g. MACRO-11 assembly was arguably higher level than C in some aspects (and lower in others). >> I will comment only on pointers, which >> is also an easy game. What is wrong with them: >> >> 1. Pointer types are improperly typed as they are matched by structure. >> Thus you cannot have two distinct pointer types for the same target type. >> The feature extremely important for building sorted containers and custom >> memory pools. > > If you can't trust yourself to not get the two types mixed up, then you can > wrap the target in a struct type. But that won't be a pointer anymore. This is another language fault that you don't have a pointer interface abstracted. You cannot define a type and dress it as a pointer. But this is a "second" layer of faults C didn't even close to, because it lacks any use-defined type altogether. >> 2. Pointers are not initialized with null, as they must for safety reasons. >> Neither are they checked for null when dereferenced. > > They often are checked for null (usually by the memory management of the > hardware). Maybe, but we are talking about the language. Whatever the hardware does or not is irrelevant. After all C does not have exceptions to deal with run-time checks. >> 6. Pointers are easily converted to integers and many C programmers >> consider such conversions OK, which leads to extremely fragile and >> non-portable code. > > Conversion of integers /to/ pointers is more of a problem, or would be in > the hands of a programmer who had no idea what he or she is doing. But > usually there is a reason for it. Language design fault is that reason. >> 7. Each object in C is assumed to be addressable, i.e. the &-operation is >> defined on each object. This was tolerable half century ago, >> notwithstanding that K&R were seemingly unaware of Boolean and packed >> arrays. But now it is a heavy burden with machines of hundreds of >> registers and many leveled cache. > > If an object is legally addressable, that why not make that assumption? Sorry, I cannot decode this. "Legally" means according to the language? If X is legally addressable, it is not an assumption it is a fact that X is addressable. > If you mean packed arrays of bit values, then the language has never allowed > individual bits to be addressable. Because it didn't have them. The language designers didn't care, there is no arrays in C anyway. And since in PDP you indeed could address literally everything, even a machine register, they, likely, unconsciously projected this to every machine, if they thought about that, which I doubt. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2014-05-01 17:10 +0000 |
| Message-ID | <20140501095725.877@kylheku.com> |
| In reply to | #2093 |
On 2014-05-01, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: > On Wed, 30 Apr 2014 18:27:08 +0100, BartC wrote: > >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> news:1965jbmywu22u$.9o9wv0bq5csu$.dlg@40tude.net... >>> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote: >>> >>>> So, let's list some (what I recall right now...) of what I think >>>> C gets correct: >>>> >>>> 1) pointers >>> >>> Since C did almost everything wrong. >> >> Are you taking account of the fact that C is a low-level language? If not, >> then you can argue that any assembly language does everything 'wrong'. > > Oh, but this is different. Firstly, of course, you should define the > "level". Presumably it is a level of abstraction away, but from what? As a starting point, a good "rough" definition of a low level of abstraction means that programs for diverse appliactions look the same. If I look at the insides of a text editor, cryptographic library, image recognition, device driver, or game, and they all look like approximately the same cruft (for instance a column of machine language instructions), then they are at a low level of abstraction compared to their application domains. A very good definition of Abstraction Level comes from the Tunes project: http://tunes.org/wiki/abstraction_20level.html Especially the criterion in the last paragraph. "A set of programs is more high-level than another one if for each problem solved by the second set of programs, there exist a higher-level program that solves the same problem in the first set." A "program" can be taken to represent not necessarily an executable sitting on your disk, but a procedure, machine language instruction or any capsule of computation. So the criterion explains why machine language is low level. For any given problem solved using machine language, the same "set of programs" is applied: the same bag of machine instructions. This is why the solutions look the same. If I see 25 lines of disassembly listing, I have no clue whether I'm looking at a text editor, device driver, or image recognition code, since it's just a combination of the "programs": the little routines in the instruction set like "compare that register to that other one". > Often repeated proposition that C is close to the hardware = not really > abstracts the machine, is plain wrong. Most of C primitives do not really > match the hardware architecture. In that sense C is by no means low-level. Level is really a lattice. There is some ideal awy of expressing what I'm doing. And multiple, though diverse, directions away from that are "lower level". Processing data with Unix piping and text manipulation is often at an inappropriate level for that data. It's low-level in some sense in that it never gets away from the irrelevant details of how the printed representation of the data is delimited, and the code doesn't really express whatis going on; it just says "I'm a mass of shell cruft that has to be read in painstaking detail to decode what is going on".
[toc] | [prev] | [next] | [standalone]
| From | "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> |
|---|---|
| Date | 2014-05-02 09:22 +0200 |
| Message-ID | <hiq5gnxt58ok.pwmzb31qbz48$.dlg@40tude.net> |
| In reply to | #2113 |
On Thu, 1 May 2014 17:10:29 +0000 (UTC), Kaz Kylheku wrote: > On 2014-05-01, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote: >> On Wed, 30 Apr 2014 18:27:08 +0100, BartC wrote: >> >>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >>> news:1965jbmywu22u$.9o9wv0bq5csu$.dlg@40tude.net... >>>> On Mon, 28 Apr 2014 21:46:00 -0400, Rod Pemberton wrote: >>>> >>>>> So, let's list some (what I recall right now...) of what I think >>>>> C gets correct: >>>>> >>>>> 1) pointers >>>> >>>> Since C did almost everything wrong. >>> >>> Are you taking account of the fact that C is a low-level language? If not, >>> then you can argue that any assembly language does everything 'wrong'. >> >> Oh, but this is different. Firstly, of course, you should define the >> "level". Presumably it is a level of abstraction away, but from what? > > As a starting point, a good "rough" definition of a low level of abstraction > means that programs for diverse appliactions look the same. > > If I look at the insides of a text editor, cryptographic library, image > recognition, device driver, or game, and they all look like approximately the > same cruft (for instance a column of machine language instructions), then they > are at a low level of abstraction compared to their application domains. And why is it lower level? If the programs look same, that presumes that means they deploy are suitable for solving diverse problems (or that the computational power of the observer (human) is not suitable to distinguish them properly). This can be both lower and higher level. It depends on how the observed uniformity was achieved. If it was through generalization, that would be higher level. If it was through decomposition into lower-level primitives it could be lower level. As an extreme example consider a program in the God's language: Do it! Is it low or high level? > A very good definition of Abstraction Level comes from the Tunes project: > > http://tunes.org/wiki/abstraction_20level.html > > Especially the criterion in the last paragraph. > > "A set of programs is more high-level than another one if for each problem > solved by the second set of programs, there exist a higher-level program that > solves the same problem in the first set." This is merely a constraint to make things comparable, because it would make no sense to talk about a "higher-level" thing that does not solve the problems of interest in first place. > A "program" can be taken to represent not necessarily an executable sitting > on your disk, but a procedure, machine language instruction or any capsule > of computation. > > So the criterion explains why machine language is low level. For any given > problem solved using machine language, the same "set of programs" is applied: > the same bag of machine instructions. This is why the solutions look the same. > If I see 25 lines of disassembly listing, I have no clue whether I'm looking at > a text editor, device driver, or image recognition code, since it's just a > combination of the "programs": the little routines in the instruction set like > "compare that register to that other one". No. You just said that human sensing operates a language different from machine language. Which is why a human has difficulty recognizing meaning of machine code. There is nothing *here*, that makes machine language lower level. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
[toc] | [prev] | [next] | [standalone]
| From | "Rod Pemberton" <dont_use_email@xnothavet.cqm> |
|---|---|
| Date | 2014-04-28 20:59 -0400 |
| Message-ID | <op.xe1zoyii6zenlw@localhost> |
| In reply to | #2037 |
On Mon, 28 Apr 2014 12:23:05 -0400, bruce axtens <bugmagnet@outlook.com> wrote: > Is it fair to say that most of the Wirth-ian programming languages are > either dead or in palliative care? Delphi seems to be about the only > thing left with any life in it. Am I missing anything? > I think it's dead. Most people on other newsgroups seem to argue against me though when I say language 'X' or 'Y' or 'Z' is dead. Other than BASIC, I think the languages of our era (being presumptuous here) learned are dead: COBOL, FORTAN, Pascal, LISP, PL/I, Forth, Ada, etc. BASIC still seems to have a life in limited situations, e.g, industrial machines, hobbyists. Whenever I point out that nearly all the newer languages use or have used C as an intermediate representation, or as assembly, or derived their internal code from compiled C code, I get attacked on that one too, even though it's true. I can cite many of them. C and C++ and various derivatives, like Java, "won" the language wars. The other languages you see are all modern creations to handle various modern issues: internet, websites, etc. IMO, the TIOBE index confirms this. C and derivatives are the majority. Most others are insignificant. As a high-level language, I liked Pascal for the most part. It had some wierd stuff in it too though. It was well structured. The problem with Pascal, almost three decades ago when I learned it, was it had two serious problems. The first was that it didn't have pointers. This was safe, but really complicated programming certain solutions. Others have pointed out (pun-intended) that Pascal has pointers today. The second was that there was no ability to access low-level features of the machine. This was a problem in the era of cheap, personal, home computers. You were trapped inside a box which couldn't control the computer using Pascal. That's fine for some applications, but mostly just prevented programmers from using their machines. Even BASIC of that era provided mechanisms to do that, although they were custom to each version of BASIC. Rod Pemberton
[toc] | [prev] | [next] | [standalone]
| From | "Rod Pemberton" <dont_use_email@xnothavet.cqm> |
|---|---|
| Date | 2014-04-28 21:10 -0400 |
| Message-ID | <op.xe1z8das6zenlw@localhost> |
| In reply to | #2050 |
On Mon, 28 Apr 2014 20:59:12 -0400, Rod Pemberton <dont_use_email@xnothavet.cqm> wrote: > I think it's dead. Most people on other newsgroups seem to argue > against me though when I say language 'X' or 'Y' or 'Z' is dead. > Other than BASIC, I think the languages of our era (being presumptuous > here) learned are dead: COBOL, FORTAN, Pascal, LISP, PL/I, Forth, Delete "learned", editing error. RP
[toc] | [prev] | [next] | [standalone]
| From | Nils M Holm <news2009@t3x.org> |
|---|---|
| Date | 2014-04-29 07:52 +0000 |
| Message-ID | <bs942mFbgnkU1@mid.individual.net> |
| In reply to | #2050 |
Rod Pemberton <dont_use_email@xnothavet.cqm> wrote: > I think it's dead. Most people on other newsgroups seem to argue > against me though when I say language 'X' or 'Y' or 'Z' is dead. > Other than BASIC, I think the languages of our era (being presumptuous > here) learned are dead: COBOL, FORTAN, Pascal, LISP, PL/I, Forth, > Ada, etc. BASIC still seems to have a life in limited situations, > e.g, industrial machines, hobbyists. I think it is even worse. Every language todays either looks like C or it is *wrong*. Because The Industry demands programmers that are well-trained in C-like languages, and dealing with something that does not increase your market value is *wrong*. So other languages are only used by lunatics and academics. This seems to be the consent among contemporary software developers, and this is sad, because it kills creativity, diversity, and innovation. -- Nils M Holm < n m h @ t 3 x . o r g > www.t3x.org
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-04-29 09:45 +0100 |
| Message-ID | <WEJ7v.226243$hB4.80959@fx20.am4> |
| In reply to | #2050 |
"Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message news:op.xe1zoyii6zenlw@localhost... > On Mon, 28 Apr 2014 12:23:05 -0400, bruce axtens <bugmagnet@outlook.com> > wrote: > As a high-level language, I liked Pascal for the most part. It had > some wierd stuff in it too though. It was well structured. The problem > with Pascal, almost three decades ago when I learned it, was it had two > serious problems. The first was that it didn't have pointers. This > was safe, but really complicated programming certain solutions. Others > have pointed out (pun-intended) that Pascal has pointers today. It certainly had pointers when I used it in the late 70s. What it didn't have was a proper array type (you had to define fixed bounds for an array, which made it incompatible with an array with different bounds) and proper string handling. > The > second was that there was no ability to access low-level features of > the machine. This was a problem in the era of cheap, personal, home > computers. You were trapped inside a box which couldn't control the > computer using Pascal. These problems would have been easy to fix. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Jacko <jackokring@gmail.com> |
|---|---|
| Date | 2014-04-29 05:37 -0700 |
| Message-ID | <c2ed1b83-f58b-4c91-bec4-39560fa5d94a@googlegroups.com> |
| In reply to | #2037 |
I'm using free Pascal at the moment. Things I like about it are not having all the makefile and command line stuff getting in the way of doing things. The units feature is very good at this. The IDE is a bit limited, but not so much as to cause real problems. It's all text based, and includes a Free Vision (Turbo Vision clone) for simple text based "GUI" stuff. It supports various dialects, but the default is just fine. There are a few simplifications (or complications) based around declaring pointer types with self reference, and procedural and functional types, but otherwise quite nice. Minor irritations on naming parameters in forward declarations, and the necessity to use semicolons to separate different typed parameters in definitions, when commas are just as syntax unique. There are OpenGL units, and quite a few other nice utility units, full unlimited length ANSI strings, and nice object features. It's basically TP7 with some minor syntax changes, and it has support for many cross compilation targets, with a nice c.h file converter. I like C and Java too, but Java is far too complex to run a fast IDE, and C has very little in the way of controllable error code generation. I try not to use pointers when arrays will do, and consider that a good optimizer will do much of the ++ and the like when appropriate optimization is selected. Old does not mean useless, in fact I'm very happy to see such a language tool available. Cheers Jacko
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.misc
csiph-web