Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Tofu Ninja via Digitalmars-d-learn

On Thursday, 3 December 2015 at 21:04:00 UTC, Nordlöw wrote:

...


I think reflection will be a bad choice for this because of 
private members and what not.

I think the correct way is:

void reset(C)(ref C c)
{
static if(is(C == class))
{
auto init = typeid(c).init();
auto objmem = ((cast(void*)c)[0 .. init.length]);
if(init.ptr == null) (cast(byte[])objmem)[] = 0;
else objmem[] = init[];
if(c.classinfo.defaultConstructor != null)
c.classinfo.defaultConstructor(c);
}
else c = C.init;
}

Seems to work for structs, classes, and basic types. It even 
calls the default constructor for classes, even if there is 
inheritance and the object passed in is not actually C but a sub 
class of C.


Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Tofu Ninja via Digitalmars-d-learn

On Friday, 4 December 2015 at 04:08:33 UTC, Tofu Ninja wrote:

On Thursday, 3 December 2015 at 21:04:00 UTC, Nordlöw wrote:

...


I think reflection will be a bad choice for this because of 
private members and what not.

I think the correct way is:

void reset(C)(ref C c)
{
static if(is(C == class))
{
auto init = typeid(c).init();
auto objmem = ((cast(void*)c)[0 .. init.length]);
if(init.ptr == null) (cast(byte[])objmem)[] = 0;
else objmem[] = init[];
if(c.classinfo.defaultConstructor != null)
c.classinfo.defaultConstructor(c);
}
else c = C.init;
}

Seems to work for structs, classes, and basic types. It even 
calls the default constructor for classes, even if there is 
inheritance and the object passed in is not actually C but a 
sub class of C.


Oh after reading chris's post, probably should change to...

void reset(C)(ref C c)
{
static if(is(C == class))
{
auto type_info = typeid(c);
auto class_info = c.classinfo;
destroy(c);
auto init = type_info.init();
auto objmem = ((cast(void*)c)[0 .. init.length]);
if(init.ptr == null) (cast(byte[])objmem)[] = 0;
else objmem[] = init[];
if(class_info.defaultConstructor != null)
class_info.defaultConstructor(c);
else throw new Exception("No default constructor");
}
else c = C.init;
}


Re: Palindromes

2015-12-03 Thread Meta via Digitalmars-d-learn

On Friday, 4 December 2015 at 01:10:41 UTC, Jim Barnett wrote:
Really? If it leads to "hard to detect errors", I have a hard 
time believing that can be "idiomatic D".


It's used throughout the standard library, granted I don't think 
there's any occurrences of importing inside a while loop. The 
issues with nested imports are well known but also hard to fix 
without breaking code. However, they cut down on template bloat 
and the standard library makes very heavy use of templates. Thus 
a tradeoff is made. It's usually not nested imports by themselves 
that create these hard to detect errors, however. It's a few 
different D features working in concert.


Observe the following code:

struct Test
{
int num = 1;
string text = `"this is a line of text"`;

void printMessage()
{
import std.conv, std.stdio;

writeln(text("My text is ", text, " and my num is ", num));
}
}

void main()
{
Test t;
t.printMessage();
}

It prints: "My text is  and my num is 0"

Why the empty space? Because instead of referring to this.text 
inside of the printMessage method, `text` refers to 
std.conv.text. The nested import overrides the member variable in 
the outer scope.


I have never seen a language that encourages the user to 
specify dependencies inside a loop. I am hoping I misunderstood 
something here.


Sorry, I thought you were referring more generally to nested 
imports. No, imports in a while loop are not encouraged; imports 
in a struct or a template are.


Re: Palindromes

2015-12-03 Thread Jim Barnett via Digitalmars-d-learn

On Friday, 4 December 2015 at 03:33:55 UTC, Meta wrote:
I have never seen a language that encourages the user to 
specify dependencies inside a loop. I am hoping I 
misunderstood something here.


Sorry, I thought you were referring more generally to nested 
imports. No, imports in a while loop are not encouraged; 
imports in a struct or a template are.


That's interesting food for thought. At this point, I am just 
trying trying to transliterate my C++ and Ruby solutions for 
project Euler problems to D, and trying to get a better grasp on 
the D type system. Compile-time optimization isn't of much 
interest to me right now, but I am glad you pointed out that is 
something else to consider.


How to check session before access to static page?

2015-12-03 Thread Suliman via Digitalmars-d-learn

