IWETHEY v. 0.3.0 | TODO
1,095 registered users | 0 active users | 0 LpH | Statistics
Login | Create New User
IWETHEY Banner

Welcome to IWETHEY!

New Advanced programming languages - why are they not used?
The fact that Smalltalk and Lisp are not widely used baffled me (and many others) for years. I think I finally understand the reason. And it's not pretty. Not at all.

Consider Smalltalk's version of "if" statement:

blah ifTrue:[ do something here ].

Contarst it with Java:

if (blah) so something;

To even begin to understand what's going on in Smalltalk, the programmer has to grock such advanced concepts as closure and message passing.

To understand the Java's version, all he has to know is what his Mom told him when he was 15 years old: if you come home after 11 o'clock, better not come home at all.

Average programmer thinks in terms of "instructions for an executor", or, more down to Earth, "How do _I_ do this task?". Things like objects, closures, code-data equivalence(I am thinking Lisp's (cond ) here) are alien concepts to him/her.

The advanced programming languages provide better productivity for those who can master them. However (an it came as a surprize to me), most people cannot. At the very best, they will keep coding C in Lisp.

The fact that Algol-like languages remain overwhelmingly popular answers the old question about 20/80. No matter how productive top programmers are with top languages, hordes of "average" people [*] write the bulk of the software currently on the market. From the business point of view, it's easier to hire 20 average people than 1 genius. Genius is hard to find, hard to retain and hard to replace. Hard to find and retain, because they are rare. Hard to replace, because they create software at abstraction where average programmers cannot create. It's impossible to give amazingly good code of one person to a 20-people team to evolve. To maintain, yes. But not to improve.

The enormous demand for software simply surpasses the ability of best people with best tools to produce it. There aren't enough top programmers in the world to satisfy the demand. Hense the need to tap into "average" people. And when "normal", algorithm-oriented programmer enters the picture, he brings his C with him. C/Java/C++/C# drive out Smalltalk, because good programmers can still be productive in any language, but "normal" ones cannot be productive in Smalltalk and Lisp. Paradoxically, the cure for low-grade languages turns out to be less demand for software.



[*] "Average" does not have to imply "dumb" or "unskilled". Those people are very skilled in understanding algorithms and writing them down. They know all the tricks involved in procedural programming (writing down of procedures for computer to follow). But the Smalltalk example above leaves them unmoved. "if-then-else" is good enough, never mind True, False, true, false, ifTrue and blocks. It's all assembly, in the end.



P.S. Additional example: TCL vs. Python. TCL has almost lisp-like minimalist syntax: an "if" is just a command, not a syntactical construct. Python is more Algol'ish in its control structures. Guess which one is more widely used :(

P.P.S Counterexample: SQL. There is nothing more alien to a C programmer. And yet it's widely used.



--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New question from a non programmer
your two examples made equal sense to me. If I am programming something I am thinking rules based event handling. Make sure that every event is evaluated and a rule is fired for each instance. If the module does not match a rule then an error event kicks in. I have not had any formal language instruction other than digging thru other folks code and watching over shoulders plus reading a book or two so am missing large chunks of whys and whereafores.
thanx,
bill
will work for cash and other incentives [link|http://home.tampabay.rr.com/boxley/resume/Resume.html|skill set]

questions, help? [link|mailto:pappas@catholic.org|email pappas at catholic.org]

As the Poets have mournfully sung.
Death takes the innocent young,
The rolling in money,
the screamingly funny,
And those who are very well hung.
W.H. Auden
New Second through fourth sentences are a blur
Could you restate :) ? Neither example refers to rules or events or modules. There are "messages" in there somewhere, but that's all.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New sorry, I went from your specific
example about message referencing to a broad overview of how I look at the task of programming regardless of language used.
thanx,
bill
will work for cash and other incentives [link|http://home.tampabay.rr.com/boxley/resume/Resume.html|skill set]

questions, help? [link|mailto:pappas@catholic.org|email pappas at catholic.org]

As the Poets have mournfully sung.
Death takes the innocent young,
The rolling in money,
the screamingly funny,
And those who are very well hung.
W.H. Auden
New Well...
in Smalltalk (dear Smalltalkers, please correct me where I am wrong), a program execution is an exchange of messages between objects. An object has a method that gets called when a particular message arrives. The object "true" belongs to class "True", and because of that it has a method to execute on message "ifTrue:" The method consists of sending a "do"(?) message to the argument that was passed :

(notation is wrong - I don't remember the proper Smalltalk file out notation)

ifTrue: aBlock
"execute the block passed to us"
aBlock do.
^self.


"false", on the other hand, belongs to the class "False", and thus has a different method for "ifTrue:" message :

ifTrue: aBlock
"ignore the block that got passed to us"
^self.

Of course, there is more. But compare this to the C++ idiom:

if (condition) operator1; else operator1;

Which one is easier to grasp? And, this is not just a learning curve issue. Most people can understand Smalltalk's approach. But they don't find it easier to create, to think at Smalltalk's level. C++ is easier not only to learn, but to live with.

--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New I am not smart enough to detect the difference
Small talk appears to have events bound by rules called objects. C++ appears to have events based on rule detection in a linear test condition.
thanx,
bill
will work for cash and other incentives [link|http://home.tampabay.rr.com/boxley/resume/Resume.html|skill set]

questions, help? [link|mailto:pappas@catholic.org|email pappas at catholic.org]

As the Poets have mournfully sung.
Death takes the innocent young,
The rolling in money,
the screamingly funny,
And those who are very well hung.
W.H. Auden
New In C++, "if" is simple
"Do this or that depending on the value". It's a narrative.

In Smalltalk, a simple "if" requires understanding of complex concepts such as class and block.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New I think I disagree, maybe
In Smalltalk, a simple "if" requires understanding of complex concepts such as class and block.

Doing an if/else in c++ also requires understanding of block. I've seen plenty of code (not c++, but ones with similar syntax) written by people who didn't have this understanding. Maybe the truth is that c++ allows you to think you understand what you're doing, when you really don't. So maybe (because I haven't done smalltalk) smalltalk requires that you actually do understand concpets before you're able to use them.
===

Implicitly condoning stupidity since 2001.
New Re: I think I disagree, maybe
C's block and Smalltalk block are very different

C's one is a scoping construct, almost purely syntactic. People who do not understand C blocks aren't programmers at all. Not even bad ones, much less average. They should not even pretend.

Smaltalk's block is an object, a semantical thing. When you say
[do. something.]
you're not grouping 2 actions together. You're creating an instance of Closure class. And, oh by the way, it can also look like this:

[ :a :b| a + b]

or like this

[ :a :b | ^a+b]

The one above returns sum of a and be
The one below terminates the method, returning the sum as method's result.

And, ofcourse, you can say

^[something]

returning a block itself as the result of method.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New I was right
I *haven't* done enough with Smalltalk to understand your point.
===

Implicitly condoning stupidity since 2001.
New Re: I think I disagree, maybe
"C's block and Smalltalk block are very different"

Generally this is true. But in the context of your original post they act the same.

if(condition) { /* true stuff to do */ }
else { /* false stuff to do */ }

acts exactly the same as

condition ifTrue: [ true stuff to do ]
ifFalse: [ false stuff to do ]

the fact that they are lexical scopes in the former and actual objects in the latter isn't terribly important in this context.



"One of the main causes of the fall of the Roman Empire was that,
lacking zero, they had no way to indicate successful termination
of their C programs."
-- Robert Firth
New Perl 6 will take that idea farther
In Perl 6 all blocks will become closures. But with semantic sugar to make them tend to act in ways that C programmers find familiar.

Ruby already goes farther along this line than Perl 5, if not as far as Perl 6 plans to.

Incidentally my pet theory on some of this thread is that Larry Wall is onto something when he says that humans have built in wiring to decode a certain amount of syntax. (Like most people who get hold of a good idea, he can be accused of taking it too far...) The more "academic" languages tend to realize (with Lisp being an extreme) that encoding some things as syntax and others in terms of a computing model causes all sorts of artificial barriers that cost you and buy you nothing on a theoretical level, and so they tend to use less semi-naturalistic syntax. Which is completely not a problem if you are capable of building a layer of abstraction, understanding it, then building on that. But is a huge barrier for many people you find in the programming world who whether for reasons of inclination or capacity tend to draw a comprehensional barrier between "this is the language" and "this is what has been built within this language". (A barrier roughly corresponding to the division between what they follow by linguistic reflex, and what is actually thought about.)

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
Expand Edited by ben_tilly June 21, 2003, 04:47:22 PM EDT
New +5 Informative.
I've been programming in my current job for 18 months, now, and that's more than long enough for me to have seen exactly what you mean. The core problem with the way our Indian contractors programmed was their inability to abstract. At one extreme, they cut-n-pasted code instead of making it an object or even a function; at the other end they didn't want to tinker with our own API...

We almost had a similar problem with our latest recruit. I hadn't quite seen it, but my colleague noticed that he had trouble coding without fully documented interfaces. His current learning curve is appreciating how configurable a lot of our code has to be... and how many things accomodate simple changes in the configuration area. :-)

Wade.

Is it enough to love
Is it enough to breathe
Somebody rip my heart out
And leave me here to bleed
 
Is it enough to die
Somebody save my life
I'd rather be Anything but Ordinary
Please

-- "Anything but Ordinary" by Avril Lavigne.

New I regard Smalltalk as a teaching language
Four years ago, I learnt Smalltalk as part of a degree course without problems. Including the concept that code blocks can be passed as data as opposed to the Java technique of writing a class that implements an interface. It's definitely, a clean language.

But I don't like it because of no compile-time type checking and no message access modifiers (private and protected). I'm aware that parameters that don't implemement the correct messages can be trapped using Design By Contract but I regard Design By Contract as impractical. Also, practical, working code needs messages that are not public. And classes that aren't public. For abstract classes based on the Template design pattern, hooks into the skeletal algorithmn should be exposed to the subclasses but not others. The famous 'Gang of Four' book suggests the use of protected.

So, I regard Java as the advanced language and Smalltalk as a teaching language. I only want specific classes of a package to be public and act as the facade. I want mistakes such as passing a string parameter instead of an integer to be trapped at compile-time, not at system testing. I want to share code that is common to similar messages in a message but not expose it to the public. So I use Delphi or Java.
Matthew Greet


But we must kill them. We must incinerate them. Pig after pig, cow after cow, village after village, army after army. And they call me an assassin. What do you call it when the assassins accuse the assassin? They lie. They lie and we must be merciful to those who lie.
- Colonol Kurtz, Apocalypse Now.
New Dixit.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New I regard it as the most powerful production tool I have
I don't like it because of no compile-time type checking


this has been shown to be a red herring - compile time type checking rarely catches anything and test driven developmen is every bit as effective at catching these trivial to find and fix errors.

and no message access modifiers (private and protected).


But we have other conventions for indicating that methods are private and they work just as well. They include method categories with names like "private-event processing", method names that start with the word private - ie privateMouseDown:, or in the case of ObjectiveC, the convention is to start the method name with an underscore or simply to not declare it in the main class interface but rather to add the method as a private category.

I grant that there is no compiler enforcement of the programmer's intent, but I view this as a plus. Particularly because, in my experience, most programmers are really bad at deciding what should be private vs public and I often have to break their conventions to get the code to do what I need.

Bottom line, Smalltalk and ObjectiveC have a philosophy of "trust the programmer" and C++/Java have more of a "do unto others first" sort of mentality. I prefer the former.



"Extreme programming is basically ... a bunch of practices that are really all about Smalltalk. Very incremental development. Very simple design. Testing, and so on." -- Ron Jeffries

New couple of comments
I only want specific classes of a package to be public and act as the facade.
Why do you care if others have visibility to the interface to these methods? I've never had much of a problem discerning what methods constitute the correct interface for a class. Just because some methods are declared public does not guarantee that they will be called in the correct circumstances (and many times may require a correct sequence).

On the one hand, you can solve this fairly trivially in Smalltalk by (a) naming the private methods in such a manner that it's obvious that they are not part of the intended public interface; and (b) creating groups of methods (messages) such that one group is called private - the facility for grouping methods into groups doesn't seem to be part of the Java culture.

On the other hand, you can make the argument that simply having 4 levels of visibility is insufficient for a project of any complexity. What may be required to be public at one layer of the software, may really be totally irrelevent to the a higher level of abstraction. Ok, so Java recognizes this be having a package level visibility, but that just ups the level to one additional layer. What about interaction and layering at the package level. At some point, it becomes obvious that the decision to expose an interface at some level of publicity becomes a design decision pitting openness and flexibility of the classes against weighing down the system with arbitrary levels of closed class interfaces.

Eiffel tries to solve this problem by allowing the granting of rights to methods to be controlled on the micro level down to which classes may access which methods. Modula-3 had a more sensible approach by allowing you to define different instances of interfaces to a class, thus allowing you to publish a spec for varying levels of abstractness to the class.

I want mistakes such as passing a string parameter instead of an integer to be trapped at compile-time, not at system testing.
And what if you are passing parameters to-and-fro in a much more loosely coupled framework - let's say something like DHTML, where the requests are filtered through web pages? When you're passing objects in and out of collections, that static type checking seemingly causes about as many errors as it solves - and collections (along with message passing) is what Object Oriented Programming should be about.

I'm in the midst of a little C# ditty and I can say that it drives me crazy to have casting in practically 10% of the assignments - and C# with it's boxing/unboxing requires less casts than Java. What does that mean. It means that the code is not flexible in that the types get hard-coded a bunch of lines of code (change the types involved and you got a whole lot of touching to do). It also means that the comiple time type checking is useless as you are passing the check on to run time (hey compiler forget that I'm assigning an Object to a String - tell me a runtime if that's what actually happens).
New Re: couple of comments
Why do you care if others have visibility to the interface to these [non-public]methods [and classes]?

At the risk of another flame war: coding philosophy. Maintenance programmers have to identify the responsible classes in a short time, so javadoc generated documentation should describe the public functions that are designed around what it should do, rather than others that deal with 'how'. As you state, naming conventions can make this distinction clear, but it's my experience that an overloaded brain can't so readily ignore even easily filterable information.

Also, when I design a class, I decide at design stage what behaviours are exposed to the outside world, subclasses or other classes of the package. I'm a strong believer in encapsulation: if a behaviour was not designed and tested as public, exposing it without a rethink and retest of the class is too dangerous. If a programmer thinks a private function could be used as public and the compiler denies this, the hurdle of changing the class source code will encourage a proper examination.
Just because some methods are declared public does not guarantee that they will be called in the correct circumstances (and many times may require a correct sequence).

What's your point? Having all message public doesn't help either.


I want mistakes such as passing a string parameter instead of an integer to be trapped at compile-time, not at system testing.

And what if you are passing parameters to-and-fro in a much more loosely coupled framework

The other flame war: I believe in well defined interfaces and strong typing is part of this. I'm a defensive coder and I want anything that can go wrong caught and shot as soon as possible. To me, a change of type is the result, as well as cause, of a change of design.

As for collections, I don't see your argument. If client code in Java is expecting a member of a collection to be an incorrect type, it will miscast it and an exception will be thrown. In Smalltalk, the client code will pass the member messages it doesn't understand and an exception will be thrown. Smalltalk just makes the code cleaner and more readable. This is good but not enough to convince to ditch Java-style typechecking.
Matthew Greet


But we must kill them. We must incinerate them. Pig after pig, cow after cow, village after village, army after army. And they call me an assassin. What do you call it when the assassins accuse the assassin? They lie. They lie and we must be merciful to those who lie.
- Colonol Kurtz, Apocalypse Now.
New Documentation tool?
At the risk of another flame war: coding philosophy. Maintenance programmers have to identify the responsible classes in a short time, so javadoc generated documentation should describe the public functions that are designed around what it should do, rather than others that deal with 'how'.
You make a couple of assumptions about maintenance programmers. First, you're assuming that the original designer is more capable of making decisions about what is applicable in the mature phase of a project. Problem with this assumption is that it disregards the very existence of the need for maintenance programming. What is that need? It's one of two things: either the original design needs to be extended or it's that the original design is errant. In either case, the maintenance programmer is trying to get around the original design limitations. It's interesting that the original designer created the problem and is now trying to handcuff others because of the belief that his design decisions should be respected (and enforced).

As you state, naming conventions can make this distinction clear, but it's my experience that an overloaded brain can't so readily ignore even easily filterable information
Are you saying that the tools for documenting Java source code are superior to those for documenting Smalltalk? I might remind that some of the best development and documentation tools for Java were originally designed for the Smalltalk environment (a not uncommon complaint is that the Java versions are pale imitations - e.g. Visual Age for Smalltalk is better than Visual Age for Java).

Anyhow, the wieght of your argument seems to be that people are (a) incapable of documenting the interface of a class without a syntax enforced public/private statement; and (b) incapable of reading a comment that a method is designed to be private. As I said, Smalltalk uses groups (actually the proper term is catagories) to document the nature of the interface. This is actually more substantial than the public/private identifier as it identifies the nature of the methods in a much more concise grouping. You may help the maintenance programmers by allowing them to disregard the private methods (something which is done in Smalltalk by putting all these methods in a Private group - and no it's not just a method naming convention). But once they get into the methods, you've provided them no additional help in identifying what the purpose of the methods are (unless they read the fine print - something you think they would ignore if you put in comments about being private).

If a programmer thinks a private function could be used as public and the compiler denies this, the hurdle of changing the class source code will encourage a proper examination.
If a programmer starts calling methods without realizing what the purpose and intent of those methods are, i'd say you got much bigger problems than can be solved by merely hiding a few methods.

Let's say we have the reverse scenario. Let's say you screwed up on the software design. Let's say six months later someone stumbles across a bug in the design. Interesting that you seem to believe that the programmer that has to fix the code should have less capacity than you had in the original design.

As for collections, I don't see your argument. If client code in Java is expecting a member of a collection to be an incorrect type, it will miscast it and an exception will be thrown.
The argument is simple. The act of having to typecast means that you are disabling compile time checking. So any time you deal with external interfaces - be it the interface via the web server in the case cited - or an interface to an external datasource such as a RDBMS - you end up having to typecast a significant amount of assigments/statements.
New Your brain is damaged
from the order in which you've encountered programming languages. :-)

if(condition) block

is no more intuitive to a complete novice than

condition ifTrue: block

The fact that the Smalltalk block closure is actually an object vs the C block simply being a lexical scope is not at all visible to the novice and need never come up.

I continue to be amazed at developers who insist that

map.put(key,object);

is somehow clearer than

dictionary at: key put: object.

They say that the Smalltalk message syntax is "weird" but its really only unfamiliar. After working with it for awhile I began to find it more natural. For one thing, you can read it out loud and understand it. The arguments are clearly labeled.

Compare the following calls:

(NSWindow alloc) initWithContentRect:aRect styleMask: NSTitledWindowMask backing:NSBackingStoreBuffered defer:YES screen:(NSScreen defaultScreen).

vs the java-ized

new NSWindow(rect,NSTitledWindowMask,NSBackingStoreBuffered,YES,NSScreen.getDefaultScreen())

So I don't think I agree with your thesis. In fact, I don't agree with people who say that so-called advanced languages like Smalltalk are somehow "too dangerous" for average programmers.

Go take a couple groups of RPG programmers - teach one Visualworks and the other Java/swing and see who is more productive. Its typically the VW guys every time.




"Smalltalk, with its emphasis on the human side of programming, was a nurturing environment in which to grow Extreme Programming. Smalltalk is still technically superior for reducing the cost of change over the life of a project, a key component in enabling XP." -- Kent Beck
New I am not saying
that Smalltalk syntax is weird. It's just another syntax.

What I am saying is that Smalltalk's (and Lisp's, and TCL's) syntax is minimalistic. Most of those languages' functionality has nothing to do with syntax.

But this is not even my main thesis. My main thesis is that Java and C++ are narratives ("If he goes left, he loses his steed. If he goes right, he loses his head"), and Smalltalk and Lisp are acts of creation. Even the simplest constructs in Smalltalk have depth unheard of in the C world. It is more powerfule and expressive, but it cannot be used by 90% of the people. Average programmers are good at writing down stories. They are no good at creating worlds.

We've just had a testimony from an average guy. Can you argue with that? You have to be disabused of the notion that all people can think like you do, it's only a matter of education or initiative. No amount of education would allow Warmachine or Tablizer to enjoy Smalltalk. Use it - yes. Enjoy it - no.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New Average guy? Come here and say that! :)
Average programmer? That's fighting talk! I'll have you know I sat 'O' level Mathematics 2 years early and got grade A. Alright, that was a long, long time ago but I'm still a fan of mathematics and popular science. Alas, I'm an engineer by profession, not an academic, so I stick to straightforward, narrative code, rather than elegant and flexible class designs. If the complete behaviour of a function can be contained within half a screen using a switch statement and a few private, member variables, rather than the scattered among the classes implementing the more elegant State design pattern(1), then its better for maintenance programmers.

Now, you might say the State design pattern is a more maintainable solution than switch statements and I'd agree with you. Except most people won't understand it. I'm studying a new computing module aimed at 3rd year undergrad level and it designs Finite State Automata using switch statements (in C++), not the State design pattern. This is from the same university that teaches Smalltalk (at 2nd year undergrad level). I kid you not! If the academics don't grok the expressiveness and elegance of Smalltalk, there is no point expecting others to do the same. Hence, I stick to the more clunky and restrictive Java.

Oh, and it also scared me to be mentioned in the same breath as Tablizer. :)


(1) Design Patterns: Elements of Reusable Object-Oriented Software, pp305-313, Erich Gamma et al, published by Addison Wesley, 1995.
Matthew Greet


But we must kill them. We must incinerate them. Pig after pig, cow after cow, village after village, army after army. And they call me an assassin. What do you call it when the assassins accuse the assassin? They lie. They lie and we must be merciful to those who lie.
- Colonol Kurtz, Apocalypse Now.
New Either you are, or...
>>>>>>>>>>>>>>>>
Now, you might say the State design pattern is a more maintainable solution than switch statements and I'd agree with you. Except most people won't understand it.
<<<<<<<<<<<<<<<<

..you work with them. You're giving me the best possible arguments, thank you.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New Yep! But give it more time.
It's simply inertia, people are too used to C syntax and are still getting used to the idea of 'tell, don't ask'. I've seen developers learn and adopt the design patterns of Factory, Proxy, Singleton and Template. Adoption of Strategy still seems slow. Double dispatching (Visitor) and block closures are still a long way off.
Matthew Greet


But we must kill them. We must incinerate them. Pig after pig, cow after cow, village after village, army after army. And they call me an assassin. What do you call it when the assassins accuse the assassin? They lie. They lie and we must be merciful to those who lie.
- Colonol Kurtz, Apocalypse Now.
New What's this got to do with the price of oil in Baghdad?
I'm an engineer too. And I also sometimes act as an academic (teach CS at undergrad level). The university system has been remade into a set of fancy vocational schools though so lets not try to tell anything by what goes on there. I mean, christ, I just had to explain to Professor Cay Horstman that his most recent [link|http://www.artima.com/weblogs/viewpost.jsp?thread=4744|article] was [link|http://www.artima.com/forums/flat.jsp?forum=106&thread=4744&start=15&msRange=15|horsepucky].

As to the rest of your post - you're talking about eschewing a state pattern design and preferring switch statements. Fine. This is a 100% language independent decision. What's it got to do with Smalltalk vs Java? Smalltalk has a switch statement (most do - you can write one in a minute of yours doesn't).

As for most of the patterns, I've found that a lot of them simply vanish in Smalltalk. It seems that many of them are workarounds for poor language design decisions in Java and C++.




"One of the main causes of the fall of the Roman Empire was that,
lacking zero, they had no way to indicate successful termination
of their C programs."
-- Robert Firth
New Oops! You're right.
I must have purged switch in Smalltalk from my memory when teaching myself to write in a less procedural fashion. Smalltalk is looking more attractive as a commercial language. Still want strong typechecking, though.
Matthew Greet


But we must kill them. We must incinerate them. Pig after pig, cow after cow, village after village, army after army. And they call me an assassin. What do you call it when the assassins accuse the assassin? They lie. They lie and we must be merciful to those who lie.
- Colonol Kurtz, Apocalypse Now.
New You've missed something I think
Still want strong typechecking, though.


We've already [link|http://z.iwethey.org/forums/render/content/show?contentid=101330|discussed] this and I think concluded that the benefits of strong type checking are grossly overrated. It seems some of its proponents like Robert C Martin are also coming to this conclusion.




"One of the main causes of the fall of the Roman Empire was that,
lacking zero, they had no way to indicate successful termination
of their C programs."
-- Robert Firth
New Re: Oops! You're right.
Still want strong typechecking, though.
I agree, although I'm perfectly happy with dynamic strong types. It doesn't have to be static.
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New OK that's true
it was some guy on the Artemis weblogs that asserted that Java syntax is more "natural" than Smalltalk.

But the narrative thing I think I still disagree with. Smalltalk can be read out loud and understood. You can't say the same thing about java.

dictionary at: x put: y.

is a narrative.

map.put(x,y) is much more cryptic about what is going on.

The really funny thing about Smalltalk is that it was designed to be used by children. For the most part, they get it. Its a little above some children - but not so far. Check out some of the kid projects at [link|http://www.squeakland.org|http://www.squeakland.org] to see kids programming robots using Smalltalk.

So my point is going to remain that its the biases instilled in the programmer by the more "conventional" languages that make Smalltalk "hard". You don't need to use all the depth. You can go as deep as you like and still get things done.




"One of the main causes of the fall of the Roman Empire was that,
lacking zero, they had no way to indicate successful termination
of their C programs."
-- Robert Firth
New Smalltalk for Small Tykes
The really funny thing about Smalltalk is that it was designed to be used by children.

I was teaching my 10 year old daughter Smalltalk at one point. I would have never considered using C or C++ instead.
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New Wrong sense of "narrative".
May be I am misusing the word.

In your example, Smalltalk and C++ are actually rather equivalent. In my examples, they are vastly different. Simple syntax in C causes simple conceptual things to happen. Everybody knows what "if-then-else" means. In Samlltalk, simple syntax causes conceptually complex[*] things to happen, even if the result is the same as for simple things. For example, my insufficient knowlege of Smalltalk fails me when I think of if-then-else statement: is it

blah ifTrue:[thenpart] ifFalse:[elsepart].

or is it

blah ifTrue:[thenpart]; ifFalse:[elsepart].

(I suspect it's the second one)

It depends on what returned from ifXXX: : result of block or self. I know where to look for the answer. Somebody who just expects C++ syntax does not. He/she will grumble about dumb computers.

Another example: how do you do chained ifs? You should not have to, but what if you do? I can see that Smalltalk has to have a better primitive for that than nested blocks. I'd go looking in True and False classes, or in collections. If it's not there, I'll write it. The other kind of programmer will simply write it off oas computer's stupidity and use the inconvenient nested blocks.

[*] "complex" in certain sence. I am comfortable with Smalltalk complexity, but I am lost with computational mathematics, which is also called complex. And I've seen really smart people who have it the other way around. "Average programmer" can be extremely smart person, and still not grock Smalltalk/Lisp way.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New (Oops)
Serves me right for posting before checking.
Of course, Smalltalk has ifTrueifFalse method. I think my ideas still stand, though :).
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New modeling English
"if(condition) block" is no more intuitive to a complete novice than "condition ifTrue: block"

One could argue that if they are native English speakers, the first is more intuitive. It fits english ordering better. "If the amount he gives you is less than the bank statement amount, then divorce the hording bastard."

I continue to be amazed at developers who insist that "map.put(key,object)"
is somehow clearer than "dictionary at: key put: object."


IMO, it depends on how often it is used. Named parameters (which the second resembles) are clearer when you encounter something for the first time in code. However, if it is repeated multiple times, than positional parameters are quicker on the eye.
________________
oop.ismad.com
New Re: Advanced programming languages - why are they not used?
I remember a programmer who would build up nested IF clauses of stupefying complexity - making the code as unreadable as if it were sprinkled with direct branches. To check his work, he would print out the 10 or so pages his top-level IF clause needed and tape it to the wall, or stretch it out on the floor, so that he could match up all the IFs and ENDIFs.

He never used any of the other available control structures.

(BTW I think I agree with you. FORTH has IF .. ELSE .. THEN. Try getting the above mentioned guy to dig on that :)
-drl
New I was going to mention Forth,
but I am not familiar enough with it to talk about it. I can't judge if the expressiveness of Forth is closer to assembly's complexity or to Smalltalk's elegance.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New Bad Marketing
I have yet to see a good case of where closures reduced the code complexity by more than roughly 5 percent. Every example I have seen had a simpler non-closure alternative that was better than the non-closure example that the closure pusher used to compare. In other words, they present a lame non-closure version to compare to.

Jay and I had a big flamewar over this, and another one on comp.object failed to produce anything beyond the 5 percent mark also.

Maybe 5 percent is worth it to some, but it does add to the learning curve of the language, reducing its acceptence. If you want people to believe that something is better, then show them *good* examples. Rigged examples will kill your credibility.
________________
oop.ismad.com
New Re-implement these examples, please
To make the comparisons fair, please implement in Perl. Perl supports closures, but not very concisely. If I could pick a language with arbitrary features that I want, they would shorten correspondingly.

[link|http://www.perlmonks.org/index.pl?node_id=50132|http://www.perlmonks....pl?node_id=50132]
[link|http://www.perlmonks.org/index.pl?node_id=54957|http://www.perlmonks....pl?node_id=54957]
[link|http://www.perlmonks.org/index.pl?node_id=34786|http://www.perlmonks....pl?node_id=34786]

And to give some idea why I said only Perl, consider the following Ruby version of the first one:

def each (arg,*more_args)
( [] != more_args ) ?
\targ.each {|l| each(*more_args) {|r| yield [l]+ r }} :
\targ.each { |r| yield [r] }\nend

each( 1..2, 'a'..'c', 'A'..'D') \\
{ |args| puts args.join " " }

Same thing as the Perl example, but Ruby's features let a lot of the calling mechanics become implicit...

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Problem description missing
The problem description for the first one is missing. It references a Yahoo folder, but it says that its empty when I click on it. (Oddly, it says it has 11 items before I click on it.) I tried it 3 times.
________________
oop.ismad.com
New Problem description
You have an array of arrays. You want to do something (in this case the something is just print them out) with every combination of elements, one from each array. Final requirement, you don't want to use an absurd amount of memory if you have a lot of reasonably large arrays. (eg Creating a list of all combinations and then looping over that list is not allowed because if you have 10 arrays of 10 elements that would create a list of 10 billion items in RAM.)

If this description is unclear, then run the Perl code. Change the arrays that you pass into it, and see how it works.

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Arrays of arrays? There's your problem.Use relational tables
________________
oop.ismad.com
New Why am I not surprised that you avoided the question?
You only commented on one of three examples, and that one only until you could say that whoever did it should be doing something totally different.

And in the future, undoubtably you will continue to say that there are no examples where closures can be of assistance.

Once again, you demonstrate that you deserve your reputation.

Regards,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New hold on, cowboy
You only commented on one of three examples

One at a time. I find discussions get messy if too many examples are discussed at a time. I never said I was "done".

and that one only until you could say that whoever did it should be doing something totally different.

I generally avoid nested arrays, and thus have little interest in managing them via code. True, sometimes I get stuck with the task of maintaining such code, but it is fortunately not that often. RDBMS-centric places are more likely to hire me than code-based-collection-oriented places, for obvious reasons. Further, your "requirements" are tied to a specific internal representation instead of what the customer wants.

The second example does not hit me as very practical either, at least not for custom biz apps, my domain. Maybe for games or systems software your techniques are a significant improvement, but don't extrapolate that to everything.

I am still studying the 3rd example.

BTW, I anti-dug your OOP comments:

"...is usually called Object-Oriented Programming. It offers a layer of abstraction between what you want done and how it is done. This hides details and makes the end code easier to maintain. In the long run it also has benefits in terms of code-reuse."


Gag me

The reuse claim is falling out of favor. It is an 80's claim more or less. You are not a "hip" OO'er it seems. The big current thing in OO is patterns and "improving cross-developer communication via patterns".
________________
oop.ismad.com
Expand Edited by tablizer June 22, 2003, 11:55:27 PM EDT
Expand Edited by tablizer June 22, 2003, 11:56:46 PM EDT
New No, you never do say that you are done
Which is why these threads go on forever. Without the addition of useful content.

Your claim was that closures never saved more than about 5%. I gave you 3 examples in 3 different problem spaces where I think that they saved more than that. I wish to see either code from you illustrating, in Perl, the fact that I am wrong, or the admission from you that your claim seems to have been too sweeping. I am not getting this. I am instead getting complaints about the problems being (in your opinion) bad techniques, or problems not in your problem space, or mixed in with comments about OO which you also disagree with. So far, despite your having more time than I originally used to write all 3 examples, you have yet to show any attempt towards coding any of the examples.

Enough already. I refuse to respond to anything more which is not concrete progress. Please don't bother responding unless your response has an attempt to code up an alternate solution, admission that you are wrong, or a request for problem clarification. Code that is too long is OK, we can work to see whether or not it is shortenable. Anything else I will call non-progress and ignore.

Regards,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Okay, I admit it was too sweeping
or the admission from you that your claim seems to have been too sweeping.

Okay, I will admit that my claim as worded was too sweeping. I have not found significant improvements for TYPICAL applications in my domain. I forgot to put on my lawyer hat when I wrote that again. Perhaps I should put it in my sig.

I want to see how it simplifies my life, not Ben Tilly's.

BTW, when I parse stuff, I generally try to parse it into an intermediate structure of some sort first, and then process it. For example, I might parse HTML into a tree structure. When that is done, I then traverse the tree to do any subsequent processing. You seem to be over-coupling the processing and parsing (although my Perl is too rusty to fully figure out what you are trying to achieve). Perhaps combining them is more efficient, but I think it is better structure and division of labor to separate parsing from processing if possible.
________________
oop.ismad.com
Expand Edited by tablizer June 23, 2003, 04:38:16 PM EDT
New Re: Okay, I admit it was too sweeping
Bryce, read the paper that Todd linked on early ST history.

+100 informative.
-drl
New Thank you
Okay, I will admit that my claim as worded was too sweeping. I have not found significant improvements for TYPICAL applications in my domain.

This statement looks accurate. The clarification also has all of the hallmarks of a self-fulfilling prophecy. Given that you are not looking for ways to apply closures, you are highly unlikely to find them. Certainly in the business problems I have dealt with, closures were helpful.

As for parsing, the code presented in the third example is not attempting to parse anything. It is attempting a complex text filtering/transforming process token by context-sensitive token. What is being read is not exactly HTML. Certain tags are not recognized. Certain non-HTML markups are recognized. Semantic content is not captured. Furthermore, insults notwithstanding, the processing logic has been separated from the information about what is and is not allowed through.

If I was parsing, you are right that a very good parsing technique is to break something into a tree, and then traverse it. That approach is taken by a variety of modules for dealing with things like HTML and XML. However now you have to organize the logic about what actions specific nodes are associated with. Surprise, one of the popular ways to do that is to arrange for callbacks, which can be arbitrary closures!

And no, I don't expect you to use this approach. But lots of people out there do. And they think that they benefit. I think that they are often right...

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New that is what I am looking for
Certainly in the business problems I have dealt with, closures were helpful.

Well, lets see some of *those* examples instead of chess boards. (And please don't rely on your code to document requirements.)

Note that I am not saying that closures have zero value, I am only saying that they do not offer enough benefits in many domains to counter their "confusion power" drawback. If you don't want a language to go mainstream, one of the best ways to ensure they don't is to include closure support.
________________
oop.ismad.com
New Re: that is what I am looking for
If you don't want a language to go mainstream, one of the best ways to ensure they don't is to include closure support.
Exactly! Like Perl! That's a mainstream language that doesn't have... oh, wait... Python? Nope... erm. C++! Oh, wait, generics can do that... C, then? Function pointers. Oh dear. Java? Strategy pattern can be used to emulate it.

Let's look at it this way: what mainstream languages don't have closures? FoxPro... yeaaaahhhh.... um... SQL. But that's a specialty data access language. Assembler? COBOL?

What was the point again...?
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New What's that?
C, then? Function pointers. Oh dear. Java? Strategy pattern can be used to emulate it.

I don't know what a strategy pattern is - what does this mean? What's a "strategy pattern"? I would prefer not to guess.

In C function pointers provided a form of overloading - I'm sure cfront must have exploited this in the early days.

Even FORTRAN had this, in the form of multiple entry points.
-drl
New Re: What's that?
[link|http://c2.com/cgi/wiki?StrategyPattern|http://c2.com/cgi/wiki?StrategyPattern]
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Actually Java Anonymous Inner Classes
are closures - but the syntax for declaring one is so cumbersome that nobody bothers to use them that way.

Bistro makes use of them that way - but Bistro is more of a thought experiment than a usable language (the preprocessor doesn't give decent diagnostics and debugging is impossible).

[link|http://bistro.sourceforge.net/|http://bistro.sourceforge.net/]



"One of the main causes of the fall of the Roman Empire was that,
lacking zero, they had no way to indicate successful termination
of their C programs."
-- Robert Firth
New If I remember correctly,
anonymous inner classes cannot use local variables from the scope around them. In fact, apart from their "inner" quality they don't have any connection to the context where they were created.

That, and not their awkward syntax is the reason they aren't used.

--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New Not entirely accurate.
Local variables and method parameters can be used if they are declared "final".

The compiler actually passes the local vars to the constructor/initializer (anonymous local classes do not have constructors) of the anonymous class. Instance members are accessed through hidden private accessor methods.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Thanks
Now I remember the anguish of copying the value to another variable just to get it through to the anonymous. What a joke.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New ICLRPD (new thread)
Created as new thread #107156 titled [link|/forums/render/content/show?contentid=107156|ICLRPD]


   [link|mailto:MyUserId@MyISP.CountryCode|Christian R. Conrad]
(I live in Finland, and my e-mail in-box is at the Saunalahti company.)
Your lies are of Microsoftian Scale and boring to boot. Your 'depression' may be the closest you ever come to recognizing truth: you have no 'inferiority complex', you are inferior - and something inside you recognizes this. - [link|http://z.iwethey.org/forums/render/content/show?contentid=71575|Ashton Brown]
New How much are you willing to pay?
The code in question is not owned by me. It is owned by my former employer. My contract is such that I cannot even discuss it in any detail.

Therefore if you want details, you will have to pay them. I am willing to put you into contact, but the rates are up to them. However given that access to the output of said programs costs thousands of dollars per month per person, the source is going to come steep...

As to your confusion issue, I will note the suggestion as having been made, and remember the source.

Cheers,
Ben

"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New If you don't have the evidence, then just say so
________________
oop.ismad.com
New You win, again
By continuing to refine your claim, and rejecting evidence which doesn't directly fit your ever-narrower statement (particuarly when you set rules that make you the only arbitrator of what evidence is worth thinking about) you can succeed in not being convinced by anyone.

Now that the problem has been refined, and I am asked to produce what is not mine to produce, no I can't produce direct evidence.

Satisfied?

Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Can't ANYBODY ever find a #@!* BIZ example?
________________
oop.ismad.com
Expand Edited by tablizer June 24, 2003, 11:53:17 PM EDT
New Ben's given me an idea.
First, Ben noted that callback functions are a type of closure.

Right. The app I am developing in my work is an intranet application that you access from a web browser. The current version is written as PHP pages which are backed by a database. You can think of the whole thing as a database application if you like, which it basically is, really. Some of the information needs to be displayed on-screen in a tree-like structure - much like the directory listing in Windows' File Explorer. Without getting into an argument about OO, we designed a Node object for representing a node. Each Node knows it's parent node, and has a list of it's children nodes. It also has a piece of arbitrary data which represents what is actually "at" that node. Thus a Tree is a Node with children Nodes, any of which can have children, etc etc. A simple recursive function is sufficient to print it using pre-order traversal, which display things as we want. But how to get something printable out of the opaque data?

In a pure OO world, the data could simply be defined as an object which responds to a suitable method. Well, while PHP's object infrastructure would support this, the rest of our app isn't pure written OO-style. Besides, these Trees are going to be created, displayed and then discarded in the same page. So we decided on a callback function: the display function takes as one of its parameters the function name which it calls for every node. The callback function is given the opaque data of the node in question as well as some optional extra information (to eliminate global variables) - all it has to do is output what is to be displayed.

Simple, clear and elegant.

FWIW, PHP also supports creating functions on-the-fly for this kind of thing, although it's a bit clunky and only works because the whole language parser is available at runtime...

Wade.

Is it enough to love
Is it enough to breathe
Somebody rip my heart out
And leave me here to bleed
 
Is it enough to die
Somebody save my life
I'd rather be Anything but Ordinary
Please

-- "Anything but Ordinary" by Avril Lavigne.

New different "core"?
In a pure OO world, the data could simply be defined as an object which responds to a suitable method. Well, while PHP's object infrastructure would support this, the rest of our app isn't pure written OO-style. Besides, these Trees are going to be created, displayed and then discarded in the same page. So we decided on a callback function: the display function takes as one of its parameters the function name which it calls for every node. The callback function is given the opaque data of the node in question as well as some optional extra information (to eliminate global variables) - all it has to do is output what is to be displayed.

I am still unclear as to why you need a closure. I suspect it is that you have complex tree traversal code, and you don't want to repeat it for each different use of the tree. Therefore, you pass the "core code" in the form of a function pointer to this complex looping or recursion thingy.

The simplistic solution is perhaps a Case structure in the middle of the loop or recursion. If you only have say 3 different processing options and they don't add new ones very often, this may work.

The "ideal" TOP solution would be to use a RDBMS that can traverse trees without coding recursion. (Oracle has this I beleive, but I cannot vouch for its friendliness.) If all usages use the same query, then simply have a global string or function to share (reuse) the same query. It is then no different from any other query-and-iterate-result-set pattern. Unfortunately, Dr. Codd excluded tree operations from his original relational operators.
________________
oop.ismad.com
Expand Edited by tablizer June 25, 2003, 09:09:55 PM EDT
New That's one way to think of it.
The point of passing the function is that code to display the tree is entirely unaware of what the data is in the nodes. It simply doesn't care because it doesn't have to care - all it needs to be concerned about is that there is a function to call. Putting that logic in the walk-the-tree code does not make sense because that location is how the tree works, not where I use the tree. (Incidentally, the recursion is peripheral to the example: it's prime purpose is to permit the tree to be an arbitrary depth.)

A closure is like passing a pointer to a function, except that the function is anonymous (i.e. has no name) and is defined right where you would specify a pointer-to-a-function if the language doesn't have closures. They're sometimes called lambda functions.

Wade.

Is it enough to love
Is it enough to breathe
Somebody rip my heart out
And leave me here to bleed
 
Is it enough to die
Somebody save my life
I'd rather be Anything but Ordinary
Please

-- "Anything but Ordinary" by Avril Lavigne.

New But if tree traversal was trivial, then it does not matter
If the relational system supports tree operations, then it is as simple as:

----Usage 1:

rs = getTreeTraversal()
while (getNext()) {
. . doSomething_1
}

----Usage 2:

rs = getTreeTraversal()
while (getNext()) {
. . doSomething_2
}

----Usage 3:

rs = getTreeTraversal()
while (getNext()) {
. . doSomething_3
}

The problem you are having is that the bread is more complex than the meat of the sandwich. Simplify the bread (tree traversal), and using tricky closure meat is no longer so important.

In practice, we probably want different filtering, cross referencing, etc. for each usage. That is where custom relational queries would shine. One-size-fits-all traversal is not that likely if there are many usages.
________________
oop.ismad.com
New It's a matter of perspective.
Using your coding style, my solution looks like:

rs = getTreeTraversal()
displayTree(rs, displayFunction)

function displayFunction(item) {
. . doSomething_1
}

Which one is easier to implement depends on the details of walking the tree*. The more state that must be kept between touching each node, the easier it is to implement it my way, although that is not the only consideration. (BTW, tree traversal need only look trivial for the code using the tree.)

Actually, implementing this with a closure makes it look like your example, but it works more like mine: you get the advantage of a loop-like construct in both places.

Wade.

* although I've let it slide 'till now, whether or not the tree is database-backed or just in-memory is not important in my example.

Is it enough to love
Is it enough to breathe
Somebody rip my heart out
And leave me here to bleed
 
Is it enough to die
Somebody save my life
I'd rather be Anything but Ordinary
Please

-- "Anything but Ordinary" by Avril Lavigne.

New A TOP example
Pardon my Ruby; it's rusty...

\n# do some work in a database transaction\ndef inTransactionDo(db)\n  db.startTrans()\n  yield\n  db.commit()\nrescue\n  db.rollback()\nend\n\ninTransactionDo(db) {\n  #use db to update the database\n}


Regards,
John

New re: transaction rollback
Why not:

sql = "select * from...."
rc = myTransaction(sql)

where "rc" is the "return code". We could also add a named parameter for specific handling:

myTransaction(sql, failure="messageAndDie")

The default could be to simply return the status in the return code.

I suppose we could even pass the name of the routine to execute if there is a problem, sort of like "onClick='foo(this)'" in JavaScript. It could be passed a dictionary structure with some info about the error. In some ways this is closure-like, but without explicit closer syntax. All we need is an Eval() or Execute() kind of operation in the language.
________________
oop.ismad.com
New Why not just use a closure?
Why not:

sql = "select * from...."
rc = myTransaction(sql)


Because a "select" doesn't need a commit or rollback? I assume you would handle the need to execute multiple SQL with the following:

I suppose we could even pass the name of the routine to execute if there is a problem, sort of like "onClick='foo(this)'" in JavaScript. It could be passed a dictionary structure with some info about the error. In some ways this is closure-like, but without explicit closer syntax. All we need is an Eval() or Execute() kind of operation in the language.

Why create a hack workaround for closures when you could just use a closure?

BTW, I've never used a language that supported Eval() in a work environment, so none of your ideas would ever be usable for me.

Regards,
John
New Eval () is a kind of closure
minus local variables, minus enclosing scope variables, minus compilation, minus parameter passing...

But it's easy to understand. So Tablizer understands it.

Perl, TCL, Shell support it. I am not sure about Python, but seems like it should support it too.

--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New Python supports it...
Most interpreted languages do.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New topic is not about me, Mr. Insult

But it's easy to understand. So Tablizer understands it.

It is not about me. I can care less whether a language supports ultra-closures or not. The issue here is why some languages are popular and some are not. Closures add more to the learning curve for "average" programmers than what the benefits they offer make up for [sentence needs rewrite]. If you need knives often, then a swiss-army-knife may be worth it. But if you don't, then a two-blade pocket knife (Eval) is probably sufficient. Eval() may not be as clean as full closures, but it offers almost the same power for *occasional* use.

I have not seen any slam-dunk realistic coded justification of full closures that one can wave in front of programmers and say, "See, it greatly simplifies the code. Thus, the learning curve is worth it".

Your sales presenation is lousy. Perhaps you are a programming genious, but a shitty marketer of languages and paradigms. Don't red herring your failure onto me. The marketing flunkage is yours, not mine. It is not my fault that putting closures in a language will kill its sales.
________________
oop.ismad.com
New Re: Eval () is NOT a kind of closure
I don't see "eval" as a kind of closure. Eval would not be able to do the kinds of things I use closures for. Nor would a closure work where I needed "eval" capability.

They are not interchangable except for extremely trivial examples.
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New You are right.

No, you can't implement car and cdr with eval.
And no, you can't ask a user to type in an anonymous function that returns another function as a result.

But all the examples that Tablizer and his opponents have in mind have been trivial so far.

--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New All?
But all the examples that Tablizer and his opponents have in mind have been trivial so far.

Did you look at the examples that I had him look at?

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New I was thinking about
transactions (where you could pass in a set of SQL statements, I guess) and regression.

Your examples are not quite doable with eval. When, oh when will I be able to think like this! I am not too much above average, it seems :( .
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New Thought you had missed those :-)
As for when you will think like that, perhaps after reading On Lisp, and working your way into The Structure and Interpretation of Computer Programming. And then some good conversations with people who already program like that...

At least that was my strategy. :-)

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Re: Thought you had missed those :-)
I've ordered The Structure and Interpretation of Computer Programming yesterday :)

BTW, the first example cam probably be done with straight recursion (but not with eval). If I get it right, the advantage of closures in that case is that you "prebuild" recursion stack, so the actual execution of recursion goes faster (you don't have to parse parameters for every call).


\n\nproc multilevel_for {varname all_ranges code} {\n    multilevel_for_implementor $varname $code {} $all_ranges\n}\n\nproc multilevel_for_implementor {varname code proc_args all_ranges} {\n    if {[llength $all_ranges] == 0} {        \n        set $varname $proc_args\n        unset varname proc_args all_ranges\n        eval $code\n        return\n    }\n    set range [lindex $all_ranges 0]\n    set from [lindex $range 0]\n    set to [lindex $range 1]\n    for {set x $from} {$x <= $to} {incr x} {\n        multilevel_for_implementor $varname $code [concat $proc_args $x] [lrange $all_ranges 1 end]\n    }\n}\n\nmultilevel_for combination { {1 10} {3 4} {10 20} } { puts $combination }\n\n\n
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New That mostly works
The one big mistake is that you assume that the ranges passed in are always ranges. I only did that in my example because it is easy to generate ranges, but the combination code doesn't care what kinds of arrays you want.

But the idea does accomplish the job.

However an advantage of closures is that they don't run into problems if, say, the function that you are calling happens to name a variable using one of your internal variable names (eg varname, proc_args, or all_ranges). Another advantage is that you don't have the same number of parsing/encoding steps to confuse you. Furthermore the code passed into eval can be a closure itself - and may have behaviour which has already been parametrized in other ways.

Still these technical advantages of closures notwithstanding, the basic notion depends on code manipulating programmable behaviour. And any method of doing that, including eval, can make it work.

Incidentally I suspect that Ruby's version of eval can replace (inefficiently) any possible use of closures. The reason being that you can capture a context, and then by passing that context to eval with the code, you can eval the code in the other context. In other words the one thing that closures fundamentally buy you (ability to access encapsulated lexical values in some other part of the code) can be done within eval. I haven't seen this capability in other languages. (Not that I have looked very hard.)

Cheers,
Ben

PS It took me a bit to figure out which language you were using... (Well, OK. It was my first guess, it just took me a bit to find my TCL interpreter and verify the guess. And a few others in gaim were just flailing.)
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Re: That mostly works
>>>>>>>>>>
The one big mistake is that you assume that the ranges passed in are always ranges. I only did that in my example because it is easy to generate ranges, but the combination code doesn't care what kinds of arrays you want.
<<<<<<<<<<<

I thought about it, but TCL has no construct equivalent to Perl's range array. And, as you know already, I hate Perl :)

I could do some special case processig to accomodate ranges and lists, something like

multilevel_for combination { {1-10} {3-4} {10 20 30} } { puts $combination }

and have a regexp to notice '-' in the middle of single-element list's only element. Very TCLish way to do things, and also very ugly, because now you need an escape for the lists that have one element ... and so on.


>>>>>>>>>>>>>>>>
However an advantage of closures is that they don't run into problems if, say, the function that you are calling happens to name a variable using one of your internal variable names (eg varname, proc_args, or all_ranges). Another advantage is that you don't have the same number of parsing/encoding steps to confuse you. Furthermore the code passed into eval can be a closure itself - and may have behaviour which has already been parametrized in other ways.
<<<<<<<<<<<<<<<<<

I know, I know. The only variable that is left to pollute the namespace is $code. I could work around it by using TCL's namespaces, but that's to much for a proof of concept.

As to parameterizing the closure, it can be acomplished to some small extent via exceedingly ugly use of concat command. I don't want to write it, and you don't want to see it :) .

Hey, I've never said it will be pretty :)


--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New Think we are even then
I thought about it, but TCL has no construct equivalent to Perl's range array. And, as you know already, I hate Perl :)

And my summary of TCL is that yes, you can base a language entirely around quoting and parsing strings, and it is a bad idea.

My solution wouldn't be very TCLish though. I would just write a function to produce ranges, and then I would pre-process arguments rather than post-process them in each function that wants to support such a basic notion. Of course the fact that this approach is not very TCLish speaks volumes for why I don't like the language...

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New A function to produce list from range
would not work very well for huge ranges.
No, you need real iterators for that. Too bad for TCL.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New So?
In the kinds of problem spaces that scripting languages are usually used for, wasting memory like that is just fine. When you get to a problem where the simple wasteful approach doesn't work, then you start to worry about it.

Though I admit that the better scripting languages have been moving for a while towards making it possible to replace basic data structures with real iterators. (With varying levels of ease.)

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Fake Closures
Ben: Incidentally I suspect that Ruby's version of eval can replace (inefficiently) any possible use of closures. The reason being that you can capture a context, and then by passing that context to eval with the code, you can eval the code in the other context. [...]

Since a closure is just code + context, you can do as you describe. Its a little tricky passing parameters since the parameter you wish is pass is generally not in the scope where the string is evaluated. I used a global stack ... global to handle the cross scope parameter passing and a stack to handle nested closure calls.

Here's a Ruby class implementing fake Closures ...
$args = Array.new\nclass FakeClosure\n  def initialize(str, bind)\n    @str = str\n    @bind = bind\n  end\n  def call(*args)\n    $args.push(args)\n    eval @str, @bind\n  ensure\n    $args.pop\n  end\nend
Ben: [...] I haven't seen this capability in other languages. [...]

TCL has it with its uplevel command. Old (pre-closure) versions of Lisp had something called "funargs" that represented scope and could be passed to eval (I don't know if modern Lisps still support funargs).
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New Wow
first geniunely new TCL command in a long while

I missed it completely. Thank you.

Together with "info level" it's almost perfect.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New Re: A TOP example
Pardon my Ruby; it's rusty...

Actuall, the Ruby DBI library has a built in transaction method ...
\n   db = DBI.connect("DBI:Pg:yadayadayada")\n   db.transaction {\n     db.do("UPDATE people_table ...")\n     db.do("UPDATE payroll_table ...")\n   }\n
Either both updates happen ... or they don't. (You might have to turn off autocommit ... I think that is DBD dependent unfortunately).
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New Multivariate Regression Analysis
Best use I found for them was the ability to solve [link|http://www.angelfire.com/tx4/cus/regress/index.html|multivariate regression]. Closures give you the ability to specify the form of the equation external to the regression operation itself without having to have a function devoted to each particular form of equation.

Of course, this is not your "standard business app", but then I'm not paid to develop standard apps. I'm paid to develop software that does whatever is required, including forecasting, etc... - statistics is but a part of the discipline of analyzing business data.
New Why not Eval()?
I have done data conversions where I put a bunch of expressions (equations) in a table and then processed each record through the conversions using Eval(). The accountant I was working with caught on to the expressions pretty quickly and started writing in some corrections to my initial guesses to the fixed assets depreciation calc conversions.

For those of you not familiar with such functions, you can do things like this:

x = "23 + b"
b = 5
r = eval(x)
print(r) // result: 28

Closures give you a bit more scope control than Eval() or Execute(), but for smaller programs it is not much of an issue. Again, I am not saying that closures won't simplify anything, I am just saying that the difference is relatively minor, and the inclusion of closures in a language often dooms it. Eval() or Execute() are non-intrusive syntax-wise; they are just functions like any other.

There are not that many places where Eval()-type things are needed, at least not all over the program, so a 5% reduction in syntax or a slight improvement in packaging for those few spots of the code is not a huge selling point. I see no reason to move them to the top of my wishlist as long as I have Eval-like functions.
________________
oop.ismad.com
New The problem is that the equations are part of the data
Eval doesn't do any good unless you want to parse a string to represent the equations - and even then you need some way to represent the equations as data (i.e. be able to manipulate it).

Your misunderstanding is to assume that I know the equation. I don't know the equation, I know one or more forms of the equation that I'd like to solve for (i.e. find the coefficients and r-square values). In your example, you are using of: x = "23 + b" - meaning that the a0 coefficient is 23 and the a1 coefficient is 1. The regression is designed to input some numbers [0,23], [1,24], [2,25], and figure out the coefficients (23,1). That just happens to be a simple linear equation that can be done without resorting to closures. However, what if wanted to solve the coefficients for:

y = a0 + a1*x + a2*x*x + a3*x*x*x

and just had a bunch of (x,y) data points. Or how about throwing in some additional exogenous variables:

y = a0 + a1*x + a2*z + a3*x*z + a4*x*x + a5*z*z

Now, how do you propose to solve for these coefficients given a series of data points? Having done this in a version of Pascal that does not have closures, my solution was to build a parser that allowed you to represent the form of the equation as a string. Problem is that a parser becomes a mini-language and occupies a good amount of space and requires an attention to detail. Whereas, by using closures in Python or code blocks in Smalltalk, I can sling together equation forms (i.e. lambda functions or anonymous functions).
Expand Edited by ChrisR June 26, 2003, 02:05:28 PM EDT
New I am not following you
My math is too rusty I guess. The equations can be stored anywhere. In tables, in files, etc. You can have something like:

equation = prompt("Enter equation:")
// assumes equation has "a" and "b" in it
a = prompt("Enter A:")
b = prompt("Enter B:")
printLine("Result is " . eval(equation))

Example run:

Enter equation: a*2 + b*b
Enter A: 3
Enter B: 4
Result is 22

(Validation and security is another lesson)
________________
oop.ismad.com
New Do you not understand Regression?
The equations can be stored anywhere.
It's easy enuf to store the equations - IF YOU HAVE THE EQUATIONS! That's your problem, you're assuming that all you are doing is storing coefficients.

// assumes equation has "a" and "b" in it
a = prompt("Enter A:")
b = prompt("Enter B:")
There's your problem. Your program is not smart enuf to figure out the coefficients A && B. What if I give you a table of:

CREATE TABLE MyData(x INT, y INT)
INSERT INTO MyData VALUES(1,0)
INSERT INTO MyData VALUES(3,1)
INSERT INTO MyData VALUES(5,2)

and I told you the equation was of the form:

y = mx + b

Now give me a program that uses the above data to derive m and b. Don't give me a program asking the end user to give me m & b. When you get that done, then start changing the form of the equation around, adding more variables and various combinations of power orders. Something simple like:

y = a + b*x + c*x*x + d*x*z + e*z*z + f*z

And don't ask the operator to supply the a,b,...f coefficients.
New Eval can be used to compute arbitrary function
with arbitrary number of arguments.

It's really inconvenient, but possible, because most evals have access to global variables (and some even to local scope variables). So you do something like this:

getFunctionValue(string f, real x[], real a[]) {
idx = 0;

foreach anX in x {
eval("x" . idx . " = " . x);
}

idx = 0;

foreach anA in a {
eval("a" . idx . " = " . a);
}

return eval(f);
}

And then you build your "f"s so that they use x0, x1 and so on for argument names, and a0, a1 and so forth for parameter names.

And then you can look for minimum sum of squares by calling getFunctionValue in the known data points x[] and varying a[].

And then you throw up in disgust at this slow unvieldy buggy contraption and choose a language that supports real anonymous functions. You do. But not Bryce. He is happy. He has just achieved another triumph of Eval.
--

Less Is More. In my book, About Face, I introduce over 50 powerful design axioms. This is one of them.

--Alan Cooper. The Inmates Are Running the Asylum
New Eval is "good enuf" for occassional use.
It's really inconvenient, but possible, because most evals have access to global variables (and some even to local scope variables).

In the languages I am familiar with, they had the *same* scope as if the expression itself was there in the code where the Eval function was. It is just like a code replacment. I suppose I should have stated that assumption, but I have yet to see it otherwise.

And then you throw up in disgust at this slow unvieldy buggy contraption and choose a language that supports real anonymous functions.

Buggy? You have not identified any specific bugs. True, you get no compile-time checking, but if we are generating stuff during run-time, we don't have that anyhow. Slow? Perhaps. But I don't use it for finite element simulations or the like.

You seem to be agreeing with me that Eval is "good enough" for occassional usage, which is my point. If code was littered with eval's or dynamic execute's, then one might find closures would clean up the scoping issues more.

And no, I *don't* remember multiple regression. That was many many moons ago. My brain does a pretty good job of house-cleaning, except that it never asks permission before tossing. Kinda like my wife. Maybe if I studied your code long enuf I might figure it out, but I have other more practical things I would rather study if I go into study mode.
________________
oop.ismad.com
New You are not familiar with Ruby then
In the languages I am familiar with, they had the *same* scope as if the expression itself was there in the code where the Eval function was. It is just like a code replacment. I suppose I should have stated that assumption, but I have yet to see it otherwise.

Ruby has several different eval functions running around. They vary in terms of whose scope they evaluate in. After all your code running in my package may do something very different from your code running in your package. Ruby gives you choice.

If you want to do something more sophisticated than the basic built-in options, there is even the notion of a binding, which can be taken anywhere, and then from anywhere else you can eval with that binding.

This is explained at [link|http://www.pragmaticprogrammer.com/ruby/articles/dynacall.html|http://www.pragmatic...les/dynacall.html]

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Of course Eval()?
Tablizer: I have done data conversions where I put a bunch of expressions (equations) in a table and then processed each record through the conversions using Eval().

Actually, this is a reasonable example of using Eval (provided you understand the dangers of passing external data to eval, but that's a different topic).

This is an example where a closure would NOT be a good choice.

Closures and Eval are NOT interchangable, except in trivial examples.
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New Re: Bad Marketing
I have yet to see a good case of where closures reduced the code complexity by more than roughly 5 percent.
Someday, perhaps you can share your metrics for measuring code complexity. I simply count lines.

Here's a real example from a real language.
f = open("filename")\nbegin\n  process_file(f)\nensure\n  f.close\nend
Here's the version with a closure.
open("filename") { |f|\n  process_file(f)\n}
I count 6 lines verses 3 lines. A 50% reduction in complexity.
Every example I have seen had a simpler non-closure alternative that was better than the non-closure example
I await a simpler version that: (1) is valid, executable code in the same language (Ruby ... I'll help with syntax if needed), and (2) is exception safe. The examples above are both.

I'll be offline over the next week ... so any replies may be delayed.
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New re: closures
That file example looks familiar.

First off, sometimes we can read the file into a string, and process it that way:

f = fileToString("filename.bar")
process(f)

The function opens and closes it on its own, so we don't have to manage closing. However, if we cannot do it that way, then the code can be simplified:

f = openFile("filename")
process_file(f)
f.close

If you consider the total code that is likely involved, then it would probably be less than 5 percent difference. I don't remember any programs I have ever done that had more than a few file open commands. If there are many, then likely it can be put into a loop or some other pattern that can be factored to fewer spots. Thus, it may add about 3 more lines to a total of something like 2000, which is not going to come close to 5 percent.

I will agree the closure may better ensure that the file gets closed, but if the language supports destructors, we can do something similar without closures. As soon as the variable/object/array goes out of scope, its destructor is called. (Different languages will support the timing and syntax differently, I would note).

If you are reading one character at a time, then the getNextChar() function could also automatically close the file at the end of the stream:

f = openFile("filename", autoClose=true)
while (getNextChar(f)) {
. . . processChar(f.char)
}

Here, the API takes care of closing for us. We could also leave it open if we want to do something else with it after the first loop.

A "killer" closure example would perhaps be one where a similar operation needs to be done many times per routine, not just once or twice, and in lots of routines. I have yet to see such. Someone suggested HTML tags as an example, but one can use wrappers for these:

s = "make me bold"
s = boldifier(s)
print(s)
function boldifier(s) {
. . . return ("[b]" . s . "[/b]")
}

(I used square brackets instead of angle brackets here, and dots to force indentation so that I don't have to mess around with HTML.)
________________
oop.ismad.com
Expand Edited by tablizer June 22, 2003, 02:52:13 PM EDT
New re: closures
(I managed to slip in one response before going out of town)
That file example looks familiar.
It should. You suggest several alternatives ...
[1] Read the entire file into memory.
[2] Inline open/process/close.
[3] Autoclose end reaching EOF.
[4] Using Destructors (RAIA idiom)

[1] is a surprising RAM-centric suggestion from the Tablizer. Surely
you realize this is impractical for anything but the smallest files.

However, if it useful for your particular application to process everything in
one big chunk, then the closure technique lends itself very well to it.
    file_contents = open("filename") { |f| f.read }
[2] Is broken code. It explicitly ignores the problems of exceptions
thrown in the process_file.

[3] Is also broken code, ignoring the problems of exception handling.
It also suffers from some implicit assumptions about the process_file
method (i.e. the process always reads to the end of the
file).

[4] is a suggestion to use the C++ idiom of Resource Allocation is
Acquisition. This will actually work quite nicely in C++. However,
it hasn't been shown that this technique is actually simpler than
closures. (C++ doesn't have a reputation for simple).
If you consider the total code that is likely
involved, then it would probably be less than 5 percent
difference. [...] Thus, it may add about 3 more lines to a total of
something like 2000, which is not going to come close to 5
percent.
Of course, to gain a 5% improvement in a 2000 program you would have
to save 100 lines. Even if I could demonstrate a one time 100 line
change (%5 improvement), you would point out that it falls below the
threshold of a 5000 line program. This is an argument that I can't
win, and as you point out, rigged examples don't do an argument any
credit.

Lets try another approach. If a closure saves around 3 lines of code
on average (I don't know if it does or not, but we are using "back of
the envelope" calculations here), then if a block is used every 60
lines of code or so, we should be right around the %5 mark.

Now all we need is a sampling of code where we can examine the total
number of blocks used against the total number of lines. Anything
where the ratio of total lines to total blocks is less than 60 would
count as meeting your 5% criteria. (Note, we are counting
all uses of a block/closure, of which the file open scenario
is just one example).

Here's a sample from the standard Ruby libraries for versions 1.6 and
1.8 ...
    Library                  Lines  Blocks Ratio\n    Ruby 1.6 Standard lib    35587     645    55\n    Ruby 1.6 site lib        50527    1245    40\n\n    Ruby 1.8 Standard lib    48146    1004    48\n    Ruby 1.8 site lib        20350     554    36
So it looks like all the standard libraries probably meet the stated
5% criteria.
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New bottom bread
is a surprising RAM-centric suggestion from the Tablizer.

Note that often I read stuff into a table(s), and then process it further. If I did a lot of that, I might do something like:

fileToTable(fileName, tableName, errorTable)

Further, many apps *do* work with small enough files to load into RAM for processing. You could argue that since it limits the size, it is less general purpose. However, the flip side is that one can do random access on RAM copies. Files don't guarentee random access. Thus, we are perhaps trading one limitation for another.

So it looks like all the standard libraries probably meet the stated
5% criteria.


For one, you appeared to assume that every block would need to have a closing portion (a "bottom bread") if closures were not used. That may not be the case. The number of blocks may also vary widely depending on programming style and language.

Further, lines of code is not the ideal metric for code density IMO. Some lines are long, and others are short. Closing things tends to be short lines. Plus, they have the added benefit of being more descriptive than "}".

It explicitly ignores the problems of exceptions
thrown in the process_file.


We don't need blocks to handle exceptions. But, that is another topic.
________________
oop.ismad.com
New Still waiting for examples
Hi! I'm back. I had a great week (thanks for asking). Back to the fray...

Tablizer: [comments on RAM-centric issues]

Absolutely irrelevent issues. I think we can agree that any solution that requires the file to be read completely into memory is a less general solution than one that does not.

Tablizer: We don't need blocks to handle exceptions.

Never said they were required. However, any correct solution must ensure that the file is closed, even in the presense of exceptions. Several of your examples did not do that.

(edit: changed title)
Tablizer: [numerical calculations assume complex bottom bread]

No such assumption was made. The only assumption was that an the example of a three line savings was typical. Even if the savings were only 2 lines of code, both site libraries would still meet that criteria. Given that you only ask for roughly 5 percent, and these are very rough measurements, the evidence certainly meets your criteria.

Just to be clear, your 5% criteria is completely vague and hard to realisitically measure. I'm not convinced that it is even a good criteria. All I'm claiming is that by one simple-minded measurement with some "back of the envelope" assumptions puts us in the ballpark range of your stated goal. This is just to demonstrate to you that closures really are used much more often than you would expect (far more than "eval" statements ... in fact, I'm not sure a "eval" statement would meet your criteria). If these numbers are not enough to convince you we're in the ballpark, just say so and we will continue with the understanding that the "5%" criteria is an impossible test that was never meant to be meet.

Just so we don't get too far adrift, here is your original statement.

Tablizer: I have yet to see a good case of where closures reduced the code complexity by more than roughly 5 percent. Every example I have seen had a simpler non-closure alternative that was better than the non-closure example that the closure pusher used to compare.

Just to recap: I'm still waiting for a non-closure example that is simpler (e.g. less code), and is better (e.g. has to work, does not introduce arbitrary restrictions).

(edit: Changed subject line)
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
Expand Edited by JimWeirich June 28, 2003, 03:40:27 PM EDT
New misunderstanding?
[comments on RAM-centric issues] Absolutely irrelevent issues. I think we can agree that any solution that requires the file to be read completely into memory is a less general solution than one that does not.

Well, that is probably debatable because forward-only reading is not "general purpose", but I will give that one to you for now because it smells like a long and winding debate.

However, any correct solution must ensure that the file is closed, even in the presense of exceptions. Several of your examples did not do that.

We are talking code complexity, not enforcing the bottom bread. An approach that requires the developer to explicitly issue a "bottom bread" command is not "wrong", just less automatic. Besides I already listed multiple non-closure solutions to auto-closing. I don't remember making any claims about them being equally automatic.

Just to recap: I'm still waiting for a non-closure example that is simpler (e.g. less code), and is better

I think you misread my statement. I was comparing NON-closure example A to NON-closure example B. (For those of you who often complain about my grammar, I am curious as to how you would reword it.)

Oh, BTW, how was your vacation (or trip away)? Go smoothly?
________________
oop.ismad.com
Expand Edited by tablizer June 28, 2003, 04:58:06 PM EDT
New misunderstanding? ... Now I'm Confused
I'm going to skip the "forward-only" comments and the "less-automatic" comments to get the this surprizing claim.

Tablizer: [...] I think you misread my statement. I was comparing NON-closure example A to NON-closure example B.

Wow. I re-read your original statement and see that you are absolutely correct. You didn't claim that your solutions were better than the closure versions. You only claimed they were better that the original non-closure example.

Does this mean that you agree that the closure versions are better than your "improved" versions?

Addressing your much weaker claim, I am not convinced that you have made your cause even there. To refresh your memory, in your examples

[1] was limited to "in-memory" applications
[2] didn't properly handle exceptions
[3] didn't properly handle exceptions and didn't work with all algorithms
[4] depended upon memory management implementation details to ensure correct behavior.

In what ways are any of your examples "better" than the original code?

Tablizer: Oh, BTW, how was your vacation (or trip away)? Go smoothly?

My wife and I took our church youth group (6 teenagers) to a CIY conference ([link|http://www.ciy.com/Library/SiteBuilder.aspx/82|http://www.ciy.com/L...teBuilder.aspx/82]). It was a very refreshing time.
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New long blocks
Although I could possibly take exception to "didn't properly handle exceptions" (pun), because you seem to define "proper" to fit your coding preferences, and some of the others, but the bottom line is that I just don't see closures a significant improvement over code I deal with.

For one, I don't like wide-reaching blocks. That is an anti-pattern IMO. I would rather see a CloseFoo command rather than an lonely little "}" sitting far from its parents and deepening the nesting. It is better "self documentation" IMO because I know where the range ends and I know WHAT is ending. "}" is too bland. Most of my close's are at the end of the routine, I would note.

The "ideal" auto-end-bread is situational. One possibility is to have it automatically close at the end of the routine if not done explicitly, but you seemed bothered by this for some reason. (Perhaps because existing languages don't support it well?).

I just don't see the big deal about closures. I don't. Their benefits seem rather minor. Again, I see no reason to move them to the top of my wishlist and it appears that enough others agree because mainstream languages keep omitting them (or at least downplaying them). They have the reputation for being mental masturbation, and part of that *is* deserved IMO.
________________
oop.ismad.com
New Back to the Example ...
Tablizer: Although I could possibly take exception to "didn't properly handle exceptions" (pun), because you seem to define "proper" to fit your coding preferences, [...]

You make it sound arbitary. It is not. In the example code, if an exception thrown during the processing of the file, the file is still properly closed. This is not the case is several of your examples.

So, if it is a "coding preference" to write exception safe code, then so be it.

As for the rest (long blocks, personal preferences, reputation jab), they are side issues; and I won't address them at this time.

The main point is back to your claim of closure advocates providing "lame" non-closure examples. I don't expect to convince you that closures are the coolest thing since sliced bread. I just wanted to make sure you saw a non-lame example.

Can we agree that this is such an example?
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New auto-close
if an exception thrown during the processing of the file, the file is still properly closed. This is not the case is several of your examples.

I don't quite know how they do it (probably destructor-like mechanisms[1]), but in some languages (or OS's), files and DB connections are automatically closed when the EXE or script ends. Thus, if we terminate the execution based on an error, those things are closed automatically.

Maybe languages and tools that you use behave differently. I only call the shots based on my experience. If I don't see something causing problems, I don't focus on looking for language techniques to manage problems that are not there. Something has been spoiling me perhaps......and I like it :-)

[1] Destructors are not limited to OO
________________
oop.ismad.com
New Exceptions
Tablizer: I don't quite know how they do it (probably destructor-like mechanisms[1]), but in some languages (or OS's), files and DB connections are automatically closed when the EXE or script ends. Thus, if we terminate the execution based on an error, those things are closed automatically.

From your comments, it seems that you are not familiar with the behavior of exceptions. Exceptions (generally) don't terminate the program, so depending on the OS to do your cleanup is pointless. It would also explain why your examples ignored exception safety.

I suppose now we can enter a discussion on exceptions and if they are needed for custom biz apps and if they can provide a roughly 5% overall decrease in complexity.

Or not.

Our last conversation on closures broke down on understanding synchronization issues and I don't want to repeat that here with exceptions. So I'm willing to drop the issue.

Perhaps you need to modify your claim to include the phrase "they present a lame non-closure version that depends upon advanced programming techniques (such as exceptions) to compare to".
--
-- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New Warning: Discussing exceptions with me is a loooong topic
________________
oop.ismad.com
     Advanced programming languages - why are they not used? - (Arkadiy) - (104)
         question from a non programmer - (boxley) - (11)
             Second through fourth sentences are a blur - (Arkadiy) - (10)
                 sorry, I went from your specific - (boxley) - (9)
                     Well... - (Arkadiy) - (8)
                         I am not smart enough to detect the difference - (boxley) - (7)
                             In C++, "if" is simple - (Arkadiy) - (6)
                                 I think I disagree, maybe - (drewk) - (5)
                                     Re: I think I disagree, maybe - (Arkadiy) - (4)
                                         I was right - (drewk)
                                         Re: I think I disagree, maybe - (tuberculosis) - (2)
                                             Perl 6 will take that idea farther - (ben_tilly) - (1)
                                                 +5 Informative. - (static)
         I regard Smalltalk as a teaching language - (warmachine) - (5)
             Dixit. -NT - (Arkadiy)
             I regard it as the most powerful production tool I have - (tuberculosis)
             couple of comments - (ChrisR) - (2)
                 Re: couple of comments - (warmachine) - (1)
                     Documentation tool? - (ChrisR)
         Your brain is damaged - (tuberculosis) - (13)
             I am not saying - (Arkadiy) - (11)
                 Average guy? Come here and say that! :) - (warmachine) - (6)
                     Either you are, or... - (Arkadiy) - (1)
                         Yep! But give it more time. - (warmachine)
                     What's this got to do with the price of oil in Baghdad? - (tuberculosis) - (3)
                         Oops! You're right. - (warmachine) - (2)
                             You've missed something I think - (tuberculosis)
                             Re: Oops! You're right. - (JimWeirich)
                 OK that's true - (tuberculosis) - (3)
                     Smalltalk for Small Tykes - (JimWeirich)
                     Wrong sense of "narrative". - (Arkadiy) - (1)
                         (Oops) - (Arkadiy)
             modeling English - (tablizer)
         Re: Advanced programming languages - why are they not used? - (deSitter) - (1)
             I was going to mention Forth, - (Arkadiy)
         Bad Marketing - (tablizer) - (69)
             Re-implement these examples, please - (ben_tilly) - (56)
                 Problem description missing - (tablizer) - (55)
                     Problem description - (ben_tilly) - (54)
                         Arrays of arrays? There's your problem.Use relational tables -NT - (tablizer) - (53)
                             Why am I not surprised that you avoided the question? - (ben_tilly) - (52)
                                 hold on, cowboy - (tablizer) - (51)
                                     No, you never do say that you are done - (ben_tilly) - (50)
                                         Okay, I admit it was too sweeping - (tablizer) - (49)
                                             Re: Okay, I admit it was too sweeping - (deSitter)
                                             Thank you - (ben_tilly) - (47)
                                                 that is what I am looking for - (tablizer) - (46)
                                                     Re: that is what I am looking for - (admin) - (6)
                                                         What's that? - (deSitter) - (1)
                                                             Re: What's that? - (admin)
                                                         Actually Java Anonymous Inner Classes - (tuberculosis) - (3)
                                                             If I remember correctly, - (Arkadiy) - (2)
                                                                 Not entirely accurate. - (admin) - (1)
                                                                     Thanks - (Arkadiy)
                                                     ICLRPD (new thread) - (CRConrad)
                                                     How much are you willing to pay? - (ben_tilly) - (37)
                                                         If you don't have the evidence, then just say so -NT - (tablizer) - (36)
                                                             You win, again - (ben_tilly) - (35)
                                                                 Can't ANYBODY ever find a #@!* BIZ example? -NT - (tablizer) - (34)
                                                                     Ben's given me an idea. - (static) - (4)
                                                                         different "core"? - (tablizer) - (3)
                                                                             That's one way to think of it. - (static) - (2)
                                                                                 But if tree traversal was trivial, then it does not matter - (tablizer) - (1)
                                                                                     It's a matter of perspective. - (static)
                                                                     A TOP example - (johnu) - (19)
                                                                         re: transaction rollback - (tablizer) - (17)
                                                                             Why not just use a closure? - (johnu) - (16)
                                                                                 Eval () is a kind of closure - (Arkadiy) - (15)
                                                                                     Python supports it... - (admin)
                                                                                     topic is not about me, Mr. Insult - (tablizer)
                                                                                     Re: Eval () is NOT a kind of closure - (JimWeirich) - (12)
                                                                                         You are right. - (Arkadiy) - (11)
                                                                                             All? - (ben_tilly) - (10)
                                                                                                 I was thinking about - (Arkadiy) - (9)
                                                                                                     Thought you had missed those :-) - (ben_tilly) - (8)
                                                                                                         Re: Thought you had missed those :-) - (Arkadiy) - (7)
                                                                                                             That mostly works - (ben_tilly) - (6)
                                                                                                                 Re: That mostly works - (Arkadiy) - (3)
                                                                                                                     Think we are even then - (ben_tilly) - (2)
                                                                                                                         A function to produce list from range - (Arkadiy) - (1)
                                                                                                                             So? - (ben_tilly)
                                                                                                                 Fake Closures - (JimWeirich) - (1)
                                                                                                                     Wow - (Arkadiy)
                                                                         Re: A TOP example - (JimWeirich)
                                                                     Multivariate Regression Analysis - (ChrisR) - (8)
                                                                         Why not Eval()? - (tablizer) - (7)
                                                                             The problem is that the equations are part of the data - (ChrisR) - (5)
                                                                                 I am not following you - (tablizer) - (4)
                                                                                     Do you not understand Regression? - (ChrisR) - (3)
                                                                                         Eval can be used to compute arbitrary function - (Arkadiy) - (2)
                                                                                             Eval is "good enuf" for occassional use. - (tablizer) - (1)
                                                                                                 You are not familiar with Ruby then - (ben_tilly)
                                                                             Of course Eval()? - (JimWeirich)
             Re: Bad Marketing - (JimWeirich) - (11)
                 re: closures - (tablizer) - (10)
                     re: closures - (JimWeirich) - (9)
                         bottom bread - (tablizer) - (8)
                             Still waiting for examples - (JimWeirich) - (7)
                                 misunderstanding? - (tablizer) - (6)
                                     misunderstanding? ... Now I'm Confused - (JimWeirich) - (5)
                                         long blocks - (tablizer) - (4)
                                             Back to the Example ... - (JimWeirich) - (3)
                                                 auto-close - (tablizer) - (2)
                                                     Exceptions - (JimWeirich) - (1)
                                                         Warning: Discussing exceptions with me is a loooong topic -NT - (tablizer)

Some have good ideas and some.. just have ideas.
455 ms