Re: Conditional compilation of array of structs initializer

2017-11-09 Thread Tony via Digitalmars-d-learn

Thanks Mike!


Re: Distinct "static" parent property contents for children

2017-11-09 Thread Timoses via Digitalmars-d-learn
On Thursday, 9 November 2017 at 14:34:10 UTC, Steven 
Schveighoffer wrote:

On 11/9/17 7:34 AM, Timoses wrote:



I suppose this is what Adam suggested, correct?


Yes, more or less. It's just an actual implementation vs. a 
description in case it wasn't clear.


[...]

It's not much different from what Adam and I suggested. The 
only thing you are missing is the ability to call the virtual 
member without an instance. But if you name your functions 
properly, and follow a convention, it will work for you.


-Steve


Greatly elaborated! Thank you, Steve!

I hope the vtable stuff is gonna be mentioned in the lectures I'm 
currently watching : P.


Re: Conditional compilation of array of structs initializer

2017-11-09 Thread Michael V. Franklin via Digitalmars-d-learn

On Friday, 10 November 2017 at 06:22:51 UTC, Tony wrote:
Doing a port of some C code that has an #ifdef in the middle of 
an initialization for an array of structs. I am getting a 
compile error trying to get equivalent behavior with "static 
if" or "version". Is there a way to achieve this other than 
making two separate array initialization sections?


struct a {
   int y;
   int z;
}

immutable string situation = "abc";

int main()
{
   a[] theArray = [
  { 10, 20 },
// version(abc)
static if (situation == "abc")
{
  { 30, 40 },
}
  { 50, 60 }
  ];
   return 0;
}


Here's my attempt. There's probably a more elegant way, but it's 
the best I could do.


import std.stdio;

struct a {
int y;
int z;
}

enum situation = "abc";

int main()
{
enum head = "a[] theArray = [ {10, 20},";
static if (situation == "abc")
{
enum middle = "{ 30, 40},";   
}
else
{
enum middle = ""; 
}
enum tail = "{ 50, 60 }];";
mixin(head ~ middle ~ tail);

writeln(head ~ middle ~ tail);

return 0;
}

