Re: Seeking computer-programming job (Sunnyvale, CA)

P

Pillsy

Unless you're writing wizard macro-defining macros[1], debugging macro
code is fairly straightforward

RLY. I've done it, and I'm assuming Spiros has too.

It's strange to be told, repeatedly, that things I do routinely,
without a great deal of difficulty or aggravation, are in fact
ridiculously hard and painful. I mean, it's the kind of thing that'll
give a guy a swollen head....

Cheers,
Pillsy
[...]
 
A

Adlai

I meant to say "Spiros", not "Spirol".

And I'm sorry about the derogatory tone of my message. However, please
understand, Mr Expansion (?), that it's quite exhasperating trying to
offer new information to somebody who just parrots back the same trite
replies. I've heard that there's no use to arguing on the internet...
well, I'm hoping that's wrong. Please consider some of the information
that we (mainly Pascal and Spiros) have put forth in past postings.


- Adlai
 
S

Seamus MacRae

Adlai said:
On May 16, 7:46 am, Series Expansion <[email protected]> wrote:
[Some attributions are missing. Sorry.]
Do things like have a pack of THINGS, rather than a pack of strings.

Paul Graham repeats often, for good reason, that one of Lisp's great
strengths is its flexibility. You can have a heterogenous list and
Lisp won't blink.

Series mentioned some Java myths being perpetuated in this thread: Java
is slow, Java lacks reflection, Java isn't Turing complete. Well, this
seems to be another one: Java doesn't have heterogeneous lists.

Heck, prior to version 5 it didn't have NONheterogeneous lists.

Sheesh!
You can have a function that returns some data, or
NIL if the data is unavailable.

Java can do this (return an object or null), and java.util.Map.get()
does it and is in the standard library.

Lispers, please at least *learn* a bit about Java before criticizing it!
You can bind the result of that function to a variable without
worrying about types.

Java programmers wish for a way to bind something to a variable that
WILL generate compiler errors if it might be null, and they want that
variable to have to be non-null. So they could write:

@NotNull String s;
{
String t = map.get(key);
if (t == null) {
// Do something;
} else {
s = t;
}
}
s.length();

and the compiler would check that the assignment of t to s cannot
possibly assign null.

Java 7 might have this feature.
Variable capture is a useful tool sometimes, for example in anaphoric
macros.

No normal application developer is going to, or should need to, concern
himself with "anaphoric" anything. At least not unless he works in
engineering on the starship enterprise, where not a day goes by without
metaphasic this, polaric that, and all kinds of fluxes and subspace
whosits needing to be dealt with.
Java is meta-programming for JVM bytecode. Lisp is meta-programming
for Lisp. By being a meta-language for itself, Lisp allows you to
express a huge variety of concepts.

Including such doozies as "this statement is false"?

Unbounded self-referentiality reputedly drove Georg Cantor mad and led
to the reformulation of half of mathematics to avoid inconsistencies
like that.
Your imagination is really the only significant limit, second maybe
to carpal tunnel

In what dream world? Here in the real world we also have to worry about
code maintainability, code readability to other people, and bug hunting,
not to mention slippery requirements and user complaints of every stripe.
 
F

Frank GOENNINGER

I'd really kill my parents if they gave me such a name...

[snip]
I just explained why the package system won't.

No, you didn't.
Adding new classes in
their own packages? No problem, the package system can distinguish
foo.String from bar.String. Adding new methods to an existing class,
say foo.String? Uh-oh. Is that baz's foo.String.doIt() or quux's
foo.String.doIt()? They have the same method name, are methods of
classes with the same name, and the classes are in the same package.
As far as the compiler is concerned, they are the same.

No, not in CLOS. You better read up on CLOS before you post such crap.
The package
system cannot distinguish them unless we add another layer of
namespacing, this time INSIDE classes, and have foo.String.baz.doIt()
and foo.String.quux.doIt() instead of just foo.String.doIt() as the
fully-qualified names. And now we're deep in migraine-headache
territory, without oar or compass...

See my comment above.

[snip]
So, basically, you're saying that the way you avoid the name clash is
to make baz's String.doIt() and quux's String.doIt() private.
No.

Of
course, this now means that anyone who wants their own code to call a
String.doIt() has to roll their own and can't get a canned one from a
library. Because if they do, and there's multiple incompatible
libraries that provide this, then we're back to square one and name
clashes.
No.


Of course, the best way to avoid multiple incompatible libraries is to
have commonly desired functionality built into the standard library.

Ah - who's the Standard Committee for Java again?
And then letting third parties create (non-private, at least) methods
in your classes is unnecessary.

Of course letting them create private ones is also tricky. They need
to be a new kind of private: private to the module that defines them,
NOT to the class they're defined in (now that those are different).
No.

Now the private/public/local/global scope system gets more
complicated.

No need to. Just doesn't happen!
Everywhere I look I see tradeoffs here.

Yep, I do too in Java. No so in Common Lisp. There's freedom and
liberty. Not everybody knows how to use this to one's benefit.
Ah, I love the smell of boilerplate code in the morning!

Ah, I love the smell of efficiency in coding in Lisp all day long ...

Frank
 
S

Seamus MacRae

Pillsy said:

Every time a serious problem is mentioned, you tend to dismiss it with
little more than a hand-wave. A can-do attitude is good to have, but
here it's verging on Pollyanna. You're liable to trip and pitch
headfirst down a six-hundred-foot chasm while staring up at the pretty
blue sky if you carry on like that.
No, Emacs + SLIME has convenient features for locating method
definitions in their source files. Just because the interface looks a
like something out of 1983 doesn't mean it doesn't work well.

I'm sure it does, by 1983 standards.

Call me when you've got a flying DeLorean and then we'll talk.

(It still beats vi and Windows Vista. Vista looks like something out of
1984. The book, that is.)
In the class definition...? If I want to say that FOO is a subclass of
BAR, I just write

(defclass foo (bar)
;; This space for rent!.
)

Yet earlier someone was saying you'd omit to specify that Complex
inherited from Number.

This is absolutely fascinating. Now you're actually becoming visibly
incoherent. The next step I suppose is overt verbal violence, followed
eventually by a Hitler comparison, and then mass kill-filings.
No, I mean, you never see any of it.

Oh, lovely. Machine-generated code you can't even find and read? It's
annoying enough to get bison-generated code to play nice with version
control. Your phantom dispatch tables are going to bedevil any serious
developer until his hair falls out and his nose gets all wrinkly.
So do I. It's a very good thing that you don't have to use it to use
CLOS.

But ... but ... but ... but you just ...

Oh, aren't you the clever troll!
You select the name of the generic function, hit Alt-., and a list
pops up listing all the methods for the generic function and their
classes. Then you click on the one you want, and you're taken to the
definition. It's really, really similar to looking up definitions in
Eclipse.

You assume people are using some particular tool, with a fairly decent
interface, that I ain't never heard of. From all indications, a straw
poll here would show most of the other lispers to be using emacs or
something else equally primitive, though, and there might also be issues
with getting such a tool to work with different dialects of Lisp reliably.
You just... use them?

Limp. Very limp.
No, I mean, "there's no problem", by which is meant that I can't even
figure out what problem you might be referring to.

Fully-qualifying the fuckin' names! What the hell else could I be
referring to? :p
I'm really not seeing much difference between that and

(defclass my-whatsit () ())

(defmethod print-object ((object my-whatsit) stream)
(print-unreadable-object (obj stream)
(format stream "I'm a whatsit!")))

That's all you have to do. No monkeying with any other code anywhere
else. No code generation.

Let me guess: no MANUAL code generation. Something in the toolchain does
it for you.

That's not quite the same thing. And there's no namespace-related stuff
in your code. OK, there was none in mine, either, but you can just slap
a "package foo;" at the top of it. Whereas yours requires you to
defmethod the pre-existing, in some widely used namespace, print-object
method, with who knows what potential risks if you screw it up.

Oh yeah, I forgot: you're perfect and simply will not ever screw it up.
Ever. :p

That was you! It's your own previous post you contradicted up there by
putting explicit subtyping declarations into some of your example code.
No, you write the four method definitions and then compile them. All
the machinery for doing the dispatch is handled by the Lisp
implementation transparently.

Like a C++ vtable, then, except that you (or a bug in your code) can
screw with the vtables for objects from the standard library, the
vtables for MY objects, ...
 
A

Adlai

Series mentioned some Java myths being perpetuated in this thread: Java
is slow, Java lacks reflection, Java isn't Turing complete. Well, this
seems to be another one: Java doesn't have heterogeneous lists.

Heck, prior to version 5 it didn't have NONheterogeneous lists.

I didn't specifically criticize Java. I don't know it well enough to
criticise it specifically. I was pointing out the advantages of having
some type flexibility. I see now that Java does have some amount of
flexibility. Lisp has complete type flexibility, with the option of
adding declarations that a good compiler will use to give you some
warnings.
No normal application developer is going to, or should need to, concern
himself with "anaphoric" anything. At least not unless he works in
engineering on the starship enterprise, where not a day goes by without
metaphasic this, polaric that, and all kinds of fluxes and subspace
whosits needing to be dealt with.

Anaphoric macros are extremely useful. There's a hidden anaphor in the
CL loop macro, which binds the value of IT onto a previously-evaluated
conditional. In other words, within a loop, you can say something like

(loop
for x in list-of-things
when (find x other-list) collect it)

That's all there is to anaphors. This example in the loop macro is the
only built-in anaphor that I know of in CL, but it's very easy to
define syntax for them using macros:[1]

