S
Series Expansion
Hereunto.
Incoherent.
Hereunto.
Yes.
It adds expressivity and easiness of extensibility to the language.
Not magical, but useful nevertheless.
Choose your terminology as you wish. Lisp and Scheme (and Dylan and
few other ones) have macro systems better integrated in the language
than any other one. This integration does give you more power.
But that is not the point.
Fine. We are all grown up and can tell the difference.
I said no. You should explain why I am wrong.
Then why don't you read exclusively the files produced by gcc -E?
They are as "raw source code" as they get.
Or maybe we should just program everything in raw assembly.
Macros give you expressive power.
Noted.
You just griped about macros generating "source code" at the end.
Yes. But the point is that macros - especially when well integrated
in a programming language - improve the overall language usability.
It doesn't get "flattened again into source code prior to
compilation"
the "macro processor"(that is, Lisp)'s "internal
representation of the code" /is/ the source code.
The compiler operates on that very same "internal representation" (i.e., the
source code).
ROTFL
FYI: Vista 64 with seed7, VS2008, HP Z800 Workstation 6GB RAM
D:\p\seed7\prg>d:\cygwin\bin\time -p ..\src\hi chk_all.sd7
HI INTERPRETER Version 4.5.4853 Copyright (c) 1990-2009 Thomas Mertes
262 D:/p/seed7/lib/syntax.s7i
3518 D:/p/seed7/lib/seed7_05.s7i
70 D:/p/seed7/lib/shell.s7i
227 chk_all.sd7
4077 lines total
271800 lines per second
1755374 bytes
compiling the compiler - okay
chkint - okay
chkstr - okay
chkprc - okay
chkbig - okay
chkbool - okay
chkset - okay
chkexc - okay
real 17.59
user 0.00
sys 0.10
Most compilers tokenize the source file prior to compilation.That would be incorrect behavior, if so. The compiler, after all, by
definition of "compiler" deals in source code, so if your statement
were correct, the output of a macro would not be in a form amenable to
being compiled.
This statement is incoherent. The source code, by definition, is the
contents of the source files fed to the compiler, in the case of
Common Lisp e.g. by executing compile-file on them from a REPL.
Right.
This, too, is incoherent, for largely the same reasons. Source code
and compiler internal representations differ by definition, unless the
internal representation at issue is something trivial, such as an
ASCII buffer read from a source file.
It is gratifying that that point has now been settled.
Useful, perhaps, but, as I stated, not magical.
Yet it does not grant some of the magical capabilities that have been
attributed to it previously in this thread.
But that is exactly the point. Source code is source code. Where it
physically resides is irrelevant, except to the matter of its
preservation across sessions, for which reason unpreprocessed source
code should exist on disk.
However, its preservation across sessions was not the original issue
here, until you brought it up apparently as a diversionary tactic.
If this is meant to imply a personal attack, I should alert you to the
fact that such attacks do not constitute logical arguments in favor of
either Lisp or Java. However, the tendency of Lispers to frequently
make such remarks might itself be regarded as circumstantial evidence
favoring Java; Lisp may be tarnished in the estimation of some readers
by the company it keeps.
You are contradicting this earlier claim, posted by your own side:
If you and Alessio disagree as to which macros operate upon, source
code or object code, then perhaps you should work that out between the
two of you before either of you continues to press your attack upon
Java. Otherwise, we on the Java side can logically be expected to
seize upon such internal inconsistencies in your position and exploit
them to destroy your side's credibility, thus inexorably swaying the
audience in favor of Java. You are therefore in danger of losing the
debate. United you may prevail; divided you court defeat.
That is an issue of readability.
That is an apples-to-oranges comparison; the translation from C to
assembly is a matter of compilation, not just preprocessing the
compiler's input.
That is not in dispute, but it is also irrelevant to the current point
of contention.
You seem to be confused.
What they are not, in the vernacular, is a "silver bullet", contrary
to claims fronted here earlier.
And while we are on the subject of Java's superiority to Lisp, when I
did a bit of digging I turned up an arguably even larger skeleton in
Common Lisp's closet: catch and throw. While these may share the names
of well-behaved constructs in the Java programming language, a cursory
examination of their definition clearly establishes that they are
anything but. Indeed, it seems they can be used to implement the worst
spaghettifying feature ever to disgrace the BASIC programming
language: a computed "goto".
I rest my case, though I will continue to provide rebuttal evidence
and testimony at need.
Kaz said:Oh look, the troll
is now permuting his From: header
to evade killfiles.
Paul said:To whom are you writing? *I* know what it is because *I* wrote it all by
myself, so not to me.
Certainly I couldn't tarnish your reputation further
It seems you're attempting to deflect attention from the substance of
the posts in this thread by frantically pursuing other topics.
It seems I'm attempting to deflect attention from the substance of
the posts in this thread by frantically pursuing other topics.
I would advise you to debate with substance rather than resorting
to that tactic if you want to get anywhere.
Seamus MacRae said:Are you claiming it's not a personal attack? Implying that reading my
posts is "stooping" certainly seems to be.
Ben Pfaff said:Nonsense. If warnings always indicated a real problem, then there
would be no need for compiler options to enable and disable them.
John B. Matthews said:I must demur. Warnings always indicate the potential for harm.
First of all apologies for the cross posting. Follow ups to
comp.lang.lisp
Never said magical. Powerful yes.
I don't know anything about magic.
I was under the impression that you did not understand how Lisp macros
work.
Lisp macros, and Alessio, who is sitting right now in the same room,
agrees with me
and with many people who actually know Java
Yes. And that is the reason why Lisp macros give you power you do not
have in Java.
Yes.
And Lisp macros are on par.
No.
They can do (almost) arbitrary source-to-source transformations.
Of course I am. I have few ideas but confused.
They are a "very good thing"TM which give the programmer power.
Again, in Java there is nothing similar.
If you took the time to get your level of knowledge of Common Lisp
near the level of competence I or Alessio or many other people here
(in comp.lang.lisp) have with Java
you would have dug out prog, tagbody and go, not to speak of other
cockraches in CL (every cockroach is beautiful to his mother).
What you completely missed are handler-bind, handler-case,
restart-bind etc etc
You also missed with-open-file
which (1) is a macro and (2) it clearly states the intent of
the programmer, and (3) it is far better than theBufferedReader
x ... try { x = new BufferedReader(...); } finally { ...
x.close(); ... } idiom.
Suit yourself. We'll be waiting for you to get up to speed on CL.
Remember - and I am not apologizing for sounding patronizing; I am
patronizing
I know at least as much Java as you do
and I know that many lispers are in the same situation.
The opposite, with you and CL does not seem to be true.
Last One Wins!
Your answer:
Most compilers tokenize the source file prior to compilation.
You can think of macros as manipulating the tokens.
Right, but the internal representations are isomorphic to the source
file, so with lisp the line is 'blurry'.
(Java is to JVM as lisp is to lisp.)
(Although lisp then goes through another pass to a lower level
'virtual machine' (i.e. assembler, JVM, gcc in some cases))
That seems acceptable, but it fails to grant macros miraculous powers
of prescience.
Isomorphic isn't identical,I have proven mathematically that if the internal representations ARE
isomorphic to the source file then your asserted miraculous properties
of gensyms are physically impossible.
In other words, Java is really to JVM as Lisp is to assembler, JVM, or
even C code.
(Lisp on the JVM. That's gotta be a match made in hell! The JVM is
full of checks and validations, which I'm sure you Lispers would
consider as anal as Java's type safety and similar "bondage and
discipline". I can just imagine the methods needed to tie it up and
gag it into accepting Lisp-derived bytecodes without blowing up in
some manner.)
Series said:These tiresome personal attacks do not constitute rational arguments
in favor of either Lisp or Java, Marco.
Richard Heathfield said:John B. Matthews said:
Please explain the potential for harm in:
struct tm foo = {0};
that causes this message:
foo.c:6: warning: missing initializer
foo.c:6: warning: (near initialization for `foo.tm_min')
and which vanishes when the code is changed to:
struct tm foo = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
which has precisely the same meaning as the prior code *except
that*, if for some reason the definition of foo changes to add more
fields, the former code does not need to be changed, and is
therefore superior.
Please explain *any* circumstance in which struct structname = {0};
justifies the diagnostic message (above) that GCC generates for it.
Mostly I agree with your position, but some compilers, by generating
rather silly warnings in some circumstances, make it very difficult
to agree with you completely.
<snip>Richard Heathfield said:Stuart said:
Not all would agree that [ = {0} ] is superior [ to = { 0, 0, 0,
0, 0, ... } ]. If additional fields are
added to foo some [particularly those in the high-integrity
domain] consider it prudent to review assignments to a structure
(particularly initializations). Having the compiler nag you if you
have overlooked some case buried deep within your code is
considered a 'superior' code design.
Well, you got me there. I don't agree with you, but I do agree that
you have a defensible position!
In the first type of initialization it is not clear whether the
author's understanding of foo matches the current definition of
foo (i.e. whether any additional fields have been added). [The
warning might be better expressed though].
Good modularisation makes it reasonably easy to ensure that one has
dealt with all the ramifications of adding a member to a struct.
If zero-initialisation is required, = {0} does the trick elegantly
and well. The only reason this wouldn't Do The Right Thing is if
some fields were required to be initialised to non-zero values.
I favour blanket zero-initialisation followed by specific
assignments to members not because I like to make work for myself,
but because - as you say - new members might be added, and this can
introduce bugs.
Consider:
struct foo { int height; int weight; int shoesize; int quux; int
quuux; int quuuux; };
struct foo bar = { 190, 81, 12, 0, 0, 0 };
(My imagination failed for the names of the last three fields, but
basically they represent any old fields that need starting values
of 0.)
Now we maintain the struct:
struct foo { int height; int weight; int iq; int shoesize; int quux;
int quuux; int quuuux; };
and we maintain the initialisation, with the intent of inserting 115
as the IQ (might be a teacher, or a police officer, or a council
official - how many readers have I just offended, I wonder?):
struct foo bar = { 190, 115, 81, 12, 0, 0, 0 };
We've put this in the wrong place, but the compiler won't tell us
that. Far better to do this:
struct foo bar = {0};
bar.height = 190;
bar.weight = 81;
bar.shoesize = 12;
bar.iq = 115; /* rjh, 29/5/2009, Change Request 2139707B */
That way, every value is associated directly with the name of the
member, making it easier to get things right.
C99 allows us to do something similar within the struct initialiser
itself:
struct foo bar = { .height = 190, .weight = 81, .iq = 115, .shoesize
= 12, 0, 0, 0 };
which is fine provided we remember that any undesignated
initialisers that follow a designated initialiser will not "jump
back" to fill in the gaps (any members in such gaps will be
zero-initialised in the absence of any other initialisation within
a part-initialisation), so it's still possible to screw this up:
struct foo bar = { .height = 190, 81, 12};
struct foo bar = { .height = 190, .iq = 115, 81, 12 };
which gives us a shoesize of 81 and a weight of 0. Here, it is
possible that full initialisation might save you by giving you a
diagnostic message:
struct foo bar = { .height = 190, .iq = 115, 81, 12, 0, 0, 0 };
It would surprise me if this code were not to generate a diagnostic
message for "too many initializers", but I can't immediately prove
from the Standard that it must (I'm not particularly familiar with
C99, and don't even have a C99 compiler).
And of course this technique does depend on your having a C99
compiler (or a compiler that includes some C99 features).
So, in the continuing absence of C99, my own preferred method is
blanket initialisation followed by explicit assignment to named
members. It would be silly to get religious about it, but as a
general guideline I find it helpful.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.