void main()
{
auto router = new URLRouter;
router.get("/", 
serveStaticFiles("D:\\code\\onlineTest\\index.html"));
router.get("/admin", 
serveStaticFiles("D:\\code\\onlineTest\\admin.html"));

router.any("/foo", );

auto settings = new HTTPServerSettings;
settings.port = 8080;
settings.bindAddresses = ["::", "127.0.0.1"];
settings.sessionStore = new MemorySessionStore; // SESSION
}


void foo(HTTPServerRequest req, HTTPServerResponse res)
{
if (req.session)
{
   res.writeBody("Hello, World!", "text/plain");
}
}

Before showing foo I can check session status. But How to check 
session status for static /admin page?





Re: utils.toBulkString is not accesible from utils

2015-12-03 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, December 02, 2015 06:33:32 Andre via Digitalmars-d-learn wrote:
> Hi,
>
> for following coding there is an error during compilation:
>
>module utils;
>
>package string toBulkString(string s)
>{
> import std.string: format;
> return "$%s\r\n%s\r\n".format(s.length, s);
>}
>
>unittest
>{
> string actual = "foobar".toBulkString();
> //...
>}
>
> >> source\utils.d(11,39): Error: function utils.toBulkString is
> >> not accessible from module utils
>
> The error disappears if I change the visibility attribute from
> package to private.
> This seems to be a bug, is it?
>
> Version: DMD v2.069.0-b2
>
> Kind regards
> André

I believe that the problem is that there is no package for toBulkString to
be in. utils is a top-level module and is not in a package. Now, arguably it
should be an error to use the package attribute in such a module rather than
giving an error when you try and use it, but I'm pretty sure that that's the
source of your problem. If utils were actually in a package, then it should
work.

- Jonathan M Davis



__traits and string mixins

2015-12-03 Thread Christian Köstlin via Digitalmars-d-learn

Hi,

I started an experiment with the informations that are available for 
compile time reflection.


What I wanted to create is a thor like cli parser library, that forces 
you to encapsulate your programs into subclasses of Dli. The commands
and options, that are understood by the generated cli are taken from the 
members, that have to be enhanced with UCA's. The __traits facility is 
used to generate from those a string mixin, that also has to be added to 
your class. A sample usage would look like this:


class Git : Dli {
  @Option string verbose;

  @Task void helloWorld(string option1, string option2) {
...
your code here
...
  }
  mixin(createDli!(Git));
}

this program should be able to understand:

./git --verbose helloWorld --option1=pretty --option2=whatever

When I created this stuff the __traits stuff got me thinking, because I 
iterate e.g. allMembers of a class, but the result of this code is mixed 
in again into the class (and creates new members on the way).


So how exactly is this done compiler wise?

Another question that came up for me is: would it not be awesome, if the 
whole AST would be available in traits? The facilities as they are, are 
already a little bit more powerful than e.g. java reflection, because 
you can e.g. get to the name of parameters of method.


thanks for your input,

christian

p.s.: if you are interested in a very rough first version of the code or 
if you have enhancements for it, please have a look at: 
https://github.com/gizmomogwai/dli




Re: Struct initializers as expressions

2015-12-03 Thread Chris Wright via Digitalmars-d-learn
On Thu, 03 Dec 2015 06:38:20 +, Mike Parker wrote:

> AFAIK, your only option is to use a struct constructor. This is the sort
> of thing they're  used for.

Which brings be back to positional arguments, which means that someone 
wishing to supply a limit on the number of query results must also give 
me the number of results per page, even if she doesn't care about the 
number of results per page.

Is it worth posting a DIP for struct literals of the form `Name{fieldname: 
value}` ?


Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Sebastiaan Koppe via Digitalmars-d-learn

On Thursday, 3 December 2015 at 21:13:59 UTC, Nordlöw wrote:
Need to assert that not a function and mutability 
(std.traits.isMutable)


Yeah you need to do that.


Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Jakob Ovrum via Digitalmars-d-learn

On Thursday, 3 December 2015 at 21:04:00 UTC, Nordlöw wrote:

Given

class C
{
// lots of members
}

and a function

f(C c)
{
}

is there a generic way, perhaps through reflection, to reset 
(inside f) all members of `c` to their default values? 
Something along


foreach(ref member; __traits(allMembers, c))
{
member = typeof(member).init;
}


import std.traits;

foreach(i, member; FieldNameTuple!C)
{
alias FieldType = Fields!C[i];
static if(isMutable!FieldType)
__traits(getMember, c, member) = FieldType.init;
}

