Re: duck!

2010-10-19 Thread Simen kjaeraas

Andrei Alexandrescu  wrote:


I think it's best to concede and call the artifact "adapt".


Aww. I liked duck.

--
Simen


Re: [due diligence] std.xml

2010-10-19 Thread Simen kjaeraas

Michel Fortin  wrote:

If someone wants to proceed I'll extract the code from the rest of my  
code and release it under the boost license.


I'd love to give this a spin.

--
Simen


Re: [due diligence] std.xml

2010-10-20 Thread Simen kjaeraas

Michel Fortin  wrote:

On 2010-10-19 21:31:04 -0400, Michel Fortin   
said:


On 2010-10-19 19:28:18 -0400, "Simen kjaeraas"   
said:



Michel Fortin  wrote:

If someone wants to proceed I'll extract the code from the rest of  
my  code and release it under the boost license.

 I'd love to give this a spin.

 Great. I'll post that code tomorrow.


Not yet tomorrow, but it's ready. Have fun.
<http://michelf.com/docs/d/mfr-xml-2010-10-19.zip>

I've included some notes in the archive about what each module do and  
what's missing. Feel free to ask if you have questions.


Thank you. I'll have a look-see.


--
Simen


Re: [debate] About D's pretension for homoiconicicity

2010-10-21 Thread Simen kjaeraas

Justin Johansson  wrote:


The formal subject proposed for debate is
"D's advanced meta-programming capabilities essentially
makes it (D) as if it were a homoiconic language, and
brings with it all the advantages of homoiconic languages."


Hardly true. While it may be possible to Greenspun together
a hacky attempt at homoiconicity in D, Doing so would bring
but a few of the benefits compared to a language designed
from the beginning with homoiconicity in mind.

That said, some of the use cases for homoiconicity may be
covered by D's capabilities, and this may be closer to what
you intended by the above paragraph.

Certainly D does not allow one to execute arbitrary
strings as if they were D code (D does however allow the
execution of arbitrary strings). There certainly are ways
to do that, but such could be said for any language.

It would certainly be possible to create a system for
manipulating ASTs at compile time in D, be they generated
by library code or the compiler itself. Converting such
a representation to a mixin string should prove no big
challenge. However, even such a system would likely lack
the elegance of lisp's macros, and I find it unlikely it
would find much use. Another problem with this is that
it's useless at runtime, unless an interface to the
compiler is offered as a library for D. This has been
discussed numerous times, and I believe most on this list
agree it would a Good Thing™.

--
Simen


Re: The Next Big Language

2010-10-21 Thread Simen kjaeraas

Paulo Pinto  wrote:


Sorry but I still don't get it.

Do you mean that the types that erased and the same code is generated?

Then let me say that .Net generics get generated on the fly and JITed for
each
different type.

Eiffel and Modula-3 generics also have specific generated code for each
type.

The major difference regarding C++ code is that the linkers are smarter  
and

are
able to remove duplicates of the generated code for the same set of type
arguments.


The point is, D and C++ templates can do a lot more than simple generics.
Generics is limited to simple copying and pasting of type names, whereas
templates can build a DSL parser for you, let you choose whether a
function should be parallelized, a type thread-safe, etc.


--
Simen


Re: How to work with an "arbitrary input range"?

2010-10-21 Thread Simen kjaeraas

Adam D. Ruppe  wrote:

[snip]

Anyway, what's the right thing to do here?


I'd say:

void fun( T )( T t ) if ( isInputRange!T && is( ElementType!T == dchar ) )  
{}


--
Simen


Re: How to work with an "arbitrary input range"?

2010-10-21 Thread Simen kjaeraas

Jonathan M Davis  wrote:

void fun( T )( T t ) if ( isInputRange!T && is( ElementType!T == dchar  
) )

{}


Though I'd suggest using Unqual!(ElementType!T).


You're right, of course.


--
Simen


Re: Q: What are the rules for emitting template code?

2010-10-24 Thread Simen kjaeraas

Austin Hastings  wrote:


If Decider uses Option1.sizeof, does any Option1 code get emitted?


For sizeof to be known, the template would have to be instantiated, yes.


If Decider uses some external function that makes use of type aliases in  
Option1, (example:  Option1() { alias byte value_t; } ) does any Option1  
code get emitted?


Again, the same.


If Decider uses some function defined inside the same module with  
Option1, but NOT inside of Option1, does any/all of the Option1 code get  
emitted?


Accessing the surrounding scope would not instantiate Option1. So no.


If Decider uses a static method of Option1, does any more of the Option1  
code get emitted?


As with the first two, it would have to be instantiated.


Now, I have the feeling this is not really what you're asking for. What
do you mean by 'code gets emitted'? Perhaps you could give a reduced  
example?


--
Simen


Re: Improving std.range.Zip

2010-10-24 Thread Simen kjaeraas
On Sun, 24 Oct 2010 21:39:24 +0200, bearophile   
wrote:



Tomek S.:

map!((a) {return myNaryFun(a._0, a._1, ...); })(zip(range1, range2,  
...));


Currently the docs of std.algorithm.map say:

Multiple functions can be passed to map. In that case, the element type  
of map  is a tuple containing one element for each function.<


But lot of time ago I have said that in my opinion that's not the best  
design. Python has a different design, its map does what you want, you  
may write your code in Python as:


map(myNaryFun, range1, range2, ...)

An example (Python 2.6):


a = ["a", "b", "c", "d"]
b = [1, 2, 3, 4]
map(lambda c,n: c * n, a, b)

['a', 'bb', 'ccc', '']

Is is possible to change the std.algorithm.map to a semantics similar to  
the Python one, that I think is more useful?


From what I can see, map currently simply doesn't support passing it
multiple ranges. It would be a trivial change to let it support multiple
ranges in addition to multiple functions.


--
Simen


Re: Simulating Multiple Inheritance

2010-10-28 Thread Simen kjaeraas

dsimcha  wrote:

I've just found a new D-specific design pattern for simulating  
non-virtual
multiple inheritance by abusing inner classes and alias this.  Here's an  
example:


class Foo {
uint num = 2;
}

class Bar {
uint num = 3;
}

class Outer : Foo {

class Inner : Bar {}

Inner inner;

this() {
inner = new Inner;
}

alias inner this;
}


I believe this is mentioned in TDPL.

--
Simen


Re: Simulating Multiple Inheritance

2010-10-28 Thread Simen kjaeraas

Jimmy Cao  wrote:


Well, you can't have multiple alias this's right?

So then, wouldn't it still only limit to 2 base classes?


It is extensible like this:

class Outer : Foo {
class Inner : Bar {
class InnerInner : Baz {
}

InnerInner innerInner;

this() {
innerInner = new InnerInner;
}

alias innerInner this;
}

Inner inner;

this() {
inner = new Inner;
}

alias inner this;
}

It should be possible to turn this into a mixin.


--
Simen


Re: Simulating Multiple Inheritance

2010-10-28 Thread Simen kjaeraas

Simen kjaeraas  wrote:


It should be possible to turn this into a mixin.


Problem is of course, no reliable way to hijack
constructors to initialize the inner class.

--
Simen


Re: GCC 4.6

2010-10-31 Thread Simen kjaeraas

Nick Sabalausky  wrote:


I can certainly understand the impossibility of actually keeping up with
bearophile, but I don't think that even he expects that every idea he  
brings

up be rushed into D.


Yeah, I always see bearophile's lists as 'maybe some of this could fit in
D at some point'. Well worth having on the list, but not to be regarded as
The Bearer of Absolute Commandments. That said, I fully understand that
Walter could get more tired of it than do I - I don't feel the pressure.

--
Simen


Re: Ruling out arbitrary cost copy construction?

2010-10-31 Thread Simen kjaeraas

Andrei Alexandrescu  wrote:

Walter and I discussed the matter again today and we're on the brink of  
deciding that cheap copy construction is to be assumed. This simplifies  
the language and the library a great deal, and makes it perfectly good  
for 95% of the cases. For a minority of types, code would need to go  
through extra hoops (e.g. COW, refcounting) to be compliant.


I'm looking for more feedback from the larger D community. This is a  
very important decision that marks one of the largest departures from  
the C++ style. Taking the wrong turn here could alienate many  
programmers coming from C++.


So, everybody - this is really the time to speak up or forever be silent.


I am almost certain you're doing the right thing by assuming cheap copy
construction, but I have no good arguments to back me up. Hence my holding
my breath and waiting, thus far.

--
Simen


Re: The Expressiveness of D

2010-11-02 Thread Simen kjaeraas

]Gary Whatmore  wrote:


The D way of returning tuples is:

  T!(int,int) ret;
  auto f = (ref T!(int,int) r){ r = e; };
  f(ret);


D also has better tuples in std.typecons.

auto t1 = tuple( 1,2 );
auto t2 = { return t1; }

--
Simen


Re: The Expressiveness of D

2010-11-02 Thread Simen kjaeraas

%u  wrote:


class A {}
class B : A {}
class C : A {}

template T(A...) { alias A T; }

void main() {
  auto a = true ? new B : new C;
// these don't work - why?
//  auto b = [new B, new C];
//  auto c = { return [1: new B,2: new C]; };


"The type of the first element is taken to be the type of all the
elements, and all elements are implicitly converted to that type."
(http://digitalmars.com/d/2.0/expression.html#ArrayLiteral)

I believe it has been discussed numerous times before that the ?:
test should be used to find the element type - not sure why it
isn't.



  T!(int,int) e = (1,2);
  e = T!(3,4);

// ah - so (1,2) syntax on initialization, T!(1,2) when assigning!
  T!(int,int) d = T!(1,2);

  e = d;

// tuples aren't first class, why?
//  auto f = { return e; };
}


Compile-time argument tuples are something of a strange beast. They
behave not very unlike tuples, but due to their ability to hold
types, literals, expressions and aliases to whatever, they are not
a very good match for what you'd expect tuples to be. (e.g, what do
you expect T!(3,T) to be?)

