www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Tart language

reply bearophile <bearophileHUGS lycos.com> writes:
Docs of Tart, a future system language:
http://docs.tart.googlecode.com/hg/intro/index.html

It looks very similar to D, with few idioms turned into nice syntax. It's in
early stage of development.

The following are quotations from the docs, I have selected some nice ideas.

---------------------------

http://docs.tart.googlecode.com/hg/intro/types.html

 Flags enum Traits {
  ABSTRACT,
  FINAL,
  STATIC,

  MASK = ABSTRACT | FINAL | STATIC,
}

var x = Traits.ABSTRACT | Traits.FINAL;

The presence of the  Flags annotation causes a number of things to happen:

        The default sequence of initialization values is 1, 2, 4, 8, and so on,
rather than 0, 1, 2, 3, etc. In other words, any enumeration constant that does
not have an explicit initialization expression will be assigned the next
available bit number after the previous value.
        The compiler will auto-generate the bitwise operators | and & for that
type.
        The compiler will also auto-generate the contains() method, which
allows the use of the in operator, enabling expressions such as if ABSTRACT in
traits.
        In the current version of Tart, the toString() method is not defined on
flag enums.

Note

Tart enumerations do not support Java’s ability to add arbitrary properties to
enums.

---------------------------

Property Declarations

The def keyword can also be used to define a property. Properties are like
variables, except that they are implemented using functions. Whenever you
attempt to read from the property, the property’s get function will be invoked,
and when you attempt to modify the value, the set function will be called.:

def myProp:int {
  get { return p; }
  set (value) { p = value; }
}

myProp = 1;   // Calls "myProp.set(1)"

---------------------------

http://docs.tart.googlecode.com/hg/intro/functions.html

Like Python, parameters can be referred to by name as well as position:

print("Hello, World!\n", padding="");

Any parameter can be referred to by its keyword name. The normal mapping of
arguments to formal parameters is that positional arguments are assigned first,
in order, and then any keyword arguments are assigned to any remaining unfilled
parameters.

Sometimes it is useful to specify a parameter that is “keyword only” meaning
that it can only be specified via keyword instead of positionally. A semicolon
can be used to segregate regular positional parameters from keyword-only
parameters:

def print (format:String; npos:int=0, sep=false);

print("Hello world!", npos=1); // OK
print("Hello world!", 1); // ERROR - too many positional arguments

In the above example, only the format argument will be filled in by positional
argument - to have additional positional arguments in this case would be an
error.

---------------------------

http://docs.tart.googlecode.com/hg/intro/classes.html

A protocol represents a contract which a type may conform to. A class or struct
is said to support the protocol if that class or struct defines all of the
method signatures that are defined by the protocol. Template arguments can be
constrained to only match types which support a specified protocol. Classes may
declare explicitly that they support a protocol, or the support can be
determined implicitly.

A protocol is a kind of abstract type that defines a contract which another
type can support. An example would be a “HasToString” protocol:

protocol HasToString {
  def toString -> String;
}

---------------------------

The extend keyword allows you to add additional methods to a user-defined type:

/* Add an additional method to the String class. */
extend String {
  static def toUpperCase() { /* ... */ }
}

Note however, that you can’t actually change the runtime representation of a
type this way. The reason is simple: The extend declaration may not be visible
everywhere in the program. If you extend class String, some modules may only
see the original, unextended class, while other modules will see the extended
version of the class. In order for all of the code to interoperate, the runtime
implementation of the class must be the same, regardless of the extension.

This means that the extension can only add certain kinds of things to a type,
namely:

    Static methods or properties.
    Final methods or properties.
    Inner types and type aliases.
    Protocol inheritance declarations.

Extensions follow the same scoping rules as other declarations, meaning that
they are only in effect if the scope in which they are declared is active.

---------------------------

Sometimes you need to test the type of a variable, the isa keyword can be used
for this. It works for both reference types and union types:

if a isa float {
  // ...
}

---------------------------

http://docs.tart.googlecode.com/hg/intro/annotations.html

Attributes can take arguments, as in the case of the  Extern attribute, which
allows you to declare an external reference to a C-language function. The
argument to  Extern allows you to specify the linkage name of the external
function:

 Extern("create_String")
def createString(length:int) -> String;