(defmacro aif (test-form then-form &optional else-form)
`(let ((it ,test-form))
(if it ,then-form ,else-form)))

There you have it -- a macro that uses variable capture to accomplish
a fairly useful task. Many functions -- and not just in Lisp -- follow
the convention of returning some useful value if they "succeed", or a
false value (NIL in Lisp, maybe False in Python or 0 in C++, etc) if
they "fail". This macro saves a lot of boilerplate in the long run if
you use functions like that.
In what dream world? Here in the real world we also have to worry about
code maintainability, code readability to other people, and bug hunting,
not to mention slippery requirements and user complaints of every stripe.

Lisp doesn't limit you from dealing with those. Lisp code can be very
readable -- most often, unreadable Lisp code is due to bad formatting,
rather than the syntax itself. Yes, some macros are hard for a non-
Lisper to understand, but 20 minutes with a good tutorial like PCL[2]
or Successful Lisp[3] is actually enough to understand most Lisp code.

It's very easy to maintain Lisp code and hunt bugs, both because of
the aforementioned ability to manipulate your code while it's running,
and because of the interactive nature of building code (not a feature
unique to Lisp).

And Lisp thrives on slippery requirements because of these
flexibilities. If you're just starting out on a problem, you can use
some form of linked cons cells to represent almost any data structure
for prototyping, and the interactive nature of building code makes it
very easy to test variations while you're building your system.

Java does have many advantages over other "standard" programming
languages in use today. I'm not trying to downplay Java in any way. If
I had to use one of the standard languages, I'd pick Java over most
other options. However, I (along with a few others here at c.l.l) am
just trying to point out the strength, flexibility, and, despite your
preconceptions about a language second only to FORTRAN in its age,
modernity of Common Lisp.

Let's both try and keep this a civil discussion.


- Adlai
 
A

Adlai

I forgot a few notes:

[1] from page 191 of On Lisp, by Paul Graham
[2] www.gigamonkeys.com
[3] http://www.psg.com/~dlamkins/sl/


By the way, for the (1+ n)th time, SLIME Emacs is a modern IDE. It has
all the functionality that you've described an IDE should have. The
ONE thing it doesn't have is popping out stuff into neat little help
bubbles, but that's cosmetic, not a functionality. It highlights
source errors, can link in to profiling utilities, has half a zillion
different ways to poke and prod your programs to assist debugging --
there is nothing 1983 about SLIME + Emacs, other than maybe the fixed-
with font in the menus.

And yes, you can use your mouse for everything you'd expect in any
other windowed program.

Emacs also has a psychotherapist, programmed in Lisp. I'm not kidding.
It's really relaxing to chat with it every now and then.


- Adlai
 
S

Seamus MacRae

Kenneth said:
Say this: Lisp programmers have programming jobs meaning they know Java
or Python or Ruby or whatever so there is prolly not much delusion
involved. It is more of an informed comparison. Yes, the bad news is
that we are also better at those languages than you. Sorry for the
comedown.

Nobody makes an arrogant statement like that on usenet without getting
his nose tweaked.

Nobody.
I took a different path

That much is certain. (I think it might be that rather well-known one
that's paved with good intentions.)
I pointed out that we Lisp Gods have Perfect Knowledge of crud

That is arguably correct also, though Perfect Knowledge is ordinarily
considered to be the sole preserve of God. Oh, wait, did you not also
explicitly say you *were* God? I believe you did.

There's probably a special place in Hell being warmed up for you by the
horned d00d while the bearded d00d sets you up for a brain aneurysm or
lightning-up-the-phone-line or something.
I find it telling that Groovy got invented because the tide had left
static typing and all-OO-all-the-time and catch-every-exception high and
dry and was not coming back.

Java myth #5! "Java programmers catch every exception". Actually we try
to catch only the relevant exceptions in a particular bit of code, or
even none (with try ... finally without catch), though occasionally some
code might catch everything to log it and rethrow.

Some BAD Java programmers put catch(Exception) or catch(Throwable) all
over the place.
<sigh> Lisp did that in the Sixties

All kinds of things got did in the Sixties. Most of them are illegal now.
Java ("programmers are incompetent").

Java myth #6! "Java programmers are incompetent".
I must say, you do not seem incompetent, you seem quite bright.

Oh wait, it looks like Java myth #6 is starting to be questioned by the
lispers. Perhaps a harbinger of bigger changes to come?
Explaining why they spend all their time complaining about it?

The compiler spends all its time complaining about our code. Turnabout
is fair play. :)

More seriously, the language can use improvement, and maintenance, and
that requires criticism and a realistic outlook.
I had a wife like that once.

What, she spent a lot of time complaining about Java?

Is she single now?
Useful? A tool? Oh, be still my beating heart. A wise man once said that
Java was the only language no one ever loved.

Another wise man once said that the surest sign that the right decision
had been made was that everyone on both sides complained about it, but
they abided by it anyway.
Ah, never had the pleasure of macros, have we? Glory be to the
readability and to the parsing and to the &whole parameter.
^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
Oh, the irony.
You seem like a great guy and quite bright at that. Do yourself a favor,
STFU

How rude!
 
S

Seamus MacRae

Pillsy said:
Nope, not really.

Pollyanna much?
Eh, in the general case you just use the packages you want to use and
that's that

Yes, and meanwhile at Mission Control, you just trigger the final
pre-orbital burn of the hypergolic propellants at max-Q and that's that.

Remind me NOT to ever trust you with a multi-million-dollar satellite
payload. :)
I'm missing the part where that's conspicuously easier than the Lisp
option.

Well, let's see...

(defpackage #:my-package
:)use #:cl #:foo))

Two lines. 42 characters (not including internal linefeed and
indentation). Nesting depth of brackets: 2.

import foo;

One line. 11 characters. Nesting depth of brackets: zero.
 
S

Spiros Bousbouras

Did you miss the bit about tight coupling making it harder to find the
bugs?

It's not clear to me what you mean by tight coupling or how
it would make it harder to find bugs.
If your editor doesn't support search and replace, I suggest you
search for a new one to replace it. :)

So in NetBeans you can specify a multi-line region of code where
perhaps the first or last lines of the code you want to change
do not occupy the whole line and then replace it with something
else ? It's quite good if you can do this but it's still less
convenient than macros.
And now you've replaced a bit of your code with the expanded version.
Later you'll change the macro for whatever reason, but at this one
spot the change won't be applied since the macro call was replaced
with its expansion in your editor at that spot. That copy now gets out
of synch with the rest of the code.

As others have pointed out it's not clear here what gugamilare
meant. Perhaps he meant that you expand the macro , see why it
doesn't work at that specific place in the code , modify the
macro code and then restore the macro call at the place in the
code where you did the expansion. But let's say instead that you
decide that the macro doesn't work quite right at a specific
place where you originally used it so you have to write the code
explicitly or write another macro for that particular place or
even write a function for that particular place. So yes that
place in the code requires from then on "special treatment", it
won't be affected when you change the macro code.

But once again the exact same scenario can happen if you only
use functions. Say you use foo() in 50 different places in your
code but on testing you find that it doesn't achieve the desired
result in one place. So you eliminate the call to foo() at that
particular spot and replace it with something else. Obviously
if later on you change the foo() code it won't affect that
particular place. So why is it more dangerous with macros?

The irony being that that was basically the criticism you leveled at
Java and its frequent need for boilerplate code: if I make 100 copies
and later need to change something I have to track them all down. You
may actually have it worse:
1. You write a macro.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2. At one point, something goes wrong so you hit a "small sequence of
keystrokes" to do an in-place replacement of a call to that macro
with its expansion.
3. You fix the bug in the macro, whatever it was, but don't change
that other code back into a macro call.
4. Later, you make a change to the macro.
5. Because you didn't copy-paste that code all over the place, you
think you DON'T have to go track down copies and make sure
they're all in synch. As a result, the expanded copy produced
in step 2 doesn't end up reflecting the change.
6. Now you've got code that's getting out of synch with other code.

And as I pointed out above the exact same thing can happen with
functions. An IDE which would help with the issue would work
just as well with macros. Now if you want to make the argument
that there are better IDEs available for Java than for Lisp that
may be true but I'm only commenting on whether Lisp macros are
inherently more dangerous than other programming constructs.
I don't see how it can fail to be. Obviously the code at the macro
call site intimately depends on the macro's innards -- for example, if
one input to the macro is an expression with side-effects, the number
of times the side-effects happen and the order in which side-effects
of different inputs happen will depend heavily on the exact macro
code. So certainly code that calls the macro will break if the macro
implementation (not just its signature) changes.

And code which calls a function will break if the function
implementation is not correct. I'm not sure what you mean by
signature.
The reverse is also
true: if the macro takes the inputs apart with car and cdr to
transform them in some way, its correctness will depend on the inputs
having the correct structure.

Even if a macro had to use car and cdr to take apart its
argument it could check that the argument has the correct
structure and if it didn't issue an error. But Common Lisp
macros do not have to use such lowly means. Consider the
following definition:

(defmacro m (a (b c) (d e (f g)))
`(list ,a ,b ,c ,d ,e ,f ,g))

