   Feedback on: a perfect programming language
  I think it would be interesting to hold a discussion on an optimal programming language. I am using the term "perfect" loosely in this case. Essentially: what constructs, instructions, data types and uses, programming paradigms, syntax, et cetera; would best be seen in a programming language, if you [we] were to design our own?For a formal discussion it would be nice to get more than four replies, so I hope this is effective enough. To keep things organized:    * Using /source or /code tags, highlight key features, or general syntax of a language you have in mind.    * Reply to what others' have posted, discussing the pros and cons of what they included in the discussion. If you truly like someone's concepts, make it known, to bring their feature into a more noted state.    * Don't forget the simple stuff. Discussing super advanced metamorphical templated vector monoliths does not have to be your only point. There are looping constructs and text display and variable allocation and memory managing and very basic syntax to think about too.    * Possibly one could discuss compiler features, libraries, and other subcategories of such a language. And so on. Please comment on what other people say as well. Thus, we can really get down to what is good and what is not good in a programming language of our design. This should be fun and interesting. Please don't be shy to get a good forum discussion going of more than a few replies, that actually has anything to do with the computer world.So, if youwere to design a language, how would wedo it?[edited by - khaos on October 22, 2003 7:23:53 AM]
  Multiple paradigm support (imperative/OO/functional)Strongly typedA good IDE (don''t underestimate this one)Optional reflective capabilitiesType inferenceLets you make every   decision concerning itIntegrated, but optional garbage collectorFunctions as first class objectsSmall runtimeIntuitive syntaxGood library supportNamespaces/packagesDiscourages Hungarian notation through compiler warning  (just kidding, that will get some responses)I can post code snippets later ;Constructs  Obvious ones are for-each; switch statements that accept more than just integers and can do comparisons. Break and continue with a labelled construct (ala perl) is essential.for (x) = (list)  doSomethingTo(x);switch (string){  case < "bar":    ...  case > "foo":    ...  case else:    ...}  Lambda expressions, higher order functions (functions that return functions) and partial application are also dead nifty:  // Lambda && higher order functions...  template  T(T) makeAddFunctor (T a)  {    return lambda (int x) { return a+x; };  }  int(int) add_to_12 = makeAddFunctor(12);    // Partial application  int(const char*) theCmp = strcmp("hello", @0);  for (char* x) = (string_list)  {    if (!theCmp(x))    { printf("Match found"); return;    }  }  Data types  Support for rationals would be nice, as well as complex numbers. Resizable arrays and trivial hashes.  int a[];  a.append(5);    int a[string];  a["foo"] = 69;  a["bar"] = 42;  Type inference is also nice: something which C++ partially supports via templates, but which many functional languages do automatically.A unified type system is terribly useful. One can use ''boxing and unboxing'' to pretend that the primitive types are varieties of lang.Object.Regular expressions are also good. Inline XML might be nifty, also:  dom.Node myDoc = <foo>text<bar>more text</bar></foo>;  Programming paradigms  Genericity is necessary. ''Nuff said.OOP is excellent. Everything must be an object, including the classes themselves. Double dispatch is nice.In-language support for events.State-based programming allows a class to customize the behaviour of its functions according to the situation, with little additional overhead at call-time:class Matrix{  state Translation:    float[3] apply (float[3] vec)    { /* apply simple translation */ }  state Complex:    float[3] apply (float[3] vec)    { /* apply complex generic transformation */ }};  Lazy evaluation and delayed evaluation are rather nifty, also.// Lazy maybe. Evaluates its argument 50% of the time.templatevoid maybe(lazy T v){  if (rand % 2)    v;}// Delayed repeat, evaluates its second argument TIMES times.templatevoid repeat(int times, lazy T expr){  for (times)    expr;}  Tail-recursion is highly desirable.Garbage collection is required by standard. Options to control/disable for certain classes or during certain parts of the program.Exolanguage wise, an IDE with debugger is essential. Tools for the language like lexer and parser generators, and documentation generators, are dead good. ;quote:Original post by antareus  Lets you make every   decision concerning it.How do you mean?quote:Good library supportThis could mean one of two things. Either that the language needs a good library of its own, or that it needs to be able to use other libraries without unreasonable difficulty. I agree with both.At the very least, it should be able to use C libraries.quote:Namespaces/packagesVery nifty.On the topic of namespaces, enums should be supported, and an enum have a namespace:enum MyEnum{  FOO, BAR, BAZ;};  Here the elements should be MyEnum::FOO, MyEnum::BAR and MyEnum::BAZ.Sometimes enums aren''t used in the disjoint way that is intended. Enums are often used to declare related flags that can be combined. Enums should be enforced, and a new construct provided for grouping flags:flagset MyFlags{  FLAG1, FLAG2, FLAG3;}  quote:Discourages Hungarian notation through compiler warning  (just kidding, that will get some responses)Too right.I''ll also risk some responses of my own by saying it definately should support multiple inheritance. ;  No more #pragma, nor the preprocessor! No more compiler dependency - ie - no more porting code from one compiler to another. Thus - only one (open source) compiler (with IDE). Oxyd.   ---Unreadable code is code written on a piece of paper, but not the one, in which its programmer is using a space in place you don''''t.  ;  -C/C++/Java syntax is fine , all the classic statements + foreach-classes,Interfaces.-all classic Java/C# types-built in dynamic arrays  and maps(tables)-maps can be hased with any type except null-higher order functions-coroutines or continuations-variant type-components are natively supported(not a bounch of zipped classes)-do not allow exposing classes thrugh components, just interfaces.-generics(safe macros ala Java 1.5)-no garbage collection, refcounting with cycle detection (+the compiler detects runtime what really needs refcounting), in alternative some sort of efficient ''linearity''.-autoboxing-small runtime(around 100-200k)-fast register based virtual machine-a good compilerBTW I''m gonna implement this language as soon I''m done with the current one...I''ll call it "Solid Hamster" ciaoAlberto -----------------------------The programming language Squirrelhttp://squirrel.sourceforge.net ;  Mayrel: choices over whether GC can be used, and if it is used, choices over whether object destruction is deterministic, perhaps some subsets of the language that make it suitable for demanding roles such as hard real-time tasks or looser tasks such as AIOn the libraries, I meant both, apologies for being vague.fagiano: you'll like C#, it has a great majority of those things you listed.Here are some more:* partial evaluation/currying (lets you 'build' function calls)* pointer usage is rare, not the norm (C++ is especially guilty of this)* passing by reference requires function caller to acknowledge that it is passing by reference:void f(ref int i){ i++;}// some functionf(ref i)   * embedded documentation generation that doesn't rely on ugly tokens in comments* MI support* More than double dispatch...multiple dispatch (proposal for C++ to support this thru n-dimensional jump tables)* closures (construct an entire function call with args and call it at a later time (ties in with what I said earlier but its still important, I think Delphi has them)What I get from the gist of all the comments is *some* sort of runtime system is needed. C++ is pretty close to as far as we can go with simply letting the compiler do the dirty work for us. But a tiny runtime would probably be more beneficial than not with all these language capabilities.   [edited by - antareus on October 22, 2003 2:03:01 PM];  I think a good starting point would be a language as versatile as Lisp. While it is a good language, I think it could be made somewhat better by adding in support for lower level programming (things like pointers etc). Most people that know Lisp know that is a good language for many purposes, but it can''t do everything well yet(things like writing a driver - why be forced to choose abstraction OR hardware access?).   "You are my friends if you do what I command you."[edited by - Big Brother on January 1, 1984 12:00:00 AM];quote:Original post by Extrarius  I think a good starting point would be a language as versatile as Lisp. While it is a good language, I think it could be made somewhat better by adding in support for lower level programming (things like pointers etc). Most people that know Lisp know that is a good language for many purposes, but it can''t do everything well yet(things like writing a driver - why be forced to choose abstraction OR hardware access?).   scheme! scheme! scheme!...Anyway.The major issue I have with LISP-esque languages is the syntax. Genius as it may be, I find that the proliferation of parantheses makes it difficult to discern structure. I''d recommend following Dylan''s example and transforming an easier-to-read syntax into an underlying LISP format.antareus:Hmm, my understanding was that ''double dispatch'' was the official term for anything that wasn''t single dispatch. I always call it ''multiple dispatch'' in my head, and usually correct it as it comes out.For my toy language, I have documentation embedded as XML as so:import std.io.*;@<fun name="main" type="int">  <arg name="args" type="char[][]" text="Arguments"/>  This program does blah, blah, blah.</fun>int main (char[][] args){  out.print(1 + @<note>This is seven, for no particular reason</note> 7);  return 0;}  fagiano: Assuming I understand you correctly, you suggest no garbage collection or reference counting? I don''t know what "linearity" means here, could you clarify? ;  Rather than LISP, start off with python... Warning : the following is an advertisement for Python  Multiple paradigm support (imperative/OO/functional)  yep  Strongly typed   hmm, no, it does have some implicit conversions.  A good IDE (don't underestimate this one)   well, it *does* have IDEs.  Optional reflective capabilities   it's built-in  Type inference   dynamic typing, baby!  Lets you make every decision concerning it    metaclasses !  Integrated, but optional garbage collector    gc.disable()  Functions as first class objects   *everything* is an object  Small runtime    well, it's smaller than java   Intuitive syntax   check ! (try it before you bash it)  Good library support   check - excellent standard lib  Namespaces/packages    check  foreach    check  case  nope, use if/elif/else  lambdacheck  partial application/currying   not built-in, but has been done - transparently  rationals   nope  complexcheck  dynamic arrays   built-in  hashcheck - that's arguably Python's core type; every nonmutable type (for obvious reasons) can be used as a hash key  unified type system   check - everything is an object  type inference   dynamic typing  regular expressions  check  inline XML   nope - there's an XML parsing lib, though  genericity   dynamic typing  multiple dispatch   not really  "state-based" programming   classes are modifiabke objects  lazy evaluation   no. generators provide 'lazy list' functionality though.  tail recursion   no  use of C libraries    need to write bindings, but can then be used as native python entities  multiple inheritance   check, the method resolution order is open to introspection.  enums    an enum metaclass exists (see Python Cookbook)  portablecheck  open-source    check  coroutines/continuations   yes, in the 'Stackless' implementation, otherwise, generators do the job  variant type   dynamic typing  components vs. interfaces    dynamic typing - adding interface testing is being discussed  refcounting with cycle detection   check, with caveats for classes with destructors (there is no general algorithm to determine how to break a cycle and which object to delete first - the programmer must decide)  small runtime   python23.lib is 175K - non-builtin library elements can add to that (script files - can be zipped).  pointers    none, the C API let you muck around, though (e.g. numarray module for efficient C-style arrays).  references    *everything* is passed by reference  embedded document generation   yes, PyDoc relies on introspection and docstrings.  deterministic gc    gc.collect()  fast VMerr... well... err... not really...   good compiler    the 'psyco' module gives you JIT compiling  closures    yes, though a bit clunky, imho  There you go  [ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ][ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]   [edited by - Fruny on October 22, 2003 4:44:01 PM]