For tuples, you should instead look into std.typecons' Tuple struct
and tuple function:

Tuple!( int, "n", string, "s" ) tup;
tup.n = 4;
tup.s = "A string! My kingdom for a string!";

auto tup2 = tuple( 1, 2 );
assert( is( typeof( tup2 ) == Tuple!( int, int ) ) );


For even better support of tuples, you should have a look-see at
Philippe Sigaud's dranges.tuple and dranges.reftuple
(http://svn.dsource.org/projects/dranges/trunk/dranges/docs/tuple.html
and  
http://svn.dsource.org/projects/dranges/trunk/dranges/docs/reftuple.html)


The latter is absolutely awesome, and should be made part of
phobos ASAP, IMO (though according to the documentation, it
is not in tip-top shape).

Examples from the reftuple page:


int a, b;
_(a,b) = tuple(b,a); // swap
_(a,b) = tuple(b,a+b); // fibonacci

int[] arr = [0,1,2,3,4];
int [] c;
_(a,b,c) = arr; // a = 0, b = 1, c = [2,3,4]



--
Simen


Re: The Expressiveness of D

2010-11-02 Thread Simen kjaeraas

Andrei Alexandrescu  wrote:


I believe it has been discussed numerous times before that the ?:
test should be used to find the element type - not sure why it
isn't.


Looks like outdated documentation to me.


Well, it certainly doesn't behave as it should, if %u's post is
anything to go by. (and my testing of the same issue - it's not
just %u) Filed as 5156.


This was already contributed to in Phobos (under a different syntax) but  
I rejected it on grounds of safety: the value built by "_" must escape  
addresses of all of its arguments, so it's not safe.


True. Bummer. Hm, now, the intent of _ is that the constructed type should
exist only as a temporary, I believe.

Maybe it is possible to do this in a safer way. I actually have a solution,
which I have posted here before, and I feel might be worthy of an
enhancement request: that templates may be used as pseudo-types, in that a
operator overloading should be allowed on non-type template instances:



import std.typecons;
import std.typetuple;
import dranges.templates;
import dranges.typetuple;

template _( T... ) if ( allSatisfy!( isAlias, T ) ) {
Tuple!( StaticMap!( TypeOf, T ) ) opAssign( Tuple!( StaticMap!(  
TypeOf, T ) ) args ) {

foreach ( i, e; T ) {
e = args[i];
}
return args;
}
}


unittest {
int a = 1; b = 1;
_!( a, b ) = tuple( b, a+b ); // Equivalent to _!( a, b ).opAssign( b,  
a+b );

}

Sadly, this currently does not work, not just due to the aforementioned
limitation, but also because the reassigned values are discarded as the
function returns. This latter part is confusing me. Is this intended
behavior?

A different solution might be @ephemeral, marking types that are not
supposed to be stored anywhere, and statically disallowing their use
as variables.


My suggestion to address this issue was (and is) to make the assigned  
part of the function call:


int a, b;
scatter(tuple(b, a), a, b);
scatter(tuple(b, a + b), a, b);
int[] arr = [0, 1, 2, 3, 4];
int[] c;
scatter(arr, a, b, c);


That certainly works, but it is not as prettiful or straightforward.


--
Simen


Re: The Expressiveness of D

2010-11-02 Thread Simen kjaeraas

Lutger  wrote:

It is stated in TDPL that the ?: test should be used, and it already  
works:


auto a = [1,2,3.5];
pragma(msg, typeof(a).stringof); // prints double[], not int[]


So it works for things that are not classes, then. That, to me, counts
as 'does not work correctly'. Filed as 5156.


--
Simen


Re: The Expressiveness of D

2010-11-02 Thread Simen kjaeraas

Simen kjaeraas  wrote:


Sadly, this currently does not work, not just due to the aforementioned
limitation, but also because the reassigned values are discarded as the
function returns. This latter part is confusing me. Is this intended
behavior?


Curiouser: T[i] = args[i]; works.


--
Simen


Re: @disable on override function

2010-11-05 Thread Simen kjaeraas

Jesse Phillips  wrote:

Should the compiler not compile the class saying something to the effect  
of:

Can not disable method hello in base class A from B.


I think this is the best solution.
"Cannot @disable overriding functions", I'd say.

--
Simen


Re: Spec#, nullables and more

2010-11-05 Thread Simen kjaeraas

Walter Bright  wrote:


Adam D. Ruppe wrote:

A non-nullable type is basically just:
 struct NotNull(T) {
   T _payload;
   alias _payload this;
   invariant() {
   assert(_payload !is null);
   }
}
 If we could disable the default constructor, this approach might just  
work. Sure,
the checks here would be at runtime, but you'd have them without having  
to

manually write the assert each time.


All that does is reinvent the null pointer seg fault. The hardware does  
this for you for free.


A null pointer is what's known as a "white hole", all attempts to access  
the object are rejected.


I believe you managed to miss the important part, "If we could disable the
default constructor". The invariant here is not about using the NotNull!T,
but for when you assign to it. In other words:

struct NotNull( T ) if ( is( T == class ) || isPointer!T ) {
private T _payload;
alias _payload this;
this( T data ) {
assert( data !is null );
_payload = data;
}
@disable this( );
@disable void opAssign( T );
}

NotNull!T notNull( T )( T ptr ) {
return NotNull!T( ptr );
}

It might not cover all bases, but the idea is it is impossible to create a
NotNull!T from a null T, and impossible to assign a null T to one.

--
Simen


Re: Spec#, nullables and more

2010-11-06 Thread Simen kjaeraas

Walter Bright  wrote:


Consider non-nullable type T:

   T[] a = new T[4];


As others have pointed out, this would be impossible for a proper
non-nullable type. The only ways to create an array of non-nullable
elements would be a literal, concatenation with non-nullable elements,
or casting an existing array of nullable elements.

You do not have write access to the length of an array of non-nullable
elements, so that you cannot increase the length (thus adding null
elements). You can decrease the length by slicing.

This way, it should be impossible to have elements of our array that are
null.

--
Simen


Re: Spec#, nullables and more

2010-11-06 Thread Simen kjaeraas

Walter Bright  wrote:


Adam D. Ruppe wrote:
It wasn't until I added the invariant and in/out contracts to all the  
functions

asserting about null that the problem's true cause became apparent.


Couldn't this happen to you with any datum that has an unexpected value  
in it?


Yes. And by augmenting the type system (such as with non-nullable
pointers or bounded integers), such a mistake could be caught early,
likely at compile time, because the bounded type or non-null pointer does
not allow assignment from arbitrary pointers or values.


Suppose, for example, you are appending the numbers 1..5 to the array,  
and somehow appended a 17. Many moons later, something crashes because  
the 17 was out of range.


Bounded!(int, 1, 5)[] myArr;
myArr ~= 1; // Compile-time error: int is not implicitly castable to  
Bounded!(int, 1, 5)

myArr ~= Bounded!(int, 1, 5)( 1 ); // Works perfectly


--
Simen


Re: Spec#, nullables and more

2010-11-06 Thread Simen kjaeraas

bearophile  wrote:


Simen kjaeraas:


Bounded!(int, 1, 5)[] myArr;
myArr ~= 1; // Compile-time error: int is not implicitly castable to
Bounded!(int, 1, 5)
myArr ~= Bounded!(int, 1, 5)( 1 ); // Works perfectly


