Re: Range of n lines from stdin

2013-12-28 Thread Jakob Ovrum

On Friday, 27 December 2013 at 20:30:52 UTC, Ivan Kazmenko wrote:
Hmm?..  From my experience, attempting to use a range in a 
wrong way usually results in a compilation error.  For example, 
I can't do

n.iota.map!(_ = readln).sort())
since MapResult isn't a random access range with swappable 
elements. I can instead do

n.iota.map!(_ = readln).array().sort())
and it allocates an array and works as expected.  So, how do I 
misuse that range?


Yes, the idea is that ranges only present interfaces that make 
sense, so cases of misuse will result in a compilation error. 
However, hacks like using map with functions that ignore their 
argument(s) throws that out of the window: `r` in `auto r = 
n.iota.map!(_ = readln);` claims to support forward, 
bidirectional and random access (all read-only, as the argument 
function returns by value) as well as slicing, but none of these 
make any sense; all access primitives do exactly the same thing, 
with the result being different every time. Even the simplest 
invariants fail, such as `r.front == r.front`, and `popFront`, 
`popBack` and slicing only has a binary effect, whether or not 
the range is empty yet.


Hmm.  For example, that could be a RNG emitting (a range of) 
random numbers, then empty is always false.  But we still 
want a new random number each time.  Something like

n.iota.map!(_ = uniform(0, 10))


That would only provide `n` random numbers, not an infinite 
number.


All the random number generator types in `std.random` are 
infinite forward ranges of random numbers, which is completely 
fine. For any PRNG `r`, `r.front == r.front` is true, and remains 
the same number until `r.popFront()`, it correctly has no length 
and is always non-empty (infinite range), and `r.save` works 
correctly etc.



So, something like
n.iota.map !(_ = readln).writeln;
is bad style but
writeln (n.iota.map !(_ = readln));
better shows what's the main action?  Makes sense for me.


No, it has nothing to do with syntax. The two examples are 
completely equivalent, and the only problem is that it breaks the 
invariant that the result of map's transformation function should 
be derived from the arguments it was given. The fact that the 
transformation function is impure is not in itself a problem: 
pure functions can also ignore arguments, and impure functions 
can return consistent results while still being necessarily 
impure.


Perhaps there's a wholly different way of thinking about this 
in which the first definition makes much more sense than then 
second one from the start.  If so, please share it.


All you have to do is look at the signature of the function, 
which is the primary part of its documentation:


Repeat!T repeat(T)(T value);

It takes one value of any type T, not a function pointer or 
delegate that returns T. Even if you give it a function pointer 
or delegate (which your example does not), it will simply repeat 
that function pointer or delegate, never calling it.


As I already explained, `readln.repeat(n)` is just a different 
way of writing `readln().repeat(n)` which in turn is also 
equivalent to `repeat(readln(), n)`. This should make it 
perfectly clear what it does - `readln` is called and its return 
value is passed to `repeat`. Barring one relatively obscure 
exception[1], this is the only way to interpret the expression 
regardless of the signature of the function, as a consequence of 
basic languages rules common to the entire C family of 
programming languages.


[1] ... in D we have something (slightly controversial) called 
the `lazy` parameter storage class, but when used, it is clearly 
visible in the signature of the function. 
http://dlang.org/function.html#parameters


Re: Ultra-pure map()?

2013-12-28 Thread David Held

On 12/27/2013 7:32 PM, Marco Leise wrote: [...]
 Side effects and altering the input object itself makes me
 want to pull out my crucifix. You shall not have impurity in
 your functional style code!

Why not?  There are many impure functional languages, and most 
non-functional languages that allow functional style allow mutation. 
OOP is all about hiding state, which is the opposite of referential 
transparency.  Are you saying we should never map/fold over OOP ranges? 
 That seems like an unnecessary restriction for dogma's sake. 