Although the standard library defines many different attribute types, in
practice there are only a few that you will encounter on a regular basis:

    Attribute 	Meaning
    EntryPoint 	Marks the entry point of a program
    Extern 	Indicates a definition external to the current module
    Flags 	Used to create a flags enumeration
    Reflect 	Tells the compiler to emit detailed reflection information.
    ThreadLocal 	Indicates a thread-local variable.
    

Different attribute types have different rules for propagating. There are three
main modes of propagation:

        Subtype propagation - attributes from a base class are copied to any
subclasses.
        Member propagation - attributes from a class are copied to the members
of the class.
        Caller propagation - attributes on a function are propagated to the
functions’s caller.

The last type is useful for implementing effect attributes. For example, you
could define a  Throws attribute which propagates to any callers:

// Any function that calls 'lookup' will also get a  Throws attribute.
 Throws(ArrayBoundsException)
def lookup(index:int) {
  return table[index];
}

Attributes also have a retention property, which says whether or not the
attribute should be retained in the final executable. There are various APIs
available for discovering at runtime what attributes are associated with a
particular function or variable.

---------------------------

http://docs.tart.googlecode.com/hg/intro/reflection.html

The  Reflect Attribute

The compiler can generate a set of reflection tables that contains all of the
information about a classes methods, properties, fields, and so on. However,
this information can be quite large, especially when dealing with templates
(each unique template instantiation gets its own copy of the reflection
tables.) Because of this, the default behavior for the compiler is to only
generate minimal information for the class - that is, information about the
name, base classes, and type parameters. Information about the methods,
properties, fields, and other class members is not generated unless you
specifically ask for it.

You can tell the compiler to generate the more detailed information by adding
the  Reflect attribute to the class:

 Reflect class SomeClass {
  // All class members will be reflected.
}

This annotation is inheritable, meaning that it applies to all subclasses as
well.

Because of this, you need to plan ahead when using reflection.

---------------------------

http://docs.tart.googlecode.com/hg/intro/collections.html

Generator expressions and comprehensions

Tart supports “generator expressions” similar to those found in Python. A
generator expression produces an iterator, which can be passed directly to the
from() method of a collection:

let s0 = ImmutableSet[int].from(x * x for x in 0 .. 10);

The initializer-list syntax is also supported, as is the map key/value operator:

let s0:ImmutableSet[int] = {x * x for x in 0 .. 10};
let m0:ImmutableMap[int, int] = {x -> x * x for x in 0 .. 10};

Sequence Unpacking

Tart supports a Python-like ability to unpack variables from a sequence:

let a, b = [1, 2];
let a:int, b:int = [1, 2];

The last variable in the unpacking assignment can be a variadic argument,
meaning it scoops up all the remaining values:

let a:int, b:int... = [1, 2, 3, 4];

As with function arguments, the ‘...’ syntax changes the type of the argument
into an array of the explicitly declared type. So the type of b is actually
int[], and would in the above example be assigned the value [2, 3, 4].

Variable unpacking works with regular assignment as well, allowing for the
Python ‘swap idiom’ to exchange the values of two variables:

a, b = b, a;

The sequence-unpacking syntax is what allows you to return multiple values from
a function:

def returnStringAndInt() -> (String, int) {
  return "Hello", 12;
}

let a:String, b:int = returnStringAndInt();

---------------------------

http://docs.tart.googlecode.com/hg/intro/macros.html

Tart macros are functions which execute in the compiler rather than at runtime.
They are introduced with the macro keyword:

macro MyMacro(t:Type) -> Type {
  // ...
}

One thing that is interesting about macros is that the arguments are not
evaluated before calling the macro. In other words, when you call a macro with
an argument of “1 + 2”, it does not pass the value “3”, but rather the
unevaluated expression “1 + 2” (technically what gets passed is an AST
fragment.) These expressions will be substituted inline in the body of the
macro. This means that you can control how many times (if at all) the
expression and its associated side effects are evaluated.

There are a number of built-in functions that give you access to the attributes
of the AST. For example, stringify() converts an AST node into its string
representation. This is used by the assert macro, which is another part of the
Tart core library:

macro assert[%T](expression:T) {
  if not expression {
    throw AssertionError(stringify(expression));
  }
}

---------------------------

http://docs.tart.googlecode.com/hg/intro/templates.html

Template guard conditions

A guard condition is an additional restriction on the kind of value that can be
bound to a template. For example, suppose we wanted a template parameter to
only bind to subclasses of “Node”, so we define a restriction using the
subclass test operator <::