However, it doesn't work in the presence of private fields. A 
better alternative is probably to `destroy` the instance then 
`emplace` to default-construct a new instance over it.


Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Nordlöw via Digitalmars-d-learn

On Thursday, 3 December 2015 at 21:04:00 UTC, Nordlöw wrote:

Something along

foreach(ref member; __traits(allMembers, c))
{
member = typeof(member).init;
}


This works for me:

void resetAllMembers(T)(T c)
if (is(T == class))
{
foreach (ref m; c.tupleof)
{
import std.traits : isMutable;
alias M = typeof(m);
static if (isMutable!M)
{
m = M.init;
}
}
}



Re: Palindromes

2015-12-03 Thread Justin Whear via Digitalmars-d-learn
On Thu, 03 Dec 2015 21:40:05 +, Jim Barnett wrote:

> TL;DR I couldn't figure out how to write `isPalindrome` in terms of
> std.algorithm.mutation.reverse
> 
> I recognize it's more efficient in terms of CPU time and memory than my
> C++ solution, but I suspect there is a shorter expression to detect
> palindromes if efficiency isn't the primary concern. So I am interested
> in seeing implementations of `isPalindrome` that utilize
> `std.algorithm.mutation.reverse`, or anyone who cares to enlighten me
> why that might be a misguided thing to want. Thanks for reading.

I don't think you want reverse because it works in-place; you'd need to 
make a copy to compare against.  std.range.retro is probably what you're 
looking for:

bool isPalindrome(R)(R range) if (isBidirectionalRange!R)
{
return range.equal(range.retro);
}

Obviously this does more work than strictly necessary, but has the 
brevity you're looking for.


Re: Palindromes

2015-12-03 Thread Jim Barnett via Digitalmars-d-learn

On Thursday, 3 December 2015 at 22:14:02 UTC, Justin Whear wrote:
I don't think you want reverse because it works in-place; you'd 
need to make a copy to compare against.  std.range.retro is 
probably what you're looking for:


bool isPalindrome(R)(R range) if (isBidirectionalRange!R)
{
return range.equal(range.retro);
}

Obviously this does more work than strictly necessary, but has 
the brevity you're looking for.


Awesome, and thank you! Clearly I need to learn more about the D 
type system and std.range, but this is exactly the type of answer 
is was looking for.


Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Nordlöw via Digitalmars-d-learn

On Thursday, 3 December 2015 at 21:38:48 UTC, Chris Wright wrote:

The terrible way is something like:

void reset(Object o)
in {
  assert(!(o is null));
}
body {
  auto p = cast(ubyte*)*cast(void**)
  auto ci = o.classinfo;
  auto init = cast(ubyte)ci.init;
  p[0..init.length] = init[];
  if (ci.defaultConstructor) {
ci.defaultConstructor(o);
  } else {
throw new Exception("no default constructor; object is in 
invalid

state");
  }
}


In what way is this better than my solution?


Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Chris Wright via Digitalmars-d-learn
On Thu, 03 Dec 2015 21:55:04 +, Nordlöw wrote:

> On Thursday, 3 December 2015 at 21:38:48 UTC, Chris Wright wrote:
>> The terrible way is something like:
>>
>> void reset(Object o)
>> in {
>>   assert(!(o is null));
>> }
>> body {
>>   auto p = cast(ubyte*)*cast(void**)
>>   auto ci = o.classinfo;
>>   auto init = cast(ubyte)ci.init; p[0..init.length] = init[];
>>   if (ci.defaultConstructor) {
>> ci.defaultConstructor(o);
>>   } else {
>> throw new Exception("no default constructor; object is in
>> invalid state");
>>   }
>> }
> 
> In what way is this better than my solution?

I called my solution "terrible", which doesn't suggest that I think well 
of it compared to alternatives. I did this mainly to provide another 
implementation that someone else had alluded to. But since you asked...

You're ignoring the distinction between runtime and compiletime types, 
and you are resetting fields to the default values of their types, not 
the default values of the fields.

To wit:

class Foo {
  int i = 5;
}
class Bar : Foo {
  int j = 6;
  this() {}
  this(int a, int b) { i = a; j = b; }
}
Foo foo = new Bar(10, 10);
nordlow.resetAllFields(foo);

We expect foo to look like a default-initialized instance of whatever it 
began life as. Like if we implemented the equality operations, we'd 
expect to see this work: `assert(foo == new Bar);` But we don't. Your 
solution doesn't know what the default field value of Foo.i is, so it 
erroneously resets it to 0. We wanted 5.

Similarly, your solution ignores the fact that we've got an instance of 
Bar here, not an instance of Foo, and there are additional fields that 
need to be reset. You're using compile time reflection, so there's no way 
around that -- unless you create a virtual method with a mixin and 
require the user to mix it into each class in the hierarchy.

My solution still gets a ton wrong. I forgot to call the destructor, for 
instance. I can't call the constructor if it has parameters, and that 
means the object might well be in an invalid state. It's not safe in the 
face of potential runtime changes.

Assuming I encountered a case that both our solutions could handle 
correctly, I'd prefer yours. It's safer.


Re: Struct initializers as expressions

2015-12-03 Thread Enamex via Digitalmars-d-learn

On Thursday, 3 December 2015 at 15:31:49 UTC, Chris Wright wrote:

On Thu, 03 Dec 2015 06:38:20 +, Mike Parker wrote:

AFAIK, your only option is to use a struct constructor. This 
is the sort of thing they're  used for.


Which brings be back to positional arguments, which means that 
someone wishing to supply a limit on the number of query 
results must also give me the number of results per page, even 
if she doesn't care about the number of results per page.


Is it worth posting a DIP for struct literals of the form 
`Name{fieldname: value}` ?


I asked about that a while ago and was given noncommittal answers 
on why it wasn't accepted. I'd support your DIP.


Reset all Members of a Aggregate Instance

2015-12-03 Thread Nordlöw via Digitalmars-d-learn

Given

class C
{
// lots of members
}

and a function

f(C c)
{
}

is there a generic way, perhaps through reflection, to reset 
(inside f) all members of `c` to their default values? Something 
along


foreach(ref member; __traits(allMembers, c))
{
member = typeof(member).init;
}



Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 3 December 2015 at 21:04:00 UTC, Nordlöw wrote:
is there a generic way, perhaps through reflection, to reset 
(inside f) all members of `c` to their default values?


You could always copy the init back over it. For a struct:

s = Struct.init;

for a class... well, the code is a lot uglier and liable to break 
if you don't have the static type right. Maybe better off 
wrapping the class members in a struct and doing it that way.


Palindromes

2015-12-03 Thread Jim Barnett via Digitalmars-d-learn
TL;DR I couldn't figure out how to write `isPalindrome` in terms 
of std.algorithm.mutation.reverse


I have dabbled in D a few times over the past few years, but 
still pretty inexperienced. I decided to work on some project 
euler problems in D for fun. A problem requires detecting a 
palindrome. I solved this problem in C++ before with this:


bool is_palindrome(const string& str)
{
  return str == string(str.rbegin(), str.rend());
}

I found Andrei's response to a stackoverflow question here:

http://stackoverflow.com/questions/14469612/template-conflict-for-palindrome-algorithm-on-string-array

In his response, he suggests this:

bool isPalindrome(Range)(Range r)
{
while (!r.empty) {
if (a.front != a.back) {
  return false;
}
r.popFront();
if (r.empty) {
return true;
}
r.popBack();
}
return true;
}

I recognize it's more efficient in terms of CPU time and memory 
than my C++ solution, but I suspect there is a shorter expression 
to detect palindromes if efficiency isn't the primary concern. So 
I am interested in seeing implementations of `isPalindrome` that 
utilize `std.algorithm.mutation.reverse`, or anyone who cares to 
enlighten me why that might be a misguided thing to want. Thanks 
for reading.




Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Nordlöw via Digitalmars-d-learn

On Thursday, 3 December 2015 at 21:04:00 UTC, Nordlöw wrote:

Given

class C
{
// lots of members
}

and a function

f(C c)
{
}

is there a generic way, perhaps through reflection, to reset 
(inside f) all members of `c` to their default values? 
Something along


foreach(ref member; __traits(allMembers, c))
{
member = typeof(member).init;
}


Back in 2007 it didn't seem to exist a standard way of doing this:

http://forum.dlang.org/post/fbs9eg$721$1...@digitalmars.com

Is tupleof the best contender?


Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Sebastiaan Koppe via Digitalmars-d-learn

Haven't compiled but it should look something like this:

foreach(member; __traits(allMembers, typeof(c)))
__traits(getMember, c, member) = typeof(__traits(getMember, 
c, member)).init;




Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Nordlöw via Digitalmars-d-learn
On Thursday, 3 December 2015 at 21:08:30 UTC, Sebastiaan Koppe 
wrote:

Haven't compiled but it should look something like this:

foreach(member; __traits(allMembers, typeof(c)))
__traits(getMember, c, member) = typeof(__traits(getMember, 
c, member)).init;


Need to assert that not a function and mutability 
(std.traits.isMutable)


Re: Reset all Members of a Aggregate Instance

2015-12-03 Thread Chris Wright via Digitalmars-d-learn
The terrible way is something like:

void reset(Object o)
in {
  assert(!(o is null));
}
body {
  auto p = cast(ubyte*)*cast(void**)
  auto ci = o.classinfo;
  auto init = cast(ubyte)ci.init;
  p[0..init.length] = init[];
  if (ci.defaultConstructor) {
ci.defaultConstructor(o);
  } else {
throw new Exception("no default constructor; object is in invalid 
state");
  }
}

An object reference is just a pointer, but we can't directly cast it. So 
we make a pointer to it and cast that; the type system allows it. Now we 
can access the data that the object reference refers to directly.

`o.classinfo` gets the runtime type information object for the actual 
class that `o` belongs to. The `init` property gives you a single blob of 
bytes representing the default field values of that class. So we copy 
that over into the object.

To finish up, if the type has a default constructor, we invoke it. We 
don't have a way to identify any other constructors that we could invoke.

This is usually not a good thing to do, but if you really need to, you 
can.


Re: dataframe implementations

2015-12-03 Thread Jay Norwood via Digitalmars-d-learn
On Saturday, 21 November 2015 at 14:16:26 UTC, Laeeth Isharc 
wrote:


Not sure it is a great idea to use a variant as the basic 
option when very often you will know that every cell in a 
particular column will be of the same type.



I'm reading today about an n-dim extension to pandas named xray.  
Maybe should try to understand how that fits.  They support io 
from netCDF, and are making extensions to support blocked input 
using dask, so they can process data larger than in-memory limits.


http://xray.readthedocs.org/en/stable/data-structures.html
https://www.continuum.io/content/xray-dask-out-core-labeled-arrays-python


In general, pandas and xray are supporting with the requirement 
of pulling in data from storage of initially unknown column and 
index names and data types.  Julia throws in support of jit 
compilation and specialized operations for different data types.


It seems to me that D's strength would be in a quick compile, 
which would then allow you to replace the dictionary tag 
implementations and variants with something that used compile 
time symbol names and data types. Seems like that would provide 
more efficient processing, as well as better tab completion 
support when creating expressions.




Re: Palindromes

2015-12-03 Thread Nordlöw via Digitalmars-d-learn

On Thursday, 3 December 2015 at 21:40:05 UTC, Jim Barnett wrote:

Thanks for reading.


My version slightly adjusted version:


/** Returns: If range is a palindrome larger than $(D minLength).
See also: 
http://forum.dlang.org/thread/dlfeiszyweafpjioc...@forum.dlang.org#post-vpzuaqxvtdpzpeuorxdl:40forum.dlang.org
See also: 
https://stackoverflow.com/questions/21849580/equality-operator-in-favour-of-std-range-equal

TODO: Test graphemes in `string` and `wstring`.
*/
bool isSymmetric(R)(R range, size_t minLength = 0) // TODO good 
value for minLength?

if (isBidirectionalRange!(R))
{
static if (isRandomAccessRange!R) // arrays excluding 
`char[]` and `wchar[]`

{
if (range.length < minLength) { return false; }
}
size_t i = 0;
while (!range.empty)
{
import std.range.primitives: front, back, popFront, 
popBack;

if (range.front != range.back) return false;
range.popFront(); i++;
if (range.empty) break;
range.popBack(); i++;
}
return i >= minLength;
}

unittest
{
assert(`dallassallad`.isSymmetric);
assert(!`ab`.isSymmetric);
assert(`a`.isSymmetric);
assert(`åäå`.isSymmetric);
assert(`áá`.isSymmetric);
assert(`åäå`.isSymmetric(3));
assert(!`åäå`.isSymmetric(4));
assert(``.isSymmetric);
assert([1, 2, 2, 1].isSymmetric);
assert(![1, 2, 2, 1].isSymmetric(5));
}
alias isPalindrome = isSymmetric;



Re: Palindromes

2015-12-03 Thread Jim Barnett via Digitalmars-d-learn

On Friday, 4 December 2015 at 00:23:45 UTC, Jim Barnett wrote:
The `import` statement inside the `for`-loop kind of smells to 
me.




Sorry, inside the `while` loop


Re: Palindromes

2015-12-03 Thread Meta via Digitalmars-d-learn

On Friday, 4 December 2015 at 00:26:23 UTC, Jim Barnett wrote:

On Friday, 4 December 2015 at 00:23:45 UTC, Jim Barnett wrote:
The `import` statement inside the `for`-loop kind of smells to 
me.




Sorry, inside the `while` loop


In D it's considered idiomatic, but it can also cause some very 
hard to detect errors from time to time... I hate it for this 
reason and never do it in my own code.


Re: Palindromes

2015-12-03 Thread Jim Barnett via Digitalmars-d-learn

On Thursday, 3 December 2015 at 23:42:31 UTC, Nordlöw wrote:

On Thursday, 3 December 2015 at 21:40:05 UTC, Jim Barnett wrote:

Thanks for reading.


My version slightly adjusted version:


/** Returns: If range is a palindrome larger than $(D 
minLength).
See also: 
http://forum.dlang.org/thread/dlfeiszyweafpjioc...@forum.dlang.org#post-vpzuaqxvtdpzpeuorxdl:40forum.dlang.org
See also: 
https://stackoverflow.com/questions/21849580/equality-operator-in-favour-of-std-range-equal

TODO: Test graphemes in `string` and `wstring`.
*/
bool isSymmetric(R)(R range, size_t minLength = 0) // TODO good 
value for minLength?

if (isBidirectionalRange!(R))
{
static if (isRandomAccessRange!R) // arrays excluding 
`char[]` and `wchar[]`

{
if (range.length < minLength) { return false; }
}
size_t i = 0;
while (!range.empty)
{
import std.range.primitives: front, back, popFront, 
popBack;

if (range.front != range.back) return false;
range.popFront(); i++;
if (range.empty) break;
range.popBack(); i++;
}
return i >= minLength;
}

unittest
{
assert(`dallassallad`.isSymmetric);
assert(!`ab`.isSymmetric);
assert(`a`.isSymmetric);
assert(`åäå`.isSymmetric);
assert(`áá`.isSymmetric);
assert(`åäå`.isSymmetric(3));
assert(!`åäå`.isSymmetric(4));
assert(``.isSymmetric);
assert([1, 2, 2, 1].isSymmetric);
assert(![1, 2, 2, 1].isSymmetric(5));
}
alias isPalindrome = isSymmetric;


Interesting solution... probably worth some future analysis for 
me...


The `import` statement inside the `for`-loop kind of smells to me.

It's a little more generalized than I was looking for, but 
interesting. Your code is also searching for a threshold of 
symmetry. I haven't encountered a problem like that personally, 
but it's interesting and makes me think.


I appreciate your response.


Re: Palindromes

2015-12-03 Thread Jim Barnett via Digitalmars-d-learn

On Friday, 4 December 2015 at 00:50:17 UTC, Meta wrote:

On Friday, 4 December 2015 at 00:26:23 UTC, Jim Barnett wrote:

On Friday, 4 December 2015 at 00:23:45 UTC, Jim Barnett wrote:
The `import` statement inside the `for`-loop kind of smells 
to me.




Sorry, inside the `while` loop


In D it's considered idiomatic, but it can also cause some very 
hard to detect errors from time to time... I hate it for this 
reason and never do it in my own code.


Really? If it leads to "hard to detect errors", I have a hard 
time believing that can be "idiomatic D". I have never seen a 
language that encourages the user to specify dependencies inside 
a loop. I am hoping I misunderstood something here.


Re: Palindromes

2015-12-03 Thread Brad Anderson via Digitalmars-d-learn

On Friday, 4 December 2015 at 00:50:17 UTC, Meta wrote:

On Friday, 4 December 2015 at 00:26:23 UTC, Jim Barnett wrote:

On Friday, 4 December 2015 at 00:23:45 UTC, Jim Barnett wrote:
The `import` statement inside the `for`-loop kind of smells 
to me.




Sorry, inside the `while` loop


In D it's considered idiomatic, but it can also cause some very 
hard to detect errors from time to time... I hate it for this 
reason and never do it in my own code.


Inside a while, I don't think, really matches the idiom's goals. 
By only sticking imports inside the code that makes use of them 
you can achieve (I've never measured it though) compilation 
performance improvements in code that then imports the containing 
module but never makes use of the code in question. Sticking the 
import in the middle of the code is just noisy though, you want 
it nearby with limited scope but otherwise out of the way.