Obviously, map() has to be lazy to support infinite ranges.  But I 
assume that reduce() must be eager so that you actually get a result (I 
mean, it could probably be made lazy at enormous expense, but that would 
just be silly).  So, if you want side effects, I guess you have to do 
the slightly dirty trick of calling reduce() without actually reducing 
anything.


I guess the right thing to do would be to make a new algorithm that 
implements an eager map() but perhaps doesn't bother with the result, 
called invoke().  This carries none of the semantic baggage of 
well-known pure higher-order functions, and even sounds more OOP-like. 
Most of the other features of map() (like parallel iteration) are pretty 
nice to have in eager form.


Dave



Re: Ultra-pure map()?

2013-12-28 Thread FreeSlave

On Saturday, 28 December 2013 at 09:18:00 UTC, David Held wrote:

On 12/27/2013 7:32 PM, Marco Leise wrote: [...]
 Side effects and altering the input object itself makes me
 want to pull out my crucifix. You shall not have impurity in
 your functional style code!

Why not?  There are many impure functional languages, and most 
non-functional languages that allow functional style allow 
mutation. OOP is all about hiding state, which is the opposite 
of referential transparency.  Are you saying we should never 
map/fold over OOP ranges?
 That seems like an unnecessary restriction for dogma's sake. 
Obviously, map() has to be lazy to support infinite ranges.  
But I assume that reduce() must be eager so that you actually 
get a result (I mean, it could probably be made lazy at 
enormous expense, but that would just be silly).  So, if you 
want side effects, I guess you have to do the slightly dirty 
trick of calling reduce() without actually reducing anything.


I guess the right thing to do would be to make a new 
algorithm that implements an eager map() but perhaps doesn't 
bother with the result, called invoke().  This carries none 
of the semantic baggage of well-known pure higher-order 
functions, and even sounds more OOP-like. Most of the other 
features of map() (like parallel iteration) are pretty nice to 
have in eager form.


Dave


If you want to get result just now, then use 'array' function 
from std.array module.


map!fun(range).array;

or

array(map!fun(range));


Re: Ultra-pure map()?

2013-12-28 Thread bearophile

David Held:


Why not?


Because mixing map/filter and wild unrestrained side effects is 
asking for troubles (bugs in your code).


Bye,
bearophile


Re: Range of n lines from stdin

2013-12-28 Thread Ivan Kazmenko

Many thanks to Marco, Ali and Jakob for the answers!

On Saturday, 28 December 2013 at 08:56:53 UTC, Jakob Ovrum wrote:
On Friday, 27 December 2013 at 20:30:52 UTC, Ivan Kazmenko 
wrote:
Hmm?..  From my experience, attempting to use a range in a 
wrong way usually results in a compilation error.  For 
example, I can't do

n.iota.map!(_ = readln).sort())
since MapResult isn't a random access range with swappable 
elements. I can instead do

n.iota.map!(_ = readln).array().sort())
and it allocates an array and works as expected.  So, how do I 
misuse that range?


Yes, the idea is that ranges only present interfaces that make 
sense, so cases of misuse will result in a compilation error. 
However, hacks like using map with functions that ignore their 
argument(s) throws that out of the window: `r` in `auto r = 
n.iota.map!(_ = readln);` claims to support forward, 
bidirectional and random access (all read-only, as the argument 
function returns by value) as well as slicing, but none of 
these make any sense; all access primitives do exactly the same 
thing, with the result being different every time. Even the 
simplest invariants fail, such as `r.front == r.front`, and 
`popFront`, `popBack` and slicing only has a binary effect, 
whether or not the range is empty yet.


OK, I'm now beginning to understand how hacky is that.

All the random number generator types in `std.random` are 
infinite forward ranges of random numbers, which is completely 
fine. For any PRNG `r`, `r.front == r.front` is true, and 
remains the same number until `r.popFront()`, it correctly has 
no length and is always non-empty (infinite range), and 
`r.save` works correctly etc.