The use of enums for this is called manifest constants 
(https://dlang.org/spec/enum.html#manifest_constants).  It's more 
analogous to #define in C.


Mixins are documented here 
(https://dlang.org/spec/statement.html#mixin-statement)


Mike


Conditional compilation of array of structs initializer

2017-11-09 Thread Tony via Digitalmars-d-learn
Doing a port of some C code that has an #ifdef in the middle of 
an initialization for an array of structs. I am getting a compile 
error trying to get equivalent behavior with "static if" or 
"version". Is there a way to achieve this other than making two 
separate array initialization sections?


struct a {
   int y;
   int z;
}

immutable string situation = "abc";

int main()
{
   a[] theArray = [
  { 10, 20 },
// version(abc)
static if (situation == "abc")
{
  { 30, 40 },
}
  { 50, 60 }
  ];
   return 0;
}


Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread rikki cattermole via Digitalmars-d-learn

On 09/11/2017 4:00 PM, Petar Kirov [ZombineDev] wrote:

On Thursday, 9 November 2017 at 13:00:15 UTC, ParticlePeter wrote:
On Thursday, 9 November 2017 at 12:19:00 UTC, Petar Kirov [ZombineDev] 
wrote:

On Thursday, 9 November 2017 at 11:08:21 UTC, ParticlePeter wrote:

Any experience reports or general suggestions?
I've used only D threads so far.


It would be far easier if you use druntime + @nogc and/or de-register 
latency-sensitive threads from druntime [1], so they're not 
interrupted even if some other thread calls the GC. Probably the path 
of least resistance is to call [2] and queue @nogc tasks on [3].


If you really want to pursue the version(D_BetterC) route, then 
you're essentially on your own to use the threading facilities 
provided by your target OS, e.g.:


https://linux.die.net/man/3/pthread_create
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx 



Though you need to be extra careful not to use thread-local storage 
(e.g. only shared static and __gshared) and not to rely on (shared) 
static {con|de}structors, dynamic arrays, associative arrays, 
exceptions, classes, RAII, etc., which is really not worth it, unless 
you're writing very low-level code (e.g. OS kernels and drivers).


[1]: https://dlang.org/phobos/core_thread#.thread_detachThis
[2]: https://dlang.org/phobos/core_memory#.GC.disable
[3]: https://dlang.org/phobos/std_parallelism#.taskPool


Forgot to mention, I'll try this first, I think its a good first step 
towards -BetterC usage. But in the end I want to see how far I can get 
with the -BetterC feature.


In short, the cost / benefit of going all the way version(D_BetterC) is 
incredibly poor for regular applications, as you end up a bit more 
limited than with modern C++ (> 11) for prototyping. For example, even 
writers of D real-time audio plugins don't go as far.


I just did some work for Guillaume Piolat (p0nce author of dplug), guess 
what is going to be used again, druntime!





Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread Jacob Carlborg via Digitalmars-d-learn

On 2017-11-09 17:52, Petar Kirov [ZombineDev] wrote:

Thanks for reminding me, I keep forgetting that it should just work 
(minus initialization?).


What do you mean "initialization"? Any type that can be used in C in TLS 
should work in D as well (except for macOS 32bit, if anyone cares).


--
/Jacob Carlborg


Re: Any book recommendation for writing a compiler?

2017-11-09 Thread Jim Hewes via Digitalmars-d-learn


Thanks for those references! I'm also interested in looking through 
those. I had computation theory in college a long time ago but never 
took a compiler course.



On 11/7/2017 5:26 AM, Tony wrote:
Author Allen Holub has made his out-of-print book, Compiler Design in C, 
available as a free pdf download:


http://holub.com/compiler/


And Torben Mogensen is doing the same with his more recent Basics of 
Compiler Design:


http://www.diku.dk/~torbenm/Basics/



---
This email has been checked for viruses by AVG.
http://www.avg.com





Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread Petar via Digitalmars-d-learn
On Thursday, 9 November 2017 at 16:08:20 UTC, Jacob Carlborg 
wrote:

On 2017-11-09 13:19, Petar Kirov [ZombineDev] wrote:

Though you need to be extra careful not to use thread-local 
storage


I think TLS should work, it's the OS that handles TLS, not 
druntime.


Thanks for reminding me, I keep forgetting that it should just 
work (minus initialization?).


Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread Jacob Carlborg via Digitalmars-d-learn

On 2017-11-09 13:19, Petar Kirov [ZombineDev] wrote:


Though you need to be extra careful not to use thread-local storage


I think TLS should work, it's the OS that handles TLS, not druntime.

--
/Jacob Carlborg


Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread Petar via Digitalmars-d-learn

On Thursday, 9 November 2017 at 13:00:15 UTC, ParticlePeter wrote:
On Thursday, 9 November 2017 at 12:19:00 UTC, Petar Kirov 
[ZombineDev] wrote:
On Thursday, 9 November 2017 at 11:08:21 UTC, ParticlePeter 
wrote:

Any experience reports or general suggestions?
I've used only D threads so far.


It would be far easier if you use druntime + @nogc and/or 
de-register latency-sensitive threads from druntime [1], so 
they're not interrupted even if some other thread calls the 
GC. Probably the path of least resistance is to call [2] and 
queue @nogc tasks on [3].


If you really want to pursue the version(D_BetterC) route, 
then you're essentially on your own to use the threading 
facilities provided by your target OS, e.g.:


https://linux.die.net/man/3/pthread_create
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx

Though you need to be extra careful not to use thread-local 
storage (e.g. only shared static and __gshared) and not to 
rely on (shared) static {con|de}structors, dynamic arrays, 
associative arrays, exceptions, classes, RAII, etc., which is 
really not worth it, unless you're writing very low-level code 
(e.g. OS kernels and drivers).


[1]: https://dlang.org/phobos/core_thread#.thread_detachThis
[2]: https://dlang.org/phobos/core_memory#.GC.disable
[3]: https://dlang.org/phobos/std_parallelism#.taskPool


Forgot to mention, I'll try this first, I think its a good 
first step towards -BetterC usage. But in the end I want to see 
how far I can get with the -BetterC feature.


In short, the cost / benefit of going all the way 
version(D_BetterC) is incredibly poor for regular applications, 
as you end up a bit more limited than with modern C++ (> 11) for 
prototyping. For example, even writers of D real-time audio 
plugins don't go as far.
If you're writing libraries, especially math-heavy template code, 
CTFE and generic code in general, then version(D_BetterC) is a 
useful tool for verifying that your library doesn't need 
unnecessary dependencies preventing it from being trivially 
integrated in foreign language environments.


Well if you like generic code as much as I do, you can surely do 
great with version(D_BetterC) even for application code, but you 
would have to make alomst every non-builtin type that you use in 
your code a template parameter (or alternatively an extern 
(C++/COM) interface if that works in -betterC), so you can easily 
swap druntime/phobos-based implementations for your custom ones, 
one by one, but I guess few people would be interested in 
following this path.


Re: Distinct "static" parent property contents for children

2017-11-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 11/9/17 7:34 AM, Timoses wrote:



I suppose this is what Adam suggested, correct?


Yes, more or less. It's just an actual implementation vs. a description 
in case it wasn't clear.






This is a more general question: Why is it not possible to 
implement/override static methods?


Static methods aren't virtual. There isn't a notion of a vtable for 
static methods on a class -- they are simply normal functions in a 
different namespace. I know other languages allow this, D does not.



interface I // or abstract class I
{
     static int fun();


This is actually a non-virtual method, it needs an implementation.


}
class A : I
{
     static int fun() { return 3; }


Note, that this isn't necessary to implement I. In other words:

class A : I {}

also works.


}
void main()
{
     I i = new A();
     i.fun();    // <--- linker error


This is calling I.fun, which has no implementation.


}

or replacing interface with an abstract base class.

Static overriding would be quite interesting in terms of compile-time 
handling of objects.


In a way, static overriding *does* work at compile time:

class A
{
  static int i() { return 1; }
}

class B : A
{
  static int i() { return 2; }
}

assert(A.i == 1);
assert(B.i == 2);

But what you are asking is to have an instance of B, even when 
statically typed as A, call the derived version of the static method. In 
essence, this is super-similar to a virtual method, but instead of 
taking an instance, it wouldn't need to. But the key here is you *need* 
an instance for it to make any sense.


It's not much different from what Adam and I suggested. The only thing 
you are missing is the ability to call the virtual member without an 
instance. But if you name your functions properly, and follow a 
convention, it will work for you.


-Steve


Re: ddox empty public methods/interfaces etc

2017-11-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 11/8/17 10:45 PM, Andrey wrote:


I just added to dub.json this:


"-ddoxFilterArgs": [
    "--min-protection=Public"
]


i.e. without --only-documented option, in this way ddox will generate 
documentation for all public methods, even if there is no docstring.


Interesting. I misunderstood then how ddox works. I thought the json it 
gets is the output from the ddoc generator, but now I realize it's the 
output from the parser itself.


So sure, this makes sense. Sorry for the misinformation!

-Steve


Re: Cannot reduce an empty iterable w/o an explicit seed value

2017-11-09 Thread Nicholas Wilson via Digitalmars-d-learn

On Thursday, 9 November 2017 at 12:40:49 UTC, Vino wrote:

Hi All,

  Request your help, when i execute the below line of code i am 
getting an error message as "Cannot reduce an empty iterable 
w/o an explicit seed value" , The below lie of code will 
iterate several file system and will report the size of the 
folder (level 1) which is greater than 10GB.


The reason you get this is because when evaluating an empty 
directory there are no files, so it is like you are trying to do

   [].sum

which can give no sensible result.



Re: Cannot reduce an empty iterable w/o an explicit seed value

2017-11-09 Thread Nicholas Wilson via Digitalmars-d-learn

On Thursday, 9 November 2017 at 12:40:49 UTC, Vino wrote:

Hi All,

  Request your help, when i execute the below line of code i am 
getting an error message as "Cannot reduce an empty iterable 
w/o an explicit seed value" , The below lie of code will 
iterate several file system and will report the size of the 
folder (level 1) which is greater than 10GB.



Program:
auto coSizeDirList (string FFs, int SizeDir) {
float subdirTotal;
float subdirTotalGB;
Array!string Result;
	auto dFiles = Array!string ((dirEntries(FFs, 
SpanMode.shallow).filter!(a => a.isDir))[].map!(a => a.name));

foreach (d; parallel(dFiles[], 1)) {
	auto SdFiles = Array!float ((dirEntries(join(["?\\", d]), 
SpanMode.depth).filter!(a => a.isFile))[].map!(a => 
to!float(a.size)));

{
	subdirTotalGB = ((reduce!((a,b) => a + b)(SdFiles)) / 1024 / 
1024 / 1024);

}
 if (subdirTotalGB > SizeDir) {
Result.insertBack(d); 
Result.insertBack(to!string(subdirTotalGB));

}
}
return Result;
}

From,
Vino.B


The problem is
subdirTotalGB = ((reduce!((a,b) => a + b)(SdFiles)) / 1024 / 1024 
/ 1024);
with reduce you need to give it a seed (an initial value to start 
with).

See
https://dlang.org/phobos/std_algorithm_iteration.html#.reduce


int[] arr = [ 1, 2, 3, 4, 5 ];
// Sum all elements
auto sum = reduce!((a,b) => a + b)(0, arr);
writeln(sum); // 15

// Sum again, using a string predicate with "a" and "b"
sum = reduce!"a + b"(0, arr);
writeln(sum); // 15


To your actual use case, you can do:

foreach (d; parallel(dFiles[], 1)) {
float subdirTotalGB = dirEntries(join(["?\\", d]), 
SpanMode.depth)

.filter!(a => a.isFile))
.map!(a => to!float(a.size)))
.fold!((a, b) => a + b)(0) // Provide an explicit seed.

if (subdirTotalGB > SizeDir) {
Result.insertBack(d);
Result.insertBack(to!string(subdirTotalGB));
}
}




Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread ParticlePeter via Digitalmars-d-learn
On Thursday, 9 November 2017 at 12:19:00 UTC, Petar Kirov 
[ZombineDev] wrote:
On Thursday, 9 November 2017 at 11:08:21 UTC, ParticlePeter 
wrote:

Any experience reports or general suggestions?
I've used only D threads so far.


It would be far easier if you use druntime + @nogc and/or 
de-register latency-sensitive threads from druntime [1], so 
they're not interrupted even if some other thread calls the GC. 
Probably the path of least resistance is to call [2] and queue 
@nogc tasks on [3].


If you really want to pursue the version(D_BetterC) route, then 
you're essentially on your own to use the threading facilities 
provided by your target OS, e.g.:


https://linux.die.net/man/3/pthread_create
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx

Though you need to be extra careful not to use thread-local 
storage (e.g. only shared static and __gshared) and not to rely 
on (shared) static {con|de}structors, dynamic arrays, 
associative arrays, exceptions, classes, RAII, etc., which is 
really not worth it, unless you're writing very low-level code 
(e.g. OS kernels and drivers).


[1]: https://dlang.org/phobos/core_thread#.thread_detachThis
[2]: https://dlang.org/phobos/core_memory#.GC.disable
[3]: https://dlang.org/phobos/std_parallelism#.taskPool


Forgot to mention, I'll try this first, I think its a good first 
step towards -BetterC usage. But in the end I want to see how far 
I can get with the -BetterC feature.


Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread ParticlePeter via Digitalmars-d-learn
On Thursday, 9 November 2017 at 12:43:54 UTC, Petar Kirov 
[ZombineDev] wrote:
On Thursday, 9 November 2017 at 12:30:49 UTC, rikki cattermole 
wrote:

On 09/11/2017 12:19 PM, Petar Kirov [ZombineDev] wrote:
On Thursday, 9 November 2017 at 11:08:21 UTC, ParticlePeter 
wrote:

Any experience reports or general suggestions?
I've used only D threads so far.


It would be far easier if you use druntime + @nogc and/or 
de-register latency-sensitive threads from druntime [1], so 
they're not interrupted even if some other thread calls the 
GC. Probably the path of least resistance is to call [2] and 
queue @nogc tasks on [3].


If you really want to pursue the version(D_BetterC) route, 
then you're essentially on your own to use the threading 
facilities provided by your target OS, e.g.:


https://linux.die.net/man/3/pthread_create
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx


You can use a library like libuv to handle threads 
(non-language based TLS too, not sure that it can be tied in 
unfortunately).


Yeah, any cross-platform thread-pool / event loop library with 
C interface should obviously be preferred than manual use of 
raw thread primitives.


Essentially, try to follow Sean Parent's advice on "No 
Raw/Incidental *":

https://www.youtube.com/watch?v=zULU6Hhp42w


This all is good input, thanks.
I was looking into:
https://github.com/GerHobbelt/pthread-win32

Anyone used this?


Cannot reduce an empty iterable w/o an explicit seed value

2017-11-09 Thread Vino via Digitalmars-d-learn

