text: One researcher tries to answer Hamming's questions.
  Posted to general by Ehud Lamm on 8/18/02; 3:04:43 AM
  The way I see it, you can start by wanting to extend the language with some new kind of functionality. You should then try to implement your extension as a library. When this fails, you'll have a good clue as to where the language really needs extending.
  In short: Why can't the (specfic) language extension be implemented as a library?
  A classic example is adding control structures. As opposed to new data types which are usually quite easy to add using ADTs, classes etc., most languages don't really support the addition of new control structures via library code.
  We do know that languages with first class functions and continuations make adding new control structures easier.
  To conclude: New language features should be introduced if they allow other interesting language features to be implemented as library code.
  See for example the BeyondJS library.
  We were able to add control structures and many other language features. For example, functional composition, currying and lazy evaluation.
  It seems like you could extend the audience of re-use for all of Scheme's great libraries (logic programming , constraint programming , lazy interpreters, pattern matching, AI ...) if Scheme could be so extended and if translation into this subset from Scheme was straightforward.
  Just brainstorming.
  You see people doing functional programming in C++.
  You see people doing Prolog in Scheme's s-expression syntax..
  Adding new control construct structures is difficult.
  > As opposed to new data types which are usually quite easy to add using
  > ADTs, classes etc., most languages don't really support the
  > addition of new control structures via library code.
  Programming Language =
  primitive data types + primitive control constructs (EOPL) + API libraries (platform)
  Java platform specifications and
  JavaCheck
  make the last component, the API libraries or platform explicit.
  JavaCheck uses an Xml specification of a Java Platform,
  (e.g. Personal Java for PDA's vs. J2ME for Cell phones
  vs. Standard J2SE vs Enterprise J2EE...Waba could also be so specified)
  to check that a program only uses API library functions within the
  particular platform definition.
  Control constructs and their syntax and semantics
  as well as data types remain fixed here,
  but they could be added to the specification,
  and then you'd have the sort of thing that IP seems
  to be aiming for:
  a completely reconfigurable language,
  "new control structures via library code."
  That's kind of what EOPL does when it defines interpreters
  but it's obvious that they've massively simplified things
  when you look at
  Table 5 "Some of the possible parameters of a generic conditional construct" in
  Toward Language Design Assistants
  which lists the details you have to attend to when defining even a
  simple if-else statement.
  So why would Scheme expressed in Java be desirable?
  > New language features should be introduced if they allow
  > other interesting language features to be implemented as library code.
  Scheme has great libraries for doing everything from logic programming
  to constraint programming to soft type checking and a recursive module system (PLT's Units)
  that is more powerful than ML's modules,
  not to mention the fact that whole legacy of
  AI programming is but a Lisp-to-Scheme translator away,
  a translation between two dialects of Lisp.
  How can an ordinary programmer working in a business
  setting use these potentially productivity enhancing language features
  and avoid the onus of being "weird" and using a "weird" language
  that no one has heard or uses like Scheme?.
  One of the standard complaints against programming anything in non-mainstream
  languages like Scheme is that you won't be able to find a programmer
  who can program in it, even if it does provide the best solution to your problem.
  There is the necessity of
  conforming to existing norms if I actually
  want my code to be usable by others.
  If I write anything in Scheme I'm going to limit myself to
  a very small audience.
  If I could write the same things in a version of
  Java extended with Scheme language features, then my
  potential audience is all Java programmers, much larger.
  What I'm getting at here is that re-usability is above all a function
  of how many people use your language in the first place.
  It would be cool if by adding Scheme control constructs to
  Java you could broaden Scheme's reusability audience,
  by a factor of ten..
  Pizza
  What I'm getting at here is that re-usability is above all a function of how many people use your language in the first place.
  Hm... and is visibility a function of how many people are looking at something? You have an interesting, populist notion of reusability. This may serve you well if you ever want to start a revolution in a country inhabited by a lower class of oppressed programmers.
  Viva la revolucion!
  In other words, there is some truth to Jon's populist view.
  To extend Frank's analogy: visibility (say, of a billboard advertisement) can indeed be a function of how many people are typically going to be looking at something, if that number of viewers cause the ad's creators to place that advertisement in better light, or on the big screen at Times Square ...
  But one can hope that eventually will have a better and faster way...
  After all, the whole point of lazy evaluation is to defer work until you have to do it. And if eXtreme Programming takes this notion to extreme, well, that's obviously a part of its nature.
  Often it is simply better programming to do so. Let me clarify.
  For something to be reusable it has to meet to goals. First, it must do something (solve a problem) that several applications have to do. Otherwise no reuse. finding such abstractions requires experience, component evolution etc.
  The other requirement from a reusable piece of code is that it plays nice, so it doesn't break other components, and it can easily be embeded inside larger applications. Some of the ways of achieving this goal are well known. For example, not using global variables and having some kind of namespace management.
  Now, these are things you should do whether you are intedning to reuse your code or not.
  I don't subscribe to all the arguments made by XP, but I do agree that in some cases building for reusability can be a hindrance instead of asset. Aiming for reusability often leads to generalizations that may not be required for the task at hand, and can obfuscate the issues.
  Given the realities of project timelines a programmer needs to seriously weigh the benefits of make the code more generalized. Is it worth the additional design time? Is it worth the creation of more complex tests, the extra debug time, the documentation?
  Don't get me wrong, I do think reusability is a good thing. It's just that I don't think that every piece of code I write needs to be reusable (in order to be good).
  No. What I said is that good code and reusable code have some common attributes. They are hardly they same thing.
  My second argument was that some properties of reusable code can be identified, and implemented, well before you actually need to reuse the code. If you reread the thread you will see that I mentioned this in order to explain what I meant by saying that the reusability of a piece of code is a property of the code itself, and not of the number of systems using it.
  What I said is that good code and reusable code have some common attributes. They are hardly they same thing.
  I would extend this to say that reusable code must be good in more ways than "simple" (non-reusable) code. This is because it will be used in more contexts. Indeed, it might be used in scenarios that are unforeseeable at development time. It is this extra "goodness" that I was debating.
  My second argument was that some properties of reusable code can be identified, and implemented, well before you actually need to reuse the code.
  The properties you specified are certainly ones I would recommend. What I question is concept you seem to be espousing, in this and the previous posts, that every code should be reuse-ready.
  When considering writing reusable code I generally ask myself three questions:
  I actually begin with the third question because if the code will never be reused, there is no point in making the effort no mater how appealing it is. This goes to jon's statement about reusability somehow being a property of the number of users. I agree in the sense that if the number of users is zero I will not make the code reusable to begin with.
  For much of the code I write, I consider it more important that the code can be refactored than reused.
  I said no such thing, since I was simply trying to elaborate on the term "reusable".
  At which point should you start thinking about reuse (or about design...) is a different debate entirely.
  Granted:
  1. There are properties of code that make it more reusable
  2. Code can written so it is more or less reusable
  What I was talking about is the actual decisions by people in
  (usually conservative) organizations to use software and
  adapt it to their ends. They are reusing software written
  by someone else and integrating it with their existing systems.
  Mainstream languages = {api infrastructure, pool of skilled programmers, large population of users}.
  Best practices = mainstream practices = less of an experiment = less career threatening.
  Most people I meet in the world of computing don't even know what Scheme is.
  Since I have to explain it to them, it is very unlikely that they are going to choose
  it for their next project. They are of course very familiar with mainstream languages
  like Cobol, C++, Perl, etc. This is the normal situation. In writing Scheme code,
  you limit your open source project or commercial product to a very narrow audience.
  I can imagine someone from marketing saying:
  "Just make Scheme look like Java and we can sell it."
  Well is this idea technically viable?
  Just as parsing technology has progressed to the point where you can
  build parsers on the fly, it seems like the stages of language design
  beyond the parser are progressing to the point where you can build
  a whole language on the fly. Given this situation, the most logical
  next step would seem to be "How can I reclaim and reuse all the relevant and
  useful code that was written in the past and use it in my new language."
  (= Source code renovation).
  What really interests me is getting the powerful tools that are already
  available written by others in non-mainstream languages into a form
  where they can be reused in mainstream languages like Java.
  JScheme and Kawa have java byte code compilers,
  so calling Scheme modules from Java would be the logical place to start.
  The Scheme modules will just be black boxes and the mainstream
  programmers won't even have to know that
  they are using Scheme.
  Black boxes never evolve and eventually die.
  If I want the modules to evolve as code in the mainstream language
  I'll have to actually transform the Scheme code into something more Java-like.
  How can I get the Scheme code into a state so that programmers who think in Java can think about it?
  And when Java dies I can transform it into the latest mainstream language.
  Lisp suffers from this problem right now.
  There was a tremendous investment in Lisp code in the 1980's
  and I don't see any of it being re-used nowadays.
  Maybe what I need is:
  1. Multiple views of source code given in an editable AST editor like IP uses.
  An AST editor with some mix of manual and automatic tree transformations.
  2. Where function applications embedded in parentheses (Scheme)
  can be transformed into a linear series of assignment statements (Java).
  (enforcing single-assignment-ness in the editor)
  3. Where Scheme functions can be inserted into appropriate Java classes.
  4. Creating some specialized Java-like syntax for Scheme language
  constructs that don't exist in Java like closures and first-class continuations:
  lambda( x . y | z = x + 1; z + y);
  begin{
  set!(x, y);
  .....
  z + y;
  };
  Looks like Java, but is derived from Scheme in a straightforward fashion.
  The subject of all embracing metaphors has been touched upon before at
  LTU. The metaphor that I keep coming back to is "COMPUTER-PROGRAM-IS-A-BOOK"
  1. The best books are translated from their original language into other
  languages so more people can benefit from them.
  (Can you imagine how insularized the world would be if there was no
  dissemination of scientific works across national-linguistic boundaries?)
  Translating natural language automatically is highly intractible but since
  programming languages are human defined tools it should be possible
  to automatically translate them.
  2. Some languages like C, Lisp, and Java become lingua-franca's
  for long periods of time, just like natural languages English and Latin.
  3. If you want to write good books you should be
  well read and familiar with the well-written books
  that others have written. A writer should be familiar with
  the range of acceptable styles and their
  good and bad points.
  Open source is like a library where a programmer can self-educate himself
  and learn to recognize excellence as well as schlock.
  4. The meaning of the book should be clear when you read it.
  You may have to read a couple of times and think about it a little,
  but you shouldn't need someone to explain it to you.
  (Code should be self-documenting)
  Jon, Scheme on Java is a bit complicated. The Java VM doesn't directly support continuations, lexical closures or tail calls. Emulating lexical closures is trivial using classes. There are various ways to get the other problems:
  The .Net framework does support tail calls but not lexical closures or continuations.