class Visitor[%T require %T <: Node] { /* ... */ }

Bye,
bearophile
Sep 14 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/15/2011 03:14 AM, bearophile wrote:
 Docs of Tart, a future system language:
 http://docs.tart.googlecode.com/hg/intro/index.html

 It looks very similar to D, with few idioms turned into nice syntax. It's in
early stage of development.

 The following are quotations from the docs, I have selected some nice ideas.

 ---------------------------

 http://docs.tart.googlecode.com/hg/intro/types.html

  Flags enum Traits {
    ABSTRACT,
    FINAL,
    STATIC,

    MASK = ABSTRACT | FINAL | STATIC,
 }

 var x = Traits.ABSTRACT | Traits.FINAL;

 The presence of the  Flags annotation causes a number of things to happen:

          The default sequence of initialization values is 1, 2, 4, 8, and so
on, rather than 0, 1, 2, 3, etc. In other words, any enumeration constant that
does not have an explicit initialization expression will be assigned the next
available bit number after the previous value.
          The compiler will auto-generate the bitwise operators | and&  for
that type.
          The compiler will also auto-generate the contains() method, which
allows the use of the in operator, enabling expressions such as if ABSTRACT in
traits.
          In the current version of Tart, the toString() method is not defined
on flag enums.

 Note

 Tart enumerations do not support Java’s ability to add arbitrary properties to
enums.

 ---------------------------
Nice.
 Property Declarations

 The def keyword can also be used to define a property. Properties are like
variables, except that they are implemented using functions. Whenever you
attempt to read from the property, the property’s get function will be invoked,
and when you attempt to modify the value, the set function will be called.:

 def myProp:int {
    get { return p; }
    set (value) { p = value; }
 }

 myProp = 1;   // Calls "myProp.set(1)"
imho D's way is superior because it does not waste the set and get keywords.
 ---------------------------

 http://docs.tart.googlecode.com/hg/intro/functions.html

 Like Python, parameters can be referred to by name as well as position:

 print("Hello, World!\n", padding="");

 Any parameter can be referred to by its keyword name. The normal mapping of
arguments to formal parameters is that positional arguments are assigned first,
in order, and then any keyword arguments are assigned to any remaining unfilled
parameters.

 Sometimes it is useful to specify a parameter that is “keyword only” meaning
that it can only be specified via keyword instead of positionally. A semicolon
can be used to segregate regular positional parameters from keyword-only
parameters:

 def print (format:String; npos:int=0, sep=false);

 print("Hello world!", npos=1); // OK
 print("Hello world!", 1); // ERROR - too many positional arguments

 In the above example, only the format argument will be filled in by positional
argument - to have additional positional arguments in this case would be an
error.
Nice.
 ---------------------------

 http://docs.tart.googlecode.com/hg/intro/classes.html

 A protocol represents a contract which a type may conform to. A class or
struct is said to support the protocol if that class or struct defines all of
the method signatures that are defined by the protocol. Template arguments can
be constrained to only match types which support a specified protocol. Classes
may declare explicitly that they support a protocol, or the support can be
determined implicitly.

 A protocol is a kind of abstract type that defines a contract which another
type can support. An example would be a “HasToString” protocol:

 protocol HasToString {
    def toString ->  String;
 }
I like this a lot.
 ---------------------------

 The extend keyword allows you to add additional methods to a user-defined type:

 /* Add an additional method to the String class. */
 extend String {
    static def toUpperCase() { /* ... */ }
 }

 Note however, that you can’t actually change the runtime representation of a
type this way. The reason is simple: The extend declaration may not be visible
everywhere in the program. If you extend class String, some modules may only
see the original, unextended class, while other modules will see the extended
version of the class. In order for all of the code to interoperate, the runtime
implementation of the class must be the same, regardless of the extension.

 This means that the extension can only add certain kinds of things to a type,
namely:

      Static methods or properties.
      Final methods or properties.
      Inner types and type aliases.
      Protocol inheritance declarations.

 Extensions follow the same scoping rules as other declarations, meaning that
they are only in effect if the scope in which they are declared is active.
ok.
 ---------------------------

 Sometimes you need to test the type of a variable, the isa keyword can be used
for this. It works for both reference types and union types:

 if a isa float {
    // ...
 }