Hi All,

  Request your help, when i execute the below line of code i am 
getting an error message as "Cannot reduce an empty iterable w/o 
an explicit seed value" , The below lie of code will iterate 
several file system and will report the size of the folder (level 
1) which is greater than 10GB.



Program:
auto coSizeDirList (string FFs, int SizeDir) {
float subdirTotal;
float subdirTotalGB;
Array!string Result;
	auto dFiles = Array!string ((dirEntries(FFs, 
SpanMode.shallow).filter!(a => a.isDir))[].map!(a => a.name));

foreach (d; parallel(dFiles[], 1)) {
	auto SdFiles = Array!float ((dirEntries(join(["?\\", d]), 
SpanMode.depth).filter!(a => a.isFile))[].map!(a => 
to!float(a.size)));

{
	subdirTotalGB = ((reduce!((a,b) => a + b)(SdFiles)) / 1024 / 
1024 / 1024);

}
 if (subdirTotalGB > SizeDir) {
Result.insertBack(d); Result.insertBack(to!string(subdirTotalGB));
}
}
return Result;
}

From,
Vino.B


Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread Petar via Digitalmars-d-learn
On Thursday, 9 November 2017 at 12:30:49 UTC, rikki cattermole 
wrote:

On 09/11/2017 12:19 PM, Petar Kirov [ZombineDev] wrote:
On Thursday, 9 November 2017 at 11:08:21 UTC, ParticlePeter 
wrote:

Any experience reports or general suggestions?
I've used only D threads so far.


It would be far easier if you use druntime + @nogc and/or 
de-register latency-sensitive threads from druntime [1], so 
they're not interrupted even if some other thread calls the 
GC. Probably the path of least resistance is to call [2] and 
queue @nogc tasks on [3].


If you really want to pursue the version(D_BetterC) route, 
then you're essentially on your own to use the threading 
facilities provided by your target OS, e.g.:


https://linux.die.net/man/3/pthread_create
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx


You can use a library like libuv to handle threads 
(non-language based TLS too, not sure that it can be tied in 
unfortunately).


Yeah, any cross-platform thread-pool / event loop library with C 
interface should obviously be preferred than manual use of raw 
thread primitives.


Essentially, try to follow Sean Parent's advice on "No 
Raw/Incidental *":

https://www.youtube.com/watch?v=zULU6Hhp42w


Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread rikki cattermole via Digitalmars-d-learn

On 09/11/2017 12:19 PM, Petar Kirov [ZombineDev] wrote:

On Thursday, 9 November 2017 at 11:08:21 UTC, ParticlePeter wrote:

Any experience reports or general suggestions?
I've used only D threads so far.


It would be far easier if you use druntime + @nogc and/or de-register 
latency-sensitive threads from druntime [1], so they're not interrupted 
even if some other thread calls the GC. Probably the path of least 
resistance is to call [2] and queue @nogc tasks on [3].