So, for both of my examples, support for desired behavior is 
provided at the different side: not a non-caching repeat for a 
given function but a range of lines or random numbers with the 
desired properties instead of such function.  Maybe that's 
usually the right thing to do in the general case, too...


Perhaps there's a wholly different way of thinking about this 
in which the first definition makes much more sense than then 
second one from the start.  If so, please share it.


All you have to do is look at the signature of the function, 
which is the primary part of its documentation:


Repeat!T repeat(T)(T value);

It takes one value of any type T, not a function pointer or 
delegate that returns T. Even if you give it a function pointer 
or delegate (which your example does not), it will simply 
repeat that function pointer or delegate, never calling it.


So what I initially wanted is possible with something like (I 
just checked):

(readln!(string)) . repeat(n) . map!(f = f('\n'))
However, I'm having a hard time trying to get rid of !(string) 
and '\n' to make something like the following work:

(readln) . repeat(n) . map!(f = f())
Anyway, even the second line (which does not compile) looks 
cryptic a bit.  And it still has the problem of silently adding 
empty lines after end-of-file was reached.


[1] ... in D we have something (slightly controversial) called 
the `lazy` parameter storage class, but when used, it is 
clearly visible in the signature of the function. 
http://dlang.org/function.html#parameters


Thank you for the link.  This is indeed what was my other 
expectation for repeat.


Ivan Kazmenko.


Re: Ultra-pure map()?

2013-12-28 Thread Timon Gehr

On 12/28/2013 10:17 AM, David Held wrote:

On 12/27/2013 7:32 PM, Marco Leise wrote: [...]
  Side effects and altering the input object itself makes me
  want to pull out my crucifix. You shall not have impurity in
  your functional style code!

Why not?  There are many impure functional languages, and most
non-functional languages that allow functional style allow mutation. OOP
is all about hiding state, which is the opposite of referential
transparency.


That's news to me. OOP does not mandate a procedural programming style.


...
Obviously, map() has to be lazy to support infinite ranges.  ...
So, if you want side effects, I guess you have to do
the slightly dirty trick of calling reduce() without actually reducing
anything.
...


What's the point? There are cleaner ways of doing the same.

The implementation of map assumes that the result is independent of how 
it is iterated, and using it with callables that make it fail this 
criterion is usually at best confusing and at worst a bug.



I guess the right thing to do would be to make a new algorithm that
implements an eager map() but perhaps doesn't bother with the result,
called invoke().  ...


I wouldn't call this an 'eager map'. It's a shallow wrapper around a 
foreach loop.


Re: getting __DIR__ and __TIME__ of compilation?

2013-12-28 Thread Jacob Carlborg

On 2013-12-27 21:14, Ravn wrote:


Eh, it does? :-?
It prints a relative path when I used writeln(__FILE__), I'm on windows 7.


Hmm, ok. It prints the full path when I run it via my text editor. But 
it prints the relative path when I run it via the command line.



Tried enum path = dirName(__FILE__), compiles normally, no error from
the compiler, but it still returns a relative path instead of a fullpath
in my machine.


Yes, same here, don't know why it didn't compile the first time I tried it.

Perhaps this deserves an enhancement request. I really though __FILE__ 
would give the full path.


--
/Jacob Carlborg


importing modules from a function

2013-12-28 Thread Hugo Florentino

Hi,

A moment ago I was reading a reply to one of my posts, and noticed 
Artur Skawina did this:



void main(string argv[]) {
   import std.string;
...


I didn't know D allowed importing modules from a function.
Now, my question is: what is the advantage of this over importing the 
regular way?


Regards, Hugo


Custom binary operators

2013-12-28 Thread Joseph Rushton Wakeling
Is there any way with D to define custom binary operators for user-defined 
types?  I'm thinking of examples like MATLAB/Octave using the operators .+, .-, 
etc. to define element-wise addition, subtraction, etc. of matrices.


AFAICS just doing something like

auto opBinary(string op, T)(T rhs)
if (op == .+)
{
...
}

... won't work, because the parser won't accept a code line like

auto c = a .+ b;

... but is there some way to make this work?

Assuming that it's not possible to define custom operators in regular code, I 
guess the alternative is to use templates to ensure an override of the regular + 
operator?


Re: Custom binary operators

2013-12-28 Thread Dicebot
AFAIK it is intentionally banned to constrain operator 
overloading abuse.


Re: importing modules from a function

2013-12-28 Thread Dicebot
On Saturday, 28 December 2013 at 14:23:17 UTC, Hugo Florentino 
wrote:

I didn't know D allowed importing modules from a function.
Now, my question is: what is the advantage of this over 
importing the regular way?


Regards, Hugo


Several advantages:

1) It is easier to maintain the code as origins of imported 
symbols become obvious immediately - less chance to get unused 
imports hanging around after some refactoring.


2) Considerably smaller chance of name clash between symbols from 
different modules (can only clash if used within same function / 
scope)


3) If it is templated function / scope, it won't be imported 
unless template is instantiated. lazy import effect. That may 
improve compilation times quite a lot in certain style of code.


Automatic translation of opUnary!++ into opOpAssign!+

2013-12-28 Thread Francesco Cattoglio
So, while I was studying the apropriate template constraints for 
my shiny new iota implementation, I found out this funny thing:


import std.stdio;

class Test{
int x = 41;
Test opOpAssign(string op)(int rhs) if (op == +) {
 x += rhs;
 return this;
}
}

void main() {
Test t1 = new Test;
//class Test has no opUnary defined, so the following
//gets automagically converted into (t1) += (1)
++t1;
writeln(t1.x); //prints 42, correct!
}

This actually comes really handy, but I couldn't find it into the 
language documentation on dlang.org, so it surprised me.
Did I miss it in the language specification? Should we add it 
somewhere to the docs?
Anyone with some spare time care to explain briefly what was the 
rationale behind this?


Re: Custom binary operators

2013-12-28 Thread Joseph Rushton Wakeling

On 28/12/13 16:24, Dicebot wrote:

AFAIK it is intentionally banned to constrain operator overloading abuse.


Ahh, makes sense.  But isn't it possible to do something with templates that 
would allow for something like,


auto a = matrix(...);
auto b = matrix(...);

auto c = ElementWise!(a * b);

... where the ElementWise template would ensure that the binary operation is 
applied successively to corresponding pairs of elements from the matrices?


Re: Custom binary operators

2013-12-28 Thread John Colvin
On Saturday, 28 December 2013 at 16:33:24 UTC, Joseph Rushton 
Wakeling wrote:

On 28/12/13 16:24, Dicebot wrote:
AFAIK it is intentionally banned to constrain operator 
overloading abuse.


Ahh, makes sense.  But isn't it possible to do something with 
templates that would allow for something like,


auto a = matrix(...);
auto b = matrix(...);

auto c = ElementWise!(a * b);

... where the ElementWise template would ensure that the binary 
operation is applied successively to corresponding pairs of 
elements from the matrices?


how about:

a.elementWise * b

where a.elementWise returns a wrapper struct around a that 
implements elementwise arithmetic as opposed to the normal 
arithmetic.


The operators would return instances of Matrix, not elementWise, 
to avoid accidentally spilling a Matrix.ElementWise struct in to 
ensuing code unintentionally. With a shorter alias it's rather 
neat.


auto e = ((a .EW* b) .EW/ c ) * d;


Re: Custom binary operators

2013-12-28 Thread Joseph Rushton Wakeling

On 28/12/13 18:50, John Colvin wrote:

how about:

a.elementWise * b

where a.elementWise returns a wrapper struct around a that implements
elementwise arithmetic as opposed to the normal arithmetic.