[snip.]
I like the typesafe approach to unions. Is 'a' typed as a float in the if body?
 http://docs.tart.googlecode.com/hg/intro/collections.html

 Generator expressions and comprehensions

 Tart supports “generator expressions” similar to those found in Python. A
generator expression produces an iterator, which can be passed directly to the
from() method of a collection:

 let s0 = ImmutableSet[int].from(x * x for x in 0 .. 10);

 The initializer-list syntax is also supported, as is the map key/value
operator:

 let s0:ImmutableSet[int] = {x * x for x in 0 .. 10};
 let m0:ImmutableMap[int, int] = {x ->  x * x for x in 0 .. 10};
Nice.
 Sequence Unpacking

 Tart supports a Python-like ability to unpack variables from a sequence:

 let a, b = [1, 2];
 let a:int, b:int = [1, 2];

 The last variable in the unpacking assignment can be a variadic argument,
meaning it scoops up all the remaining values:

 let a:int, b:int... = [1, 2, 3, 4];

 As with function arguments, the ‘...’ syntax changes the type of the argument
into an array of the explicitly declared type. So the type of b is actually
int[], and would in the above example be assigned the value [2, 3, 4].

 Variable unpacking works with regular assignment as well, allowing for the
Python ‘swap idiom’ to exchange the values of two variables:

 a, b = b, a;

 The sequence-unpacking syntax is what allows you to return multiple values
from a function:

 def returnStringAndInt() ->  (String, int) {
    return "Hello", 12;
 }

 let a:String, b:int = returnStringAndInt();
Nice.
 ---------------------------

 http://docs.tart.googlecode.com/hg/intro/macros.html

 Tart macros are functions which execute in the compiler rather than at
runtime. They are introduced with the macro keyword:

 macro MyMacro(t:Type) ->  Type {
    // ...
 }

 One thing that is interesting about macros is that the arguments are not
evaluated before calling the macro. In other words, when you call a macro with
an argument of “1 + 2”, it does not pass the value “3”, but rather the
unevaluated expression “1 + 2” (technically what gets passed is an AST
fragment.) These expressions will be substituted inline in the body of the
macro. This means that you can control how many times (if at all) the
expression and its associated side effects are evaluated.

 There are a number of built-in functions that give you access to the
attributes of the AST. For example, stringify() converts an AST node into its
string representation. This is used by the assert macro, which is another part
of the Tart core library:

 macro assert[%T](expression:T) {
    if not expression {
      throw AssertionError(stringify(expression));
    }
 }
That is not 'a function that executes in the compiler', that is an AST macro.
 ---------------------------

 http://docs.tart.googlecode.com/hg/intro/templates.html

 Template guard conditions

 A guard condition is an additional restriction on the kind of value that can
be bound to a template. For example, suppose we wanted a template parameter to
only bind to subclasses of “Node”, so we define a restriction using the
subclass test operator<::

 class Visitor[%T require %T<: Node] { /* ... */ }
The “require” clause must come after all of the template arguments: class Visitor[%A, %B require %A <: %B] { /* ... */ } The spec is not clear on whether or not class Foo[%A <: InputRange, %B <: OutputRange] works. (class Foo[%A <: InputRange] does work.) // while loop, showing a test expression that also declares a variable. while let m = re.match(str) { console.stdout.writeLn(m.group(1)); } *clap, clap, clap* No ctfe. No string mixins. D wins. I think something like the protocol feature might be a worthy addition, considering the fact that implicit static interfaces are an integral part of D programming.
Sep 14 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 Is 'a' typed as a float in the if body?
I don't think so (with the current design). Bye, bearophile
Sep 15 2011
prev sibling parent reply Jimmy Cao <jcao219 gmail.com> writes:
On Wed, Sep 14, 2011 at 9:34 PM, Timon Gehr <timon.gehr gmx.ch> wrote:

 No ctfe. No string mixins. D wins.
It has macros though: http://docs.tart.googlecode.com/hg/intro/macros.html
Sep 15 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/15/2011 02:18 PM, Jimmy Cao wrote:
 On Wed, Sep 14, 2011 at 9:34 PM, Timon Gehr <timon.gehr gmx.ch
 <mailto:timon.gehr gmx.ch>> wrote:


     No ctfe. No string mixins. D wins.


 It has macros though:

 http://docs.tart.googlecode.com/hg/intro/macros.html