What the macro does is trivial, it just prints its arguments but
the point is to show how the definition of the macro can specify
the structure of its arguments. If I call the macro like

(m 1 2 3 4 5 6 7)
or
(m 1 (2 3) (3 4 5 6))

I will get an error message. I have to call it like

(m 1 (2 3) (3 4 (5 6)))

in which case variable a will be bound to 1, b to 2, etc. So
the Lisp compiler automatically checks that the arguments passed
to the macro have the right structure and binds each variable
appearing in the macro definition to the corresponding part of
the arguments given to the macro.
So, the macro definition and every call site of the macro will be
tightly coupled.

A Java method or C function definition is more loosely coupled. Since
it's just values of some sort passed as parameters, rather than code,
the order of side-effects of the arguments is well-defined: each
happens once, in left-to-right-order, at the call site and just before
the call itself.

Actually if in C you do foo(expr1 , expr2) the order in which
expr1 and expr2 will be evaluated is unspecified. In any case
the order of evaluation is precisely specified in Lisp. The
appropriate parts of the code passed as an argument to the macro
will be assigned to the macro variables and what happens from
then on depends on what the macro does. It can decide which code
to evaluate and in which order.
With pass-by-value (Java primitives and non-pointer C
parameters) the function also won't alter the passed-in data. With
pass-by-reference (Java objects with mutable state, pointers, C++
references) the function can alter the passed-in data but its
implementation still won't influence side effects and order of
evaluation of the argument expressions.

But it will influence the order of evaluation of all the expressions
that
appear inside the function. In other words writing

a = expr1;
b = expr2;

may have different side effects than writing

b = expr2;
a = expr1;