I can't say this is a nice syntax :-)
(Isn't the implicit conversion + bound test better?)


Not sure. This way is more explicit, and errors will be caught at
compile-time.

--
Simen


Re: Spec#, nullables and more

2010-11-06 Thread Simen kjaeraas

bearophile  wrote:


Simen kjaeraas:


Not sure. This way is more explicit, and errors will be caught at
compile-time.


I see. But if a syntax is ugly and too much heavy, people (rightly)  
don't use it... (This is why bounded values are good as builtins).


Of course. Now, aliases help a bit here, turning that into something
like:

alias Bounded!(int, 1, 5) myInt;

myInt[] myArr;
myArr ~= myInt( 1 );


I believe using an alias would be a good idea in most such cases, as
one's bound to write Bounded!(int,1,6) in a long program, and
wonder why it doesn't compile.

--
Simen


Re: Spec#, nullables and more

2010-11-06 Thread Simen kjaeraas

Simen kjaeraas  wrote:


bearophile  wrote:


Simen kjaeraas:


Not sure. This way is more explicit, and errors will be caught at
compile-time.


I see. But if a syntax is ugly and too much heavy, people (rightly)  
don't use it... (This is why bounded values are good as builtins).


Of course. Now, aliases help a bit here, turning that into something
like:

alias Bounded!(int, 1, 5) myInt;

myInt[] myArr;
myArr ~= myInt( 1 );


I believe using an alias would be a good idea in most such cases, as
one's bound to write Bounded!(int,1,6) in a long program, and
wonder why it doesn't compile.


Worth adding too: myInt(648492) is of course not catchable at compile
time, while such would be easy with builtin bounded integers.


--
Simen


Re: null [re: spec#]

2010-11-06 Thread Simen kjaeraas

steveh  wrote:

I've known there are hidden tradeoffs when using these 'intelligent'  
types. Non-null types add terrible runtime checks everywhere. It's  
simply not acceptable in a systems programming language. Operating  
system kernel uses very efficient uninitialized arrays for buffers. It's  
crazy to force this non-null hype down our throats.


And here you are sorely mistaken. The point of non-nullable types is the
exact opposite. In fact, the only time you need a runtime check is when
converting a nullable type to a non-nullable - after that, it's guaranteed
not to be null. When in addition there is no way to create a non-nullable
variable without initializing it (and possibly checking that the
initializing value is not null, if it comes from a nullable source),
the result is a great decrease in runtime checks, not an increase.


--
Simen


Re: Should pure functions be prevented from reading changeable immutable static variables?

2010-11-06 Thread Simen kjaeraas

Don  wrote:


Pure functions are allowed to read immutable global variables.
Currently, this even includes globals which are initialized from inside  
'static this()'.

Here's an example of how this can be a problem:

immutable int unstable;

pure int buggy() { return unstable; }

static this() {
 // fails even though buggy is pure
 assert( buggy() == ( ++unstable , buggy() ) );
}

I suspect that such functions should be forbidden from being 'pure'.
Note that they cannot be used in CTFE (conceptually, all other @safe  
pure functions could be used in CTFE, even though the current  
implementation doesn't always allow it).


The motivation for wanting to ban them is to prevent the optimiser from  
generating bad code. But if they were disallowed, there would also be  
benefits for breaking circular module dependencies:

* if module A imports only pure functions from module B,
we know that the static this() of A does not directly depend on the  
static this() of module B.

(Note though it might still depend on C, which depends on B).
* if the static this() of module A only calls pure functions, it does  
not depend on the static this() of any other module.


Probably, this would only avoid the most trivial circular module  
dependencies, so not a huge win, but still a nice bonus.


This feels a bit wrong to me - the only time when that needs to be
disallowed is in static constructors, so it seems like an edge case.

As you say, there are benefits to this solution, but I'm not sure they
outweigh the disadvantages. It all comes down to a case of 'I feel' vs.
'you feel', though.

--
Simen


Re: Spec#, nullables and more

2010-11-06 Thread Simen kjaeraas

Gary Whatmore  wrote:


non-nulls don't solve basic problems like arrays, basic collections in
the library (custom fill policy).


As I've posted elsewhere, arrays (and other collections) will have to
work slightly differently for non-nullable elements:

1 .length is read-only (or read/decrease only)
2 Length can be increased by concatenation only
3 Can only be created with a nonzero length with a runtime check of a
  nullable-element array/collection, or as a literal containing only
  non-nullable elements.

And yes, there may be cases where this is not good enough, and you need
to have nullable elements. That does not mean non-nullable types are
borked by default, you just use nullable elements, and accept that you
have to work harder to prevent segfaults. In many cases, rule #3 will
allow you to create your collection using nullable elements, and casting
it to non-nullable afterwards.


Can't force me to read. I've made my choice of using D already. Nothing  
will change that.


He's not trying to make you change language, but to inform you of how
other languages have solved the problem.

--
Simen


Re: Spec#, nullables and more

2010-11-06 Thread Simen kjaeraas

tls  wrote:


I never seen segfault in practice. Have you?


Have you ever touched a computer? I see segfaults about daily. In my own
code, not that often.


--
Simen


Re: Spec#, nullables and more

2010-11-06 Thread Simen kjaeraas

Walter Bright  wrote:

I don't see that non-null is such a special case that it would benefit  
from a special case syntax. For example:


There are some things that set non-null apart:

1. Few operations change the value of a pointer/class reference:
   assignment
   pointer arithmetic
   ref passing
Of these, the last two can be disallowed in most cases. For e.g. an
int, operator overloading adds bunches of more cases, and for structs/
classes where fields factor into the calculation, every single public
member function and field would need to be wrapped. Simply put, null
pointers are low-hanging fruit.

2. There is a single invalid value
This is a simplification, of course, as you could argue that a reference
to an A is not a valid reference to a B, and pointers may point to
arbitrary areas of memory, where nothing of interest may be found.
Again, low-hanging fruit.


The value 25 requires far more context for the compiler to identify it  
as a bad value and determine how the developer should handle it.


The compiler wouldn't do it. It would be a user supplied filter for a  
user defined subtype.


Definitely a possibility, also for non-nullable. However, for such a
system to be foolproof (and that's what we want), we need a way to
disable the default constructor for structs.

There is also the problem of arrays, as I expounded on in a different
post. Without language support, this will be a hole in the system.

--
Simen


Re: D Best Practices: Default initializers for structs

2010-11-07 Thread Simen kjaeraas

d'oh  wrote:


Arguable floating points would do better with -Infinity


Why? A signaling nan tells you 'you'trying to use an uninitialized value!'.


and integral types with a negative value e.g. -1, -2 or as negative as  
possible.


Why? I can see some reasons, like foo * -1 yields a negative answer, while
foo * 0 yields 0, which is a fairly common value. Still what are your
reasons for saying it's the best?



I suspect booleans would do better with true (this being the furtherest
away from false .. that if is false is taken to be the origin of the
boolean value axis).


And if true is taken to be the origin, then false would be the best?


--
Simen


Re: Can non-nullable references be implemented as a library?

2010-11-07 Thread Simen kjaeraas

Denis Koroskin <2kor...@gmail.com> wrote:

Since many people think that non-nullable references can be implemented  
as a library and thus don't belong to core language, I've decided to  
show that it is in fact impossible to do so.


How do you enforce the following behavior:

[snip]


Without support of these use-cases NonNull!(T) is useless.

There can be other examples, but I think these are enough to prove that  
non-nullable references can not be implemented in library.


Indeed. There is also the arrays I've mentioned before, and as you
mention here, fields of classes and structs. Good catch.

--
Simen


Re: null [re: spec#]

2010-11-07 Thread Simen kjaeraas

Roman Ivanov  wrote:


I know what your mean, but the example is flawed:

public void foo()
{
if (m) {
 Object p = new Object();
 p.toString();
}
}


You misunderstand. The idea is this:

void foo( ) {
  Object p;
  if ( m ) {
p = new Object( );
p.DoSomethingThatNeedsToBeDoneNow( );
  }
  // 20 lines of code here
  if ( m ) {
p.doSomethingWeird( dataFromAbove );
  }
}


int x = {
if (s == Dri.one)
return 1;
else if (s == Dri.two)
return 2;
else
return 3;
}();

This works. I'm not sure how efficient it is, but that would solve the
issue with initialization without any path analysis.


I'm not sure the compiler actually does this, but it would be fairly
trivial to inline that delegate.


--
Simen


Re: Can non-nullable references be implemented as a library?

2010-11-07 Thread Simen kjaeraas

Simen kjaeraas  wrote:


Denis Koroskin <2kor...@gmail.com> wrote:

Since many people think that non-nullable references can be implemented  
as a library and thus don't belong to core language, I've decided to  
show that it is in fact impossible to do so.


How do you enforce the following behavior:

[snip]


Without support of these use-cases NonNull!(T) is useless.

There can be other examples, but I think these are enough to prove that  
non-nullable references can not be implemented in library.


Indeed. There is also the arrays I've mentioned before, and as you
mention here, fields of classes and structs. Good catch.


Worth adding:
Even if non-null references/pointers cannot be perfectly implemented in a
library, they may still be a worthwhile addition to Phobos, to mark
function arguments and the like.

--
Simen


Re: null [re: spec#]

2010-11-07 Thread Simen kjaeraas

Nick Sabalausky  wrote:

If you do that, then there's two possibilities:

A. You intended p to get inited on all code paths but forgot a codepath.
With real init-checking the compiler will tell you and you can fix it.  
With

D as it is, you're not informed at all, and you may or may not catch the
problem before deployment. Obviously the former is better.

B. You *intended* p to not always be inited, in which case the correct  
code

is this:

void foo( ) {
  Object p=null;
  if ( m ) {
p = new Object( );
p.DoSomethingThatNeedsToBeDoneNow( );
  }
  // 20 lines of code here
  if ( p != null ) {
p.doSomethingWeird( dataFromAbove );
  }
}


There is a third option, wherein the if condition will only be true if
p !is null, but the actual condition is more complex:

if ( m > 4 ) {
p = new Object( );
p.DoSomethingThatNeedsToBeDoneNow( );
}

// code

if ( m > 12 ) {
p.doSomethingWeird( dataFromAbove );
}


--
Simen


Re: null [re: spec#]

2010-11-07 Thread Simen kjaeraas

Nick Sabalausky  wrote:


- if ( m > 12 ) {
+ if ( p && m > 12 ) {

And you can toss in an "if(m>12) assert(p);" if you're worried about  
that.


Of course. But the point is, this is unnecessary. We know p !is null
when m > 4.

--
Simen


Re: null [re: spec#]

2010-11-08 Thread Simen kjaeraas

Eric Poggel  wrote:


On 11/6/2010 6:50 AM, bearophile wrote:

foobar:

Any type can be wrapped by an OPTION type. trying to do the converse  
of this is impractical and is bad design.


Discussing this is a waste of time now, this part of the D language  
will probably never change.

This is why other people and me are proposition something different.

Bye,
bearophile


I still live in D1 land, so forgive me if I'm out of the loop--but what  
keeps this from being implemented at the library level as templated  
type:  NotNull!(T) ?  If there are limitations, maybe these areas of the  
language can be improved to get us there?


NotNull!T needs to have its default constructor disabled. That is the #1
blocker. There are other problems, mostly related to this - classes and
structs with NotNull!T fields must define a constructor, and for structs
that means the default destructor either needs to be possible to define
or possible to disable. Arrays of NotNull!T may not be resized to a
greater length, as that would require calling the default constructor of
NotNull!T.

I think that's it.

--
Simen


Re: null [re: spec#]

2010-11-08 Thread Simen kjaeraas

Andrei Alexandrescu  wrote:


On 11/7/10 4:21 PM, bearophile wrote:

Andrei Alexandrescu:


And what was exactly the claim that was wrong?


That there is no need of compiler&  syntax support to implement "good  
enough" nonnullable reference types in D.


The only change needed is constructor flow to make sure types with  
@disable'd constructors are always properly initialized. Array  
construction can be supported with a library function.


One more thing: structs with NotNull!T fields will need to have their
default constructor disabled automagically.

--
Simen


Re: null [re: spec#]

2010-11-08 Thread Simen kjaeraas

Denis Koroskin <2kor...@gmail.com> wrote:

On Mon, 08 Nov 2010 12:08:01 +0300, Simen kjaeraas  
 wrote:



Eric Poggel  wrote:


On 11/6/2010 6:50 AM, bearophile wrote:

foobar:

Any type can be wrapped by an OPTION type. trying to do the converse  
of this is impractical and is bad design.


Discussing this is a waste of time now, this part of the D language  
will probably never change.

This is why other people and me are proposition something different.

Bye,
bearophile


I still live in D1 land, so forgive me if I'm out of the loop--but  
what keeps this from being implemented at the library level as  
templated type:  NotNull!(T) ?  If there are limitations, maybe these  
areas of the language can be improved to get us there?


NotNull!T needs to have its default constructor disabled. That is the #1
blocker. There are other problems, mostly related to this - classes and
structs with NotNull!T fields must define a constructor, and for structs
that means the default destructor either needs to be possible to define
or possible to disable. Arrays of NotNull!T may not be resized to a
greater length, as that would require calling the default constructor of
NotNull!T.

I think that's it.



Not exactly disabled. The following should work:

class Foo
{
 this() {
 bar = new Object();
 }

 NonNull!(Object) bar; // fine here
}

while the following shouldn't:

NonNull!(Object) bar; // error here
bar = new Object();


I belive you have misunderstood me. The NonNull struct would need to have
its default constructor disabled. Then, extra logic would need to be added
to class and struct constructors to ensure NonNull fields have their
constructors called.

Context-sensitive constructor disabling is a theoretical possibility, but
seems to me to conflict with D's other goals.

--
Simen


Re: null [re: spec#]

2010-11-08 Thread Simen kjaeraas

Jonathan M Davis  wrote:


??? Structs have no default constructor.


True. Disabling the default constructor here means that

struct Foo{
@disable this();
}
Foo f;

should halt compilation at Foo f;, and certain other places where a
default constructor would normally be used.



They have an init property with is used for default initialization.


Indeed. And this is different from a default constructor that you can't
touch how?



And if you could enforce that a struct be properly
initialized rather than default initialized, that would be a big change.


Indeed. And that is what we are trying to achieve.


Either init needs to be changed to allow for real default constructors  
and/or objects need to be legal CTFE - ideally both.


Disabling the default constructor (which ostensibly looks this:
this( ) { this = init; }) is a very good step in the right direction.
Having proper default constructors would be better, and I can not
remember the reason we don't have that.



So, there is not
currently a way to have NotNull!T hold anything but null initially when  
it's a
member variable of a struct, and there's no sign of that changing any  
time soon.


Indeed, and this will never change - it can't. However, we are arguing that
it could be null before the struct's constructor is called, and flow  
control

(or out contracts, if necessary) enforce that it is not null when the
constructor returns.

I admit I here somewhat miss C++'s initialization lists:

struct Foo {
NonNull< Bar > bar;
Foo( ) : bar( new Bar() ) {
}
}


--
Simen


Re: null [re: spec#]

2010-11-08 Thread Simen kjaeraas

Jonathan M Davis  wrote:

I was not aware of that. I didn't think that you could do that for  
structs since

default constructors are illegal in the first place.


And you can't. That doesn't mean it can't be possible in the future.



It would likely have the
negative side effect of making it illegal to put Foo in arrays though,  
since it

wouldn't be possible to fill in the array values with init.


Indeed. That's been discussed here, and in short, these are the rules:

Arrays of non-null cannot have their lengths increased.

To create an array of non-null, use a literal, a function that checks
all parameters and builds an array from it, or a function that checks
all elements of a passed array of nullable elements.

To create a longer array, append two arrays.



> They have an init property with is used for default initialization.

Indeed. And this is different from a default constructor that you can't
touch how?


Default initialization is used all over the place - including both stuff  
like the
declaration Foo f; and in array declarations. Every type is default  
initialized

when not initialized directly, and it has nothing to do with default
constructors. init must be known at compile time whereas default  
constructors

are run at runtime.


I mean, the compiler is doing something to move .init to the new instance
of the type, and this could very well be considered the default  
constructor.




init gets used a fair bit (such as when you declare an array of a given
size and the compiler _must_ initialize all of its elements), and it's
vital to how D functions.


static arrays would require initializers in this case:

NonNull!(T)[2]; // Compile-time error: NonNull!T has no default constructor

NonNull!(T)[2] = [nonNull(new T), nonNull(new T)]; // Works


Depending on exactly how init works, it could be a _huge_ change to try  
and make a default constructor run instead.


Possibly, though I don't think so. As said before, some code needs to be
executed to copy .init to the new instance. This code could likely be
replaced with a default constructor. Even so, the disabling of default
constructors is not really about constructors, but as you say, about
disabling .init. This will not require execution of new code, only
a compile-time check for whether the constructor has been disabled.

--
Simen


Re: null [re: spec#]

2010-11-09 Thread Simen kjaeraas

Jonathan M Davis  wrote:

We definitely want to avoid the nastier issues, but the lack of default
constructors continually pops up as being a major problem. The QtD folks  
in
particular were have a lot of problems because of it as I understand.  
I've
certainly had problems with it my code. Even a restricted default  
constructor

would be better than none.


In my experience, disabling the default constructor would be enough.
That way the compiler warns you that 'this object has no valid default
state, so use a constructor.'


If we could have default constructors on structs but have it so that any  
struct
with a default constructor cannot be used where you have to have a bare  
init

with no constructor call


And where is that? Currently no such thing exists, as we have no default
constructors for structs. That means we could interpret any use of .init
as a constructor call. Disabling default constructors has this same
advantage, while avoiding the problems. The only problem is you will have
to use a constructor explicitly.

--
Simen


Re: null [re: spec#]

2010-11-09 Thread Simen kjaeraas

Daniel Gibson  wrote:


Nick Sabalausky schrieb:

"so"  wrote in message news:op.vlv3iukp7dt...@so-pc...
There's no usage of an undeclared variable, but the right-hand-side  
of the
second line uses 'i' before *the programmer* initializes it. Yes, the  
D
compiler chooses to automatically initialize it, but by doing so it  
silently
creates a bug every time the programmer intends 'i' to start out as  
anything
other than 0. And it's not easily noticed since 0 is a commonly-used  
value.
(Something like 0xDEADBEEF would at least be an improvement (albeit a  
small

one) since at least that would stand out more and likely fail more
spectacularly.)
So you want language force you to type either "int x=0;" or "int  
x=void;".
Fair enough and i agree it "might" be a bit better. But you are making  
it as it is something so much important.
 I tend to get a bit fired up by it because Walter's reasoning on it  
being *better* to automatically assume some init value baffles me.




It gives deterministic results/errors.


Yup. Also, as opposed to certain other solutions, it does not require
advanced flow control, that is likely to be incomplete. Incomplete flow
control here will make people write code 'to shut the compiler up'. And
that is worse than uninitialized variables.

--
Simen


Re: null [re: spec#]

2010-11-09 Thread Simen kjaeraas

Nick Sabalausky  wrote:

Also, as I've said when this was discussed in the past, I wouldn't even  
want

the flow analysis to be perfect because all that would accomplish is to
encourage garbage like the above (which would just end up being highly
fragile anway).


But if it isn't, we must either define what it should do, or accept that
some compilers will catch some of the uninitialized variable bugs, where
others do not. We do not want that.


--
Simen


Re: class instance construction

2010-11-11 Thread Simen kjaeraas

spir  wrote:


First, what is the actual point of "new"?


Mostly, it's a remnant from C++.


I find this keyword rather helpful in that it reminds me the element is  
referenced/heap-allocated/GC'ed. But is there any ambiguity on the  
language's side? We cannot construct a class instance in any other way,  
AFAIK, and "calling" a class can hardly have any other sense. Maybe  
classes' opCall could be set to the creation routine (whatever new  
calls); then we would get a single object-creation syntax.


Indeed it could. I believe Andrei Alexandrescu has discussed in favor of
such a change in the past.


Still, an other case when "new" annoys me is method chaining, because it  
makes syntax heavier and less readable:

c = (new C(p)).do(x);
versus:
c = C(p).do(x);
Or, maybe, the parser could be clever enough to correctly decode:
c = new C(p).do(x);


One would think it possible to stop searching right upon first finding a
function call parentheses (as opposed to a template parentheses). This is
complicated by the allowance of the syntax 'new C;'.


Second, could there be a default constructor for classes, like for  
structs? Namely, one that sets declared fields:

class C {int i;}
...
auto c = new C(1);


There could. :p

As for whether there should, I'm not sure. I would say such a
constructor should disappear, should the class designer add other
constructors. That, coupled with classes usually being more complex than
that (mine are, at least), this seems like a feature that would have
little actual air-time.


This is one great advantage of static languages, that the compiler knows  
more thank to declarations. Isn't it sensible to use this knowledge when  
helpful? I simply find the following stupid (I mean it's job for a  
machine, not for a programmer):

class C {
int i;
this (int i) {this.i = i;}
}
As we already enjoy this feature for structs...


The syntax

this( int this.i ) {}

has been suggested for automatic initialization of fields. I like this
suggestion, but it is unlikely to find its way into the language any
time soon.


--
Simen


Re: why a part of D community do not want go to D2 ?

2010-11-11 Thread Simen kjaeraas

spir  wrote:

But why not design from the start new Phobos libs with inspiration from  
known-to-be-good Tango ones?


We got kinda spooked by the incident with SHOO and std.time. It likely
was not as bad as it seemed, but it brought some bad blood.

--
Simen


Re: One year of Go

2010-11-13 Thread Simen kjaeraas

Nick Sabalausky  wrote:


try {
return true;
} finally {
return false;
}


try {
throw new AssertionError();
} finally {
return false;
}

I wonder how D handles those


Error: return statements cannot be in finally, scope(exit) or
scope(success) bodies

--
Simen


Re: The D Scripting Language

2010-11-15 Thread Simen kjaeraas

Per Ångström  wrote:


/++
Simulates type-returning or-expression
+/
template or(T) {
 T _(T a, lazy T b) {T tmp = a; return tmp ? tmp : b;}
}


You should probably use a function template[1] or at least an eponymous  
template here:


// function template:
auto or( T )( T a, lazy T b ) {
return a ? a : b;
}

// eponymous template:
template or( T ) {
auto or( T a, lazy T b ) {
return a ? a : b;
}
}

[1]: http://digitalmars.com/d/2.0/template.html#function-templates


--
Simen


Re: "In praise of Go" discussion on ycombinator

2010-11-17 Thread Simen kjaeraas

Matthias Pleh  wrote:


Am 17.11.2010 14:55, schrieb Steven Schveighoffer:

Being someone who likes the "brace-on-its-own-line" style


i++


Surely you mean:

i
++
;

--
Simen


Re: casting class pointer

2010-11-19 Thread Simen kjaeraas

Jesse Phillips  wrote:


 auto hi = "hello" in b.all;

 auto foo = cast(B) hi;


The result was that b.label wasn't the same, and printing out stuff  
resulted in a bunch of garbage.


Not surprising. hi is pointing to a reference (pointer) to a B instance,
not a proper B, and certainly not the one you hope for. Thus, random
garbage from the memory surrounding the reference is outputted.


The questions I have are, should casting a class pointer to a class  
change its behavior so it just gives you the class? Is is there a use  
case for the current behavior? And should I bother working to reproduce  
this?


The idea behind the in operator for AAs is that it indicate whether there
was something at the specified index, by returning null if there wasn't.
IOW, 'a in AA'  does not return a class reference, and shouldn't.

You may have reasons to put nulls in your AA, in which case the returned
B* may be non-null, while *hi is null. I have not thought of a good use
case for this, though. However, the main reason I see is symmetry. Having
to explain that for T[U] t, 'a in t' returns a T* is ok. Having to explain
that this simple rule breaks when T is a class, is not good.

Last, a cast is a message to the compiler of "Trust me, I know what I'm
doing". That could mean that your B* is actually a B (a reference), that
somehow ended up being a B*. In such a case, the only reasonable thing to
do is interpreting the bits as a B instead of a B*.

What you should do in the above code is
auto foo = *hi;

tl;dr: making the casting of class reference pointers to class references
do the shortcut of interpreting the pointer as a reference is asymmetric
and limits the language.

--
Simen


Re: Repairing BigInt const

2010-11-21 Thread Simen kjaeraas

Matthias Walter  wrote:


On 11/21/2010 04:33 PM, Don wrote:

Matthias Walter wrote:
as it seems, the current version of BigInt is not capable of const,  
i.e.

BigInt(1) + const(BigInt)(1) does not work.

Is there already an effort to fix this or would it make sense if I had
taken some time to create a fix for it? I have no idea of all the asm  
in

the x86 specialization but as const is an interface thing, I should be
able to figure out everything without that knowledge. Or are there
general design problems, such that this would be a waste of time?


It's been prevented by some compiler bugs. The changes to pure in
2.050 were triggered by attempts to make BigInt pure. 2.051 will
include several fixes to nothrow.

You mean by "making BigInt pure" that all the computation-methods (like
opBinary, etc.) will be pure, right? Or can D structs be pure as well?
(Whatever this would mean...)


"Making BigInt pure" means making it usable in pure functions. That is,
make all member functions pure that can be pure.



--
Simen


Re: Basic coding style

2010-11-23 Thread Simen kjaeraas

bearophile  wrote:

From what I'm seeing in D.learn there is a problem in the D community:  
some people seem irrationally attached to the idea they are free to  
write D code as they like. I have four or five times tried to explain  
why coding standards are important for the development of the D  
community, but it seems not everybody is understanding it.


First off, in your posts on D.learn, you come off as overzealous and
vindicatory, as if you are on a holy crusade for The One True Style™.
This, I believe, is not a good way to greet newcomers.


That said, I agree there should be a One True Style™, and here are my
suggestions:

Make the style in three parts, where one is considered nigh obligatory,
and concerns public interface only. That is, names and structure.

The second part concerns only official D code. That is, if you want
your code in Phobos, make sure it follows these rules.

The third part should be guidelines to beautiful code. This is a
somewhat subjective measurement, and should be threated as such.


Whenever code is posted on the newsgroup that does not follow part 1,
feel free to suggest that the poster read the style guide. If it does
not follow part 2, leave it alone. If it blatantly violates the
intent of part 3, link to part 3.

--
Simen


Re: name guess by the compiler

2010-11-25 Thread Simen kjaeraas

On Thu, 25 Nov 2010 11:10:29 +0100, spir  wrote:

PS: for got to ask: is there any kind of namespace in D -- especially  
one kind usable for module export?


D does not have namespaces per se. However, modules introduce a sort of
namespace, templates create parametrized namespaces, and final abstract
classes may be used to fake namespaces, should the other features not
be sufficient:

final abstract class MyNamespace {
static:
// stuffs
}


I have no idea how dmd guesses possible names. But surely there is a  
kind of probability evaluation used to rank possible guesses. If I'm  
right, then dmd should not output its best guess in every case, but only  
when its probability value is higher than a given threshold (to be  
carefully defines).


This sounds reasonable, but hardly top of the list on urgency.


Also, the case above probably reveals some kind of bug, since it is hard  
to imagine how "to" can ever be the best guess for "i" (and there is no  
alias in the test case). PS: "alias to" is only guessed when the module  
imports std.conv:to. Still, how to guess "to" from "i"? Finally, should  
the guessing feature exclude (unqualfied) imported symbols?


Absolutely not.

--
Simen


Re: What are modules for?

2010-11-25 Thread Simen kjaeraas

rickned  wrote:


Modules, files, packages, compilation units...

I have a class that is designed to be derived from. Can I put it in
a module (file) so other people can import the module (file) like a
C-c++ header so they can derive from it?


Yes. Any non-final public class in an imported module can be derived
from.



Is that the idomatic way to do that in D?


There is the option of using a .di file, if you want to hide
implementation. .di files are normal D source files, with
implementation stripped. Due to the compilation speed (I believe) and
no requirement to hide implementation, most projects I've seen simply
use .d files.



I don't want to expose the method definitions,
mind you. I understand deeply the C++ way of doing things like
hiding implementation and interfaces etc. Can someone bring it all
together for me in D?


See above. .di files are basically what you'd expect to be the D
equivalent of a .h file.



And note that the hiding part is not the gist
of my question, but rather that I want to understand the D way but
am probably trying to contrast it to the C++ way. I have TDPL
(borrowed from the library, and it's a one without Andy's name on
the cover), but I started reading it in the module chapter but
found it rather confusing, if not lacking all the pertinent info.



--
Simen


Re: What are modules for?

2010-11-26 Thread Simen kjaeraas

Jonathan M Davis  wrote:

You can, create .di files which have function declarations
leaving the definitions in a .d file (  
http://www.digitalmars.com/d/2.0/dmd-
linux.html#interface_files ), but those are specific to dmd (as opposed  
to the D

language)


This is false. .di files are simply .d files with a different extension.
Any compiler that supports the compilation of .d files will support .di
files (granted, it may only look for .d files).



And I'm
not sure that those work very well with templates, since you need the  
whole
template definition when instantiating a template, and templates are  
typically

very heavily used in D.


Template definitions are left in the .di file.

--
Simen


Re: What are modules for?

2010-11-26 Thread Simen kjaeraas

Jonathan M Davis  wrote:


On Friday 26 November 2010 00:44:03 Simen kjaeraas wrote:

Jonathan M Davis  wrote:
> You can, create .di files which have function declarations
> leaving the definitions in a .d file (
> http://www.digitalmars.com/d/2.0/dmd-
> linux.html#interface_files ), but those are specific to dmd (as  
opposed

> to the D
> language)

This is false. .di files are simply .d files with a different extension.
Any compiler that supports the compilation of .d files will support .di
files (granted, it may only look for .d files).


I believe that Walter has stated that .di files are a dmd-specific thing  
and are
not actually a part of the D language. That doesn't stop other compilers  
from
supporting them, but they are effectively a dmd-specific language  
extension. The
language itself specifies .d files as being d source files but says  
nothing about

.di files.


They are not a defined part of the D language because they don't need to.
They are simply D source files. The dmd-specific part of it is that dmd
supports generating .di files from .d files.

--
Simen


Re: Logical const

2010-11-28 Thread Simen kjaeraas

Jonathan M Davis  wrote:

So, _I_ am certainly not aware of a good solution, but if you play  
games, you
should be able to get _something_ working. Overall though, I think that  
the
lesson is that you should really be making const functions truly const  
and not

try and deal with logical const at all.


Highly unsafe, but works in the cases you'd expect. Use with extreme
caution:


import std.traits;
@system
ref Unqual!T unqualified( T )( ref const T t ) {
Unqual!(T)* p = cast(Unqual!(T)*)&t;
return *p;
}

--
Simen


Re: const a storage class or a type modifier?

2010-11-29 Thread Simen kjaeraas

Andrej Mitrovic  wrote:


D's slogan should be "There's a keyword for that." :p


And here I thought we only needed 'static'...

--
Simen


Re: Logical const

2010-11-29 Thread Simen kjaeraas

Walter Bright  wrote:


immutable - Data will never, ever change, through any reference.
const - Data will never change through this reference.
newlevel - Data will never logically change through this reference.


The problem with newlevel is (to repeat myself) it is unverifiable.


As long as it is transitive, I believe it is verifiable:

struct S {
int n;
}

struct foo {
int n;
foo* p;
newlevel S s;
newlevel int m;
void bar( ) newlevel {
m++; // works, m is newlevel
n++; // compile-time error, n is const for newlevel this
s.n = 3; // Works, s.n is newlevel
p.n = 4; // compile-time error, p is newlevel, p.n is const for
 //  newlevel this
p.m++; // Works, p.m is newlevel
}
void baz( ) const {
m++; // compile-time error, m is const for const this
}
}

void qux( newlevel foo f ) {}
void quux( ref foo f ) { f.n++; }

void main() {
const foo f;
f.bar( ); // compile-time error, f is const, cannot call newlevel
  //  functions on it
qux( f ); // compile-time error, const(foo) cannot be implicitly
  //  cast to newlevel(foo)

newlevel foo g;
quux( g ); // compile-time error, newlevel(foo) cannot be implicitly
   //  cast to foo
}

This leaves const as a strong, transitive guarantee, and newlevel as a
transitive guarantee that only newlevel members may be changed.


I am not convinced that such an extension of the type system should be
made, but I believe you are wrong in that it is not verifiable. but
please, do show me my mistake.

--
Simen


Re: Logical const

2010-11-29 Thread Simen kjaeraas

Steven Schveighoffer  wrote:

Except the language says what results from your code (casting away const  
and then mutating) is undefined behavior.  This means all bets are off,  
it can crash your program.  I'm unsure how the compiler could take that  
route, but that's what's in the spec.


Maybe because of the way const works, it never really is undefined, but  
there will always be that loophole.


The thing is, immutable is implicitly castable to const, and immutable
data could be stored in write-protected memory. Apart from that, I believe
it is safe to cast away const.

--
Simen


Re: D's greatest mistakes

2010-11-29 Thread Simen kjaeraas

Andrej Mitrovic  wrote:


Why not do the same for templates? Something like this:

void foo(A, B, C)(A a, B b, C c)
constraint
{
isDynamicArray(a);
isIterable(a);

}


Consider:

void foo( A )( A a )
constraint {
  isBar!A;
}


void foo( B )( B a )
constraint {
  isQux!B;
}

Which error message should I show?

--
Simen


Re: Logical const

2010-11-29 Thread Simen kjaeraas

Walter Bright  wrote:


Simen kjaeraas wrote:

I am not convinced that such an extension of the type system should be
made, but I believe you are wrong in that it is not verifiable. but
please, do show me my mistake.


It is not verifiable because nothing prevents you from assigning:

m = random();

That is not logical const.


Pardon my stubbornness (and perhaps ignorance), but how is this any less
logical const than is 'm = 4;' or 'm = n * 3 + cast(int)phaseOfMoon();'?

--
Simen


Re: D's greatest mistakes

2010-11-29 Thread Simen kjaeraas

Andrej Mitrovic  wrote:


Which error message should I show?


I'm not sure what you're getting at. :)

[snip]

But anyway it's just an idea and I'm probably missing something
important, I haven't used D in a while..


I believe you are missing that more templates could bear the same
name, and they could all fail for varying reasons. In such a case,
do you print the error messages from 100 templates and let the
user sort through them, or do you show the error the compiler
currently shows?

I admit my example was flawed, or at least incomplete:


void foo( A )( A a )
constraint {
   isBar!A;
}

void foo( B )( B a )
constraint {
   isQux!B;
}


void main( ) {
int n;
assert( !isBar!int );
assert( !isQux!int );
foo( n );
}

The call to foo would match neither template, giving errors akin
to this:

test.d(15) Error: template instantiation foo!int failed.
test.d(3)   Error: template constraint failed
test.d(6)   Error: template constraint failed

Seems good for two or three templates, but I fear this would grow
quickly out of hand for more templates.

--
Simen


Re: Logical const

2010-11-29 Thread Simen kjaeraas

Jesse Phillips  wrote:


In fact, couldn't opAssign be


 ref opAssign(U)(auto ref U v)  if(Unqual!U == U)
 {
 return mutable() = v;
 }

This way only mutable references are only ever assigned to it? Then it  
can be marked as @trusted and used in safe code as it will never cause  
the program to crash?


Indeed it could. This brings me to this code:


struct Mutable( T ) if ( is( T : Unqual!T ) ) {
private T _payload;

this( Unqual!T t ) {
_payload = t;
}

@trusted @property ref T get( )( ) const {
T* p = cast( T* )&_payload;
return *p;
}
alias get this;

@trusted ref opAssign( U )( auto ref U u ) const if ( is( Unqual!U ==  
U ) && is( U : T ) ) {

T* p = cast( T* )&_payload;
return *p = u;
}

bool opEquals( )( ref const Mutable other ) const {
return _payload == other._payload;
}

bool opEquals( U )( auto ref U other ) const if ( is( U : T ) || is( T  
: U ) ) {

return _payload == other;
}
}

It works in many cases, but not for function calls:

void bar( int n ) {}

class A {
Mutable!int n;
}

A a = new A;
bar(a.n);//Error: function bar (int n) is not callable using argument  
types (const(Mutable!(int)))



--
Simen


Re: Logical const

2010-11-29 Thread Simen kjaeraas

Simen kjaeraas  wrote:

This way only mutable references are only ever assigned to it? Then it  
can be marked as @trusted and used in safe code as it will never cause  
the program to crash?


Indeed it could.


Wait. Correction: In the case when the object harboring the mutable
member is moved into read-only memory (I do not know if this might
actually happen), this ceases to be true.

--
Simen


Re: Logical const

2010-11-29 Thread Simen kjaeraas

Simen kjaeraas  wrote:


It works in many cases, but not for function calls


Some more testing brought this bug to my attention:

void bar( ref int n ) {
n++;
}

void main( string[] args ) {
const int n = args.length * 0;
assert( is( typeof( n ) == const(int) ) );
bar( n ); // Uhm...
assert( n == 1 ); // WTF?!?
}


I would say this is seriously bad.
http://d.puremagic.com/issues/show_bug.cgi?id=5291


--
Simen


Re: Logical const

2010-11-29 Thread Simen kjaeraas

Walter Bright  wrote:

Logical const means the same value is returned every time, not a  
different one.


So you would have only pure functions work with logical const?


The new keyword 'newlevel' defined earlier could certainly include pure.
Also, the compiler could have the automatically generated opEquals
ignore fields marked 'newlevel'. This way, logical constness is
preserved, no?

Going further, one could define mutable state only in (pure) member
functions. This state would actually be stored in the object, but would
be inaccessible to other member functions, and would not be considered
by opEquals. I believe this is the closest we could come to enforcing
logical constness.

--
Simen


Re: Logical const

2010-11-29 Thread Simen kjaeraas

Andrej Mitrovic  wrote:


Oh this one is even more spectacular:

void bar( ref int n )
{
n++;
}

void main( string[] args )
{
immutable int n = args.length * 0;
assert( is( typeof( n ) == const(int) ) );
bar( n ); // Uhm...
assert( n == 1 );
}

K:\code>dmd bug.d -release -O -inline
K:\code>bug
object.Error: assert(0) or HLT instruction

I'll update the bugzilla entry.


Don't. It's your first assert, failing as
const(int) != immutable(int)

--
Simen


Re: Logical const

2010-11-30 Thread Simen kjaeraas

Walter Bright  wrote:

It still is not verifiable. That's why logical constness is not a  
language issue, it is a convention.


And finally I understood what you meant. Sorry about this taking a while.

--
Simen


Re: D's greatest mistakes

2010-11-30 Thread Simen kjaeraas

bearophile  wrote:

I like very much the idea of constraint blocks. Much better than  
expanding func header line, reuses an existing syntactic construct, and  
far cleaner.


But I'd like that syntax to allow for an error message for each  
constraint. So it becomes like contract programming, done at  
compile-time on types and compile-time constants, and the "in" keyword  
is enough:


in {
  static assert(isDynamicArray!T, "err msg 1");
  static assert(isIterable!T, "err msg 2");
  ...
} body {
  ...
}


The problem with such a solution is that the compiler needs to evaluate
the 'in' clause differently from all other code, as code further down in
the 'in' clause could use parameters in a way that would be illegal at
compile-time. Hence the new keyword or, for giggles, why not 'static in'?

--
Simen


Re: D's greatest mistakes

2010-11-30 Thread Simen kjaeraas

bearophile  wrote:


I think the syntax of is() is awful and I'd like to shoot it.


In my opinion, the syntax for is() is not all that bad. However:

- It lacks is ( Type : TypeSpecialization , TemplateParameterList ) and
is ( Type == TypeSpecialization , TemplateParameterList )
- It does not deduce base templates. Given is ( T == U!V, U, V... ), it
fails. Given is ( T == MyTemplate!U, U... ), it works.

--
Simen


Re: D's greatest mistakes

2010-11-30 Thread Simen kjaeraas

Steven Schveighoffer  wrote:

On Tue, 30 Nov 2010 13:13:47 -0500, Steven Schveighoffer  
 wrote:



IMO opinion,


IMO opinion?  Hm... wonder what that O stands for :D


Own?

--
Simen


Re: D's greatest mistakes

2010-11-30 Thread Simen kjaeraas

bearophile  wrote:


- It lacks is ( Type : TypeSpecialization , TemplateParameterList ) and
 is ( Type == TypeSpecialization , TemplateParameterList )


I think is() needs less stuff, not more. The functionality needs to be  
moved to a nicer syntax (and according to Andrei a better semantics too).


The versions I suggest 'is' lacks are simplifications of existing options,
and would IMO simplify the feature.

I also feel that is() is logical. That is, the parts without the  
Identifier.

is( A : B ) makes sense, as does is( A == B ) and is( A : B!T, T... ).
is( A B : C!T*, T... ), on the other hand...

--
Simen


Re: delegates and heap usage

2010-12-01 Thread Simen kjaeraas

Franciszek Czekala  wrote:


What part of stack frame is exactly copied when a delegate is used?


Generally, only the used variables.

You can check the size of the closure's stack copy using
GC.sizeOf(dg.ptr).



For example what is the heap usage due to delegates usage in the
following code?


Adding this code to the end of it:

  int n = 0;
  void* ptr = null;
  foreach ( e; dlg ) {
if ( e.ptr != ptr ) {
  ptr = e.ptr;
  n += GC.sizeOf( e.ptr );
}
  }
  writeln( n );


We can see that 1600 bytes are used.

The library reference speaks about the enclosing function but I do not  
think
that it suffices to copy the stack frame of the directly enclosing  
function.

Is the whole stack copied?


All enclosing functions need to have their stack frames copied. That is,
not the whole stack, but any functions for which the delegate would be a
nested function.



What happens in the case of recursive calls?


int recurse( int delegate() dg ) {
int n = 1;
return GC.sizeOf( dg.ptr ) + ( dg() ? recurse( { return dg() - n; } )  
: 0 );

}

void main(){
writeln( recurse( { return 100; } ) );
}

Outputs 1600.

--
Simen


Re: tail const

2010-12-01 Thread Simen kjaeraas

vincent picaud  wrote:

To summarize there would be just one keyword to add in D : "const_".  
This attribute would have sense only for Objects (the same logic would  
also hold for "immutable_"). To my IMHO the syntax const_ is easy to  
unerstand, because "_" clearly shows the place holder position and its  
missing "const"

(remembering C++)


The issue is not with syntax (I am of the impression that most who want
this, like Michel Fortin's const(A) ref a). The problem is Walter does
not want to do it, as he considers it impossible to get right. Of that
I'm not sure, but he's proven me wrong in the past, so it could happen
again.

--
Simen


Re: delegates and heap usage

2010-12-01 Thread Simen kjaeraas

Franciszek Czekala  wrote:

I am not sure that this is a correct answer. 1600 bytes is just 100x2x8  
bytes.
Since delegates are fat (double) pointers this is probably just the  
memory
occupied by dlg variables themselves, not the memory to which they  
point. Indeed
adding an extra z variable in my code to the g() function and using it  
in writeln

does not change the output: it is still 1600 bytes.


Wrong. The delegates would be 100x2x4 bytes, as DMD only produces 32-bit
exes. The 16 bytes per delegate is because that's the smallest block the
GC will allocate.

Proof:


long recurse( long delegate() dg ) {
long n = 1;
   long m = 0;
long r = 0;
long s = 0;
long t = 0;
return GC.sizeOf( dg.ptr ) + ( dg() ? recurse( { return dg() - n + m -  
r + s + t; } ) : 0 );

}

void main(){
writeln( recurse( { return 100L; } ) );
}

Outputs 6400.

--
Simen


Re: tail const

2010-12-02 Thread Simen kjaeraas

Michel Fortin  wrote:


I'm not sure I get the problem. Can you show me in code?


const a = map!"a+a"( [1,2,3] );

foreach ( e; a ) {
}

The foreach fails because popFront is not const. What is needed is for
typeof(a) to be Map!("a+a", const(int)[]). IOW,
is( const(Map!("a+a", int[])) == Map!("a+a", const(int)[]) ).

One possible way to do this is for all types T to have defined types
immutable_t and const_t, which by default alias to immutable(T) and
const(T), but can be defined to alias to other types. The compiler
would then automagically convert cast(const)T to cast(T.const_t)T.

--
Simen


Re: tail const

2010-12-03 Thread Simen kjaeraas

Andrei Alexandrescu  wrote:


On 12/2/10 6:54 PM, Simen kjaeraas wrote:

Michel Fortin  wrote:


I'm not sure I get the problem. Can you show me in code?


const a = map!"a+a"( [1,2,3] );

foreach ( e; a ) {
}

The foreach fails because popFront is not const. What is needed is for
typeof(a) to be Map!("a+a", const(int)[]). IOW,
is( const(Map!("a+a", int[])) == Map!("a+a", const(int)[]) ).

One possible way to do this is for all types T to have defined types
immutable_t and const_t, which by default alias to immutable(T) and
const(T), but can be defined to alias to other types. The compiler
would then automagically convert cast(const)T to cast(T.const_t)T.


Well the code asks for a constant object, and I don't see it as  
reasonable for the type system to automagically infer the intent.


True. I believe I was thinking that T should be implicitly convertible
to T.const_t  (or tailconst_t, as may be more appropriate).

What might be appropriate is a function tailconst( T )( T t ) that
returns a tail const version of the passed type. That is, given a
T[], const(T[]), const(T)[], immutable(T[]), or immutable(T)[], it
returns a const(T)[]. For a MyRange!R, const(MyRange!R), or
immutable(MyRange!R), it returns a MyRange!(R).tailconst_t. See bottom
of post for a (naïve) implementation.



What should work is this:

const(int)[] data = [1,2,3];
auto a = map!"a+a"(data);
foreach (e;a) {
}


That does work.



import std.traits;

/**
 * Return the tail-const type for a  given type
**/
template TailConst( T ) {
static if ( is( T U : U[] ) ) {
alias const(Unqual!U)[] TailConst;
} else static if ( is( T U : U* ) ) {
alias const(Unqual!U)* TailConst;
} else static if ( is( T.tailconst_t ) ) {
alias T.tailconst_t TailConst;
} else static assert( false );
}

unittest {
struct test {
alias int tailconst_t;
}

assert( is( TailConst!( int[] ) == const(int)[] ) );
assert( is( TailConst!( immutable( int[] ) ) == const(int)[] ) );
assert( is( TailConst!( const(int)[] ) == const(int)[] ) );
assert( is( TailConst!test  == int ) );
}

/**
 * Converts the given parameter to tail const
**/
TailConst!T tailconst( T )( T t ) {
TailConst!T tmp = t;
return tmp;
}

unittest {
struct test( T ) {
alias test!(const T) tailconst_t;
this( const test!( Unqual!T ) t ) {}
}

assert( __traits( compiles, { tailconst( [1,2,3] ); } ) );
assert( __traits( compiles, { test!int t; tailconst( t ); } ) );
}

--
Simen


Re: tail const

2010-12-04 Thread Simen kjaeraas

Simen kjaeraas  wrote:


What might be appropriate is a function tailconst( T )( T t ) that
returns a tail const version of the passed type. That is, given a
T[], const(T[]), const(T)[], immutable(T[]), or immutable(T)[], it
returns a const(T)[]. For a MyRange!R, const(MyRange!R), or
immutable(MyRange!R), it returns a MyRange!(R).tailconst_t. See bottom
of post for a (naïve) implementation.


To expound further on this, I have created the attached module.
Critique wanted.

--
Simen

tailconst.d
Description: Binary data


Re: tail const

2010-12-05 Thread Simen kjaeraas

Andrei Alexandrescu  wrote:


On 12/4/10 12:23 PM, Simen kjaeraas wrote:


To expound further on this, I have created the attached module.
Critique wanted.



Looks promising. A few comments.

* For TailXxx you need to handle built-in simple types (int, float...)  
to return themselves. Also, structs for which hasIndirections returns  
false also return themselves.


Done.

* tailconst_t does not obey Phobos' naming convention. I think it's fine  
to use TailConst in spite of the apparent ambiguity.


It adds some .'s:
alias SimpleRange!(.TailConst!T) TailConst;
static if ( !is( T == .TailMutable!T ) ) {
this( SimpleRange.TailImmutable r ) {

Not sure if this is a problem.


* You may want to add more stringent checks for tailconst_t (well  
TailConst etc) to make sure it's not bogus - has the same size,  
compatible members etc.


I've tried, and it seems adding
  static assert( T.sizeof == T.TailConst.sizeof );
does not work (no size yet for forward reference).

Checking that all members are the same type and order is easy and
works. Comparing member names bumped me into bug 5079. Likely related
to the above, seeing as both have to do with unfinished types.



I've also considered a template on the form

mixin tailConst!( SimpleRange, SimpleRange!( Tail!T ) );
or
mixin tailConst!( SimpleRange, Tail!T );

which would automagically define aliases. More work for me, perhaps
less work for users.

This could not define constructors, as overloads from inside template
mixins don't work with overloads outside.

--
Simen

tailconst.d
Description: Binary data


tailconst2.d
Description: Binary data


Re: tail const

2010-12-05 Thread Simen kjaeraas

Simen kjaeraas  wrote:


I've also considered a template on the form

 mixin tailConst!( SimpleRange, SimpleRange!( Tail!T ) );
or
 mixin tailConst!( SimpleRange, Tail!T );


A closer look at this reveals that it won't work that simply, because
SimpleRange in this context is the struct, not the template. This,
however, works:

mixin tailConst!( .SimpleRange, TailT! );

Not sure how I like this.

--
Simen


Re: const(Object)ref is here!

2010-12-06 Thread Simen kjaeraas

spir  wrote:


On Mon, 6 Dec 2010 00:31:41 -0800
Jonathan M Davis  wrote:


toString() (or writeFrom() or whatever
it's going to become)


guess it was writeTo() ;-) but "writeFrom" is nice as well, we should  
find some useful use for it


This reminded me of INTERCAL's WRITE IN and READ OUT.


--
Simen


Re: const(Object)ref is here!

2010-12-07 Thread Simen kjaeraas

Michel Fortin  wrote:

And that's what my patch does. It only gets confusing when you add  
modifiers:


alias const(Object)ref A;
alias const(Object ref) B;
alias const(Object) C;

A ref a;
B ref b;
C ref c;

With my patch, variables 'a', 'b', and 'c' are all of the same type:  
"const(Object)ref", the later 'ref' changing the constness of the  
reference specified in the 'B' alias.


const(Object ref) is implicitly castable to const(Object) ref, no?

So to me, it seems all of these should be const(Object) ref.
Seeing Foo ref name, I read this as 'non-const reference to some
class'. IOW, if you want a rebindable reference to a class T, the type
of T should not affect what hoops you must jump through to get there.

--
Simen


Re: Scripting again.

2010-12-09 Thread Simen kjaeraas

so  wrote:


Hello!

In D, it is much harder to say something is impossible to implement  
comparing to other languages.
If you are coming from C/C++ land, you should know that if you want to  
script your program,
you are going to fall back to another language, possibly a "scripting"  
language.
But why? why should i fall back to a dummy language for this? Tons of  
workarounds to export stuff, it is just a mess!
It doesn't matter if we have tools like boost python bindings or PyD, it  
is still ugly.


All i can see right now is the lack of compile(file, module  
dependencies, ...).

Is it just technical limitations or is this is another religious issue?


Mostly, there is no D compiler written in D that can be included in the
standard library.


--
Simen


Re: rationale: [] and ()

2010-12-10 Thread Simen kjaeraas

Manfred_Nowak  wrote:


What is the rationale for having both: normal and square brackets?


Mostly that C has both. Changing this would make the language feel rather
more different from C/C++ than it already does.

It is also syntactic sugar for element lookup. Rather than having to
write some function name (that may or may not be the same for all
collections), you can use [].



I ask because in plain old C I interpreted the lexical difference of
funtion calls and accesses to elements of arrays as a permanent hint for
linear runtime in case of arrays.

But because of `opIndex' this assumption has been invalidated a long
time ago.


No it hasn't. opIndex should still  be O(1), it just can't be enforced.

--
Simen


Re: rationale: [] and ()

2010-12-10 Thread Simen kjaeraas

Steven Schveighoffer  wrote:

On Fri, 10 Dec 2010 09:42:51 -0500, Simen kjaeraas  
 wrote:



Manfred_Nowak  wrote:



But because of `opIndex' this assumption has been invalidated a long
time ago.


No it hasn't. opIndex should still  be O(1), it just can't be enforced.



er.. make that O(lg(n)) :)  Essentially sub-linear.


Ah, yes. Sorry.


--
Simen


Re: Verbose checking of range category

2010-12-11 Thread Simen kjaeraas

Jonathan M Davis  wrote:

It would be great if dmd said which constraint failed, but since you're  
dealing
with an arbitary boolean expression, in many cases, would not be  
particularly
straightforward to say what failed, and I expect that it would be a  
_big_ change

for the compiler.


Not to mention SFINAE, which would lead to a wall of text when multiple
specializations of a template exists (15 templates failed, each for 3
different reasons = 60 lines of error messages, none of which are
likely to be useful). And in such a case, no error messages are to be
printed if one match is found, right?


--
Simen


Re: const / in

2010-12-11 Thread Simen kjaeraas

Jonathan M Davis  wrote:

It has definitely been suggested before that const should be the  
default, and
some people would love that, but there's no way that it's going to  
happen in D2,
and much as I like const, I think that it would be a huge mistake to do  
it in
any version of D and likely any version of any C-based language. It's  
too big of

a break with other versions of D and other C-based languages.


I'm torn about the issue. I see reasons to have const by default (or even
immutable), but having it as the 'real' default would as you say, turn
away too many programmers.

Hence, I suggest that modules may be marked default-const:

const module foo;

int n; // const int
mutable int m; // int

This could also be extended to cover pure:

pure const module foo;


Is this a good idea? No idea.

--
Simen


Re: Why Ruby?

2010-12-11 Thread Simen kjaeraas

so  wrote:

I am not here asking for syntax or commanding phobos team to implement  
something, I just want to know about technical limitations and license  
issues, but got no answer to these.
Why? Either i am labeled here as a troll (maybe something worse since my  
usage of English is not the best)


Your posts have at times come off as less than polite, but your knowledge
and insight have shown it to likely be caused merely by limited mastery of
the language.

--
Simen


Re: Why Ruby?

2010-12-11 Thread Simen kjaeraas

Ary Borenszweig  wrote:
Code is read many more times than it is written and so it is of huge  
important that code is as readable as possible. Of course this is a  
subjective matter, but I don't understand why some people think __traits  
or __gshared are ok.


__gshared is ok. It is supposed to indicate low-level hackery and
unpleasant, rough edges. __traits, however, is an abomination and should
be shot repeatedly with something high-caliber.

--
Simen


Re: String to boolean inconsistency

2010-12-11 Thread Simen kjaeraas

Andrej Mitrovic  wrote:


Actually I'm having a hard time understanding this:

void main()
{
string s = "";
assert(s);  // pass, but why?
assert(s !is null);  // pass
}

void main()
{
string s = "".idup;
assert(s);  // fail
assert(s !is null);  // pass
}



Try adding writeln( s.ptr ); in there. Should probably give you an
indication of what is and == do.

Answer:

== null:
 Length
P==0 !=0
t ==0 T   F
r !=0 T   F


is null:
 Length
P==0 !=0
t ==0 T   F
r !=0 F   F

Where T and F stand for true and false, respectively.


So likely, idup on an empty string returns an array with null ptr and
0 length, while "" is 'allocated' in the data segment, and thus given a
ptr value.

--
Simen


Re: String to boolean inconsistency

2010-12-11 Thread Simen kjaeraas

Ellery Newcomer  wrote:


I forget, why are we supposed to use is instead of == with null?


'[] is null' compares ptr and length, while '[] == null' compares only
the length. Weirdly though, '[] is null' is false for ptr == 0,
length != 0. Not likely to happen much in practice.

--
Simen


Re: String to boolean inconsistency

2010-12-11 Thread Simen kjaeraas

Simen kjaeraas  wrote:


Ellery Newcomer  wrote:


I forget, why are we supposed to use is instead of == with null?


'[] is null' compares ptr and length, while '[] == null' compares only
the length. Weirdly though, '[] is null' is false for ptr == 0,
length != 0. Not likely to happen much in practice.


To actually answer your question, == calls opEquals for classes, and
that is called on both lhs and rhs. null.opEquals however, segfaults.

is, on the other hand, compares pointer equality, without caring for the
details of what opEquals wants to do.

--
Simen


Re: String to boolean inconsistency

2010-12-11 Thread Simen kjaeraas

Jonathan M Davis  wrote:

This behavior is intended. Arrays are actually something like this under  
the hood:


struct array(T)
{
T* arr;
size_t length;
}


Actually, that is:

struct array(T)
{
size_t length;
T* ptr;
}

To get the layout and names right.
( http://digitalmars.com/d/2.0/abi.html )

--
Simen


Re: String to boolean inconsistency

2010-12-12 Thread Simen kjaeraas

spir  wrote:


On Sun, 12 Dec 2010 04:00:36 +0100
"Simen kjaeraas"  wrote:


So likely, idup on an empty string returns an array with null ptr and
0 length, while "" is 'allocated' in the data segment, and thus given a
ptr value.


.dup & .idup should not change a string's truth value. For sure, _this_  
is a bug.
I think explicite empty strings/arrays should not have null pointers, as  
opposed to uninitialised strings/arrays.


I'm not sure I agree here. It seems foolish to me to allocate 16 bytes (the
minimum allocation size for the GC) for an empty array. Of course, "" is
not really an empty array. Rather, it is the equivalent of "\n"[0..$-1].

That said, I think cast(bool)array should be true only in the cases where
both ptr and length != 0;


--
Simen


Re: Why Ruby?

2010-12-12 Thread Simen kjaeraas

Lutger Blijdestijn  wrote:


Simen kjaeraas wrote:


Ary Borenszweig  wrote:

Code is read many more times than it is written and so it is of huge
important that code is as readable as possible. Of course this is a
subjective matter, but I don't understand why some people think  
__traits

or __gshared are ok.


__gshared is ok. It is supposed to indicate low-level hackery and
unpleasant, rough edges. __traits, however, is an abomination and should
be shot repeatedly with something high-caliber.



Is std.traits not sufficient for that?


I have yet to see std.traits.compiles( some code ). There is a very nice
enhancement request in Bugzilla that __traits be replaces with a magic
namespace. meta.compiles( some code ) is heads and heels superior to
__traits( compiles, some code ). I've not checked if others of __traits'
capabilities are impossible to implement as templates.

It has also been suggested that __LINE__ and __FILE__ be stored in this
namespace, but I find that rather less likely to happen.

--
Simen


Re: Why Ruby?

2010-12-12 Thread Simen kjaeraas

so  wrote:

If we take a look at the very first code example from the talk it looks  
like this:


account.people.each do |person|
 puts person.name
end

You could translate this in two ways when translating into D.
First way:

foreach (person ; account.people)
 writeln(person.name);


Am i alone thinking D one better here?


Absolutely not. Ruby reads like Yoda-speak, while D is almost plain
English. Had foreach used 'in' instead of the semicolon, only
punctuation and 'ln' would be off.

--
Simen


Re: Why Ruby?

2010-12-12 Thread Simen kjaeraas

Nick Sabalausky  wrote:


void myfun(void delegate(string) lol) {
   lol("say it ");
}

void main() {
   myfun = (string what) {
   assert(0, what ~ " lol");
   };
}



I'm sure that's going to disappear when D's properties get implemented as
intended.


I'm not. Consider:

@property void myfun(void delegate(string) lol) {
   lol("say it ");
}

void main() {
   myfun = (string what) {
   assert(0, what ~ " lol");
   };
}


--
Simen


Re: Why Ruby?

2010-12-12 Thread Simen kjaeraas

Andrei Alexandrescu  wrote:


fun (a, b ; c) stmt

=>

fun(c, (a, b) { stmt })

This could and should be generalized for more parameters, which I'm sure  
is very useful:


fun (a, b ; c, d) stmt

=>

fun(c, d, (a, b) { stmt })

Of course "fun" could be actually "obj.method".

With this we have a compelling syntax that has semantics obtained via  
lowering.


This is very nice. UP VOTES!!1


--
Simen


  1   2   3   4   5   6   7   8   9   10   >