Yah, I kinda like those. They'd be especially useful in combination with ctfe and string mixins. D has the macro keyword. All that is missing is a good design for it...
Sep 15 2011
prev sibling next sibling parent "Marco Leise" <Marco.Leise gmx.de> writes:
Am 15.09.2011, 03:14 Uhr, schrieb bearophile <bearophileHUGS lycos.com>:=


 Docs of Tart, a future system language:
 http://docs.tart.googlecode.com/hg/intro/index.html

 It looks very similar to D, with few idioms turned into nice syntax.  =
 It's in early stage of development.

 The following are quotations from the docs, I have selected some nice =
=
 ideas.

 ---------------------------

 http://docs.tart.googlecode.com/hg/intro/types.html

  Flags enum Traits {
   ABSTRACT,
   FINAL,
   STATIC,

   MASK =3D ABSTRACT | FINAL | STATIC,
 }

 var x =3D Traits.ABSTRACT | Traits.FINAL;

 The presence of the  Flags annotation causes a number of things to  =
 happen:

         The default sequence of initialization values is 1, 2, 4, 8, a=
nd =
 so on, rather than 0, 1, 2, 3, etc. In other words, any enumeration  =
 constant that does not have an explicit initialization expression will=
=
 be assigned the next available bit number after the previous value.
         The compiler will auto-generate the bitwise operators | and & =
=
 for that type.
         The compiler will also auto-generate the contains() method,  =
 which allows the use of the in operator, enabling expressions such as =
if =
 ABSTRACT in traits.
         In the current version of Tart, the toString() method is not  =
 defined on flag enums.

 Note

 Tart enumerations do not support Java=E2=80=99s ability to add arbitra=
ry =
 properties to enums.
In Delphi, you don't Flag the enum itself, but declare a 'set' of the = enum type for which all basic set operators are defined. 'does a contain= = all of b', 'is x in a' and so on. The enum values are converted to bit = positions in the set by the compiler. The Tard way looks inspired by tha= t. = Anyway it is a nice feature, looks clean, saves typing and documents the= = use of the enum. You can still add explicit constants if required.
 Property Declarations

 The def keyword can also be used to define a property. Properties are =
=
 like variables, except that they are implemented using functions.  =
 Whenever you attempt to read from the property, the property=E2=80=99s=
get =
 function will be invoked, and when you attempt to modify the value, th=
e =
 set function will be called.:

 def myProp:int {
   get { return p; }
   set (value) { p =3D value; }
 }

 myProp =3D 1;   // Calls "myProp.set(1)"
 http://docs.tart.googlecode.com/hg/intro/functions.html

 Like Python, parameters can be referred to by name as well as position=
:
 print("Hello, World!\n", padding=3D"");

 Any parameter can be referred to by its keyword name. The normal mappi=
ng =
 of arguments to formal parameters is that positional arguments are  =
 assigned first, in order, and then any keyword arguments are assigned =
to =
 any remaining unfilled parameters.

 Sometimes it is useful to specify a parameter that is =E2=80=9Ckeyword=
only=E2=80=9D =
 meaning that it can only be specified via keyword instead of  =
 positionally. A semicolon can be used to segregate regular positional =
=
 parameters from keyword-only parameters:

 def print (format:String; npos:int=3D0, sep=3Dfalse);

 print("Hello world!", npos=3D1); // OK
 print("Hello world!", 1); // ERROR - too many positional arguments

 In the above example, only the format argument will be filled in by  =
 positional argument - to have additional positional arguments in this =
=
 case would be an error.
It may help understanding code that uses 'those seldom used 5th paramete= r' = if you had to refer to it by name. Especially in cases where you have lo= ts = of "false, 0, null" and you wonder if these would have been the default = = values and if not, what they do.
 http://docs.tart.googlecode.com/hg/intro/classes.html

 A protocol represents a contract which a type may conform to. A class =
or =
 struct is said to support the protocol if that class or struct defines=
=
 all of the method signatures that are defined by the protocol. Templat=
e =
 arguments can be constrained to only match types which support a  =
 specified protocol. Classes may declare explicitly that they support a=
=
 protocol, or the support can be determined implicitly.

 A protocol is a kind of abstract type that defines a contract which  =
 another type can support. An example would be a =E2=80=9CHasToString=E2=
=80=9D protocol:
 protocol HasToString {
   def toString -> String;
 }