Now let's imagine that C had a special syntax which allowed you
to decide in which order the arguments of a function get
evaluated. So in a call like foo(expr1 , expr2) you could use
the special syntax to decide if expr1 gets evaluated before
expr2 or vice versa. What makes you think that this would
present any greater programming problems or potential for bugs
than what C actually does offer? It seems to me that order of
evaluation is a central aspect of (non-functional) programming
so I don't see how having one more place where you can influence
order of evaluation makes such a great difference.
Macros may be able to do powerful things, but with that power comes
the greater potential for problems. (Others have mentioned variable
capture, so I won't go into detail about that here.)

Has someone mentioned variable capture in this thread? I missed
this. Anyway there is a standard and easy way to avoid this
(unless of course you want variable capture to happen and on
some occasions you do) which is explained in chapter 8 of
``Practical Common Lisp''.

< Snip comments about modifying running images >

--
He could sometimes be caustic in his reminiscences of the
South during that era, once writing that "even in the 'Bible
Belt' the Bible is a relatively unknown book -- sacred, of
course, but quite unfamiliar."
Refers to theologian Langdon Gilkey Dies
 
S

Seamus MacRae

Adlai said:
No normal application developer is going to, or should need to, concern
himself with "anaphoric" anything. At least not unless he works in
engineering on the starship enterprise, where not a day goes by without
metaphasic this, polaric that, and all kinds of fluxes and subspace
whosits needing to be dealt with.

Anaphoric macros are extremely useful. There's a hidden anaphor in the
CL loop macro, which binds the value of IT onto a previously-evaluated
conditional. In other words, within a loop, you can say something like

(loop
for x in list-of-things
when (find x other-list) collect it)

That's all there is to anaphors. This example in the loop macro is the
only built-in anaphor that I know of in CL, but it's very easy to
define syntax for them using macros:[1]

(defmacro aif (test-form then-form &optional else-form)
`(let ((it ,test-form))
(if it ,then-form ,else-form)))

There you have it -- a macro that uses variable capture to accomplish
a fairly useful task. Many functions -- and not just in Lisp -- follow
the convention of returning some useful value if they "succeed", or a
false value (NIL in Lisp, maybe False in Python or 0 in C++, etc) if
they "fail". This macro saves a lot of boilerplate in the long run if
you use functions like that.

It sounds like it's probably got performance, thread-safety, and even
reentrancy problems, big-time. If this creates a local "it" in each
scope, there may be a performance problem with the extra pointer
assignment in loops where it's usually not used but that might be it,
and the compiler might even be smart enough to optimize it away where
it's unused. On the other hand if "it" is a global variable and you try
to use this in anything more complex than some toy project, you're screwed.
In what dream world? Here in the real world we also have to worry about
code maintainability, code readability to other people, and bug hunting,
not to mention slippery requirements and user complaints of every stripe.

Lisp doesn't limit you from dealing with those. Lisp code can be very
readable -- most often, unreadable Lisp code is due to bad formatting,
rather than the syntax itself. Yes, some macros are hard for a non-
Lisper to understand, but 20 minutes with a good tutorial like PCL[2]
or Successful Lisp[3] is actually enough to understand most Lisp code.

Forgive me if I take that all with a grain of salt.
Java does have many advantages over other "standard" programming
languages in use today. I'm not trying to downplay Java in any way. If
I had to use one of the standard languages, I'd pick Java over most
other options. However, I (along with a few others here at c.l.l) am
just trying to point out the strength, flexibility, and, despite your
preconceptions about a language second only to FORTRAN in its age,
modernity of Common Lisp.

Modernity ... that's cute, all things considered. The last time I
looked, the language still assumes that not even CGA graphics have been
invented yet. And so do the typical development tools. :)
Let's both try and keep this a civil discussion.

That would be nice.
 
A

Alessio Stalla

Now, is there any Lisp implementation for which this is true?
Particularly, as broad coverage of common requirements (GUIs,
networking, threading, math) as Java has in standard/widely-used
libraries?

Commercial implementations offer their libraries, and they do cover
the areas you mentioned. There are many open source libraries too, but
we're still far from the "grab from the shelf" philosophy Java strives
to achieve (and manages to, often ;). But, the library situation in
Lisp is in fact better than most people think, especially with respect
to the size of the Lisp community, which is tiny compared to Java.
You're kidding. Especially in BIG applications? But we've just been
through why the static typing overhead is a smaller proportion of the
work the bigger the app, and the bug-finding savings bigger.

No, I'm not talking about the overhead of static typing here. The
"tangent about XML" you removed from the quotation was an example of
how, in big applications, Java programmers often resort to sub-optimal
means (like very complex XML configuration files) only to achieve
something they have from the start in dynamic languages - namely, more
dynamism, or if you prefer, less constraint from static types. And by
doing so they lose the benefit of static typing, AND do not have a
strong enough support for dynamic typing that would compensate for
that loss (like it happens in Lisp and other languages).

As an example, try using Spring and voluntarily mistype the name of a
bean's property: you'll only see it fail at runtime. In Lisp the same
would happen, but you would use Lisp and not XML: most Lisp compilers
issue a warning about calls undefined functions (such as a mistyped
accessor); plus in Lisp you can test in isolation the single function
or macro where you have made the typo, and catch it early.

My point is that sooner or later at least some dynamic language
features are inevitably needed (especially in big applications). If
you have a language that is natively dynamic you have means to deal
with the negative side of the dynamism. If you emulate those features
on a statically typed language, you'll get worse implementation of the
same features and less tools to cope with type errors and other kinds
of errors at runtime.

Just my opinion, of course...
Alessio
[a whole lot of some tangent about XML]
I'm not saying Java is unusable and should be dropped tomorrow. Just
that maybe it's not the be-all, end-all of programming languages ;)

I'm not sure any of them are.

Don't knock having the compiler check for type errors until you've
tried it.
 
S

Spiros Bousbouras

No normal application developer is going to, or should need to, concern
himself with "anaphoric" anything. At least not unless he works in
engineering on the starship enterprise, where not a day goes by without
metaphasic this, polaric that, and all kinds of fluxes and subspace
whosits needing to be dealt with.

"Mr. Spock is a Lisp hacker". Yes , I like this.
Including such doozies as "this statement is false"?

An interesting thing to ponder.
Unbounded self-referentiality reputedly drove Georg Cantor mad and led
to the reformulation of half of mathematics to avoid inconsistencies
like that.

Nahhh , certainly not half of mathematics , just some techical
details in set theory.
 
S

Seamus MacRae

Adlai said:
I forgot a few notes:

[1] from page 191 of On Lisp, by Paul Graham
[2] www.gigamonkeys.com
[3] http://www.psg.com/~dlamkins/sl/


By the way, for the (1+ n)th time, SLIME Emacs is a modern IDE. It has
all the functionality that you've described an IDE should have. The
ONE thing it doesn't have is popping out stuff into neat little help
bubbles, but that's cosmetic, not a functionality.

Being able to see a nicely organized workspace with visible context for
displayed informaton, instead of just one page of text at a time in one
window, is "cosmetic, not functionality"? Pardon me if I disagree.

Contrast these alternatives, for example:

There's code on the screen. You arrow to a macro, type some hotkey
newbies will keep having to go to the help or use a crib-sheet to
remember, and the screen changes to a screen showing the macro
definition. To get back, either you have to reopen the previous file and
page down to where you were, or maybe there's some hotkey that functions
like a browser's "back" button. Maybe unsaved changes were lost if the
first file was modified and not saved, and the macro definition was in a
different file; hopefully not.

There's code on the screen. You right-click on a macro and see
neatly-labeled options including "view definition". Clicking that
produces a separate window containing the definition. You can drag it to
position it so that you can view the definition and the code that's
using the macro side-by-side if you want to, or expand it into a
full-size window and make changes to the macro if you want to. The
editor will keep both files open, simultaneously, in windows you can
arrange or overlap as you see fit, or in browser tabs, or similarly. It
certainly won't discard unsaved changes without prompting you first.

The former is the typical experience with a relatively "enlightened"
terminal-mode editor, restricted as it is to a single grid of ASCII text
and keyboard input; even if you can have multiple files open at once you
will generally only see one at a time and may not even see any tab
headings or other indications that there are any others open than the
one in front of you right now. Generally the limited capabilities of the
display will limit the software's ability to provide cues and to inform
you peripherally of the general status of the system. At best, it's like
using NetBeans while peering through a keyhole, then, with your mouse
busted, and at worst like trying to juggle multiple files in WordStar 1.0.

The latter is the typical experience with a well-designed modern IDE
like NetBeans.
It highlights
source errors, can link in to profiling utilities, has half a zillion
different ways to poke and prod your programs to assist debugging --
there is nothing 1983 about SLIME + Emacs, other than maybe the fixed-
with font in the menus.

And yes, you can use your mouse for everything you'd expect in any
other windowed program.

Now I'm confused. Which windowed program were we discussing? Not the
text editor, which predates Windows 1.0 by more than a decade. SLIME? I
thought someone said it was a script in the editor's internal scripting
language.
Emacs also has a psychotherapist, programmed in Lisp. I'm not kidding.
It's really relaxing to chat with it every now and then.

This is software you expect me to take seriously? And here I'd thought
putting that damn paperclip in office productivity software was asking
for it. (And was proved right.)
 
T

thomas.mertes

(e-mail address removed) wrote:

[snip]
The test program (chk_all.sd7) starts other programs one by one. It
does this with popen(). The system function popen() opens a pipe and
the result of the command execution can be read from this pipe. To
read (hopefully) the whole pipe into a string the function 'gets'
is called with the request to read 999999999 characters. The Seed7
function 'gets' is implemented with the C function filGets()
(in file_rtl.c). The function filGets() is really low level (other
interpreters/librarys probably also have similar functions) and
uses several strategies to do its job. In order to work reasonable
good in the common case (reading just some characters) memory for
the requied maximum length is requested with malloc(). After the
data is read the result string is shrinked to the actual size (with
realloc). When the memory cannot be requested a different strategy
is used. In this case the function trys to find out the number of
available characters (which is possible for a regular file but not
for a pipe). If this fails also a third strategy is used. A smaller
block is requested, this block is filled with data and resized in a
loop. So it is nothing special when a malloc fails in the filGets()
function. There are alternative code paths to provide the requested
functionality.

Limiting the length to 0x1FFFFFFF (~0.5 GiB) in gets() eliminates the
warning:

$ include "seed7_05.s7i";
include "shell.s7i";

const proc: main is func
local
var file: outFile is STD_NULL;
begin
outFile := popen("./hi -q echo.sd7 echo test", "r");
writeln(gets(outFile, 16#1FFFFFFF));
end func;

Great. I will use this limit in filGets().
There are a number of warnings when compiling fil_rtl.c, but I don't see
a connection:

fil_rtl.c: In function 'getBigFileLengthUsingSeek':
fil_rtl.c:263: warning: passing argument 1 of 'bigFromUInt64' as
unsigned due to prototype
fil_rtl.c:265: warning: passing argument 1 of 'bigFromUInt32' with
different width due to prototype
fil_rtl.c: In function 'filBigLng':
fil_rtl.c:315: warning: passing argument 1 of 'bigFromUInt64' as
unsigned due to prototype
fil_rtl.c:317: warning: passing argument 1 of 'bigFromUInt32' with
different width due to prototype
fil_rtl.c: In function 'filBigTell':
fil_rtl.c:389: warning: passing argument 1 of 'bigFromUInt64' as
unsigned due to prototype
fil_rtl.c:391: warning: passing argument 1 of 'bigFromUInt32' with
different width due to prototype
fil_rtl.c: In function 'filSetbuf':
fil_rtl.c:848: warning: passing argument 4 of 'setvbuf' as unsigned due
to prototype

You are right: There is no connection to the malloc error.
Regarding the warnings: For some reason your C compiler is not
capable to evaluate the expression

sizeof(offsettype) == 8

at compile time. So the C compiler is complaining about things in
unreachable code. The other warnings can be avoided with casts.
I will try to remove this warnings.

BTW: Thank you for the list of warnings you sent by mail. I will
take a closer look at the list, but at first sight I consider the
warnings harmless. I will try to reduce them nevertheless.
I think it does return NULL; the helpful message appears on stderr.

This supports my theory. About being helpful I have a different
view. I do not consider something, which violates the specification,
as helpful. Imagine what happens when every function decides to
write to stderr under some conditions. The programmer should know
what he/she is doing. I don't like when some library or OS thinks it
is smarter than the programmer. When functions start complaining to
stderr the program does not have the possibility to silently provide
an alternate solution.
Turning off the alarm still leaves one curious about the smoke:)

There is no smoke. The program can choose an alternate solution
or raise an exception.

Many thanks for your help.
I still have some questions:

Do you have other ideas regarding Seed7?
Which parts of Seed7 need improvement?
Is the documentation sufficient?
Which librarys do you need when you are programming?

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
 
A

Adlai

Anaphoric macros are extremely useful. There's a hidden anaphor in the
CL loop macro, which binds the value of IT onto a previously-evaluated
conditional. In other words, within a loop, you can say something like
(loop
   for x in list-of-things
   when (find x other-list) collect it)
That's all there is to anaphors. This example in the loop macro is the
only built-in anaphor that I know of in CL, but it's very easy to
define syntax for them using macros:[1]
(defmacro aif (test-form then-form &optional else-form)
  `(let ((it ,test-form))
     (if it ,then-form ,else-form)))
There you have it -- a macro that uses variable capture to accomplish
a fairly useful task. Many functions -- and not just in Lisp -- follow
the convention of returning some useful value if they "succeed", or a
false value (NIL in Lisp, maybe False in Python or 0 in C++, etc) if
they "fail". This macro saves a lot of boilerplate in the long run if
you use functions like that.

It sounds like it's probably got performance, thread-safety, and even
reentrancy problems, big-time. If this creates a local "it" in each
scope, there may be a performance problem with the extra pointer
assignment in loops where it's usually not used but that might be it,
and the compiler might even be smart enough to optimize it away where
it's unused. On the other hand if "it" is a global variable and you try
to use this in anything more complex than some toy project, you're screwed.

Enter lexical scoping. If you look in the example code I presented
from On Lisp, the variable IT is bound within a LET form. This means
that IT has that meaning, within the lexical (read: word/language
dependant) scope of the LET form. It's actually quite similar to the
scope of local variables within a method in Java (IIRC).

Thus, different iterations of the macro within a loop would be blind
to eachother, and although I'm no concurrent programming whiz, I'd be
quite surprised if concurrent scopes collide with eachother -- any
Lisper with threading expertise know about this one?
Lisp doesn't limit you from dealing with those. Lisp code can be very
readable -- most often, unreadable Lisp code is due to bad formatting,
rather than the syntax itself. Yes, some macros are hard for a non-
Lisper to understand, but 20 minutes with a good tutorial like PCL[2]
or Successful Lisp[3] is actually enough to understand most Lisp code.

Forgive me if I take that all with a grain of salt.

Well, ideally, you would actually try it out for yourself -- read
Peter Seibel's chapter on macros, and see for yourself their
transparancy. Macro code is just like any language; after a bit of
familiarity with the syntax, you just have to piece your way through
and you'll be able to figure it out.

Now obviously what I've said will be wrong if you try to understand,
right off the bat, how some complex macro works. However, many macros
are not very complex, and you wouldn't write a macro more complicated
than you could understand, the same way that you wouldn't write a Java
program more complicated than you could understand. You would build up
from simpler exercises, through practical projects, and by the time
you reached the more complicated levels, you would have the experience
to mentally parse them.
Modernity ... that's cute, all things considered. The last time I
looked, the language still assumes that not even CGA graphics have been
invented yet. And so do the typical development tools. :)