If you really want to pursue the version(D_BetterC) route, then you're 
essentially on your own to use the threading facilities provided by your 
target OS, e.g.:


https://linux.die.net/man/3/pthread_create
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx 


You can use a library like libuv to handle threads (non-language based 
TLS too, not sure that it can be tied in unfortunately).


Re: Distinct "static" parent property contents for children

2017-11-09 Thread Timoses via Digitalmars-d-learn
On Wednesday, 8 November 2017 at 18:33:15 UTC, Steven 
Schveighoffer wrote:

On 11/8/17 12:38 PM, Timoses wrote:

Hey,

wrapping my head around this atm..



[snip]

so what you want is a static variable per subclass, but that 
the base class can access.


What I would recommend is this:

abstract class Base
{
   int x();
}

class A : Base
{
  private static int _x = 1;
  int x() { return _x; }
}

class B : Base
{
  private static int _x = 2;
  int x() { return _x; }
}

Note that this doesn't do *everything* a static variable can, 
since x() requires an instance (i.e. you can't do A.x). But the 
actual variable itself is static since the backing is static. 
This is the only way to provide access of x to the Base that I 
can think of.


-Steve


I suppose this is what Adam suggested, correct?



This is a more general question: Why is it not possible to 
implement/override static methods?


interface I // or abstract class I
{
static int fun();
}
class A : I
{
static int fun() { return 3; }
}
void main()
{
I i = new A();
i.fun();// <--- linker error
}

or replacing interface with an abstract base class.

Static overriding would be quite interesting in terms of 
compile-time handling of objects.


Re: How you guys go about -BetterC Multithreading?

2017-11-09 Thread Petar via Digitalmars-d-learn

On Thursday, 9 November 2017 at 11:08:21 UTC, ParticlePeter wrote:

Any experience reports or general suggestions?
I've used only D threads so far.


It would be far easier if you use druntime + @nogc and/or 
de-register latency-sensitive threads from druntime [1], so 
they're not interrupted even if some other thread calls the GC. 
Probably the path of least resistance is to call [2] and queue 
@nogc tasks on [3].


If you really want to pursue the version(D_BetterC) route, then 
you're essentially on your own to use the threading facilities 
provided by your target OS, e.g.:


https://linux.die.net/man/3/pthread_create
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx

Though you need to be extra careful not to use thread-local 
storage (e.g. only shared static and __gshared) and not to rely 
on (shared) static {con|de}structors, dynamic arrays, associative 
arrays, exceptions, classes, RAII, etc., which is really not 
worth it, unless you're writing very low-level code (e.g. OS 
kernels and drivers).


[1]: https://dlang.org/phobos/core_thread#.thread_detachThis
[2]: https://dlang.org/phobos/core_memory#.GC.disable
[3]: https://dlang.org/phobos/std_parallelism#.taskPool


How you guys go about -BetterC Multithreading?

2017-11-09 Thread ParticlePeter via Digitalmars-d-learn

Any experience reports or general suggestions?
I've used only D threads so far.



Re: Distinct "static" parent property contents for children

2017-11-09 Thread Timoses via Digitalmars-d-learn
On Wednesday, 8 November 2017 at 17:46:42 UTC, Adam D. Ruppe 
wrote:

On Wednesday, 8 November 2017 at 17:38:27 UTC, Timoses wrote:

Are there better options/ways of achieving this?


What are you actually trying to achieve? What are you using 
these variables for?


Well, I have the following outline:

class File
{
Section[] sections;
}
abstract class Section
{
enum Part { Header, Content, Footer};
SectionEntry[Part] entries;
}
class SectionEntry
{
bool isComment;
string[] lines;
}

And then I'd like to have somthing like predefined sections, e.g.:

class SectionTypeA : Section
{
 // provide "static" information that is
 // always the same for this type of seciton
  // however, the Content part may vary
}


Are there more elegant ways of achieving this?


My first thought is you should abandon the variable approach 
and just use an abstract function that returns the value for 
each child via overriding. It won't be static, but it also 
won't take any per-instance memory.


Sounds like a good approach. I'll try this out for sure.