Do I understand that right? They renamed interface to protocol? :) Well, in C++ at least where a struct can implement interfaces that would= = be the case. Structs are different creatures in D and the decision was = made to use implicit interfaces. There is a bit more to the story I thin= k. = Personally I like explicit interfaces and use them where possible.
 The extend keyword allows you to add additional methods to a  =
 user-defined type:

 /* Add an additional method to the String class. */
 extend String {
   static def toUpperCase() { /* ... */ }
 }

 Note however, that you can=E2=80=99t actually change the runtime repre=
sentation =
 of a type this way. The reason is simple: The extend declaration may n=
ot =
 be visible everywhere in the program. If you extend class String, some=
=
 modules may only see the original, unextended class, while other modul=
es =
 will see the extended version of the class. In order for all of the co=
de =
 to interoperate, the runtime implementation of the class must be the  =
 same, regardless of the extension.

 This means that the extension can only add certain kinds of things to =
a =
 type, namely:

     Static methods or properties.
     Final methods or properties.
     Inner types and type aliases.
     Protocol inheritance declarations.

 Extensions follow the same scoping rules as other declarations, meanin=
g =
 that they are only in effect if the scope in which they are declared i=
s =
 active.
C++ friend functions, JavaScript and universal calls in D come to my min= d. = Protocol inheritance should solve itself in D with implicit interfaces. = = *Did I just say something pro implicit interfaces?* Maybe if I want to a= dd = a helper function to someone else's API within my code this feature come= s = handy. An example might be a curl wrapper that lacks a simple download U= RL = method that supports any protocol.
 Sometimes you need to test the type of a variable, the isa keyword can=
=
 be used for this. It works for both reference types and union types:

 if a isa float {
   // ...
 }
Many OOP languages only support this for classes, but D also has is(a : = b). I'll make a cut here. You are right, another C++ replacement project is = a = good source for inspiration.
Sep 15 2011
prev sibling parent reply renoX <renozyx gmail.com> writes:
Thanks for the link and short description of the Tart language.

Some remarks from the short description:
- the  Flags enum is nice, but the MASK field in the example needs to repeat
all the name of the enums which is a case of DRY violation.
The lack of pretty printing of enums is a pet peeves of mine in several
languages, too bad that Tart is one of those.

- the possibility to separate the positional arguments from the keywords-only
arguments is nice too, I don't remember seeing this before.

Looking at the Tart syntax, it has still the int[10] C-like array declaration
(bleh!), but it has multiple return values (nice!).

I haven't found what happen in case of integer overflow or out of bound array
index though, I hope it does the right thing and throw an exception (come on:
*Ada* did it!!).

I hope it does the right thing and initialize by default ints and floats to zero
(Nan initialisation for D's float is a big mistake: even Andrei makes a mistake
about this in his book!).

BR.
Sep 16 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
renoX:

 The lack of pretty printing of enums is a pet peeves of mine in several
languages, too bad that Tart is one of those.
D isn't one of those any more, I presume :-)
 I haven't found what happen in case of integer overflow or out of bound array
index though, I hope it does the right thing and throw an exception (come on:
*Ada* did it!!).
I hope they will get this right. D looks hopeless on this.
 I hope it does the right thing and initialize by default ints and floats to
zero
 (Nan initialisation for D's float is a big mistake: even Andrei makes a
mistake about this in his book!).
The initialization of FP to NaN has caused me only two related troubles: - While porting to D a C program that assumed a global FP array to be initialized to zeros. - Binary super-inflation caused by a large global FP array (being initialized to NaN instead of zeros means the compiler puts all the NaNs in the binary. In this case I'd like a little routine to initialize the array to NaNs before the main). Having FP initialized to NaN is a bit less handy than having them initialized to 0.0 (most times a zero is more useful than a NaN), but in the D compiler initialize to a value that's poisonous and sticky like NaN, that allows you to find the initialization bug quickly. So unless D adds the refined logic similar Tart contains several good ideas. Bye, bearophile
Sep 16 2011
parent renoX <renozyx gmail.com> writes:
My issue with the initialization of float to NaN is that it is
inconsistent with integer initialization with zero.
Both are numbers, both should be treated as much as possible in the
same way: either both are initialized with an undefined value or both
should be initialized with zero.

It is a bad idea to define an undefined value for integers due to the
performance loss (which has only a very small increase in maintainability) so
it should be zero for both.

BR.
Sep 16 2011