Just because something isn't in the ANSI CL standard doesn't mean it's
in use by the CL community. Some of the commercial implementations
have their own graphics libraries, and there are several cross-
platform graphics libraries as well. Just google common lisp graphics
to see a sample of these.


- Adlai
 
A

Adlai

Adlai said:
I forgot a few notes:
[1] from page 191 of On Lisp, by Paul Graham
[2]www.gigamonkeys.com
[3]http://www.psg.com/~dlamkins/sl/
By the way, for the (1+ n)th time, SLIME Emacs is a modern IDE. It has
all the functionality that you've described an IDE should have. The
ONE thing it doesn't have is popping out stuff into neat little help
bubbles, but that's cosmetic, not a functionality.

Being able to see a nicely organized workspace with visible context for
displayed informaton, instead of just one page of text at a time in one
window, is "cosmetic, not functionality"? Pardon me if I disagree.

I think it depends... for example, some information can just as
concisely be displayed in the status bar of the editor, as is the
information I mentioned earlier about the syntax of the current form.
Contrast these alternatives, for example:

There's code on the screen. You arrow to a macro, type some hotkey
newbies will keep having to go to the help or use a crib-sheet to
remember, and the screen changes to a screen showing the macro
definition. To get back, either you have to reopen the previous file and
page down to where you were, or maybe there's some hotkey that functions
like a browser's "back" button. Maybe unsaved changes were lost if the
first file was modified and not saved, and the macro definition was in a
different file; hopefully not.

