D - First-class Functions
- Mark Evans (4/4) Feb 19 2003 Think beyond "anonymous functions" -- go all the way and make functions
- Mark Evans (10/14) Feb 19 2003 That Wellesley CS professor's summary of first-class functions is not en...
- Mark Evans (2/2) Feb 19 2003 Frequently Asked Questions for comp.lang.functional:
- Mark Evans (16/16) Feb 20 2003 Dan keeps talking about delegates. This talk is dangerous.
- Bill Cox (20/41) Feb 21 2003 Hi, Mark.
- Mark Evans (35/44) Feb 21 2003 Well McCarthy, the creator of Lisp, got some things wrong.
- bill viasic.com (17/24) Feb 21 2003 Well, I probably don't rate as a great lisp programmer... I once tried ...
- Mark Evans (8/8) Feb 21 2003 The author deliberates between C, C++, Java, OCaml, Scheme, Lisp. Maybe...
- bill viasic.com (10/18) Feb 21 2003 Yes, languages for smart people are more fun. However, nearly all softw...
- Sean L. Palmer (22/30) Feb 22 2003 I feel like that burned out hacker he talks about.
- Bill Cox (8/15) Feb 22 2003 Man, I'm with you there... I've gotten so frustrated, I've even written...
- Walter (3/4) Feb 22 2003 Could you elaborate, please? (I apologize if you have before.)
- Bill Cox (73/80) Feb 22 2003 Sure. It's somewhat complicated. I wish I could sumarize the problems
- Patrick Down (10/28) Feb 22 2003 Actually it was me but to give credit where credit is due I got the
- Walter (11/14) Feb 22 2003 A great read. The article lists as a new requirement:
- Bill Cox (32/53) Feb 22 2003 Hi.
- Walter (14/41) Feb 23 2003 That's the way I read it, too, but how is it different from (in C++):
- Andy Friesen (13/76) Feb 23 2003 I think the idea is that Foo could just use Bar instances without regard...
- Patrick Down (112/129) Feb 23 2003 I think you missed the point. He was not
- Bill Cox (6/23) Feb 23 2003 I can try to use both techniques to inherit graph functionality into a
- Bill Cox (117/146) Feb 24 2003 I've messed around with reusing a simple graph package a bit, and now
- Bill Cox (16/16) Feb 24 2003 The reuse construct should have read:
- Bill Cox (4/21) Feb 23 2003 I'll try out both methods and post how it goes. It will probably take a...
- Dan Liebgold (19/25) Feb 23 2003 Because now in your class inherited from Foo, you can only refer to p as...
- Walter (12/40) Feb 24 2003 Thanks, your explanation makes sense to me. -Walter
- Bill Cox (7/42) Feb 22 2003 This is the short version of what goes wrong representing graphs. With
- Ken Carpenter (8/9) Feb 23 2003 I was trying to think back and remember mentioning anything about a
- Walter (4/84) Feb 22 2003 I suspect that templates are the answer, but I haven't really thought
- Robert M. Münch (19/20) Feb 23 2003 Hi, I'm very interested in this graph stuff as well. But sorry, I can't ...
- Bill Cox (9/30) Feb 23 2003 It sounds like they have some good software. Their "Network" algorithm
- Robert M. Münch (6/12) Feb 25 2003 Hi, yes their algorithms are very advanced.
- Mark Evans (2/2) Feb 21 2003 Brief but informative slides on the proper compilation of function closu...
- Mark Evans (23/23) Feb 21 2003 A must read from Paul Graham. I could not have offered a better rationa...
- bill viasic.com (15/17) Feb 21 2003 Hi, Mark.
- Walter (3/4) Feb 22 2003 D: C++ is too complicated
- Mark T (2/6) Feb 23 2003 ; Java, C# use VMs and don't have generics
- Ken Carpenter (7/16) Feb 23 2003 Many people hear "C# uses a VM" and assume that it's the same as Java.
- Mike Wynn (10/17) Feb 24 2003 as do most modern JavaVM's (only the early 1.0.x where pure interpreters...
- Sean L. Palmer (34/44) Feb 24 2003 The way most cpu's compile if/else is:
- Walter (9/21) Feb 24 2003 Their respective VM's are pretty similar in how they work, and similar i...
- Ken Carpenter (14/19) Feb 25 2003 point
- Walter (13/14) Feb 22 2003 A good read. The major cases where D significantly increases the succint...
- xyzzy (8/13) Feb 23 2003 A tangental idea comes from Edward De Bono's call for Simplicity. Or put...
- Dan Liebgold (17/17) Feb 25 2003 A good description of what first class functions entail from the excelle...
- Mark Evans (5/7) Feb 26 2003 The Oz book claims that 'procedure' is the more general concept (2.3.4)....
- Walter (11/20) Feb 20 2003 entirely
Think beyond "anonymous functions" -- go all the way and make functions first-class. Then you have real power at your fingertips, a true functional language. -M. http://puma.wellesley.edu/~cs251/spring02/first-class-functions.pdf
Feb 19 2003
That Wellesley CS professor's summary of first-class functions is not entirely correct. (He skirts some issues for the sake of not confusing students.) Microsoft's Vault site has a better discussion. It warns, "The distinction between a Vault function and a C function pointer can be rather subtle." The concept of closure is what counts here. http://research.microsoft.com/vault/learn/tutorial/closures.htm It is vindication for my point of view that Microsoft should adopt first-class functions in its version of "the next systems language" and I hope D does the same. MarkThink beyond "anonymous functions" -- go all the way and make functions first-class. Then you have real power at your fingertips, a true functional language. -M. http://puma.wellesley.edu/~cs251/spring02/first-class-functions.pdf
Feb 19 2003
Frequently Asked Questions for comp.lang.functional: http://www.cs.nott.ac.uk/~gmh//faq.html
Feb 19 2003
Dan keeps talking about delegates. This talk is dangerous. Proper language design "compiles out" many legacy design patterns, and I recently posted links on that subject. The pattern disappears when the language removes all need for it. So describing a language in terms of the patterns it replaces is convoluted and confusing; it describes with something that no longer exists. Instead, describe the language in terms of the features that do exist, and that replaced the patterns. Terms like "closure" and "first-class function" are very standard. Walter's remark about difficulty of implementation is worrisome. D is a new language, and first-class functions should not be overly difficult, though they entail a good refactoring and redesign. The kind of evolutionary dead-end suggested by Walter's remarks is exactly why I keep harping on the dangers of using C++ exclusively as a design foundation. It's critically important to think more generally than that; widen the gene pool with other languages. You all know what happens when the gene pool is too small -- defects and extinction! Mark
Feb 20 2003
Hi, Mark. BTW, I've really enjoyed following all the links you've posted. Very educational. Keep it up! I cut my baby programmer teeth on Lisp, which has first class functions. Some people look at my code and say Lisp ruined me (too many small functions). I also write a LOT of C, and some C++. In all the C code I've written, I haven't missed Lisp's first class functions. Not once. I think they are an anceint concept (40 or 50 years now?) that may be evolving out of the gene pool. I'm much more interested in some of the newer features being included in some of the languages you've dug up. D already includes many of them. Two of the ones I believe I would actually use are: - Powerful iterators. I hate writing recursive iterators and passing callback functions to them. Newer schemes like Sather's eliminate that. - Modifying existing classes directly. Nice does this, allowing additional methods. Sather does this even better, allowing class code to be directly incorporated into a new class with arbitrary modifications. That really rocks. I'd use that all the time. Bill Cox Mark Evans wrote:Dan keeps talking about delegates. This talk is dangerous. Proper language design "compiles out" many legacy design patterns, and I recently posted links on that subject. The pattern disappears when the language removes all need for it. So describing a language in terms of the patterns it replaces is convoluted and confusing; it describes with something that no longer exists. Instead, describe the language in terms of the features that do exist, and that replaced the patterns. Terms like "closure" and "first-class function" are very standard. Walter's remark about difficulty of implementation is worrisome. D is a new language, and first-class functions should not be overly difficult, though they entail a good refactoring and redesign. The kind of evolutionary dead-end suggested by Walter's remarks is exactly why I keep harping on the dangers of using C++ exclusively as a design foundation. It's critically important to think more generally than that; widen the gene pool with other languages. You all know what happens when the gene pool is too small -- defects and extinction! Mark
Feb 21 2003
I cut my baby programmer teeth on Lisp.... I also write a LOT of C, and some C++. In all the C code I've written, I haven't missed Lisp's first class functions. Not once.Well McCarthy, the creator of Lisp, got some things wrong. http://www.cs.brown.edu/courses/cs173/2001/Lectures/2001-09-21.pdf It's also possible that you were never a good Lisp programmer. I know plenty of imperative (C, Pascal, FORTRAN) programmers who write code in functional languages which reads just like their favorite native tongue. The expressiveness of a functional language is wasted on them. I write "a LOT" of C and C++ too, but use other languages regularly, and often move between imperative and functional paradigms even within the same project. The difference in expressive power is quite staggering. As a rule I would always prefer to write something in a higher level style as would any intelligent programmer. It's just easier. I refer you back to my colleague's remarks about OCaml, which offers first-class functions. The computer science Ph.D.'s at Microsoft Research have incorporated first-class functions into Vault pursuing goals practically identical to D's. They are right on the money.I think they are an anceint concept (40 or 50 years now?) that may be evolving out of the gene pool.That's like saying the wheel is going out of style. Here is a very interesting productivity contest between Lisp, Java, and C++. http://www.norvig.com/java-lisp.html "His results show that the resulting Lisp programs ran faster on average than C, C++ or Java programs (although the fastest Lisp program was not as fast as the fastest C program), and that Lisp programs took less development time than the other languages." Walter wrote:One point is the article saying that nested functions 'capture' the value of variables in the enclosing environment at the point of declaration of the nested function.That 'environment capture' is called a closure. 'Nested functions' are not the key idea, so worrying about stack frames is off the mark. The nesting just arose because they wanted to show how FCF's permit precise scope control, i.e. no one but its caller needs visibility on that function. The Needle language offers not only first-class functions, but first-class continuations too. Icon has the same idea, though I'm not sure it's truly first-class. It's been a while since I wrote Icon code. Continuations are probably over the top for D, but I can envision them helping with interrupt service routines and multithreading. A better starting point on multithreading would be the Oz book which puts the entire subject in context. http://www.nongnu.org/needle/ http://www.info.ucl.ac.be/people/PVR/book.html Mark
Feb 21 2003
In article <b3665m$2juo$1 digitaldaemon.com>, Mark Evans says...Well, I probably don't rate as a great lisp programmer... I once tried to get a group of engineers to use a Scheme interpreter I wrote to control a place and route tool I was working on. Big mistake. I junked it, and wrote a Basic interpreter instead which they actually used (this was before TCL). Ever since, I've been weary of language features that confuse engineers. Imagine trying to teach an average group of guys in the industry about tail recursion instead of loops, or continuations for error handling. Can you give me a example of how first class functions can be used to improve an average programmer's productivity without confusing him or the poor guy who will inherit his code? Personally, I think we do most programmers a favor by simplifying computer languages while adding a minimum of new features. I love that Java doesn't have pointers, and that D discourages them. I think all pointers, including function pointers and delegates, are like the C proprocessor: you don't really need them if the language provides the capabilities you were trying to emulate directly. BillI cut my baby programmer teeth on Lisp.... I also write a LOT of C, and some C++. In all the C code I've written, I haven't missed Lisp's first class functions. Not once.Well McCarthy, the creator of Lisp, got some things wrong. http://www.cs.brown.edu/courses/cs173/2001/Lectures/2001-09-21.pdf It's also possible that you were never a good Lisp programmer.
Feb 21 2003
The author deliberates between C, C++, Java, OCaml, Scheme, Lisp. Maybe I should have put the subject as "Re: OCaml" but that was getting tired. -M. http://www.paulgraham.com/vanlfsp.html 'Writing Java code, though not particulary painful in the sense that C is painful (core dumps etc.), puts me to sleep. Writing Ocaml ... is exciting. My motivation to tackle the project has tripled overnight.... Why are "languages designed for smart people" (LFSPs) so much more fun to program in than "languages designed for the masses" (LFMs)?'
Feb 21 2003
In article <b370f0$a7r$1 digitaldaemon.com>, Mark Evans says...The author deliberates between C, C++, Java, OCaml, Scheme, Lisp. Maybe I should have put the subject as "Re: OCaml" but that was getting tired. -M. http://www.paulgraham.com/vanlfsp.html 'Writing Java code, though not particulary painful in the sense that C is painful (core dumps etc.), puts me to sleep. Writing Ocaml ... is exciting. My motivation to tackle the project has tripled overnight.... Why are "languages designed for smart people" (LFSPs) so much more fun to program in than "languages designed for the masses" (LFMs)?'Yes, languages for smart people are more fun. However, nearly all software that sell well, and even most open-source code, is eventually worked on by the other kind of people. This is why GNU recommends staying away from C++, and contributing code in plain old C. The real trick is making the language as powerful as possbile, while keeping the compiler lean, and keeping those other kinds of people from shooting themselves in the foot. Bill P.S. I happen to specialize in keeping programmers' feet healthy.
Feb 21 2003
I feel like that burned out hacker he talks about. I need a new language in a bad way. C++ is getting really really old. I find myself fighting the language more than focusing on the original problem. Hell most of my problems are caused directly by the implementation language and the crystal structure that C++ programs naturally solidify into as they grow. I grow bored with the problem by the time I get halfway through implementing its solution, or a deadline comes along and it has to be put on hold until I forget about it, or until the feature gets dropped due to lack of time. Maybe it's just me. But I really am not all that excited about programming anymore. A new language that gave me lots of expressive power while simultaneously freeing me from the mundane worries of memory management and cleanup and type checking and syntactical nitpicking would be a godsend. Maybe I should check out OCaml more. I looked at it but it seems, how shall I put it, a little inelegant. I don't have much time for learning languages anymore. It's hard to decide which one to pursue. Sean "Mark Evans" <Mark_member pathlink.com> wrote in message news:b370f0$a7r$1 digitaldaemon.com...The author deliberates between C, C++, Java, OCaml, Scheme, Lisp. Maybe I should have put the subject as "Re: OCaml" but that was gettingired. -M.http://www.paulgraham.com/vanlfsp.html 'Writing Java code, though not particulary painful in the sense that C is painful (core dumps etc.), puts me to sleep. Writing Ocaml ... isexciting. Mymotivation to tackle the project has tripled overnight.... Why are"languagesdesigned for smart people" (LFSPs) so much more fun to program in than "languages designed for the masses" (LFMs)?'
Feb 22 2003
Sean L. Palmer wrote:I feel like that burned out hacker he talks about. I need a new language in a bad way. C++ is getting really really old. I find myself fighting the language more than focusing on the original problem. Hell most of my problems are caused directly by the implementation language and the crystal structure that C++ programs naturally solidify into as they grow.Man, I'm with you there... I've gotten so frustrated, I've even written my own language to solve the issues I've been fighting forever. I have the authority to make our company use it... but even if it doubles our productivity, that would probably be stupid. D is remarkably close to what I have been working on, and I think it has a real chance of success. If it could just support directed graphs well, I'd be happy. Bill
Feb 22 2003
"Bill Cox" <bill viasic.com> wrote in message news:3E57BCC7.6050301 viasic.com...If it could just support directed graphs well, I'd be happy.Could you elaborate, please? (I apologize if you have before.)
Feb 22 2003
Hi, Walter. Walter wrote:"Bill Cox" <bill viasic.com> wrote in message news:3E57BCC7.6050301 viasic.com...Sure. It's somewhat complicated. I wish I could sumarize the problems in one or two lines, but I can't. Just to jump ahead, I think a good solution can be found in Sather. Their "reuse" construct looks easy to implement (of course, templates looked easy too...). Ken Carpenter's suggested "framwork" idea seems to also work well. If you look at the non-reusable pseudo-code I posted for the Pizza Contest, I think you'll find it both readable, and likely to lead to an efficient implementation (Ok, I haven't compiled it yet... you'll probably find that I've got glaring errors). I think when you see the reusable versions people hopefully will write for the contest, you'll see that they are either very complex, or not very efficient. With a "reuse" construct, I think you could directly reuse the simple and otherwise non-reusable version. First, let's look at why the pseudo code I suggested is not reusable in D. This is simple. Inheriting from Node, Edge, and Graph is the only way to reuse this code, since it wasn't defined as an interface or template. If Netlist were to inherit from Graph, it would inherit a linked list of nodes, but what I asked for was two doubly linked lists, one of Instances, and one of Nets. Similar problems occur with the other classes. We also run into the problem of having to do lots casts to derived classes if we ever want to traverse the derived objects. Let's try that again, but this time with templates. Graph, Node, and Edge could all be rewritten to be template classes, and the container classes could be provided by the user. But all that does is let us define various kinds of directed graphs. It doesn't allow me to directly embed graph functionality in my netlist. The two doubly linked lists in Netlist are not easily going to get defined by using the Graph template class. You'd have to do something goofy like inherit from two versons of the Graph template at the same time. It's all down-hill from there. Ken Carpenter suggested making Graph, Node, and Edge template classes that inherit from template parameters. This may actually lead to the winning implementation, but I think it's going to be pretty convoluted. Frankly, if a programmer didn't shoot himself in the foot with such code, I'd buy a gun and shoot it for him. How about using interfaces? This actually works, but has some issues. Now we have to define a large interface that mimics every method and attribute used in the pseudo code. It could be dozens of methods. Every one of them has to be defined by the user. Worse, every time I add a graph related atribute or method to the Graph interface, every user has to upgrade his code, even if he doesn't need the new graph functionallity. There are all kinds of attributes that would eventually be needed. For example, we have a level attribute in our simple code for the contest. There are other problems. The foreach(Graph, node) functionality would have to be done with some sort of virtual iterator. When writing the foreach loop in the Graph code, you can't just instantiate the iterator on the stack as you would in C++, because you don't know it's size. That's determined by the user's choice of contaner class, which is hidden behind the interface. You have to use something like Java Enumeration interfaces, which leads to pretty slow code. The darned iterators are going to wind up on the heap! Finally, there's the potential overhead of lots of virtual function calls since everything is done through an interface. However, if the D compiler were to do global optimizations across modules, it might succeed in binding most of them statically. It seems to me that writing a good reusable graph module in D is hard. I think it should make for an interesting contest, if I can get any competitors interested. If someone could show me how to do a really good one that D specifically enables, I think I'd ask my company to start using D, since we currently have to rewrite basic code like this every day in C. I haven't used the Sather "reuse" constructs before, so I don't know what hidden pitfalls are there. However, it seems to mimic what I do today in C: copy the functions and class attributes from one module and paste them into my new module, and then rename things to make it all work. It's very similar to the "framwork" stuff Ken Carpenter was talking about, which also seems like it would do the trick. I sure hope I'm wrong about all this, and someone just shows me how to reuse code... It would definately be worth the 30 bucks for pizza. BillIf it could just support directed graphs well, I'd be happy.Could you elaborate, please? (I apologize if you have before.)
Feb 22 2003
Bill Cox <bill viasic.com> wrote in news:3E57E58F.4080108 viasic.com:Hi, Walter. Walter wrote:Actually it was me but to give credit where credit is due I got the the framework idea from an article by Tim Sweeney. http://www.gamespy.com/legacy/articles/devweek_b.shtm A notable quote is... <quote> While object-oriented languages handled pure objects well, they modeled complex relationships between objects poorly. Frameworks and collections turn out not to be truly modular or extensible because the languages can't represent families of objects. </quote>"Bill Cox" <bill viasic.com> wrote in message news:3E57BCC7.6050301 viasic.com...Sure. It's somewhat complicated. I wish I could sumarize the problems in one or two lines, but I can't. Just to jump ahead, I think a good solution can be found in Sather. Their "reuse" construct looks easy to implement (of course, templates looked easy too...). Ken Carpenter's suggested "framwork" idea seems to also work well.If it could just support directed graphs well, I'd be happy.Could you elaborate, please? (I apologize if you have before.)
Feb 22 2003
"Patrick Down" <pat codemoon.com> wrote in message news:Xns932AB5EFBBD40patcodemooncom 63.105.9.61...Actually it was me but to give credit where credit is due I got the the framework idea from an article by Tim Sweeney. http://www.gamespy.com/legacy/articles/devweek_b.shtmA great read. The article lists as a new requirement: "The language needs to support "function references bound to specific objects;" such entities (unsupported in C++ and Java) are the essential glue for binding parametric components together; without them, you often have to write an enormous amount of "duct tape" code to hold a framework together." D does this with delegates. I didn't really understand what they were talking about with inner classes, and why the same effect could not be achieved by simply adding a pointer to a class as a member of the framework class.
Feb 22 2003
Walter wrote:"Patrick Down" <pat codemoon.com> wrote in message news:Xns932AB5EFBBD40patcodemooncom 63.105.9.61...Hi. I agree, it's a really good artical. I tend to focus more on what he calls "virtual classes", more than delegates. I haven't ever seemed to need delegates, so I'm unfamiliar with the problem he's solving. If I read it right, "virtual classes" are simply classes that can be replaced (just like virtual functions). You define a higher level containing class, inherit the whole thing, and replace classes that need custom definitions for your app. A lot of programmers and languages use the concept of a class to replace the concept of a module. Personally, I prefer a module to be named a "module", and the classes within "classes". If you rename entities a bit, I think you'll see that Patrick Down's "frameworks" and "virtual classes" are essentially the same thing. As far as I can tell, they are also very similar to Sather's "reuse" construct. All of these have one thing in common: They let me inherit all the code in a module into my module, while letting me replace the things that don't work for me. This is very much like class inheritance, where I get to fix the methods by overriding them. However, it applies at a module level. I think this is what it takes to reuse code with multiple inter-relating classes cleanly. Of these concepts, Sather's reuse concept seems to me to be the most straight-forward to implement. It also seems easier to explain to people. I wouldn't like to have to teach "virtual classes" to new programmers. However the "reuse" stuff looks like what they already do: copy, paste, and edit. I can explain it in terms of actions rather than higher-level polymorphism. On the other hand, a lot of C++ programmers might give D a serious look if they though they could achieve higher level polymorphism through virtual classes. Marketing is everything. Mabe D should incorporate Strategic Programming, too :-) BillActually it was me but to give credit where credit is due I got the the framework idea from an article by Tim Sweeney. http://www.gamespy.com/legacy/articles/devweek_b.shtmA great read. The article lists as a new requirement: "The language needs to support "function references bound to specific objects;" such entities (unsupported in C++ and Java) are the essential glue for binding parametric components together; without them, you often have to write an enormous amount of "duct tape" code to hold a framework together." D does this with delegates. I didn't really understand what they were talking about with inner classes, and why the same effect could not be achieved by simply adding a pointer to a class as a member of the framework class.
Feb 22 2003
"Bill Cox" <bill viasic.com> wrote in message news:3E584E7A.2060908 viasic.com...If I read it right, "virtual classes" are simply classes that can be replaced (just like virtual functions). You define a higher level containing class, inherit the whole thing, and replace classes that need custom definitions for your app.That's the way I read it, too, but how is it different from (in C++): class Foo { class Bar *p; }; where you can inherit from Foo, derive from Bar, and replace p?A lot of programmers and languages use the concept of a class to replace the concept of a module. Personally, I prefer a module to be named a "module", and the classes within "classes".So do I. I discovered quite by accident that the module concept makes the C++ concept of "friends" irrelevant. That was a nice surprise. Modules are so much more natural.If you rename entities a bit, I think you'll see that Patrick Down's "frameworks" and "virtual classes" are essentially the same thing. As far as I can tell, they are also very similar to Sather's "reuse" construct. All of these have one thing in common: They let me inherit all the code in a module into my module, while letting me replace the things that don't work for me. This is very much like class inheritance, where I get to fix the methods by overriding them. However, it applies at a module level. I think this is what it takes to reuse code with multiple inter-relating classes cleanly.Yup, the 'friend' issue.Of these concepts, Sather's reuse concept seems to me to be the most straight-forward to implement. It also seems easier to explain to people. I wouldn't like to have to teach "virtual classes" to new programmers. However the "reuse" stuff looks like what they already do: copy, paste, and edit. I can explain it in terms of actions rather than higher-level polymorphism. On the other hand, a lot of C++ programmers might give D a serious look if they though they could achieve higher level polymorphism through virtual classes. Marketing is everything. Mabe D should incorporate Strategic Programming, too :-)I think I'll just find a way to bury all those buzzwords into the D spec so that D pops up when people google on them <g>.
Feb 23 2003
Walter wrote:"Bill Cox" <bill viasic.com> wrote in message news:3E584E7A.2060908 viasic.com...I think the idea is that Foo could just use Bar instances without regard for polymorphism, and it would all just work if you subclassed Foo and Bar. Existing Foo methods would use the derived class. class Baz : Foo { class Bleagh : Bar { ... } // Foo methods will use Bleagh instead of Bar } In languages like D, this is a simple matter of using a method of Foo as a factory; subclass and override that to return new instances of your derived class, and you're gold. Override the factory, and everything uses the new inner class.If I read it right, "virtual classes" are simply classes that can be replaced (just like virtual functions). You define a higher level containing class, inherit the whole thing, and replace classes that need custom definitions for your app.That's the way I read it, too, but how is it different from (in C++): class Foo { class Bar *p; }; where you can inherit from Foo, derive from Bar, and replace p?A lot of programmers and languages use the concept of a class to replace the concept of a module. Personally, I prefer a module to be named a "module", and the classes within "classes".So do I. I discovered quite by accident that the module concept makes the C++ concept of "friends" irrelevant. That was a nice surprise. Modules are so much more natural.If you rename entities a bit, I think you'll see that Patrick Down's "frameworks" and "virtual classes" are essentially the same thing. As far as I can tell, they are also very similar to Sather's "reuse" construct. All of these have one thing in common: They let me inherit all the code in a module into my module, while letting me replace the things that don't work for me. This is very much like class inheritance, where I get to fix the methods by overriding them. However, it applies at a module level. I think this is what it takes to reuse code with multiple inter-relating classes cleanly.Yup, the 'friend' issue.Of these concepts, Sather's reuse concept seems to me to be the most straight-forward to implement. It also seems easier to explain to people. I wouldn't like to have to teach "virtual classes" to new programmers. However the "reuse" stuff looks like what they already do: copy, paste, and edit. I can explain it in terms of actions rather than higher-level polymorphism. On the other hand, a lot of C++ programmers might give D a serious look if they though they could achieve higher level polymorphism through virtual classes. Marketing is everything. Mabe D should incorporate Strategic Programming, too :-)I think I'll just find a way to bury all those buzzwords into the D spec so that D pops up when people google on them <g>.
Feb 23 2003
"Walter" <walter digitalmars.com> wrote in news:b3a0o8$2sbt$1 digitaldaemon.com:"Bill Cox" <bill viasic.com> wrote in message news:3E584E7A.2060908 viasic.com...I think you missed the point. He was not talking about one class containing another. The framework provides a context in which all the classes in it may be overridden by inheritance and all the classes will still retain the same relationships with each other. class A { B b } class B { C c } class C { } Here A, B and C have a defined relationship with one another. class D : A {} class E : B {} class F : C {} Now D doesn't own an E it owns a B. D, E and F don't have the same relationship to each other the A, B and C do. Sometimes this is what you want but sometimes what you want is the relationship of A, B and C to be a abstract pattern for a concrete implementation ion of E, D and F. Let's take Bill Cox's Graph library as an more concrete example. Graph, Node and Edge are related to one another. There are graph algorithms in the library that advantage of these relations to do certain tasks. Finding shortest path between two nodes is an example. class Graph { void shortestPath(Node from, Node to, out Node[] pathNodes, out Edge[] pathEdges); } class Edge { int getWeight(); Node getFrom(); Node getTo(); } class Node { Edge[] getEdges(); } class Road : Edge { char[] getName(); } class City : Node { char[] getName(); } Graph usa = new Graph... City[] stops; Road[] route; // ERROR shortestPath wants Node[] and Edge[] // not City[] and Road[] usa.shortestPath(boston,los_angles,stops,route); You can get around this with some nasty casting. Templates can supply a solution too. There is an example of this in the "Directed Graph Support" thread. But it's clunky. The framework way of doing this would be. framework GraphLib { class Graph { void shortestPath(Node from, Node to, out Node[] pathNodes, out Edge[] pathEdges); } class Edge { int getWeight(); Node getFrom(); Node getTo(); } class Node { Edge[] getEdges(); } } framework Map : GraphLib { class Edge { char[] getName(); } class Node { char[] getName(); } } The Map framework brings forward the implementation of all the classes in GraphLib and extends them. I see framework as more of a template definition. GraphLib provides a pattern that can be extended. It might even be recast into the template syntax. Like this... template GraphLib { class Graph { void shortestPath(Node from, Node to, out Node[] pathNodes, out Edge[] pathEdges); } class Edge { int getWeight(); Node getFrom(); Node getTo(); } class Node { Edge[] getEdges(); } } instance GraphLib MyGraph { // Append this definition to GraphLib's // Edge and node definition class Edge { char[] getName(); } class Node { char[] getName(); } }If I read it right, "virtual classes" are simply classes that can be replaced (just like virtual functions). You define a higher level containing class, inherit the whole thing, and replace classes that need custom definitions for your app.That's the way I read it, too, but how is it different from (in C++): class Foo { class Bar *p; }; where you can inherit from Foo, derive from Bar, and replace p?
Feb 23 2003
Walter wrote:"Bill Cox" <bill viasic.com> wrote in message news:3E584E7A.2060908 viasic.com...I can try to use both techniques to inherit graph functionality into a hyper-graph, and let you know how I did. I find a concrete example can help solidify things. It might take me a couple of days to get around to it. BillIf I read it right, "virtual classes" are simply classes that can be replaced (just like virtual functions). You define a higher level containing class, inherit the whole thing, and replace classes that need custom definitions for your app.That's the way I read it, too, but how is it different from (in C++): class Foo { class Bar *p; }; where you can inherit from Foo, derive from Bar, and replace p?
Feb 23 2003
Bill Cox wrote:Walter wrote:I've messed around with reusing a simple graph package a bit, and now have a simple example. The following code is from my toy compiler I've been playing with (which I call "Sail"). The 'reuse' construct is the same as Sather's "include" construct. It's also similar to the "framework" Patrick Down proposed, and "virtual classes", and Eiffel's "covariation". I like it because it puts the code needed to reuse the graph package to one place. My second favorite is Patrick's frameworks, which read very nicely. Here's a simple piece of graph code in Sail. It parses, but I haven't implemented the reuse stuff yet, so it doesn't run. The code just detects loops in directed graphs: module graph; class Graph { // We have a linked list of nodes, and nodes point back // to their graph. cascade LinkedList of Node nodes:graph; bool findLoop() { Node node; clearNodeFlags(); // This itterator gets generated by the LinkedList code foreach(nodes, node) { if(!node.visited && node.findLoop()) { return true; } } return false; } clearNodeFlags() { Node node; foreach(nodes, node) { node.visited = false; node.marked = false; } } } class Node { // This adds two linked-list containters to Node, and two back // pointers to Node from Edge. cascade LinkedList of Edge outEdges:fromNode, inEdges:toNode; bool visited, marked; findLoop() { Node otherNode; Edge edge; visited = true; marked = true; foreach(outEdges, edge) { // The fromNode.owner member of Edge is generated by // the linked-list outEdges relationship. otherNode = edge.fromNode.owner; if(otherNode.marked || !otherNode.visited && otherNode.findLoop()) { marked = false; return true; } } marked = false; return false; } } class Edge { // No fields are declared here, but the Node back-pointers are added // by the linked-list containers in Node. } Now lets reuse the code in a realistic application, a simple PCB router. A printed circuit board has layers of wires, interconnected by vias. Net's are a collection of these wires, which interconnect components on the board. I just list the Net, Wire, and Via classes, but their would be others to model the whole board. module router; class Net { // We have a doubly linked list of wires, and wires point back // to their nets. cascade DoublyLinkedList of Wire wires:net; } class Wire { // We have an undirected graph of wires connected by vias. // This still requires two containers, abitrarily called // via1s and via2s. cascade LinkedList of Via via1s:wire1, via2s:wire2; } class Via { } Note that this sub-schema of classes is isomorphic to the schema for directed graphs. (Schema just means a diagram of classes drawn as nodes, and relationships drawn as edges. Schemas are isomorphic if they are basically the same graph, just with names changed.) To reuse all the graph stuff, I need only specify the mapping of classes and relationships between the modules: reuse graph { // Nets act like Graphs Graph : Net; // The wires relationship acts like the nodes relationship Graph.nodes : Net.wires; Node : Route; Node.outEdges : Route.via1s; Node.inEdges : Route.via2s; Edge : Via; } Now, I can determine if a Net has a loop with net.findLoop(). Note that I could include graph functionality multiple times if needed, since there may be multiple isomorphisms with sub-schemas of my module. This code causes all the graph module's code to be included in the router module. During the copy, we replace or rename identifiers as specified in the mapping. Unmapped identifiers are copied as-is. Without a construct of this kind, we are left with templates, interfaces, and inheritance to try to reuse the graph package. So far as I can tell, none of these work well for this kind of code reuse. Patrick's "frameworks" work perfectly well here. Frameworks look more like an inheritance mechanism, while this "reuse" construct looks more like a fancy preprocessor thing where we include code, but replace some things. Sather calls it "include", but is otherwise identical to this "reuse" construct. I think "include" would possibly confuse C programmers, but perhaps it would give them the right notion. Bill"Bill Cox" <bill viasic.com> wrote in message news:3E584E7A.2060908 viasic.com...I can try to use both techniques to inherit graph functionality into a hyper-graph, and let you know how I did. I find a concrete example can help solidify things. It might take me a couple of days to get around to it. BillIf I read it right, "virtual classes" are simply classes that can be replaced (just like virtual functions). You define a higher level containing class, inherit the whole thing, and replace classes that need custom definitions for your app.That's the way I read it, too, but how is it different from (in C++): class Foo { class Bar *p; }; where you can inherit from Foo, derive from Bar, and replace p?
Feb 24 2003
The reuse construct should have read: reuse graph { // Nets act like Graphs Graph : Net; // The wires relationship acts like the nodes relationship Graph.nodes : Net.wires; Node : Wire; Node.outEdges : Wire.via1s; Node.inEdges : Wire.via2s; Edge : Via; } That's the problem with untested code... It's never right. I just work on this thing for fun, but I hope to eventually implement full support for the reuse construct. If it would help, I could do it sooner than later, and post what kind of trouble I run into. Bill
Feb 24 2003
Walter wrote:"Bill Cox" <bill viasic.com> wrote in message news:3E584E7A.2060908 viasic.com...I'll try out both methods and post how it goes. It will probably take a couple days to get to it. BillIf I read it right, "virtual classes" are simply classes that can be replaced (just like virtual functions). You define a higher level containing class, inherit the whole thing, and replace classes that need custom definitions for your app.That's the way I read it, too, but how is it different from (in C++): class Foo { class Bar *p; }; where you can inherit from Foo, derive from Bar, and replace p?
Feb 23 2003
In article <b3a0o8$2sbt$1 digitaldaemon.com>, Walter says...That's the way I read it, too, but how is it different from (in C++): class Foo { class Bar *p; }; where you can inherit from Foo, derive from Bar, and replace p?Because now in your class inherited from Foo, you can only refer to p as a Bar (not the inherited type) unless you litter your code with type-casts. This can be a major source of type incompabilities and bugs. Eiffel prominently features a fix for this conceptual problem; they call it "covariation". When you inherit from Foo, you can declare p as a member with a new type, but only if the type is Bar or a subclass of Bar. It will then completely replace Foo's p. I'm not sure if you could do this in D. It seems that you would run into problems in Foo's methods, for example if Foo's constructor is called on a subclass that replaces p, it might attempt to allocate a Bar instead of the appropriate subclass of Bar. You can fix this incurring some performance lossage by using the properties methods in D or setter/getters in C++: instead of referring to p directly set and get p through a method that subclasses of Foo will override. That is really the idea lurking behind Sweeney's "virtual classes" concept. I do agree that this problem can be a major constraint on large object-centric programs. Dan
Feb 23 2003
Thanks, your explanation makes sense to me. -Walter "Dan Liebgold" <Dan_member pathlink.com> wrote in message news:b3blva$17h2$1 digitaldaemon.com...In article <b3a0o8$2sbt$1 digitaldaemon.com>, Walter says...BarThat's the way I read it, too, but how is it different from (in C++): class Foo { class Bar *p; }; where you can inherit from Foo, derive from Bar, and replace p?Because now in your class inherited from Foo, you can only refer to p as a(not the inherited type) unless you litter your code with type-casts. Thiscanbe a major source of type incompabilities and bugs. Eiffel prominently features a fix for this conceptual problem; they callit"covariation". When you inherit from Foo, you can declare p as a memberwith anew type, but only if the type is Bar or a subclass of Bar. It will then completely replace Foo's p. I'm not sure if you could do this in D. It seems that you would run into problems in Foo's methods, for example if Foo's constructor is called on a subclass that replaces p, it might attempt to allocate a Bar instead oftheappropriate subclass of Bar. You can fix this incurring some performance lossage by using thepropertiesmethods in D or setter/getters in C++: instead of referring to p directlysetand get p through a method that subclasses of Foo will override. That isreallythe idea lurking behind Sweeney's "virtual classes" concept. I do agree that this problem can be a major constraint on largeobject-centricprograms. Dan
Feb 24 2003
Patrick Down wrote:Bill Cox <bill viasic.com> wrote in news:3E57E58F.4080108 viasic.com:Oops... Sorry Patrick. Ken suggested the pizza link.Hi, Walter. Walter wrote:Actually it was me but to give credit where credit is due I got the the framework idea from an article by Tim Sweeney."Bill Cox" <bill viasic.com> wrote in message news:3E57BCC7.6050301 viasic.com...Sure. It's somewhat complicated. I wish I could sumarize the problems in one or two lines, but I can't. Just to jump ahead, I think a good solution can be found in Sather. Their "reuse" construct looks easy to implement (of course, templates looked easy too...). Ken Carpenter's suggested "framwork" idea seems to also work well.If it could just support directed graphs well, I'd be happy.Could you elaborate, please? (I apologize if you have before.)http://www.gamespy.com/legacy/articles/devweek_b.shtm A notable quote is... <quote> While object-oriented languages handled pure objects well, they modeled complex relationships between objects poorly. Frameworks and collections turn out not to be truly modular or extensible because the languages can't represent families of objects. </quote>This is the short version of what goes wrong representing graphs. With only one class, like with a binary tree, you're in good shape. As soon as the data structures involve multiple inter-related classes, reuse gets hard. Bill
Feb 22 2003
"Bill Cox" <bill viasic.com> wrote in message news:3E58454F.7030500 viasic.com...Oops... Sorry Patrick. Ken suggested the pizza link.I was trying to think back and remember mentioning anything about a framework to you! I almost convinced myself that I might have, since I've done something similar with a code generator I wrote at work. :-) Ken Carpenter
Feb 23 2003
I suspect that templates are the answer, but I haven't really thought through applying it to the problem you pose. "Bill Cox" <bill viasic.com> wrote in message news:3E57E58F.4080108 viasic.com...Hi, Walter. Walter wrote:"Bill Cox" <bill viasic.com> wrote in message news:3E57BCC7.6050301 viasic.com...Sure. It's somewhat complicated. I wish I could sumarize the problems in one or two lines, but I can't. Just to jump ahead, I think a good solution can be found in Sather. Their "reuse" construct looks easy to implement (of course, templates looked easy too...). Ken Carpenter's suggested "framwork" idea seems to also work well. If you look at the non-reusable pseudo-code I posted for the Pizza Contest, I think you'll find it both readable, and likely to lead to an efficient implementation (Ok, I haven't compiled it yet... you'll probably find that I've got glaring errors). I think when you see the reusable versions people hopefully will write for the contest, you'll see that they are either very complex, or not very efficient. With a "reuse" construct, I think you could directly reuse the simple and otherwise non-reusable version. First, let's look at why the pseudo code I suggested is not reusable in D. This is simple. Inheriting from Node, Edge, and Graph is the only way to reuse this code, since it wasn't defined as an interface or template. If Netlist were to inherit from Graph, it would inherit a linked list of nodes, but what I asked for was two doubly linked lists, one of Instances, and one of Nets. Similar problems occur with the other classes. We also run into the problem of having to do lots casts to derived classes if we ever want to traverse the derived objects. Let's try that again, but this time with templates. Graph, Node, and Edge could all be rewritten to be template classes, and the container classes could be provided by the user. But all that does is let us define various kinds of directed graphs. It doesn't allow me to directly embed graph functionality in my netlist. The two doubly linked lists in Netlist are not easily going to get defined by using the Graph template class. You'd have to do something goofy like inherit from two versons of the Graph template at the same time. It's all down-hill from there. Ken Carpenter suggested making Graph, Node, and Edge template classes that inherit from template parameters. This may actually lead to the winning implementation, but I think it's going to be pretty convoluted. Frankly, if a programmer didn't shoot himself in the foot with such code, I'd buy a gun and shoot it for him. How about using interfaces? This actually works, but has some issues. Now we have to define a large interface that mimics every method and attribute used in the pseudo code. It could be dozens of methods. Every one of them has to be defined by the user. Worse, every time I add a graph related atribute or method to the Graph interface, every user has to upgrade his code, even if he doesn't need the new graph functionallity. There are all kinds of attributes that would eventually be needed. For example, we have a level attribute in our simple code for the contest. There are other problems. The foreach(Graph, node) functionality would have to be done with some sort of virtual iterator. When writing the foreach loop in the Graph code, you can't just instantiate the iterator on the stack as you would in C++, because you don't know it's size. That's determined by the user's choice of contaner class, which is hidden behind the interface. You have to use something like Java Enumeration interfaces, which leads to pretty slow code. The darned iterators are going to wind up on the heap! Finally, there's the potential overhead of lots of virtual function calls since everything is done through an interface. However, if the D compiler were to do global optimizations across modules, it might succeed in binding most of them statically. It seems to me that writing a good reusable graph module in D is hard. I think it should make for an interesting contest, if I can get any competitors interested. If someone could show me how to do a really good one that D specifically enables, I think I'd ask my company to start using D, since we currently have to rewrite basic code like this every day in C. I haven't used the Sather "reuse" constructs before, so I don't know what hidden pitfalls are there. However, it seems to mimic what I do today in C: copy the functions and class attributes from one module and paste them into my new module, and then rename things to make it all work. It's very similar to the "framwork" stuff Ken Carpenter was talking about, which also seems like it would do the trick. I sure hope I'm wrong about all this, and someone just shows me how to reuse code... It would definately be worth the 30 bucks for pizza. BillIf it could just support directed graphs well, I'd be happy.Could you elaborate, please? (I apologize if you have before.)
Feb 22 2003
"Bill Cox" <bill viasic.com> schrieb im Newsbeitrag news:3E57BCC7.6050301 viasic.com...If it could just support directed graphs well, I'd be happy.Hi, I'm very interested in this graph stuff as well. But sorry, I can't code it for some pizza ;-)) even it would be a lot of fun. Anyway, graphs are on my todo list for some other project I need them for. I highly suggest to take a look at these links: http://www.mpi-sb.mpg.de/LEDA/leda.html http://www.algorithmic-solutions.de/leda.htm I have used the LEDA graph stuff some years ago. Very advanced and well done. Easy to use as plug-in etc. That's the concept I want to use to do it in D. What I'm mostly interested in is doing persistens graphs and traversal of persistens graphs. Perhaps using Berkely DB as base... Just thinking loud. -- Robert M. Münch IT & Management Freelancer Mobile: +49 (0)177 2452 802 Fax : +49 (0)721 8408 9112 Web : http://www.robertmuench.de
Feb 23 2003
Hi, Robert, and Thanks for the links. Robert M. Münch wrote:"Bill Cox" <bill viasic.com> schrieb im Newsbeitrag news:3E57BCC7.6050301 viasic.com...It sounds like they have some good software. Their "Network" algorithm components sound like the kind of thing I do a lot. I read some of their on-line documentation. You have to create graphs in their database, run their algorthms, and then read out the results. It's not really reusable code. For example, you couldn't use it to add graph functionality to hyper-graphs. BillIf it could just support directed graphs well, I'd be happy.Hi, I'm very interested in this graph stuff as well. But sorry, I can't code it for some pizza ;-)) even it would be a lot of fun. Anyway, graphs are on my todo list for some other project I need them for. I highly suggest to take a look at these links: http://www.mpi-sb.mpg.de/LEDA/leda.html http://www.algorithmic-solutions.de/leda.htm I have used the LEDA graph stuff some years ago. Very advanced and well done. Easy to use as plug-in etc. That's the concept I want to use to do it in D. What I'm mostly interested in is doing persistens graphs and traversal of persistens graphs. Perhaps using Berkely DB as base... Just thinking loud.
Feb 23 2003
"Bill Cox" <bill viasic.com> schrieb im Newsbeitrag news:3E590E6E.4050204 viasic.com...It sounds like they have some good software. Their "Network" algorithm components sound like the kind of thing I do a lot.Hi, yes their algorithms are very advanced.I read some of their on-line documentation. You have to create graphs in their database, run their algorthms, and then read out the results. It's not really reusable code. For example, you couldn't use it to add graph functionality to hyper-graphs.Really? Hm... must have changed radical since last time I used it. Normaly you get a set of classes and than make your way. But I have to say I didn't had a closer look into the online documentation. Robert
Feb 25 2003
Brief but informative slides on the proper compilation of function closures. -M. http://pauillac.inria.fr/~xleroy/talks/compilation-agay.pdf
Feb 21 2003
A must read from Paul Graham. I could not have offered a better rationale for first-class functions, though the principle stated is general, and so deserves its own thread. The design goals of D put certain constraints on the full development of this idea, but the ceiling is a lot higher than anyone involved with D really understands. Vault's decision to use first-class functions is one evidence of that fact. -M. http://www.paulgraham.com/power.html http://www.paulgraham.com/fix.html "It seems to me that succinctness is what programming languages are for. Computers would be just as happy to be told what to do directly in machine language. I think that the main reason we take the trouble to develop high-level languages is to get leverage, so that we can say (and more importantly, think) in 10 lines of a high-level language what would require 1000 lines of machine language. In other words, the main point of high-level languages to make source code smaller." "The main value of the succinctness test is as a guide in designing languages. The most useful comparison between languages is between two potential variants of the same language. What can I do in the language to make programs shorter?" "Aiming for succinctness seems a good way to find new ideas. If you can do something that makes many different programs shorter, it is probably not a coincidence: you have probably discovered a useful new abstraction." "...programs written in more powerful languages tend to have fewer bugs."
Feb 21 2003
Hi, Mark. Great links! The second one is the funniest computer language related page I ever read.http://www.paulgraham.com/power.html http://www.paulgraham.com/fix.htmlI agree for the need of powerful constructs. The smoke test for a language's power that I use is a simple reusable directed graph package. Every popular efficiently compiled language I've tried it in has failed to elegantly support it! We've talked a about it on this newsgroup, and haven't come up with a clean solution in D. In C and C++, I write the same stupid isomorphic functions over and over and over... Want to break loops in a directed graph in a single linear traversal? I've written it dozens of times. How about finding a max weighted path from primary inputs to outputs (representing circuit delay)? It hurts every time I write it. The types change, but never the algorithms. Bill
Feb 21 2003
"Mark Evans" <Mark_member pathlink.com> wrote in message news:b37347$cdr$1 digitaldaemon.com...http://www.paulgraham.com/fix.htmlD: C++ is too complicated
Feb 22 2003
In article <b38jlm$1nb9$1 digitaldaemon.com>, Walter says..."Mark Evans" <Mark_member pathlink.com> wrote in message news:b37347$cdr$1 digitaldaemon.com...http://www.paulgraham.com/fix.htmlD: C++ is too complicated
Feb 23 2003
"Mark T" <Mark_member pathlink.com> wrote in message news:b3aonm$dpc$1 digitaldaemon.com...In article <b38jlm$1nb9$1 digitaldaemon.com>, Walter says...code (CIL), but they are then compiled to native code before they are executed. Ken Carpenter"Mark Evans" <Mark_member pathlink.com> wrote in message news:b37347$cdr$1 digitaldaemon.com...http://www.paulgraham.com/fix.htmlD: C++ is too complicated
Feb 23 2003
as do most modern JavaVM's (only the early 1.0.x where pure interpreters) Java VM's are not all JIT (compile before) some are dynamic compilers (compile if its used more than once as compilation + execute time can be longer than interpret once time) also this allows the true main line of the code to be compiled. with C compilers 'if' is usally compiled as branch over the if clause, with a dynamic compiler if the if cluase is not entered then it is compiled as a branch out of the main line to the if clause making the common case code faster (missed branches are less expencive on most cpu's than taken branches).code (CIL), but they are then compiled to native code before they are executed.D: C++ is too complicated
Feb 24 2003
The way most cpu's compile if/else is: if it's just an if clause, it assumes the branch *will* be taken, and puts the code inline if it's an if/else clause, it assumes the else is the most likely branch, but keeps the 'if' portion inline also which requires a jump-around. This is so an implementation detail. Some cpu's can't branch very far so it pays to keep the code close together in memory. On some the branch is expensive if taken, on some it's expensive both ways, on others (older cpu's) it's no more expensive than any other instruction. The compiler vendor is the one that should be worrying about how to encode the semantics of the program into the cpu's instruction set and optimizing around its performance characteristics. The only case where I feel something is missing is with SIMD instructions; there is a basic register type on the machine that we don't have access to at high level. Arrays can fill this role, but many SIMD operations involve rearranging the slots or converting from one bit size to another... things array operations do not easily represent. And the SIMD instructions usually are designed for a specific size array. Sure you can use any size and ignore the remainder of the results. Inline assembler is good for expressing an routine as efficiently as possible. It's not good for exposing a low level datatype. Sorry I seem to have changed the subject... ;) I agree with the subject line. Succinctness *is* power. Explicitness just adds bloat. It's useful bloat sometimes, but it can and does get in the way. The requirement for being explicit should be in the coding standards for the company or project, not in the language. The language should allow succinctness or explicitness, as the circumstances require. Sean "Mike Wynn" <mike.wynn l8night.co.uk> wrote in message news:b3dgjj$2qiq$1 digitaldaemon.com...as do most modern JavaVM's (only the early 1.0.x where pure interpreters) Java VM's are not all JIT (compile before) some are dynamic compilers (compile if its used more than once as compilation + execute time can be longer than interpret once time) also this allows the true main line ofthecode to be compiled. with C compilers 'if' is usally compiled as branch over the if clause,witha dynamic compiler if the if cluase is not entered then it is compiled asabranch out of the main line to the if clause making the common case code faster (missed branches are less expencive on most cpu's than taken branches).
Feb 24 2003
"Ken Carpenter" <kencr shaw.ca> wrote in message news:b3cg9g$1tfo$1 digitaldaemon.com..."Mark T" <Mark_member pathlink.com> wrote in message news:b3aonm$dpc$1 digitaldaemon.com...Their respective VM's are pretty similar in how they work, and similar inIn article <b38jlm$1nb9$1 digitaldaemon.com>, Walter says..."Mark Evans" <Mark_member pathlink.com> wrote in message news:b37347$cdr$1 digitaldaemon.com...http://www.paulgraham.com/fix.htmlD: C++ is too complicatedcode (CIL), but they are then compiled to native code before they are executed.Of course. However, the native code is not stored anywhere, so at some point during the execution of your app it is going to spend time compiling. For a large app, this can be a very substantial performance hit. The upside of JITting is the generated code can be customized to the particular CPU being used.
Feb 24 2003
"Walter" <walter digitalmars.com> wrote in message news:b3f78a$h06$1 digitaldaemon.com...Of course. However, the native code is not stored anywhere, so at somepointduring the execution of your app it is going to spend time compiling. Foralarge app, this can be a very substantial performance hit. The upside of JITting is the generated code can be customized to the particular CPUbeingused.Actually, it is possible to "pre-JIT" the code using the ngen utility (Native Image Generator). This can be used to precompile all (or some) of the assemblies used in your application. You might, for example, choose to do this at install time. There is one major caveat, however. The JIT performs on-the-fly code optimizations, while ngen does not. Thus, depending on the type of code in a given .NET assembly the JIT may run slower or faster than the precompiled version. Your profiler is your friend here. Ken Carpenter
Feb 25 2003
"Mark Evans" <Mark_member pathlink.com> wrote in message news:b37347$cdr$1 digitaldaemon.com...http://www.paulgraham.com/power.htmlA good read. The major cases where D significantly increases the succintness of programs: 1) garbage collection - all that memory management code is gone. It's amazing how this cleans up and simplifies code. 2) class objects referenced by handles only - gone are the need for and complicated semantics of copy constructors and assignment overloads. 3) array management - the whole scheme of slicing, concatenation, and automatic memory management of arrays is a big shrinker of programs. 4) templates - I believe (though not yet born out by experience) that D's practice of grouping a bunch of related declarations under one template is a big shrinker for template programming.
Feb 22 2003
On Sat, 22 Feb 2003 05:51:03 +0000 (UTC), Mark Evans <Mark_member pathlink.com> wrote:A must read from Paul Graham. I could not have offered a better rationale for first-class functions, though the principle stated is general, and so deserves its own thread.A tangental idea comes from Edward De Bono's call for Simplicity. Or put another way, a programming language should be simple but not simplistic, plus that in order to implement something that is simple to use, may very well involve a deal of complexity 'under the hood'. -- xyzzy
Feb 23 2003
A good description of what first class functions entail from the excellent "Structure and Interpretation of Computer Programs", by Abelson and Sussmen: "In general, programming languages impose restrictions on the ways in which computational elements can be manipulated. Elements with the fewest restrictions are said to have first-class status. Some of the ``rights and privileges'' of first-class elements are:64 * They may be named by variables. * They may be passed as arguments to procedures. * They may be returned as the results of procedures. * They may be included in data structures. Lisp, unlike other common programming languages, awards procedures full first-class status. This poses challenges for efficient implementation*, but the resulting gain in expressive power is enormous. *: The major implementation cost of first-class procedures is that allowing procedures to be returned as values requires reserving storage for a procedure's free variables even while the procedure is not executing." Dan Liebgold
Feb 25 2003
The Oz book claims that 'procedure' is the more general concept (2.3.4). So it talks about first-class procedures, which is a new twist, but basically sound, though it might ruffle feathers among functional programmers. http://www.info.ucl.ac.be/people/PVR/book.html MarkA good description of what first class functions entail from the excellent "Structure and Interpretation of Computer Programs", by Abelson and Sussmen:
Feb 26 2003
"Mark Evans" <Mark_member pathlink.com> wrote in message news:b30vu9$np6$1 digitaldaemon.com...That Wellesley CS professor's summary of first-class functions is notentirelycorrect. (He skirts some issues for the sake of not confusing students.) Microsoft's Vault site has a better discussion. It warns, "Thedistinctionbetween a Vault function and a C function pointer can be rather subtle."Theconcept of closure is what counts here. http://research.microsoft.com/vault/learn/tutorial/closures.htm It is vindication for my point of view that Microsoft should adoptfirst-classfunctions in its version of "the next systems language" and I hope D doesthesame.One point is the article saying that nested functions "capture" the value of variables in the enclosing environment at the point of declaration of the nested function. This is in contrast to pascal where the nested function directly references the enclosing stack frame.
Feb 20 2003