The “static” Keyword In Java 5.803k
Java Tutorial: “this” Keyword 5.589k
Interface in Java 4.627k
Java Tutorial: The “extend” Keyword 4.402k
Java's Access Specifiers 2.935k
Java Tutorial: Arrays 2.673k
Java Tutorial: Defining a Function 2.596k
The “abstract” Keyword In Java 2.316k
Xah's Java Tutorial 2.168k
There are several links to them from stackoverflow.com.
Java is the most inane language. I did Java for half a year in a day
job in 2000. At the time, i was not really sure what i was doing.
(this is a typical situation when coding in a day job on someone
else's project.) Then, in 2005 i studied Java in some detail, and
wrote my tutorial. However, i actually don't code Java, am not good at
it, and will never code anything in Java. (am rather sad that Google
choose it as its main lang. (but, it's still much better than C or C+
+.))
Also, of all big software companies, i HATE Sun Microsystems with
passion. It is the company with the most despicable marketing fuck,
and loves to create random meaningless jargons and abuse established
terms. For detail on the jargon part, see:
* Jargons of Info Tech Industry
* Interface in Java
* What are OOP's Jargons and Complexities
Of all the 2 thousand tech tutorials and essays i wrote about
computing in the past 10 years, the “What are OOP's Jargons and
Complexities” one actually among the top 5 i consider most
significant. Am proud of it.
for links, see:
http://xahlee.blogspot.com/2010/10/inanities-of-java.html
Xah ∑ http://xahlee.org/ ☄
> This month, my Lisp tutorial become quite popular.
...
> Lisp is the most inane language.
...
> However, i actually don't code Lisp, am not good at it,
For Java to succeed, surely it is not necessary to sow disinformation
and confusion amongst Lisp newbies?
--
RGB
Out of sheer curiosity I checked a few links.
Your problem with Java is that it is an OOP language, and you hate OOP.
OOP indeed isn't a one-size-fits-all tool. If you are unconfortable with
it or if it just simply does not serve your purpose it is quite okay to
leave it alone.
Case closed.
--
Mayeul
that can't be right. OOP feels so friggin' sweet in an apt language
such as Ruby (which is even far more OO than java)...
I just wanted to pipe in because I have a huge pet peeve on this. Java
has these things which Java calls "references". In any other context
besides Java, such things would be called pointers. Java has pointers
and does not have references using the technical language agnostic
terms. It's highly frustrating and annoying that Java decided to reuse
an existing concept and existing name, but the name formerly described
a related but very distinct concept. The only thing they did was
remove all forms of pointer arithmetic, but it's still pointers.
Related: Java only has pass by value - its functions pass its pointers
(which it calls references) by value.
So, now I'm stuck calling them references in most situations when
they're most clearly not, all because that's what the language
standard calls them.
Joshua, OF COURSE java doesn't have pointers. How else do you explain the
fact that we get NullPointerExceptions all over our code? It's the
complete lack of pointers!
tom
--
She got destiny, she got supremacy, she got everything ever from A to Z.
The term "pointer" does have a PR problem - they have caused any number
of bugs in apps written in C and its relatives. Such bugs are typically
the result of careless programming - like all bugs, really - but pointers
got a reputation as a "dangerous" feature nonetheless. So I can under-
stand why Sun wanted to avoid using the dreaded "P word." But Joshua is
right - they chose the wrong replacement for it.
sherm--
--
Sherm Pendley
<http://camelbones.sourceforge.net>
Cocoa Developer
Do you mean Java only has pass by copy? All parameters to methods In
Java are copied, whether they be primitives or object pointers. For
pointers, the method receives a new pointer to the same object.
That is why you can do things like setting an object parameter to a new
instance and it won't affect the reference that was passed in from
outside method scope.
2 x yes
Arne
One could argue that constructs that make small mistakes result in
serious problem to be a very good definition of dangerous when
it comes to programming languages.
Arne
Wrong.
C# use the term reference as well.
> Java has pointers
> and does not have references using the technical language agnostic
> terms. It's highly frustrating and annoying that Java decided to reuse
> an existing concept and existing name, but the name formerly described
> a related but very distinct concept.
http://en.wikipedia.org/wiki/Reference_%28computer_science%29
"For this reason, a reference is often called a pointer or address"
> So, now I'm stuck calling them references in most situations when
> they're most clearly not, all because that's what the language
> standard calls them.
You should not expect all language to use C++ terminology.
Arne
Yes, that's my feelings as well. I don't think i like OOP at all, but
as example, i don't have a problem using it in perl, javascript. And
i know it's in python and ruby too. Even i hardly ever use them. I can
understand that oop is quite useful in some programing tasks, and or
that it is a alternative valid way of modeling software other than
functional programing.
i think, if i were to summarize my hatred of java by single sentence,
it would be more to it being a low level, or system lang. (in the same
way, i hate C, C++, even though i don't even have a working knowledge
of these) Sun Micro's tremendouly marketing shit piled onto Java just
made my hatred of java far far worse.
Xah ∑ http://xahlee.org/ ☄
btw, what's the tech diff between pointer and ref? is the diff of term
mostly due to just C++ using them both and distinguish them?
i scan'd Wikipedia
http://en.wikipedia.org/wiki/Pointer_%28computing%29
http://en.wikipedia.org/wiki/Reference_%28computer_science%29
but isn't much helpful.
--------------------------------------------
in any case, this is not the type of jargon abuse i hated about Sun
Micro though. The “pointer” and “reference” type of terminologies are
i think oldish classical comp sci of 1960 or 70s. Lots of those term's
meaning changes over time. e.g. data structure once meant low level
stuff as in C's struct, or linked list, at the hardware level, but
today, people don't even know what's a “struct”. To most programers
today, “data structure” more means dimention or shape of nested list/
hash etc.
similiar, the term “list”, means entirely different things in
different langs. Classically, in C era, they usually always mean
linked list at the level of what we'd say in compiler implementation.
But today, most lang are high level (or called scripting langs), and
“list” simply means what java calls Collection interface.
Xah ∑ http://xahlee.org/ ☄
First, C# is widely known to be a Microsoft "copy" of Java, so it is
no surprise that it copies the Java terminology, so that example isn't
particularly illuminating example.
Second, do I really have to argue when Java throws
'NullPointerException's?
Third, you're quoting wikipedia, not the most reliable of sources.
Admittingly, I also went there looking for sources.
Let me put it another way. At the very least, I can claim that the
definitions of "pointer" and "reference" were quite clear in the
context of the extended family of C-like languages before Java. It is
my understanding that C effectively defined the term "pointer". Later C
++ defined an additional concept which it called "references".
Java is a member of the extended family of C-like languages.
Specifically, Java was designed as a "better" C++, itself a derivation
of C. It shares much of the same syntax and semantics, and the
designers of Java had C++ in mind as the starting point for their new
language. As it is clearly based off of C++ and C, and shares much of
the same syntax, semantics, and nomenclature, it is a horrible
disservice that it should take two pre-existing names of terms and so
conflate and confuse them.
So yes, I expect that when Java takes from C++, it should use the C++
terminology. At the very least, it should not have taken from C++ two
very related but distinct ideas, taken the semantics of one but the
name of the other. It just confuses people. Yes it's not that
confusing, and yes it's not that bad - that's why I called it a pet
peeve. It's still annoying.
I also suspect as Sherm Pendley does else-thread that this decision
was taken because "pointer" was a dirty word with regards to their
design goals for Java, but that doesn't excuse them on this.
The term "reference" has been used to describe Lisp and similar
languages since the 60's. References aren't the same as pointers.
Pointers must have a dereferencing operator to access elements. In C
these are prefix * and the abbreviation ->, as in p->a, which is short
for (*p).a. Pointers and pointer arithmetic are not connected at the
hip. Pascal and Ada have pointers but no pointer arithmetic.
References are present along with pointers and values in C++ (which
predates Java, I believe). Many languages include both references and
values: Javascript, Perl, Python, and Lisp are a few. All this is to
say that your anger is probably misplaced. References really aren't
pointers. Java wasn't first or last to use the term. The
NullPointerException is not too surprising if you consider that JVM's
are normally implemented in C or C++.
I believe that is the only way to pass parameters in Python - by
"value of a reference".
>
> So, now I'm stuck calling them references in most situations when
> they're most clearly not, all because that's what the language
> standard calls them.
You can't increment/decrement them and you can't assign an arbitrary
memory location (including invalid memory locations) as you can C/C++
pointers. They can only "point" to controlled areas of memory where an
object of a specific type exists. They aren't the same as C/C++
pointers which I think is why they didn't call them pointers. But I
have no idea why they used NullPointerException instead of
NullReferenceException.
Java references are indeed different from C/C++ pointers. They have more
in common with Pascal pointer types.
Patricia
A pointer is a datatype whose value is the address of some other object
(or possibly itself, if you really want to blow your mind). References,
can have a few different meanings, but the general gist of references
(think `pass by reference') is that it is a source-level alias for a
variable. Hence why C++ references are lvalues.
What Java calls object references is perhaps most well-described as
pointers, but pointers have a somewhat bad rap do to the memory safety
problems inherent in pointer arithmetic.
--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth
>
>First, C# is widely known to be a Microsoft "copy" of Java,
>no surprise that it copies the Java terminology
No ... C# is widely misperceived (mainly by Java users) to be a
derivative of Java. However, beyond minor syntactic differences lie
much greater semantic differences. C# and Java are, in fact, quite
different languages that only superficially look similar.
OTOH, J# definitely is a virtual clone of Java with nearly identical
syntax and semantics.
What really makes C# most similar to Java is that it is yet another
attempt at dumbing down C++ for use by - to put it charitably - those
who probably should not be programming in the first place.
Moreover, the .NET CLR was not a copy of the JVM ... it evolved from a
fusion of COM with the managed environments of Visual Basic and Foxpro
(all of which predate Java). Microsoft's IL byte code evolved from
the Visual Basic pcode engine which itself evolved from prior versions
going back at least to 1985 and Microsoft C 3.0.
[I can't locate a cite for the introduction of the M$ pcode compiler,
but I know from personal experience with C 3.0 in 1987 that some
version of it was included. What I remember most about it was that
there was absolutely no floating point support.]
There is little doubt that there was cross pollination of CLR from the
MSJVM which was an incompatibly extended 1.0 JVM that Sun sued to
exterminate. But feature and implementation wise, CLR and JVM were
going in parallel but different paths almost from the start.
[Similarities between the JDK and .NET programming frameworks are for
a different discussion.]
>Let me put it another way. At the very least, I can claim that the
>definitions of "pointer" and "reference" were quite clear in the
>context of the extended family of C-like languages before Java. It is
>my understanding that C effectively defined the term "pointer".
>Later C++ defined an additional concept which it called "references".
No, Algol 68 introduced both the concept of an address container
variable of and by-address parameters, and the distinction between
maybe-NIL (NULL) and never-NIL usages.
Algol called them all "references" and used the keyword "REF" to
designate both address containers and by-address parameters. C's
pointers and Java's references are semantically equivalent to Algol's
REF variables ... C++ references combine semantics of both Algol's REF
variables and REF parameters.
AFAIK, C introduced the term "pointer" into popular usage and also
introduced the explicit dereference operator ... Algol REF types were
implicitly derefenced in most common uses - they required a type cast
for uncommon uses. (Algol also introduced type casting as we know it
in C.)
[Algol 60 had a POINTER keyword ... at least the Burroughs
implementation did ... but I don't recall specifics of its use. Algol
68 had only REF and mainly is responsible for pointer and reference
semantic as we recognize them today.
The B language from which C evolved also had a dereference operator
but no identifiable pointer type - data in B was just "bits" collected
into "words".]
>Java is a member of the extended family of C-like languages.
>Specifically, Java was designed as a "better" C++, itself a derivation
>of C. It shares much of the same syntax and semantics, and the
>designers of Java had C++ in mind as the starting point for their new
>language.
Not really. Gosling wanted to use a familiar syntax (for some notion
of "familiar"), but semantically he wanted to move away from C++ ...
he has written at length about his motivations for the differences in
object models and the elimination of pure procedural features.
C++ allows OOP whereas Java requires it ... it is not possible to
write Java code that does not somehow use objects. In contrast, it is
perfectly possible to write C++ code that uses no objects at all.
[And yes, I am aware that structures *are* objects in C++.]
Some people claim that C++ code that avoids objects is just C code -
sometimes they qualify it as "better C". But C++ is not a C superset.
C overlaps the procedural subset of C++ to a very large extent (about
99%), but each has semantics which are not supported by the other.
This is true regardless of which standard you choose for either
language. Because of this, I maintain that one can write purely
procedural code which is uniquely C++.
>As it is clearly based off of C++ and C, and shares much of
>the same syntax, semantics, and nomenclature, it is a horrible
>disservice that it should take two pre-existing names of terms and so
>conflate and confuse them.
There is some semantic overlap between Java objects and C++ objects,
but much less than people logically might assume given the similarity
in syntax.
>So yes, I expect that when Java takes from C++, it should use the C++
>terminology. At the very least, it should not have taken from C++ two
>very related but distinct ideas, taken the semantics of one but the
>name of the other. It just confuses people. Yes it's not that
>confusing, and yes it's not that bad - that's why I called it a pet
>peeve. It's still annoying.
I applaud any attempt toward establishing a canon of terminology. I
despise authors who use acronyms without first defining them, who give
new meaning to an existing acronym (within the same field) and who
invent new acronyms for things that already have acronyms - all common
occurrences in CS related papers which are not so common in papers
from other fields.
>I also suspect as Sherm Pendley does else-thread that this decision
>was taken because "pointer" was a dirty word with regards to their
>design goals for Java, but that doesn't excuse them on this.
I suspect you are correct, but offer this pointer to the reference
discussion above 8-)
George
"George Neuner" <gneu...@comcast.net> wrote in message
news:t3lfb6ptmem1bif2g...@4ax.com...
> On Thu, 14 Oct 2010 19:10:10 -0700 (PDT), Joshua Maurice
> <joshua...@gmail.com> wrote:
>
>>
>>First, C# is widely known to be a Microsoft "copy" of Java,
>>no surprise that it copies the Java terminology
>
> No ... C# is widely misperceived (mainly by Java users) to be a
> derivative of Java. However, beyond minor syntactic differences lie
> much greater semantic differences. C# and Java are, in fact, quite
> different languages that only superficially look similar.
C# has evolved to become a much bigger language than Java, and significantly
different, e.g. the two took very different approaches to generics. But C#
1.0 was very much Java with slightly different syntax, and a few added bits
of syntactic sugar (events, delegates, stc.)
I think a lot of this stems from the fact that Microsoft took their JVM
and used it as the basis of the .NET runtime.
I did not actually know this. Is there a source for this? All I've ever
heard is that that .NET runtime began as a modified MS JVM.
Much of it is documented, but I'm afraid it is spread through decades
of whitepapers, product release, developer and technical notes. If
you have access to some old versions of M$ developer tools and SDKs,
you should be able to find some of it.
Some history you can probably glean by searching MSDN. Searching
"p-code", for example, you'll find - eventually - articles on QBasic,
debugging p-code executables in DOS 4 and how to get VB2 to make
p-code OLE DLLs for Windows 3.1 (all of which predate the first
release of JVM).
The only non-M$ source I'm aware of is in Kevin Burton's book:
".NET Common Language Runtime - Unleashed".
The first chapter talks some about the evolution of COM into CLR and
discusses the goals of the various intermediate projects - which IMO
pretty clearly demonstrates that CLR had different goals than JVM from
the start. Burton doesn't really establish a clear time line for the
history, but he does touch briefly on most of the salient points.
There are other interesting tidbits scattered through the book.
[It's a 1000 page book so don't buy it for a history lesson ... but
despite the age (2002), IMO it's still one of the best introductions
into .NET development.]
Sorry I can't just point you to a URL.
George
This is an often misunderstood aspect of C and C++. Attempting any
kind of "unorthodox" pointer cast or pointer arithmetic results in
undefined behavior. You're not allowed to have a pointer pointing to a
sufficiently different type and dereference (with some small
exceptions).
C and C++ could very well have the full bounds check, type checking,
etc., of Java. It's not required by the language standards, but it's
allowed, whereas Java requires it. The C and C++ standards are in
terms of an abstract machine, so there is no requirement that a C
pointer be an actual hardware memory address. It's just that the most
common implementation of C and C++ is that pointers are raw memory
addresses of the underlying hardware (as this is consistent with the
general design goals of C and C++).
However, as evidenced by "NullPointerException" and well known facts
of JVM implementations, this is also the common and intended
implementation technique for Java. Each Java reference is commonly
just a hardware memory location, though it's not required to be so. At
the compiler level, pointer arithmetic is simply disallowed whereas in
C and C++ it is allowed, but "bad use" results in undefined behavior.
> But I
> have no idea why they used NullPointerException instead of
> NullReferenceException.
I would surmise that's because the expected underlying implementation
technique is the same as C pointers, and because Java references were
modeled after C pointers.
I still say that Java was intended to be a "better" or "safer", and
more portable, C++, and many of its ideas were directly taken from C
and C++, though greatly modified since then to meet Java's new design
goals. Java's syntax is an obvious derivation of C and C++, and its
closest past relatives are C and C++, so again to purposefully
conflate and confuse these two pre-existing terms is a disservice.
While I dispute the claim that Java references are "very" different
from C and C++ pointers, I can continue from what you just said to
again conclude that Java did a disservice by using the term
"reference" instead of the well known term "pointer".
I won't speak for Xah, but I suspect many people (especially that use
CL) don't get Java's very inexpressive form of OO, and consider it
pretty much broken.
Agreed. I think Sun made a bad choice in moving in the direction of
muddled terminology, rather than going for clarity and education.
Patricia
:-)
Arne
But the C standard also uses the word "pointer" to refer to
a *value* of pointer type. See, for example, C99 7.20.3.3p3:
The malloc function returns either a null pointer or a pointer to
the allocated space.
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
That does nothing to address my concern. It fact, it adds to my
concern. My concern is: Java is a derivative of C and C++, and Java
shared a lot of the common syntax and semantics of C and C++. As such,
it causes undo confusion to purposefully confuse and conflate two
formerly distinct, well defined terms.
> However, this is another meaning of »pointer« than in C,
> where pointers are not values, but variables (which are
> called »objects« in C):
>
> »A pointer type describes an object whose value provides
> a reference to an entity of the referenced type.«
>
> ISO/IEC 9899:1999 (E), 6.2.5, #20
>
You cherry picked quotes, and/or the quotes are incorrect. The
terminology in this domain of discourse is loose. This probably is
because we all understand what's going on. It's like mixing up class
and object - you instantiate a class to create an object. You can't
new a class, though we all know what the speaker means. Your cherry
picked quote is an informal use of the term "value". A Java reference
is not a "value", even according to the Java standard.
What follows are the actual definitions, simplified for brevity. (I
don't want to quote an entire treatise on type theory.)
In C, objects are pieces of memory (on some abstract machine) which
hold values. A value of an object is the sequence of bits of the
object, aka the data contents of that object. Each object has a type
which constrains the allowed bit patterns of the object, and provides
a means to interpret those bit patterns, and provides operations on
those bit patterns.
In C, variables are objects which have declarations and definitions
with names in source code.
//Please forgive the C code.
//x is a variable and an object
int x;
//y is a variable and an object, *y is an object but not a variable
int* y = new int;
In C, a pointer is a somewhat vague term. A type can be a pointer (a
pointer-type). An object can be a pointer (an object of pointer-type).
A variable can be a pointer (an object of pointer-type).
Obviously, in Java the situation is slightly different because Java
defines Object to be a very particular thing, and Java defines objects
to be garbage collected entities allocated from the heap. The
definition of "value" remains largely unchanged: a value is the "bit
pattern" (simplification) of a Java object, a Java reference, or a
Java primitive. A value is the current contents of the entity, the
state of the entity.
> So, matching up terms from different languages is a difficult
> business where it does not matter much if the same words
> are used or not. (Strictly, C does nowhere define »pointer«
> nor »pointer type«, but only says what a pointer type
> »describes« - a wording too vague for my taste.)
It's only difficult in this case because Sun purposefully changed the
meaning, and their change largely broke with past definitions of the
terms. The syntax of Java references and C pointers is largely the
same, and the semantics are exactly the same. A Java reference behaves
exactly like a C pointer (except with null pointer checking and no
pointer math). It does not behave as a C++ reference, which does not
have a distinct "state" apart from the referred-to object. C++ has
pass by reference and pass by value. Java only has pass by value - but
the only things which can be passed are primitives and Java
references.
Again, my contention is that they didn't need to pick a new word which
could cause confusion when a clear and precise term, pointer, clearly
and aptly described the semantics, and again, it's only a minor
inconvenience. It's not the end of the world.
Pretty much, except that an object doesn't necessarily inherently have a
type. For example, malloc() allocates memory and returns a void*
pointer to it; that memory doesn't have a type until you impose one on
it, for example by assigning the void* pointer to a some_type* pointer
(the standard uses the term "effective type".
(Note that the C++ standard's definition of "object" is very similar
to C's; a C++ "object" isn't necessarily of some class type.)
The sequence of bits is the representation of an object. The value is
an interpretation of those bits with respect to some specified type.
> In C, variables are objects which have declarations and definitions
> with names in source code.
> //Please forgive the C code.
> //x is a variable and an object
> int x;
> //y is a variable and an object, *y is an object but not a variable
> int* y = new int;
That's a perfectly reasonable definition of the word "variable", but the
C standard doesn't define or use the term.
> In C, a pointer is a somewhat vague term. A type can be a pointer (a
> pointer-type). An object can be a pointer (an object of pointer-type).
> A variable can be a pointer (an object of pointer-type).
If you think of "pointer" as an adjective, there's no vagueness;
you can have a pointer type, a pointer object, or a pointer value.
But yes, the unqualified term "pointer" is potentially ambiguous.
It most commonly refers to a pointer object, though the standard
also uses it to refer to a pointer value. (I don't think a pointer
type is commonly called a "pointer", though.) In practice this
doesn't usually cause problems; in most contexts the meaning is clear
enough, and when it isn't it's easy enough to qualify it.
[...]
I think C# was heavily influenced by Java, sufficiently so that you
could put a link in there on one of those "History of Programming
Languages" timelines. I might even go so far as to call it a
`derivative', by which I mean that C# incorporated some concepts from
Java and learned from some of the mistakes that Java made in the
language. Which also means that Java is, to a degree, derivative of C#,
especially in the realm of generics.
An acyclic graph the history of programming languages is not.
I completely agree that:
- C# was heavily influenced by Java when it started
- ideas for Java 7 has been heavily inspired by C# 2/3/4
But Java got generics a year before C#, so ...
Arne
Would you agree I can do:
int *a = (int *) 22222222;
double *b = (double *) 1111111;
and the memory addresses do not have to be valid to compile and
attempt a run?
How would you do that in Java with references?
or how would you use Java references and do:
while (*myInt++ != 0)
Would you tell a C programmer who wanted to convert his code to Java
that "You don't have to worry about your code that uses pointers -
Java has you covered there, except they call them references"??
You seemed to miss something I said, which you even quoted. Let me
replicate it:
> Attempting any
> kind of "unorthodox" pointer cast or pointer arithmetic results in
> undefined behavior.
As I said, the difference between Java references and C pointers
largely is no pointer math and no null pointer checking. Obviously I
missed "casting from unrelated types without runtime checks" as well.
I also emphasized that the difference largely was when you misuse C
pointers, you get undefined behavior, whereas when you misuse Java
references, you get well defined behavior (typically an exception).
Obviously they're not interchangeable. However, under "correct use"
their semantics are mostly the same, much moreso than C++ references
and Java references, enough that it causes /minor/ confusion because
of the ill naming of Java references.
What do you mean by undefined behavior? That it is up to the compiler
implementation what takes place? I think every C compiler will produce
the same output from
int *ip = (int *) 222222;
And I think a lot of applications depend on that compiler output. How
else to write to video card memory that is at memory address 222222?
Tthe C standard does not specify any specific behavior for this
instruction. It's entirely implementation dependant.
It is exactly the case for most other programming languages.
In most other programming language, you may have a pair of functions
peek(address) and poke(address,byte) to access random memory bytes. The
same HAS TO BE DONE in C if you want to write a portable program.
Notably, C is totally useless when it comes to device drivers on x86
processors, since they are usually accessed not in the memory address
space, but in the I/O address space with the INP and OUT
microinstructions. So you need a iopeek() and iopoke() pair of
functions anyways.
In conclusion, pointer and pointer arithmetic in C is useless and should
be removed from any serrious system programming language. You can do
arithmetic with integers, and let the peek and poke primitive deal with
the mapping between integers and hardware addresses.
--
__Pascal Bourguignon__ http://www.informatimago.com/
Really off-topic here, but let me correct this. While I agree that
this should be done for other reasons, portability is not one of them.
As soon as you're writing to particular hardware memory addresses,
there is no such thing as portability, with peek and poke functions or
not. It is inherently tied to the system, and the C standard says
little to nothing about such things (though it was explicitly written
to allow the system to take some of the undefined behavior and make it
defined /for that platform/).
What I have said in this thread was for portable C programs, aka
programs written to the C standard and not to platform extensions.
Obviously writing device drivers and such is possible in C and not in
Java because of C's unchecked pointer casts and other "unsafe" pointer
stuffs. It's not fair to compare this. What is fair is to compare the
semantics of pointers and Java references. You can assign to a pointer
without changing the pointed-to object, changing a passed by value
pointer in a function call leaves the callee pointer unchanged, and so
on. This is very much unlike C++ references which act more like
aliases, and I again contend that because Java in its beginning
largely lifted its syntax and semantics from C++, it should not have
conflated and confused these two terms because it causes (minor) undue
confusion in the communities.
I beg to differ.
You can get your addresses from a configuration file.
The semantics and of sequences of peeks and pokes depend more on the
device, than on the system. There may be different routing, it's true,
but this also can be dealt with in a modula way. Ultimately, on sane
hardware, I think it's perfectly possible to write portable drivers or
systems. Linux and Microsoft Windows are clear examples.
> What I have said in this thread was for portable C programs, aka
> programs written to the C standard and not to platform extensions.
> Obviously writing device drivers and such is possible in C and not in
> Java because of C's unchecked pointer casts and other "unsafe" pointer
> stuffs. It's not fair to compare this.
I'm saying you can do the same in Java provided the JVM gives you access
to a low level peek and poke, and some wait to control timing
(eg. disable garbage collection for time-critical sections). Or any
other programming language such as Lisp on the LispMachine.
> What is fair is to compare the semantics of pointers and Java
> references. You can assign to a pointer without changing the
> pointed-to object, changing a passed by value pointer in a function
> call leaves the callee pointer unchanged, and so on. This is very much
> unlike C++ references which act more like aliases, and I again contend
> that because Java in its beginning largely lifted its syntax and
> semantics from C++, it should not have conflated and confused these
> two terms because it causes (minor) undue confusion in the
> communities.
There's so few words...
>Also, of all big software companies, i HATE Sun Microsystems with
>passion
You are a bit out of date. It has not existed for some time.
Perhaps the rest of your opinions are out of date too.
--
Roedy Green Canadian Mind Products
http://mindprod.com
Microsoft has a new version out, Windows XP, which according to everybody is the "most reliable Windows ever." To me, this is like saying that asparagus is "the most articulate vegetable ever."
~ Dave Barry
Some references for those interested:
- http://63.249.85.132/langs/bcpl/bcpl.html
- http://cm.bell-labs.com/cm/cs/who/dmr/chist.html
> ...
> George
Java's form of OO seems quite on par with my academic education and very
competitive with state-of-the-art alternate approaches, but I stay open
to suggestion.
What exactly do you mean by CL? Google seems to leave me with a lot of
old candidates.
--
Mayeul
CL means Common Lisp. Common Lisp has a general OOP system called
CLOS, see
http://en.wikipedia.org/wiki/Common_Lisp_Object_System
OOP in lisp predates java. I don't know CL so i cant really say but i
think Java heat around 1990s brought invigoration into CLOS, but am
not sure to what degree, whether there's new work into it or new spec
etc. But certainly more awareness and use.
Xah ∑ http://xahlee.org/ ☄
Ahhh, how quickly they forget!!! BLISS <http://en.wikipedia.org/wiki/BLISS>
predated C (at least publicly), and not only had pointers and an explicit
dereference operator (the infamous "dot"!) but pointers in BLISS could be
restricted to bitfields within words, e.g., this BLISS expression:
foo[13]<12,4> = .foo[13]<12,4> + 5;
would have to be written this way (or equiv.) in C:
foo[13] = (foo[13] & ~0xf000) | ((foo[13] + (5 << 12)) & 0xf000);
-Rob
p.s. Sure, one might well object that C has bitfields, so one could
define FOO as an array of structs of a chosen type, then say:
foo[13].my_nibble += 5;
Well, BLISS had macros, so you could easily define "my_nibble" as "12,4"
then say:
foo[13]<my_nibble> = .foo[13]<my_nibble> + 5;
But even better, BLISS has "structures" which were actually little
*user*-defined pieces of code for calculating a pointer, including
subfields [the "P" (offset) & "S" (width) values above], so a more
idiomatic way to write it [assuming "foo" had previously been "mapped"
with an appropriate structure] would be:
foo[13, my_nibble] = .foo[13, my_nibble] + 5;
-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
> Java's form of OO seems quite on par with my academic education and
> very competitive with state-of-the-art alternate approaches, but I stay
> open to suggestion.
>
> What exactly do you mean by CL? Google seems to leave me with a lot of
> old candidates.
CL in this context would be Common Lisp. CL has an object system -
CLOS - which is very different than Java's and whose ancestors diverged
from the ancestor's of Java's quite a long time ago. It's different to
the extent that people only exposed to Java-style OO will often reject
CL's object system as not being OO at all (despite the fact that it's a
relatively small amount of work to implement a Java-style OO system in
CLOS).
Not implying I am a great result of my education, but in my case it was
more:
- Theory of abstract classes and polymorphism, pseudo-language and
trivial design patterns.
- UML
- C++
- And /then/, Java.
>> competitive with state-of-the-art alternate approaches, but I stay open
>> to suggestion.
>
> Alan Kay coined the term �OOP� in 1967.
> In 2003, he wrote with regard to OOP:
>
> �It can be done in Smalltalk and in LISP. There are
> possibly other systems in which this is possible, but
> I'm not aware of them.�
>
> http://www.purl.org/stefan_ram/pub/doc_kay_oop_en
>
> For example, in Java, blocks are not objects, while OOP
> makes heavy use of (possibly, parameterized) blocks as
> objects. Also, Java has many primitive values that are not
> objects.
Okay. I guess I concentrated too much on Java to realize the value of those.
--
Mayeul
>George Neuner <gneu...@comcast.net> wrote:
>+---------------
>| AFAIK, C introduced the term "pointer" into popular usage and also
>| introduced the explicit dereference operator ...
>+---------------
>
>Ahhh, how quickly they forget!!! BLISS <http://en.wikipedia.org/wiki/BLISS>
>predated C (at least publicly), and not only had pointers and an explicit
>dereference operator (the infamous "dot"!)
You're right ... I did forget about BLISS. However, my comment was
about when the term entered popular usage - which I don't believe
BLISS accomplished.
FWIW: some of the early Lisps had single word "boxes" - the idea of
the pointer is as old as programming itself.
> but pointers in BLISS could be
>restricted to bitfields within words, e.g., this BLISS expression:
>
> foo[13]<12,4> = .foo[13]<12,4> + 5;
>
>would have to be written this way (or equiv.) in C:
>
> foo[13] = (foo[13] & ~0xf000) | ((foo[13] + (5 << 12)) & 0xf000);
>
>
>-Rob
>
>p.s. Sure, one might well object that C has bitfields, so one could
>define FOO as an array of structs of a chosen type, then say:
>
> foo[13].my_nibble += 5;
>
>Well, BLISS had macros, so you could easily define "my_nibble" as "12,4"
>then say:
>
> foo[13]<my_nibble> = .foo[13]<my_nibble> + 5;
>
>But even better, BLISS has "structures" which were actually little
>*user*-defined pieces of code for calculating a pointer, including
>subfields [the "P" (offset) & "S" (width) values above], so a more
>idiomatic way to write it [assuming "foo" had previously been "mapped"
>with an appropriate structure] would be:
>
> foo[13, my_nibble] = .foo[13, my_nibble] + 5;
Interesting ... but does a pointer to a partial word have any utility
beyond device register control? (Maybe what it was meant for?)
George
We're arguing over definitions of portability. I'll grant you this
point in large part. However, I was trying to claim something much
more broad. Sure you can write a program that manipulates hardware
addresses and runs on a large portion of desktops. However, that thing
will not run on an old PDP-11, nor will it run on some new arbitrary
embedded processor. This is unlike a portable program which calculates
PI to the nth decimal place, which could be written in C or Java. This
PI program could run on any conceivable hardware to produce sensible
results, unlike your device drivers.
> > What is fair is to compare the semantics of pointers and Java
> > references. You can assign to a pointer without changing the
> > pointed-to object, changing a passed by value pointer in a function
> > call leaves the callee pointer unchanged, and so on. This is very much
> > unlike C++ references which act more like aliases, and I again contend
> > that because Java in its beginning largely lifted its syntax and
> > semantics from C++, it should not have conflated and confused these
> > two terms because it causes (minor) undue confusion in the
> > communities.
>
> There's so few words...
Ok. Presumably you still disagree. I'm still curious as to where. Stop
me where you disagree:
1- Java is a direct descendant of C++. It is not an extension of, nor
does it share the same design goals. However, Java is based largely
off the C family of languages, and specifically C++. Java was meant as
a better C++.
2- The C family of languages largely popularized the term "pointer".
The term "reference" was already well known, and its definition was
vague and meant many different related things in different contexts.
3- Java's references have identical semantics to C pointers (minus
unsafe casting, pointer math, and null pointer checking), and they are
very different than C++ references. That is, there is a pre-existing
term widely known by all which excellently captured the semantics of
this construct of the new language Java, and that term was "pointer".
The identifying characteristic of "pointer" is not pointer math, nor
unsafe casting, nor null pointer checking or lack thereof, as
evidenced by the term pointer being used in other languages which also
lack those things. The term pointer references to an "object" or
"entity" which refers to another object. You can change the pointer to
point to a new object, and you can change the pointed-to object
without changing the pointer's state. They have distinct state.
4- The term which Java did pick, references, was vague in the
literature. It could refer to pointers, aliases, and any of kind of
thing which "references" another thing. Moreover, "references" had a
domain specific definition in C++, the language on which Java is
based.
5- By choosing the vague term "reference" which was already overloaded
in its predecessor language which denoted a thing very related but
distinct from pointer, the Java creators introduced confusion into the
programming world. Yes, this confusion is quite minor, perhaps not
even enough to write home about. I merely noted it as a pet peeve.
It's probably a pet peeve of mine because it's a form of political
correctness - they wanted to use a "safe" kind of pointers, which they
could and did by removing the "dangerous" aspects of pointers, but
they wanted to sell their language and "pointer" was a dirty word so
they picked a different word. To compound this annoyance, they picked
a term which could lead to (minor) confusion.
I've been here before, and there is only fire, no light.
http://www.c2.com/cgi/wiki?DefinitionsForOo
Contained within are all of the good arguments, counter arguments, and
so on.
Maybe not in the general public, though it certainly made it
to a large subset of DEC users... and not always favorably! ;-} ;-}
+---------------
| >But even better, BLISS has "structures" which were actually little
| >*user*-defined pieces of code for calculating a pointer, including
| >subfields [the "P" (offset) & "S" (width) values above], so a more
| >idiomatic way to write it [assuming "foo" had previously been "mapped"
| >with an appropriate structure] would be:
| >
| > foo[13, my_nibble] = .foo[13, my_nibble] + 5;
|
| Interesting ... but does a pointer to a partial word have any utility
| beyond device register control?
+---------------
Sure, the same thing as bitfields in C -- any time you have compact
data structures where you want to pack multiple values per machine word.
+---------------
| (Maybe what it was meant for?)
+---------------
Not really. Actually, BLISS's pointers almost *exactly* mirror the
hardware byte pointers in the DEC PDP-10 instruction set. The BLISS code:
foo[13]<12,4> = .foo[13]<12,4> + 5;
could be written in PDP-10 assembler like this:
movei t0, foo+15 / Note: Default base in MACRO-10 is octal.
hrli t0, 140400 / Make a byte pointer from &foo[13].
ldb t1, t0 / Load byte using byte pointer in t0.
addi t1, 5
dpb t1, t0 / Deposit byte.
If you need the subscript "13" to be computed dynamically, then you
can use the built-in indexing in byte pointers, and construct one
at compile time [assuming you can fix which register will be used
for indexing -- here we assume that "t2" == register 7]:
myfield: xwd 140407,foo / Byte pointer to foo[t2]<12,4>
Then the code becomes:
move t2, ...[the index]...
ldb t1, myfield / The contents of t2 get used by the hardware
addi t1, 5 / in the calculation of the effective addr.
dpb t1, myfield
The motivation for having such flexible byte pointers in hardware came
in part from the fact that the PDP-10 was a 36-bit wide word-addressed
machine that used 7-bit ASCII for normal text files [packed 5 to a word
with one bit wasted] but also used *6*-bit subset ASCII for file names
and extensions, as well as keywords in system calls. But the hardware
actually supported *any* byte size from 1 to 36. [In fact, it even
supported a byte size of 0, which gave a sometimes-useful no-op!]
I should also mention that there were also ILDB & IDPB instructions,
which would first *increment* the referenced byte pointer [by decrementing
the "position" field by the "size" field] and then perform the LDB or DPB
function on the ultimate target location. If there weren't enough bits
left in the byte pointer for the field to fit in the current word [the
"position" field went negative], the ILDB/IDPB would increment the *word*
address and reset the position field to 0, thus allowing the use of
ILDB/IDPB to step sequentially through the bytes of a packed string.
-Rob
p.s. Yes, I used mixed-endian conventions in my sample code in the
previous posting. The BLISS code there (and the PDP-10 assembler above)
used big-endian byte descriptions, while the C code used little-endian.
[I was trying to keep it simple.]
Sorry I was a little dense - I never used a PDP, they were a little
before my time :-) I'm more at home with VAX.
I forgot about the PDP's long words, packed strings, etc. In that
context, having such a field pointer construct makes perfect sense.
Thanks for taking the time to explain them.
George
>Stop me where you disagree:
>
>1- Java is a direct descendant of C++. It is not an extension of, nor
>does it share the same design goals. However, Java is based largely
>off the C family of languages, and specifically C++. Java was meant as
>a better C++.
You can stop right here.
To my mind, a "better" version of a programming language should be at
least equivalent in utility - the "better" can be in other dimensions
such as safety and ease of use.
Gosling wrote that his motivation was to [clean up syntax, remove
redundancy and make the language safer and easier to use] (I'm
paraphrasing here, the actual quotes are long [1]).
But Gosling did not simply remove redundancy, he also removed critical
language functionality without offering an equivalent. As compared
to C++, Java is less expressive and provides less functionality.
How is that making it "better"?
YMMV, but I don't believe "dumbing down" a programming language can be
considered an improvement. Programming languages are not door knobs,
toasters or consumer MP3 players ... they are tools that need a sharp
edge. You can put a guard over the edge or you can teach people to be
careful, but removing the edge makes the tool useless.
Though still far from equivalent, C# nevertheless is closer than Java
to being a functional replacement for C++.
>2- The C family of languages largely popularized the term "pointer".
>The term "reference" was already well known, and its definition was
>vague and meant many different related things in different contexts.
No, the definition of reference was not vague. As the C (and Pascal)
families use them, the terms "reference", "reference variable" and
"reference parameter" all were defined by Algol.
The languages of the C family, including Java, all use Algol's notions
unchanged.
>3- Java's references have identical semantics to C pointers (minus
>unsafe casting, pointer math, and null pointer checking), and they are
>very different than C++ references. That is, there is a pre-existing
>term widely known by all which excellently captured the semantics of
>this construct of the new language Java, and that term was "pointer".
>The identifying characteristic of "pointer" is not pointer math, nor
>unsafe casting, nor null pointer checking or lack thereof, as
>evidenced by the term pointer being used in other languages which also
>lack those things. The term pointer references to an "object" or
>"entity" which refers to another object. You can change the pointer to
>point to a new object, and you can change the pointed-to object
>without changing the pointer's state. They have distinct state.
Partly.
Modulo automatic dereferencing, C and C++ pointers, and Java's
references all are semantically equivalent to Algol's reference
variables. C++ references include the non-NIL, init-only attributes
of Algol's reference parameters.
[Stroustrup's mistake, I think, was in making C++ references first
class objects akin to pointers. Had references been simply name
syntax, I don't think there would be as much (or even any) confusion
about them.]
>4- The term which Java did pick, references, was vague in the
>literature. It could refer to pointers, aliases, and any of kind of
>thing which "references" another thing. Moreover, "references" had a
>domain specific definition in C++, the language on which Java is
>based.
The term was not vague in relevant literature. Rather I think people
superimpose the everyday meaning of the term upon their (often
shallow) understanding of the semantics as defined by the programming
language ... and then are surprised when the real semantics don't
conform to their bogus understanding.
>5- By choosing the vague term "reference" which was already overloaded
>in its predecessor language which denoted a thing very related but
>distinct from pointer, the Java creators introduced confusion into the
>programming world. Yes, this confusion is quite minor, perhaps not
>even enough to write home about. I merely noted it as a pet peeve.
C++ does not "overload" the term reference. Algol did, to some
extent, with dual notions of reference both as a syntactic identifier
and as a first-class, address container object.
C++ does not have Algol's notion of reference as "syntax" ... it has
only the notion of "container object". So despite whatever
misconceptions people may have, there is no overloaded meaning.
Similarly, Java has only the notion of "container object".
Moreover, all the notions of "pointers" and "references", regardless
of language, include notions of object identity and aliasing, so those
too are not overloaded meanings.
George
[1] James Gosling, Henry McGilton, "The Java language Environment: A
white paper", Sun Microsystems, 1996
If, in removing some functionality, you can cut the number of bugs by
eye-popping amounts, I would consider it better.
I presume you're referring to manual memory management and pointer
arithmetic as the tools that Java lacks to make it "less functional".
> YMMV, but I don't believe "dumbing down" a programming language can be
> considered an improvement. Programming languages are not door knobs,
> toasters or consumer MP3 players ... they are tools that need a sharp
> edge. You can put a guard over the edge or you can teach people to be
> careful, but removing the edge makes the tool useless.
Not necessarily. I may not easily be able to express exactly how long I
want this Java object to last, but it's not a feature I use very often
when I have that capability.
The world doesn't need a One True Programming Language� which solves any
problem under the sun--what you get when you try that is an unholy
kludge of a language which has surprisingly little compiler
interoperability, is truly understood by almost nobody, and which
requires style guidelines to limit you to a strict subset of the
language to be usable in production code.
Instead, it is better to have multiple languages which work very well
for their design goals and are reasonably interoperable between each
other. For example, you can call C code from pretty much any language,
and some dynamic languages even have modules to allow you to dynamically
call C code ("ctypes").
Not having to deal with memory management and pointer arithmetic is, by
far, the biggest reason I prefer Java over C++.
--
Steve Sobol, Apple Valley, California, USA
sjs...@JustThe.net
No offense to Stefan intended, but I intend great offense towards the
source of that quote. I don't even know what to say to it. It's so
stupid. Scheme is a functional programming language, a Lisp dialect,
whereas Java and C++ are very much based on ALGOL and imperative
programming (though they both offer limited support for functional
programming styles). The semantics of Java and the semantics of Lisp
and Scheme are worlds apart.
+1
Pointer arithmetic probably has no place in a high-level language. And,
no, much as I like it, I don't consider C to be a HLL - more a structured
assembler.
--
martin@ | Martin Gregorie
gregorie. | Essex, UK
org |
> Joshua Maurice <joshua...@gmail.com> writes:
>>The semantics of Java and the semantics of Lisp
>>and Scheme are worlds apart.
>
> LISP was the first language with a garbage collector, now
> Java also has a GC, while C++ does not have a GC. But this
> is only one aspect.
One could try to use BoehmGC.
Unfortunately, I'm not sure at 100% that it would be safe, given how
hard C++ libraries and preconized C++ usage tries to make it hard for a
GC to work well with C++ code...
Nonetheless, some success have been reported, eg. with using Qt with
BoehmGC.
> However, in Java, one can partially
> emulate the LISP style, where functions (like CONS) return
> complex entities (dotted pairs) allocated at runtime which
> might be linked and passed around in complex ways. In C++,
> this is much more difficult, because there is no garbage
> collector.
Indeed. There's still Lpp (but you'd need an old gcc).
http://www.informatimago.com/articles/life-saver.html
I assume you're talking about C++ jargon, where you somehow pass
the *place* (Lisp jargon, means a mutable cell in the caller's
space, or even a higher-up caller's space if the "reference" is
passed through multiple levels of function calling) where a value
can be updated directly by the called function.
But in ordinary language, a reference is:
- A citation of prior art, listing title of book or journal and
enough additional information to find the article or book in a
library. (Used in a new article/book that cites information from
the prior art.)
- A letter attesting to a claim that somebody is of good quality,
such as does good work and/or is of good moral character. (Used
when applying for a job or a security clearance or housing etc.)
So instead of arguing whether C++ or Java uses the word
"correctly", when in fact *neither* does, best to avoid the word
entirely.
For what C++ passes, what the Lisp Machine called locatives, we
should use the Common Lisp jargon "place". Tell the function the
*place* where it is allowed to make references despite the fact
that *place* is in a higher-up space hence normally is forbidden
for access by the called function.
Place = mutable cell.
Locative = mechanism by which a place is passed to a function.
All the application programmer cares about is that the function
knows the place; the application programmer needn't know the
mechanism; hence my preference for "place" instead of "locative" in
API documentation.
For what Java passes, we could call it a "handle", because it's
more than just a pointer (machine address), it's a tagged pointer,
something that identifies both the machine address and the type of
data to be found there, by a tag accompanying the machine address
and/or by inspection of what is seen in the target. Likewise Lisp
pointers should also be called "handles" rather than "pointers".
For what C passes, that's just a machine address, with no type info
at runtime, so it's a "pointer". (And with casting to/from void*,
even the compiletime typing isn't really enforced.)
int x = 5;
int* px = &x;
void* pv = px;
double* pf = pv;
double y = sqrt(*pf);
Untested. Did I get all that correct? I'm not really expert at C.
BTW many years ago, before Common Lisp, I made a try at designing a
new kind of Lisp where all parameters were places/locatives, even
when a computed value was being passed (the place within the stack
where that temporary value appears would be passed). It would be
the responsibility of the called function to fetch the old value
from that place if it was needed, and/or store the updated value
there before returning. It would be the responsibility of the
application programmer not to waste CPU cycles by passing a
temporary value to a function that was going to change it (and then
after return the caller has no way to make any use of that updated
value). In this way, SETF macros would never be needed. Instead of:
(setf (car x) 5) ==macroExpand=> (let ((val 5)) (rplaca x val) val)
with my system we could just write
(setq (car x) 5)
and it would work as-is, compiling code to use the locative to the
CAR of whatever x was at the time. But I was busy with other stuff
and never developed the idea much, and then discovered Common Lisp
with SETF macros and got lazy and just adapted to SETF.
Now I realize that one of the principles of OO, namely that places
can be hidden from the outside, requiring a method call to view
and/or set them, is often a good safety precaution, to protect
against disrupting data structures to be invalid (with respect to
the usual algorithms for them), thus to prevent the occurrance of
really hard-to-diagnose bugs. So now each ADT has a formal API
which is the *only* way any foreign code is allowed to
examine/modify the structures per the ADT, and the idea of passing
a locative (to a place within your data structure) to somebody who
may then modify that place any time it wants, thereby potentially
invalidating your data structure, so that *your* code breaks
because of what the other code did to your data, seems way too
dangerous.
totally agree here. To say that java's semantic is mostly based or
connected to scheme lisp in would be the most egregious sophistry.
one might as well say any 2 langs is based on any other.
btw, did anyone actually stated that somewhere?
Xah
> Maybe I confounded Java with JavaScript in this
> regard? For JavaScript, Wikipedia says:
>
> »JavaScript also has many functional features
> based on the Scheme language.«
>
> http://en.wikipedia.org/wiki/JavaScript
yep. JavaScript is based on Scheme, alright. It was said by the js
inventor.
Xah
>On 10/19/2010 04:04 PM, George Neuner wrote:
>> But Gosling did not simply remove redundancy, he also removed critical
>> language functionality without offering an equivalent. As compared
>> to C++, Java is less expressive and provides less functionality.
>>
>> How is that making it "better"?
>
>If, in removing some functionality, you can cut the number of bugs by
>eye-popping amounts, I would consider it better.
>
>I presume you're referring to manual memory management and pointer
>arithmetic as the tools that Java lacks to make it "less functional".
No.
It's amazing to me that Java enthusiasts/apologists have so much
contempt for things they can't seem to master. Moreover, those same
things are the first thoughts that pop into their heads whenever
someone mentions C or C++.
What Java lacks that limits its utility with respect to C or C++ is
the ability to overlay a logical view of structured data at an
arbitrary memory location. This ability is the single feature of C
and C++ which makes them strictly more powerful than Java.
[C and C++ union types are not types in their own right but merely
convenience syntax for overlaying views of multiple data structures at
the same location.]
Java doesn't have any equivalent. The often recommended nio.Buffer,
ByteBuffer, MappedByteBuffer, etc. are severely limited and offer only
some of the functionality of a union type.
First, there is no way *reliably* to obtain an arbitrary location
mapping on memory. Not all systems will support such mappings and
even if a particular platform does support it (e.g., Linux's /dev/mem,
/proc/<ID>/mem, etc.) there may be in place security protocols in the
JVM and/or host system which will prevent it.
Second, Java provides no way to determine the offset of a particular
data field within an object. The physical layout of an object in
memory is implementation dependent ... only the JVM knows how to find
an object's data fields. So even if you could get a reliable location
mapping, you still could not overlay ByteBuffer views of different
objects on it. Working within Java, you can achieve unions of only
the primitive types.
[Of course, you can achieve a union using JNI, but then you're
cheating by going outside the language ... not to mention that you'll
end up coding in the very language that Java was supposed to have
improved upon.]
In contrast, both C and C++ do guarantee the order of data fields in a
struct. Field alignment padding is implementation dependent, but
virtually all compilers allow unaligned/unpadded structs if desired.
Both C and C++ provide the standard macro offsetof() for determining
the offset of a data field from the beginning of the structure. Thus
you could directly access a byte buffer containing an instance of a
struct without overlaying a view of the struct on the buffer.
Moreover, C#, which lots of people accuse of being a clone of Java,
also has the ability to overlay data structures on memory.
>> YMMV, but I don't believe "dumbing down" a programming language can be
>> considered an improvement. Programming languages are not door knobs,
>> toasters or consumer MP3 players ... they are tools that need a sharp
>> edge. You can put a guard over the edge or you can teach people to be
>> careful, but removing the edge makes the tool useless.
>
>Not necessarily. I may not easily be able to express exactly how long I
>want this Java object to last, but it's not a feature I use very often
>when I have that capability.
So what? C++ has this feature called a "library" that, among other
things, allows you to use functions that you didn't write.
Among the many "libraries" that are available for C++ there are ...
OMG! Garbage Collectors ?!? Not refcounting hacks ... real
collectors from names you might actually recognize - that is if you
know anything at all about GC.
Guess what? C and C++ programmers don't have to manually manage
memory unless they want to. True, GC is not a *standard* library ...
yet ... but, you see, there is this thing called the World Wide Web
and it has a thing called "Google" that finds non-standard libraries
for you.
Searching Google with "C++ garbage collector" you will immediately
locate the best known and very well respected Boehm-Demers-Weiser
collector. http://www.hpl.hp.com/personal/Hans_Boehm/gc/
Searching Google with "C memory management library" you will find
others, some of which are just as good as BDW.
>The world doesn't need a One True Programming Language™ which solves any
>problem under the sun -- what you get when you try that is an unholy
>kludge of a language which has surprisingly little compiler
>interoperability, is truly understood by almost nobody, and which
>requires style guidelines to limit you to a strict subset of the
>language to be usable in production code.
This is bullshit.
There are languages that offer power fully equivalent to C++ but which
are cleaner, safer and easier to use. Some of them are OO, some are
functional. Almost all have built-in GC.
Java is not among them.
>Instead, it is better to have multiple languages which work very well
>for their design goals and are reasonably interoperable between each
>other.
Finally a reasonable statement that I can agree with.
>For example, you can call C code from pretty much any language,
>and some dynamic languages even have modules to allow you to dynamically
>call C code ("ctypes").
Haven't you been arguing all along that nobody should be using C?
FWIW: I don't give a rat what language anybody chooses to use. What I
do care about is that comparisons made between languages be fair and
include ALL the relevant information so that people unfamiliar with
them are not drawing erroneous conclusions from unsupported claims.
George
This doesn't work as well in C/C++ as you think. Specifically, in:
union {
int a;
double b;
} x;
x.a = 5;
The value of double is undefined. And let's not get into type punning.
I have occasionally desired union types in Java, but never really union
types.
> First, there is no way *reliably* to obtain an arbitrary location
> mapping on memory. Not all systems will support such mappings and
> even if a particular platform does support it (e.g., Linux's /dev/mem,
> /proc/<ID>/mem, etc.) there may be in place security protocols in the
> JVM and/or host system which will prevent it.
How can Java be more powerful than what its host system provides? You
could probably do nio on /dev/mem, e.g., for Linux, though.
In any case, I have found little reason to do this, even in C or C++.
About the closest I can think of is mmap'ing binary files for
performance--nio can do that--or perhaps easier binary I/O, in which
case Java's Object{Input,Output}Stream is sufficient for my
serialization needs.
> In contrast, both C and C++ do guarantee the order of data fields in a
> struct. Field alignment padding is implementation dependent, but
> virtually all compilers allow unaligned/unpadded structs if desired.
> Both C and C++ provide the standard macro offsetof() for determining
> the offset of a data field from the beginning of the structure. Thus
> you could directly access a byte buffer containing an instance of a
> struct without overlaying a view of the struct on the buffer.
offsetof has limitations. Specifically, offsetof does not work on
non-POD classes. Which was the first and only time to date I have needed
it [1].
You also forgot about the implementation-dependent issue of endianness.
> So what? C++ has this feature called a "library" that, among other
> things, allows you to use functions that you didn't write.
So does Java.
> Among the many "libraries" that are available for C++ there are ...
> OMG! Garbage Collectors ?!? Not refcounting hacks ... real
> collectors from names you might actually recognize - that is if you
> know anything at all about GC.
Garbage collection is not built in, and I do recall there being some
issues with garbage collection in C++, especially when you do large,
multithreaded programs. One program I worked on attempted to convert
from refcounting to garbage collection and failed.
> There are languages that offer power fully equivalent to C++ but which
> are cleaner, safer and easier to use. Some of them are OO, some are
> functional. Almost all have built-in GC.
>
> Java is not among them.
All I am trying to say is that a language doesn't need to do everything.
Also, if such languages exist, why does almost no one use them?
[1] Specifically, I was trying to write a C++ bridge library for dynamic
interlanguage trampolining, and needed offsets to the fields of a class,
so my use case totally involves non-POD classes.
> In any case, I have found little reason to do this, even in C or C++.
> About the closest I can think of is mmap'ing binary files for
> performance--nio can do that--or perhaps easier binary I/O, in which
> case Java's Object{Input,Output}Stream is sufficient for my
> serialization needs.
I think you really do need this kind of
get-at-an-arbitrary-location-in-memory to do a lot of low-level things
like device drivers &c. Neither Java nor Common Lisp support that sort
of thing without non-standard extensions as far as I know (well, I know
CL does not, and I think I know Java does not).
I fail to see why device drivers & co. are considered by C++ folks as
a common and fundamental enough problem to have the language heavily
adapt to it, while, e.g., multithreading is not. If I need to program
a device driver, I'd expect to use a specialized language for writing
device drivers. C might still be considered as one, but C++ is "sold"
as a general-purpose OO language...
So for the sake of "efficiency" C++ is an extremely static language,
everything is decided in advance, and the result of compilation is a
solid block of stone. GC is theoretically possible, but the language
does not require it, and code is rarely written with a GC in mind. The
result is complexity beyond any other language known to man, because
you have to carefully explain to the compiler *everything* that's
required to know statically in order to translate all those "high-
level" concepts to a solid block of stone. That's the cause for the
utter madness that are templates, the severely leaky abstractions in
the OO system, the absurdly long compilation times and
incomprehensible error messages, among other things. Oh, and C++0x is
going to add *more* complexity.
Java is syntactically in the C/C++ family, but it follows a pretty
different philosophy. While certainly limiting expressiveness in some
situations, and requiring definitely too much verbosity in others, it
is far more dynamic than most people think. It has GC, some form of
runtime typing, dynamic code loading, poor man's closures,
reflection... In that regard, Gosling's sentence about Java bringing C+
+ programmers halfway to Lisp is not far off.
Alessio
Define 'powerful'!
My answer is:
- emergent properties,
- turing equivalence,
- virtual machine.
That is, mostly: do not care what occurs on the host.
You can write any power inside the VM.
Of course, if your definition of power is to use the raw hardware, then
you should go to assembly, or C.
But if you accept to abstract things away a little, then any Turing
Equivalent VM can be more powerful, in the sense that it will let you
write more efficiently programs that are more expressive and more able
than anything you could do on bare hardware or with crude tools such as
C or C++.
>> Among the many "libraries" that are available for C++ there are ...
>> OMG! Garbage Collectors ?!? Not refcounting hacks ... real
>> collectors from names you might actually recognize - that is if you
>> know anything at all about GC.
>
> Garbage collection is not built in, and I do recall there being some
> issues with garbage collection in C++, especially when you do large,
> multithreaded programs. One program I worked on attempted to convert
> from refcounting to garbage collection and failed.
One of the most problematic aspects of C++, is that since it's an
unfinished programming language, each project defines its own
programming "conventions", in effect, defines its own programming
language, and thus may produce libraries that are in practice
incompatible with others.
In the specific case of memory management, it may be very difficult or
even impossible to mix and match objects obtained from different
libraries.
But neither do C or C++ either. Since you have to add implementation
specific extensions anyways, you can as well add them to a Common Lisp
implementation!
> But neither do C or C++ either. Since you have to add implementation
> specific extensions anyways, you can as well add them to a Common Lisp
> implementation!
I'm pretty sure that in C you can write code which is "essentially
legal" which on a known platform will let you get at specific memory
locations. ("essentially legal" because I bet there are restrictions
on dereferencing pointers to memory you did not allocate and so on, but
in practice compilers can't spot this and don't complain). Obviously
that code is not portable, but it doesn't need to be.
However, I definitely was not trying to argue that this is a good
reason for using C rather than CL or Java in almost all cases!
> reflection... In that regard, Gosling's sentence about Java bringing C+
> + programmers halfway to Lisp is not far off.
Wasn't that Steele?
Petter
--
.sig removed by request.
[...]
> Not implying I am a great result of my education, but in my case it was
> more:
> - Theory of abstract classes and polymorphism, pseudo-language and
> trivial design patterns.
> - UML
> - C++
> - And /then/, Java.
>
http://en.wikiquote.org/wiki/Alan_Kay: "Actually I made up the term
"object-oriented", and I can tell you I did not have C++ in mind."
yes, about Gosling's Mocklisp... ;)
Again, let's not restart this argument. Please see:
http://c2.com/cgi/wiki?ObjectOrientedProgramming
for a pretty complete list of all of the available arguments on all
sides.
> On 10/21/2010 02:58 AM, George Neuner wrote:
>> What Java lacks that limits its utility with respect to C or C++ is the
>> ability to overlay a logical view of structured data at an arbitrary
>> memory location. This ability is the single feature of C and C++ which
>> makes them strictly more powerful than Java.
>
> This doesn't work as well in C/C++ as you think. Specifically, in:
>
> union {
> int a;
> double b;
> } x;
>
> x.a = 5;
>
> The value of double is undefined. And let's not get into type punning.
>
Spot on. If you're using unions to remap an area then you're misusing
them.
The intention, as I understand it, of the union was a sort of
polymorphism that would allow an array or list of structs to be built
with one or more common fields in the struct together with a union of
other structs and/or data types. One of the common fields says what
member of the union is being used in this instance of the container
struct.
The only HLL where memory remapping works as you would expect is COBOL,
and even there its only really useful if the REDEFINES all map onto a
character string and all the definitions have the same length. If you try
to do anything else you get tripped up by the alignment requirements of
COMPUTATIONAL data items and end up confusing the hell out of any poor
sod who has to maintain the mess.
Ok, sorry, I misquoted. But the meaning of the sentence remains true.
Here's another variant:
public interface Unyon <T>
{
/** @return T underlying value. */
T getValue();
}
public class Intyon implements Unyon <Integer>
{
private final Integer value;
/** @param v Integer wrapped value. */
public Intyon( Integer v ) { this.value = v; }
@Override
public Integer getValue() { return this.value; }
}
public class Doubyon implements Unyon <Double>
{
private final Double value;
/** @param v Double wrapped value. */
public Doubyon( Double v ) { this.value = v; }
@Override
public Double getValue() { return this.value; }
}
Java works pretty well as a type-declarative language..
--
Lew
>r...@zedat.fu-berlin.de (Stefan Ram) writes:
>
>> Joshua Maurice <joshua...@gmail.com> writes:
>>>The semantics of Java and the semantics of Lisp
>>>and Scheme are worlds apart.
>>
>> LISP was the first language with a garbage collector, now
>> Java also has a GC, while C++ does not have a GC. But this
>> is only one aspect.
>
>One could try to use BoehmGC.
>
>Unfortunately, I'm not sure at 100% that it would be safe, given how
>hard C++ libraries and preconized C++ usage tries to make it hard for a
>GC to work well with C++ code...
The Boehm Demers Weiser collector (Boehm maintains it) works fine with
libraries that use the standard allocator - which it replaces. If a
library uses a private allocator it will continue to use that.
You do have to be a little careful when writing a very long running
program, e.g., a server application. But for programs that are used
for a while and then terminated it is, IMO, 99% safe for 32-bit Linux
and Windows (the primary targets). I've not yet used it for a 64-bit
project.
It suffers the same problems as other GC systems if the program
accidentally holds references to large structures. And if you use
finalization then recovery of the object memory is delayed for one
cycle.
The BDW collector is very well respected and is regarded as the best
all around collector for C or C++. There are some others though which
may be more suitable for particular projects. Google is your friend.
George
>On 10/21/2010 02:58 AM, George Neuner wrote:
>> What Java lacks that limits its utility with respect to C or C++ is
>> the ability to overlay a logical view of structured data at an
>> arbitrary memory location. This ability is the single feature of C
>> and C++ which makes them strictly more powerful than Java.
>
>This doesn't work as well in C/C++ as you think. Specifically, in:
>
>union {
>int a;
>double b;
>} x;
>
>x.a = 5;
>
>The value of double is undefined. And let's not get into type punning.
I'm not talking about simplistic crap like the above. I'm talking
about, e.g., receiving a stream of bytes into a network buffer and
overlaying a defined structure to interpret them.
Endian bullshit is a matter of data encoding - not structure.
>I have occasionally desired union types in Java, but never really union
>types.
I don't care about union types per se ... I mentioned them because
they fall naturally out of the ability to overlay data structures on
arbitrary memory.
>> First, there is no way *reliably* to obtain an arbitrary location
>> mapping on memory. Not all systems will support such mappings and
>> even if a particular platform does support it (e.g., Linux's /dev/mem,
>> /proc/<ID>/mem, etc.) there may be in place security protocols in the
>> JVM and/or host system which will prevent it.
>
>How can Java be more powerful than what its host system provides? You
>could probably do nio on /dev/mem, e.g., for Linux, though.
C and C++ by default can access any location within the process. For
systems without virtual memory remapping, they can access RAM
location. Java can't do this without assistance from non-Java code.
>In any case, I have found little reason to do this, even in C or C++.
Then you don't write the kinds of programs for which this matters and
for which Java can't be used.
>> In contrast, both C and C++ do guarantee the order of data fields in a
>> struct. Field alignment padding is implementation dependent, but
>> virtually all compilers allow unaligned/unpadded structs if desired.
>> Both C and C++ provide the standard macro offsetof() for determining
>> the offset of a data field from the beginning of the structure. Thus
>> you could directly access a byte buffer containing an instance of a
>> struct without overlaying a view of the struct on the buffer.
>
>offsetof has limitations. Specifically, offsetof does not work on
>non-POD classes. Which was the first and only time to date I have needed
>it [1].
>[1] Specifically, I was trying to write a C++ bridge library for dynamic
>interlanguage trampolining, and needed offsets to the fields of a class,
>so my use case totally involves non-POD classes.
Yes and it is well documented that offsetof() will not work with
non-POD objects. However, there are POD objects. offsetof() does
work on an object derived from a POD structure.
That is, you can do:
struct A { ... };
class B : public A { ... };
and offsetof() will work on the *public* data members of B even if B
defines additional data members. The structure inheritance must be
public for offsetof() to work.
>> There are languages that offer power fully equivalent to C++ but which
>> are cleaner, safer and easier to use. Some of them are OO, some are
>> functional. Almost all have built-in GC.
>>
>> Java is not among them.
>
>All I am trying to say is that a language doesn't need to do everything.
>Also, if such languages exist, why does almost no one use them?
Mainly familiarity I think - most people reach for what they've used
before. Culture has a lot to do with it too. Historically, much of
the computer industry bloomed in the U.S. where universities used Unix
and C ... so it was natural for grads going into industry to reach for
C, and then later C++. Business people became familiar with them (at
least with the names) by osmosis.
What are IMO better languages like Modula-3, Oberon-2 and Ada all are
descendents from Pascal. Pascal and its follow-ons were more
successful in Europe and Japan than in the U.S. Pascal initially was
popular with U.S. micro hackers, but when they grew up and went to
work many converted to C because their employers demanded it.
Modula-3 largely has fallen by the wayside with most of the mind-share
having been transferred to Oberon or to Concurrent Pascal. They have
reasonable presence in embedded programming, as does Ada which
dominates the field for safety critical applications. Ada and Oberon
both provide their own modular threaded execution environments so they
are the basis of an operating system kernel by themselves.
CaML just didn't get enough exposure - it was used mainly academically
for programming multiprocessors but there was little push to bring it
to the masses. It's OO derivative Ocaml is oriented more toward
general applications and I don't really know if it still is suitable
for system programming.
Occam's overt data-flow orientation was just too weird for many
people. Oz, I think, suffers from the same fate.
George
Even in CL, most implementations have *some* equivalent of the ancient
"peek()" & "poke()" unsafe memory access routines. For example [as I've
written about several times here before], CMUCL has the extension
functions SYSTEM:INT-SAP [turn an integer into a System Area Pointer]
and SYSTEM:SAP-REF-{8,16,32} [which are also SETF-able], which together
with UNIX:UNIX-OPEN & UNIX:UNIX-MMAP is enough to let one peek & poke
at mmap-ed files or hardware registers from within a user-mode CL program.
And if your particular CL implementation doesn't have such, it only
takes a page or so of C API (or CFFI) glue to add them...
-Rob
-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
> On Thu, 21 Oct 2010 08:11:39 -0400, Joshua Cranmer
> <Pidg...@verizon.invalid> wrote:
>
>>On 10/21/2010 02:58 AM, George Neuner wrote:
>>> What Java lacks that limits its utility with respect to C or C++ is
>>> the ability to overlay a logical view of structured data at an
>>> arbitrary memory location. This ability is the single feature of C
>>> and C++ which makes them strictly more powerful than Java.
>>
>>This doesn't work as well in C/C++ as you think. Specifically, in:
>>
>>union {
>>int a;
>>double b;
>>} x;
>>
>>x.a = 5;
>>
>>The value of double is undefined. And let's not get into type punning.
>
> I'm not talking about simplistic crap like the above. I'm talking
> about, e.g., receiving a stream of bytes into a network buffer and
> overlaying a defined structure to interpret them.
>
> Endian bullshit is a matter of data encoding - not structure.
Indeed. And I don't see any advantage of
(((*p++)&0x70)>>4)
over:
(ldb (aref p (incf i)) (byte 3 4))
If you feel that *p++ is a good abstraction, you can even write:
(defun strncpy (src dst len)
(loop :repeat len :do (setf (deref++ dst) (deref++ src))))
CL-USER> (let* ((a "Hello World!")
(b (make-string 10 :initial-element #\space)))
(strncpy (& a 6) (& b) 5)
b)
"World "
CL-USER>
With:
(defstruct pointer base-address offset)
(defun & (array &optional (offset 0))
(assert (<= 0 offset (1- (array-total-size array))))
(make-pointer :base-address array :offset offset))
(defun deref (pointer &optional (offset 0))
(assert (< -1 (+ (pointer-offset pointer) offset) (array-total-size (pointer-base-address pointer))))
(row-major-aref (pointer-base-address pointer)
(+ (pointer-offset pointer) offset)))
(defun ++deref (pointer)
(assert (< -1 (pointer-offset pointer) (1- (array-total-size (pointer-base-address pointer)))))
(row-major-aref (pointer-base-address pointer)
(incf (pointer-offset pointer))))
(defun --deref (pointer)
(assert (< 0 (pointer-offset pointer) (array-total-size (pointer-base-address pointer))))
(row-major-aref (pointer-base-address pointer)
(decf (pointer-offset pointer))))
(defun deref++ (pointer)
(assert (< -1 (pointer-offset pointer) (array-total-size (pointer-base-address pointer))))
(prog1 (row-major-aref (pointer-base-address pointer)
(pointer-offset pointer))
(incf (pointer-offset pointer))))
(defun deref-- (pointer)
(assert (< -1 (pointer-offset pointer) (array-total-size (pointer-base-address pointer))))
(prog1 (row-major-aref (pointer-base-address pointer)
(pointer-offset pointer))
(decf (pointer-offset pointer))))
(defun (setf deref) (value pointer &optional (offset 0))
(assert (< -1 (+ (pointer-offset pointer) offset) (array-total-size (pointer-base-address pointer))))
(setf (row-major-aref (pointer-base-address pointer)
(+ (pointer-offset pointer) offset)) value))
(defun (setf ++deref) (value pointer)
(assert (< -1 (pointer-offset pointer) (1- (array-total-size (pointer-base-address pointer)))))
(setf (row-major-aref (pointer-base-address pointer)
(incf (pointer-offset pointer))) value))
(defun (setf --deref) (value pointer)
(assert (< 0 (pointer-offset pointer) (array-total-size (pointer-base-address pointer))))
(setf (row-major-aref (pointer-base-address pointer)
(decf (pointer-offset pointer))) value))
(defun (setf deref++) (value pointer)
(assert (< -1 (pointer-offset pointer) (array-total-size (pointer-base-address pointer))))
(prog1 (setf (row-major-aref (pointer-base-address pointer)
(pointer-offset pointer)) value)
(incf (pointer-offset pointer))))
(defun (setf deref--) (value pointer)
(assert (< -1 (pointer-offset pointer) (array-total-size (pointer-base-address pointer))))
(prog1 (setf (row-major-aref (pointer-base-address pointer)
(pointer-offset pointer)) value)
(decf (pointer-offset pointer))))
(defun strncpy (src dst len)
(loop :repeat len :do (setf (deref++ dst) (deref++ src))))
> And if your particular CL implementation doesn't have such, it only
> takes a page or so of C API (or CFFI) glue to add them...
Yes, I know this & equivalent things can be done for Java of course, or
probably any language (I bet there were people who did bit-twiddling in
prolog). But that's still quite different than C which is really
designed for that kind of bit-twiddling (I mean, historically, it
really was designed for just that sort of thing).
Bits are bits.
Once you have bit operators, you can do bit twiddling as easily in any
language.
Actually, bit operations in Lisp are easier to write, and potentially
compiled more easily to more efficient code. dpb, ldb, ldb-test,
deposit-field, mask-field, integer-length, logand, logandc1, logandc2,
logeqv, logior, lognand, lognor, lognot, logorc1, logorc2, logxor
logbitp, logcount, logtest, ash, byte, are much richer bit manipulation
primitives than what is provided by C or most other programming
languages.
> Once you have bit operators, you can do bit twiddling as easily in any
> language.
Sorry, by "bit twiddling" I meant "poking at specific, known locations
in memory" (which is different, I know - I used the wrong term).
Obviously CL does have a very rich set of bit-twiddling (properly
defined) operators, but it has none at all which let you get at
specific locations on physical or virtual memory.
> Sorry, by "bit twiddling" I meant "poking at specific, known locations
> in memory" (which is different, I know - I used the wrong term).
> Obviously CL does have a very rich set of bit-twiddling (properly
> defined) operators, but it has none at all which let you get at
> specific locations on physical or virtual memory.
But pretty much every relevant implementation provides an operator (or
three) for this, I believe?
--
Frode V. Fjeld
Except those running on the JVM, that is ;)
> p...@informatimago.com (Pascal J. Bourguignon) writes:
>>Indeed. And I don't see any advantage of
>>(((*p++)&0x70)>>4)
>>over:
>>(ldb (aref p (incf i)) (byte 3 4))
>
> Strange that you don't. To me it is obvious:
>
> The first one more often has:
>
> one graphical symbol = one meaning
>
> , the brain can easily distinguish the expressive symbols
> and sometimes see combinations, such as »++« or »>>« as
> a single picture (unit, symbol).
This is why you program primarily in APL, no doubt (no dig at APL
intended).
[...]
>
> Indeed. And I don't see any advantage of
>
> (((*p++)&0x70)>>4)
> over:
> (ldb (aref p (incf i)) (byte 3 4))
>
Wait. What? *p++ fetches the data from p then increments p.
(aref p (incf i)) increments "p" then fetches the data.
Shouldn't you have written:
(ldb (aref p i) (byte 3 4))
(incf i)
or, maybe,
(prog1
(ldb (aref p i) (byte 3 4))
(incf i))
Which is what I see you did in your deref++ and deref-- functions once I
looked further.
The big thing about C (even more than C++) is the ability/ease to compile
"unhosted" and write code that can be booted on "bare metal" with
something less than a page of (boiler-plate) assembly between START and
main().
Writing device drivers or network protocol stacks or file format readers
and writers: history shows that this can be done perfectly adequately in
lisp or Java or Oberon or Ada or whatever (even C++). Very few of these
languages have so little run-time mechanism that bring-up on bare metal is
easy enough to be considered trivial.
Cheers,
--
Andrew
[Side note: The "bytespec" comes *first*, guys!!!]
When trying to port the C post-increment/decrement idioms I prefer
to keep the PROG1/INCF [or PROG1/DECF] as localized as possible, e.g.:
(ldb (byte 3 4) (aref p (prog1 i (incf i))))
This becomes more important as the expression using the "previous"
value gets larger:
(prog1
(let (...lots
of
bindings...)
...code
containing
one use of
i
somewhere
in the
middle...)
(incf i))
versus:
(let (...lots
of
bindings...)
...code
containing
one use of
(prog1 i (incf i))
somewhere
in the
middle...)
Plus, the "very localized" style tends to get the side effects right
[or at least more nearly right] in cases where (PROG1 I (INCF I)) is
used *more* than once within the larger expression.
-Rob
p.s. This is also one of those cases where I personally find the CL idiom
(PROG1 I (INCF I)) *more* readable/portable than trying to be clever/cute
by defining a macro for it. I.e., (DEFMACRO 1++ (X) `(PROG1 ,X (INCF ,X)))
is more likely to be misunderstood and/or used incorrectly [for complex args]
than the explicit PROG1 form.
> p...@informatimago.com (Pascal J. Bourguignon) writes:
>>Indeed. And I don't see any advantage of
>>(((*p++)&0x70)>>4)
>>over:
>>(ldb (aref p (incf i)) (byte 3 4))
>
> Strange that you don't. To me it is obvious:
>
> The first one more often has:
>
> one graphical symbol = one meaning
>
> , the brain can easily distinguish the expressive symbols
> and sometimes see combinations, such as �++� or �>>� as
> a single picture (unit, symbol).
>
> The one below uses longer complex symbols, which are built
> from elementary symbols themselves, i.e., words of letters.
> The brain might need more effort time to first parse these
> words, then pronounce them internally and finally derived a
> meaning from the sound of these words.
Yuo're wnrog. In a treinad raeder, the barin rginceoze the wrods it
knows glalolby. This is why you can sltil raed this pgaarraph.
On the other hand, the advantages of alphabetical composition of words,
over ideographic composition, are innumerous.
> Moreover, all words look approximately the same or similar
> to each other (they have to be scanned and read internally
> to be understood),
This processing occurs only for words you don't know. On the other
hand, this is something you just cannot do on ideographs, or
special-character-combinations.
> while the visible differences between the
> symbols, such as �*� and �>� are more prominent, which helps
> to read them faster.
>
> This is akin to the difference between:
>
> ----->
>
> And
>
> Please use the right lane here.
And in the USA, they keep using words in street signs, because they've
noticed they're more universal, and more easily understood.
> (In this case, even people who know English, but have
> difficulties with �left� and �right� might be able to
> immediatly grasp the arrow. Both the meaning of an arrow
> and the meaning of �*� are culturally defined and have
> to be learned during the life.)
But anyways this is irrelevant, since we're talking about programming,
that is, writting texts describing algorithms. There are too many
concepts, you don't have enough special characters combinations to
enumerate them.