Not at all like Emacs. You're thinking about some version of Emacs
from before when I was born. I just now went to Help -> About Emacs,
and here's the version info:

This is GNU Emacs 22.1.1 (i386-mingw-nt5.1.2600) of 2007-06-02
There's code on the screen. You right-click on a macro and see
neatly-labeled options including "view definition". Clicking that
produces a separate window containing the definition. You can drag it to
position it so that you can view the definition and the code that's
using the macro side-by-side if you want to, or expand it into a
full-size window and make changes to the macro if you want to. The
editor will keep both files open, simultaneously, in windows you can
arrange or overlap as you see fit, or in browser tabs, or similarly. It
certainly won't discard unsaved changes without prompting you first.

That's basically what programming in Emacs is like nowadays!
The former is the typical experience with a relatively "enlightened"
terminal-mode editor, restricted as it is to a single grid of ASCII text
and keyboard input; even if you can have multiple files open at once you
will generally only see one at a time and may not even see any tab
headings or other indications that there are any others open than the
one in front of you right now. Generally the limited capabilities of the
display will limit the software's ability to provide cues and to inform
you peripherally of the general status of the system. At best, it's like
using NetBeans while peering through a keyhole, then, with your mouse
busted, and at worst like trying to juggle multiple files in WordStar 1.0..