The operators would return instances of Matrix, not elementWise, to avoid
accidentally spilling a Matrix.ElementWise struct in to ensuing code
unintentionally. With a shorter alias it's rather neat.

auto e = ((a .EW* b) .EW/ c ) * d;


That's a rather cool idea -- thanks for that! :-)

That said, I think it'd be difficult to really justify it as a pattern for 
general use.  If you're doing mathematical work à la MATLAB, you want a proper 
operator, not a trick which lets you sort of write something that looks a little 
like one.  I'm a little disappointed there's no ready way to do this :-(


Re: Automatic translation of opUnary!++ into opOpAssign!+

2013-12-28 Thread monarch_dodra
On Saturday, 28 December 2013 at 15:37:06 UTC, Francesco 
Cattoglio wrote:
So, while I was studying the apropriate template constraints 
for my shiny new iota implementation, I found out this funny 
thing:


import std.stdio;

class Test{
int x = 41;
Test opOpAssign(string op)(int rhs) if (op == +) {
 x += rhs;
 return this;
}
}

void main() {
Test t1 = new Test;
//class Test has no opUnary defined, so the following
//gets automagically converted into (t1) += (1)
++t1;
writeln(t1.x); //prints 42, correct!
}

This actually comes really handy, but I couldn't find it into 
the language documentation on dlang.org, so it surprised me.
Did I miss it in the language specification? Should we add it 
somewhere to the docs?
Anyone with some spare time care to explain briefly what was 
the rationale behind this?


I seem to remember that this is mentioned in TDPL? That's not 
spec of course, but I think it's mentioned here.


I'm a bit fuzy about the shortcuts, but I *think* there are a 
couple other shortcuts like this, such as a += b = a = a + b?


In any case, http://dlang.org/operatoroverloading.html; needs to 
be updated


DLL's reflection and Exceptions

2013-12-28 Thread TheFlyingFiddle

Hello everyone!

I'm currently working on a run-time reflection module. The intent 
of this module is to simplify the process of loading functions / 
classes / structs from DLL's loaded at run-time.


It works something like this ATM:

//In pluggin.d (A dll module)

void foo() { ... }
class Bar  { ... }
struct Baz { ... }

... more members

At the end of the file i have a function like this

export extern(C) MetaAssembly getMetaAssembly()
{
   //Tuple of filters to only load relevant stuff.
   alias filters = standardFilters;
   return AssemblyGenerator!(filters, module1, ..., moduleN).data;
}


//In program.d (A host program)
void main()
{
   auto dll = loadDll(pluggin0.dll);
   MetaAssembly assembly = 
dll.func!(getter_t)(getMetaAssembly)()


   //Use assembly to find some classes
   //construct them and invoke some methods.
   MetaClass c = assembly.
  classes.
  find!(x = x.name == Foo)[0];
   RTObject fooObj = c.constructors[0].create();

   MetaMethod method = c.methods[0];
   method.invoke(fooObj, Hello);
}


AssemblyGenerator!(...) extracts all needed information from the 
modules and stores them in a collection of structs that can be 
used at run-time to do stuff like create instances / set fields / 
check attributes. Normal reflection stuff.


This works fine for normal code flow. However it all falls apart 
as soon as any function located in a DLL throws an exception. If 
an exception is thrown the application freezes, usually visual 
studio crashes with First hand exception: Privileged Instruction 
(some address).


I have hacked my way around this limitation like so:

//pluggin.d

alias exception_handler_t = void function(Throwable) nothrow;
__gshared exception_handler_t exceptionHandler;

//program.d
Throwable t = null;
void exceptionHandler(Throwable thrown) nothrow
{
t = thrown;
}

bool exceptionThrown()
{
   return t !is null;
}

void rethrowException()
{
   DLLException e = new DLLException(t.toString());
   t = null;
   throw e;
}

void main()
{
   auto dll = loadDLL(pluggin0.dll);
   MetaAssembly assembly = 
dll.func!(getter_t)(getMetaAssembly)()	

   auto field = assembly.
staticFields.
find!(x = x.name == exceptionHandler);

   field.set(exceptionHandler)
}

The reflection api wrapps all functions / methods with a try - 
catch that will
call the exceptionHandler if an exception occurs. At the calle 
side (program.a)
after every call it will check if an exception was thrown and if 
so rethrowng it

as a DLLException.

This workaround works, (atleast for now) but i don't like it. It 
complicates the low-level reflection api alot and it only solves 
the problem of calls from program.d to pluggin.d not the other 
way around (unless i wrap them aswell).


So now to the questions.

1. Why can't i throw exceptions over a DLL boundary?
2. Are there any problems with my hack other then the ones 
already stated?

3. Does other workarounds exist?


Thank you for your time!





Re: Custom binary operators

2013-12-28 Thread H. S. Teoh
On Sat, Dec 28, 2013 at 07:35:00PM +0100, Joseph Rushton Wakeling wrote:
 On 28/12/13 18:50, John Colvin wrote:
 how about:
 
 a.elementWise * b
 
 where a.elementWise returns a wrapper struct around a that implements
 elementwise arithmetic as opposed to the normal arithmetic.
 
 The operators would return instances of Matrix, not elementWise, to
 avoid accidentally spilling a Matrix.ElementWise struct in to ensuing
 code unintentionally. With a shorter alias it's rather neat.
 
 auto e = ((a .EW* b) .EW/ c ) * d;
 
 That's a rather cool idea -- thanks for that! :-)
 
 That said, I think it'd be difficult to really justify it as a
 pattern for general use.  If you're doing mathematical work à la
 MATLAB, you want a proper operator, not a trick which lets you sort
 of write something that looks a little like one.  I'm a little
 disappointed there's no ready way to do this :-(

The other way is to use a compile-time DSL, which lets you implement
whatever operators you want in whatever syntax you fancy.


T

-- 
Today's society is one of specialization: as you grow, you learn more and more 
about less and less. Eventually, you know everything about nothing.


scope(faliure) flow control.

2013-12-28 Thread TheFlyingFiddle

int foo()
{
   scope(failure) return 22;
   throw new Exception(E);
}

unittest
{
   assert(foo() == 22);
}

Is this defined behavior? At least in x64 dmd the exception is 
swallowed and the assert evaluates to true.


In any case what should happen? Should the method return or 
should the exception be propagated up the callstack?


Re: scope(faliure) flow control.

2013-12-28 Thread Casper Færgemand
On Saturday, 28 December 2013 at 20:31:14 UTC, TheFlyingFiddle 
wrote:

int foo()
{
   scope(failure) return 22;
   throw new Exception(E);
}

unittest
{
   assert(foo() == 22);
}

Is this defined behavior? At least in x64 dmd the exception is 
swallowed and the assert evaluates to true.


In any case what should happen? Should the method return or 
should the exception be propagated up the callstack?


It's rewritten as follows:

int foo()
{
   try {
  throw new Exception(E);
   } catch (Exception e) { // or whatever the D syntax is, I 
never used it

  return 22;
   }
}

So yes, it's intended. scope(exit) uses finally instead of catch.


Re: Custom binary operators

2013-12-28 Thread John Colvin

On Saturday, 28 December 2013 at 20:06:46 UTC, H. S. Teoh wrote:
On Sat, Dec 28, 2013 at 07:35:00PM +0100, Joseph Rushton 
Wakeling wrote:

On 28/12/13 18:50, John Colvin wrote:
how about:

a.elementWise * b

where a.elementWise returns a wrapper struct around a that 
implements

elementwise arithmetic as opposed to the normal arithmetic.

The operators would return instances of Matrix, not 
elementWise, to
avoid accidentally spilling a Matrix.ElementWise struct in to 
ensuing

code unintentionally. With a shorter alias it's rather neat.

auto e = ((a .EW* b) .EW/ c ) * d;

That's a rather cool idea -- thanks for that! :-)

That said, I think it'd be difficult to really justify it as a
pattern for general use.  If you're doing mathematical work à 
la
MATLAB, you want a proper operator, not a trick which lets you 
sort

of write something that looks a little like one.  I'm a little
disappointed there's no ready way to do this :-(


The other way is to use a compile-time DSL, which lets you 
implement

whatever operators you want in whatever syntax you fancy.


T


Yeah. To risk being glib, if you want a domain specific language, 
use a domain specific language.


Then again, including some convenient abstraction for some common 
tasks while remaining within the main language is nice.


Re: scope(faliure) flow control.

2013-12-28 Thread Ali Çehreli

On 12/28/2013 12:50 PM, Casper Færgemand shortt...@hotmail.com wrote:

 On Saturday, 28 December 2013 at 20:31:14 UTC, TheFlyingFiddle wrote:
 int foo()
 {
scope(failure) return 22;
throw new Exception(E);
 }

 unittest
 {
assert(foo() == 22);
 }

 Is this defined behavior? At least in x64 dmd the exception is
 swallowed and the assert evaluates to true.

 In any case what should happen? Should the method return or should the
 exception be propagated up the callstack?

 It's rewritten as follows:

 int foo()
 {
 try {
throw new Exception(E);
 } catch (Exception e) { // or whatever the D syntax is, I never 
used it

return 22;

There must also be the re-throwing of the caught exception:

 throw e;

What happens is, the return statement does not allow that to happen.

 }
 }

 So yes, it's intended. scope(exit) uses finally instead of catch.

The spec brings restrictions to scope(exit) and scope(success) but does 
not say much about scope(failure):


  http://dlang.org/statement.html#ScopeGuardStatement

Yeah, it appears that OP's code is legal.

Ali



extern(C) function declarations and extra keywords.

2013-12-28 Thread Jeremy DeHaan
I was thinking of adding some keywords like final, pure, and 
nothrow in to my library to improve various things where 
improvements could be made. As I was thinking about this, I 
wondered about my extern(C) function declarations and how 
keywords could improve those as well.


Since the C functions can't access anything from D code save for 
what is passed through as parameters, can it be called pure? And 
if so, does the compiler know how to distinguish C and D in this 
instance and make it inherently pure? Does purity do anything in 
terms of speed/safety here?


I noticed that in Deimos and Derelict that most(if not all) C 
function declarations are marked as nothrow. What are the 
speed/safety benefits of including this? And likewise as with the 
pure aspect, does the compiler know how to distinguish C and D 
and make it inherently nothrow?


C's name mangling doesn't allow function overloading, but as far 
as I know you can overload extern(C) functions in D. Does adding 
final help with speed improvements in the D side of things if 
added to an extern(C) function declaration?


Thanks much!


Re: extern(C) function declarations and extra keywords.

2013-12-28 Thread ponce
Since the C functions can't access anything from D code save 
for what is passed through as parameters, can it be called pure?


Probably not since it might not be pure and eg. mutate global 
variables.



Does purity do anything in terms of speed/safety here?
A pure function is expected to give the same result given the 
same parameters.
Similar calls to a pure function (same parameters) can be 
optimized out by the compiler.


I noticed that in Deimos and Derelict that most(if not all) C 
function declarations are marked as nothrow. What are the 
speed/safety benefits of including this?


No speed or safety benefit, but it allows to call these C 
functions in functions marked nothrow themselves. As a rule of 
thumb you can put nothrow systematically when binding C code.


And likewise as with the pure aspect, does the compiler know 
how to distinguish C and D and make it inherently nothrow?


No.

C's name mangling doesn't allow function overloading, but as 
far as I know you can overload extern(C) functions in D. Does 
adding final help with speed improvements in the D side of 
things if added to an extern(C) function declaration?


No.