The latter is the typical experience with a well-designed modern IDE
like NetBeans.



Now I'm confused. Which windowed program were we discussing? Not the
text editor, which predates Windows 1.0 by more than a decade. SLIME? I
thought someone said it was a script in the editor's internal scripting
language.

YES, this is Emacs, the same old text editor from the GNU that has
gone through 22.1.1 versions to this current incarnation that I use
right now. I can use the mouse to select text, navigate menus, choose
options, etc -- just like Microsoft Word & co. Heck, search and
replace is child's play for this Emacs -- it can do all the same
search and replace stuff with RegExps too. Put that in NetBeans's pipe
and smoke it!

Look, all we're saying is, Emacs today isn't what Emacs was 30 (?)
years ago. It's the same as with IBM. If somebody who had been in a
coma for 30 years heard that I was using an IBM Thinkpad, he'd
probably envision some sort of "padded" mainframe, not a laptop.
This is software you expect me to take seriously? And here I'd thought
putting that damn paperclip in office productivity software was asking
for it. (And was proved right.)

OK, the shrink is a bit of a joke, it's a clone of an early AI program
that simulates a Rogerian Psychiatrist. But aside from the shrink,
Emacs nowadays is as functional a word processor as any. SLIME adds
integration to an external Lisp compiler (Emacs Lisp is a different
dialect of Lisp, and it's basically only useful for customizing
Emacs). Everybody here is completely serious when they say that Emacs
is just as powerful as NetBeans, or any other modern IDE.


- Adlai
 
S

Spiros Bousbouras

The preprocessor in gcc lets you write macros that glue symbol names
together out of pieces. I think it's not an ANSI-standard feature
though. On the other hand, gcc-only compatibility is enough to get you
pretty wide operating-system and hardware portability these days.

If you are referring to the ## operator it exists in the C99
standard.
 
J

Jussi Piitulainen

Seamus said:
Now I'm confused. Which windowed program were we discussing? Not the
text editor, which predates Windows 1.0 by more than a decade.
SLIME? I thought someone said it was a script in the editor's
internal scripting language.

Emacs Lisp is a full-scale programming language. Most of Emacs is
written in it.

Googling for Emacs and Slime, the first hit I got was this page:
<http://common-lisp.net/project/slime/>. The page is short and to the
point, and it begins with a description and feature highlights.

There is a screenshot of a window that seems to match Adlai's
description, more or less. A link to a long QuickTime movie is dead,
but a link to a shorter demo works, apparently it is in Flash:
<http://www.unixuser.org/~euske/vnc2swf/slime.html> The link to the
manual works. The link to the mailing list works, and development
seems to be active.

(I don't mean this as a flame, and I don't see how this can be
construed as such. If it happens, it happens, and so be it.)
 

Ask a Question

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.

Ask a Question

Members online

Forum statistics

Threads
474,433
Messages
2,571,683
Members
48,796
Latest member
Greg L.

Latest Threads

Top