Bitwise ranges

2010-09-06 Thread Stanislav Blinov

Hello,

I'm working on range adapters that should allow reading and writing 
individual bits from/to other ranges. Right now for simplicity I only 
allow that for ranges that have numerics as ElementType.


Making an input bitwise range is pretty straightforward: popFront on 
original range is called as soon as all bits from it's 'front' have been 
read.


What I'm stuck with is an output bitwise range. If the adapted output 
range works via mutable front/popFront mechanism, implementing bitwise 
output is almost identical to bitwise input. But when adapted range 
provides output interface via put() method, I have no possible way to 
output data bit-by-bit. What I can do is a deferred put(), e.g. store a 
buffer in the bitwise range which I would fill with bits and put() it 
into adapted range as soon as all its bits have been written.
This may expose additional interface for clients: when bitwise range is 
'done' with adapted range, there may be a remaining partially filled 
buffer, which must also be put() into adapted range. This, in turn, may 
be done either implicitly (via destructor) or explicitly (via, e.g. 
complete() method of bitwise range).


Now I have a feeling that this somewhat falls out from standard range 
mechanisms. Consider:


ubyte[] input = [ 1, 2, 3 ];
uint[] output = new uint[1];

copy(bitwiseRead(input), bitwiseWrite(output));

Let's assume that output would only allow put() method. Now what copy() 
does is call popFront() on bitwiseRead and put() on bitwiseWrite. But no 
data would actually be written into output during copy(). Instead, there 
would be bits accumulated inside bitwise adapter when copy() returns, 
and they would be put() into output 'silently', without copy() 
explicitly asking for it.


Are such 'deferred popFront/deferred put' approaches a 'good' way to go 
with ranges? Or should bitwise adapter's popFront()/put() method always 
call popFront()/put() on adapted range?


Re: Bitwise ranges

2010-09-06 Thread bearophile
Stanislav Blinov:
 What I'm stuck with is an output bitwise range. If the adapted output 
 range works via mutable front/popFront mechanism, implementing bitwise 
 output is almost identical to bitwise input. But when adapted range 
 provides output interface via put() method, I have no possible way to 
 output data bit-by-bit. What I can do is a deferred put(), e.g. store a 
 buffer in the bitwise range which I would fill with bits and put() it 
 into adapted range as soon as all its bits have been written.
 This may expose additional interface for clients: when bitwise range is 
 'done' with adapted range, there may be a remaining partially filled 
 buffer, which must also be put() into adapted range. This, in turn, may 
 be done either implicitly (via destructor) or explicitly (via, e.g. 
 complete() method of bitwise range).

I am not sure, but this looks related to the idea of Vectorized Lazines that 
I have shown time ago (from MonetDB/X100), and that later has partially 
appeared in the Clojure language as Chunked Sequences:
http://digitalmars.com/d/archives/digitalmars/D/Re_Vectorized_Laziness_100676.html
http://blog.fogus.me/2010/01/22/de-chunkifying-sequences-in-clojure/
http://www.reddit.com/r/programming/comments/afyav/clojure_11_rc1_out_cuts_some_overhead_of/
http://www.infoq.com/news/2009/12/clojure-11-rc1-transients

I think the Range protocol needs some standard way to face the need of chunked 
or buffered lazynes.

Bye,
bearophile


Re: Bitwise ranges

2010-09-06 Thread Stanislav Blinov

 06.09.2010 15:37, bearophile wrote:


I am not sure, but this looks related to the idea of Vectorized Lazines that 
I have shown time ago (from MonetDB/X100), and that later has partially appeared in the 
Clojure language as Chunked Sequences:
http://digitalmars.com/d/archives/digitalmars/D/Re_Vectorized_Laziness_100676.html
http://blog.fogus.me/2010/01/22/de-chunkifying-sequences-in-clojure/
http://www.reddit.com/r/programming/comments/afyav/clojure_11_rc1_out_cuts_some_overhead_of/
http://www.infoq.com/news/2009/12/clojure-11-rc1-transients

I think the Range protocol needs some standard way to face the need of chunked 
or buffered lazynes.

Thanks, I'll look at that when home.


Re: Understanding isInfinite(Range)

2010-09-06 Thread Pelle

On 09/04/2010 02:11 PM, Simen kjaeraas wrote:

Peter Alexander peter.alexander...@gmail.com wrote:


== Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article

On Fri, 03 Sep 2010 11:12:29 -0400, Andrej Mitrovic
andrej.mitrov...@test.com wrote:
 What does char[1 + Range.empty] do? It looks rather cryptic..
char[1+Range.empty] is a type. If Range.empty is a compile-time
constant,
then this type is valid, otherwise it's not valid (the is expression
results to true if the argument is a valid type).
If it's valid, then Range.empty never changes. If it never changes and
it's always false, then it's infinite.
-Steve


That's really ugly code :-(

Is there a way you could write an isStatic(expr) template? Using
something like that would make the
code a hell of a lot more readable. At the moment, the code itself
does a very poor job of conveying
what it's trying to accomplish.

These SFINAE-like tricks should be black-boxed as much as possible, or
(at the very least)
commented so that people know what's going on.


template isStatic( alias T ) {
enum isStatic = is( char[1+T] );
}

unittest {
int n = 3;
assert( !isStatic!n );
assert( isStatic!1 );
enum r = 5;
assert( isStatic!r );
}


enum s = Hello;

assert (isStatic!s);

Gonna need more work than that.


Re: Understanding isInfinite(Range)

2010-09-06 Thread Philippe Sigaud
On Mon, Sep 6, 2010 at 18:47, Pelle pelle.mans...@gmail.com wrote:

 On 09/04/2010 02:11 PM, Simen kjaeraas wrote:

 Is there a way you could write an isStatic(expr) template? Using


 template isStatic( alias T ) {
 enum isStatic = is( char[1+T] );
 }

 unittest {
 int n = 3;
 assert( !isStatic!n );
 assert( isStatic!1 );
 enum r = 5;
 assert( isStatic!r );
 }


 enum s = Hello;

 assert (isStatic!s);

 Gonna need more work than that.


Why? That's exactly the behavior we want, or so it seems to me.


Re: Understanding isInfinite(Range)

2010-09-06 Thread Stanislav Blinov

Andrej Mitrovic wrote:

Apparently I can't post to D.learn from gmail without waiting for a review? 
What the..?

Anyway, I've posted this:

On a related note, I always wanted to make a template to replace the
dreaded is(typeof('delegate literal'())); calls.

For example, instead of this:

enum bool isInputRange = is(typeof(
{
   R r; // can define a range object
   if (r.empty) {}  // can test for empty
   r.popFront;  // can invoke next
   auto h = r.front; // can get the front of the range
}()));

We'd have a much cleaner call like so:

enum bool isInputRange = validate!(
{
   R r; // can define a range object
   if (r.empty) {}  // can test for empty
   r.popFront;  // can invoke next
   auto h = r.front; // can get the front of the range
});

But I haven't found a way to do it properly. If I call validate on a
type R range which doesn't feature the empty() method, then no matter
what the definition of validate is the compiler will error out because
it sees the call to r.empty() in the function literal, and 'r' doesn't
have an empty method.



What about __traits(compiles) ?


Re: Understanding isInfinite(Range)

2010-09-06 Thread Mafi

Am 06.09.2010 21:24, schrieb Andrej Mitrovic:

Apparently I can't post to D.learn from gmail without waiting for a review? 
What the..?

Anyway, I've posted this:

On a related note, I always wanted to make a template to replace the
dreaded is(typeof('delegate literal'())); calls.

For example, instead of this:

enum bool isInputRange = is(typeof(
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
}()));

We'd have a much cleaner call like so:

enum bool isInputRange = validate!(
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
});

But I haven't found a way to do it properly. If I call validate on a
type R range which doesn't feature the empty() method, then no matter
what the definition of validate is the compiler will error out because
it sees the call to r.empty() in the function literal, and 'r' doesn't
have an empty method.



You could just let your template get a string. Then
validate!q{}
should work. It looks almost exactly the same but has a 'q'.

Maybe you could even create an template overload which gets delegate 
which has always failing static assert with message you forget the 'q' 
but I don't know if template initialization comes before semantic 
analisys so I'm not sure this will work.


Mafi




Re: Understanding isInfinite(Range)

2010-09-06 Thread Andrej Mitrovic
I'd love to see this used more in Phobos. I don't know if there are any 
drawbacks, but this looks and works nicely:

import std.stdio : writeln;

void main()
{
writeln(isInputRange!(N));
}

class N
{
N test;

bool empty()
{
return false;
}

@property
void popFront()
{
}

@property
N front()
{
return test;
}
}


template isInputRange(R)
{
enum bool isInputRange = __traits(compiles,
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
});
}

If you uncomment some of those methods in class N, then you get back false, 
which is what you want. Currently isInputRange is defined like so in Phobos:

template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
}()));
}

It's getting close to LISP! :)

Andrej Mitrovic Wrote:

 Yeah, that could work:
 
 template isInputRange(R)
 {
enum bool isInputRange = __traits(compiles,
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
});
 }
 
 It does look nice. It would look even nicer if __traits gets renamed to meta.
 
 Stanislav Blinov Wrote:
 
  What about __traits(compiles) ?
 



Re: Understanding isInfinite(Range)

2010-09-06 Thread Pelle

On 09/06/2010 08:53 PM, Philippe Sigaud wrote:

On Mon, Sep 6, 2010 at 18:47, Pelle pelle.mans...@gmail.com
mailto:pelle.mans...@gmail.com wrote:

On 09/04/2010 02:11 PM, Simen kjaeraas wrote:

Is there a way you could write an isStatic(expr) template? Using


template isStatic( alias T ) {
enum isStatic = is( char[1+T] );
}

unittest {
int n = 3;
assert( !isStatic!n );
assert( isStatic!1 );
enum r = 5;
assert( isStatic!r );
}


enum s = Hello;

assert (isStatic!s);

Gonna need more work than that.


Why? That's exactly the behavior we want, or so it seems to me.




Sorry if I was unclear, that assert fails. Due to that you cannot add an 
integer and a string, not not that the string isn't static. It's an 
enum, so it definitely is static.


Re: Understanding isInfinite(Range)

2010-09-06 Thread Andrej Mitrovic
Is this legal?:

enum a = test;
a = test2;

Because it seems to compile. But that shouldn't work afaik..?

I can't reassign other enum types:

enum b = 4;
b = 5;  // error

which is expected.

Pelle Wrote:

 On 09/06/2010 08:53 PM, Philippe Sigaud wrote:
  On Mon, Sep 6, 2010 at 18:47, Pelle pelle.mans...@gmail.com
  mailto:pelle.mans...@gmail.com wrote:
 
  On 09/04/2010 02:11 PM, Simen kjaeraas wrote:
 
  Is there a way you could write an isStatic(expr) template? Using
 
 
  template isStatic( alias T ) {
  enum isStatic = is( char[1+T] );
  }
 
  unittest {
  int n = 3;
  assert( !isStatic!n );
  assert( isStatic!1 );
  enum r = 5;
  assert( isStatic!r );
  }
 
 
  enum s = Hello;
 
  assert (isStatic!s);
 
  Gonna need more work than that.
 
 
  Why? That's exactly the behavior we want, or so it seems to me.
 
 
 
 Sorry if I was unclear, that assert fails. Due to that you cannot add an 
 integer and a string, not not that the string isn't static. It's an 
 enum, so it definitely is static.



alias this ...

2010-09-06 Thread BLS

// ..snip
point3D p; // Da
p.x = 10;
p.y = 20;
p.z = 100;

point3D = = new point3D(10,20,30) // Njet
//etc
}

struct point {
int x;
int y;
}

struct point3D {

point p;
alias p this;
int z;

// NOPE :(
/*static point3D opcall(int _x, int _y, int _z) {
// ..snip
}*/

// NOPE :(
/*
this(int _x, int _y, int _z) {
// .. snip
}
*/
}
would be nice to use alias this as struct inheritance substitute, 
especially in conjunction with Implements!()


But maybe I don't get the alias this thingy. So what's my mistake  TIA


Re: alias this ...

2010-09-06 Thread BLS

On 06/09/2010 22:36, BLS wrote:

point3D = = new point3D(10,20,30) // Njet
 //etc


should be
point3D p3 = new point3D(10,20,30) // Njet


sorry


Re: Understanding isInfinite(Range)

2010-09-06 Thread Stanislav Blinov

Andrej Mitrovic wrote:

I'd love to see this used more in Phobos. I don't know if there are any 
drawbacks, but this looks and works nicely:

import std.stdio : writeln;

void main()
{
writeln(isInputRange!(N));
}

class N
{
N test;

bool empty()

{
return false;
}

@property

void popFront()
{
}

@property

N front()
{
return test;
}
}


template isInputRange(R)
{
enum bool isInputRange = __traits(compiles,
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
});
}

If you uncomment some of those methods in class N, then you get back false, 
which is what you want. Currently isInputRange is defined like so in Phobos:

template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r; // can define a range object
if (r.empty) {}  // can test for empty
r.popFront;  // can invoke next
auto h = r.front; // can get the front of the range
}()));
}

It's getting close to LISP! :)



If I remember correctly, it has been discussed not long ago that those 
is(typeof(...))s should really be __traits(compiles). Maybe it's just 
some code was written before those lovely __traits were introduced?..


Re: alias this ...

2010-09-06 Thread Stanislav Blinov

BLS wrote:

On 06/09/2010 22:36, BLS wrote:

point3D = = new point3D(10,20,30) // Njet
 //etc


should be
point3D p3 = new point3D(10,20,30) // Njet


sorry


Struct is value type, not reference type like class. You don't need 
'new' to create it, just uncomment your constructor ('this') and remove 
'new':


point3D p3 = point3D(10,20,30);

If you really need to allocate a point on the heap, then you'd have to 
use pointers:


point3D* p3 = new point3D(10,20,30);

Though you probably wouldn't need that much.


Re: Understanding isInfinite(Range)

2010-09-06 Thread Stanislav Blinov


Andrej Mitrovic wrote:


It does look nice. It would look even nicer if __traits gets renamed to meta.


By the way, there's no stopping writing

template isValidCode(alias code) { enum bool isValidCode = 
__traits(compiles, code); }


:)


Re: Understanding isInfinite(Range)

2010-09-06 Thread Andrej Mitrovic
is(typeof( is used a lot in Phobos. There's some ~260 calls like that, a quick 
search revealed. :p

Stanislav Blinov Wrote:

 If I remember correctly, it has been discussed not long ago that those 
 is(typeof(...))s should really be __traits(compiles). Maybe it's just 
 some code was written before those lovely __traits were introduced?..



Re: Understanding isInfinite(Range)

2010-09-06 Thread Andrej Mitrovic
That still won't work. Observe:

import std.stdio : writeln;

void main()
{
   writeln(isInputRange!(N));
}

class N
{
N test;

//~ bool empty() // oops, were not an input range anymore
//~ {
//~ return false;
//~ }

@property
void popFront()
{
}

@property
N front()
{
return test;
}
}


template isInputRange(R)
{
enum bool isInputRange = isValidCode!(
{
R r;// can define a range object
if (r.empty) {} // can test for empty
r.popFront; // can invoke next
auto h = r.front;   // can get the front of the range
});
}

template isValidCode(alias code) { enum bool isValidCode = __traits(compiles, 
code); }

Instead of returning false, it will give out a compiler error.

Stanislav Blinov Wrote:

 
 Andrej Mitrovic wrote:
 
  It does look nice. It would look even nicer if __traits gets renamed to 
  meta.
 
 By the way, there's no stopping writing
 
 template isValidCode(alias code) { enum bool isValidCode = 
 __traits(compiles, code); }
 
 :)



Re: Understanding isInfinite(Range)

2010-09-06 Thread Stanislav Blinov

Andrej Mitrovic wrote:

That still won't work. Observe:




Oops, sorry, I was too quick to conclude.


Using getchar

2010-09-06 Thread Andrej Mitrovic
I have some D1 code that I'm transfering to D2, and it's using getchar. I think 
I need to flush the buffer or something because the loop tends to skip:

import std.c.stdio;
import std.stdio;

void main()
{
char k;

for(int i = 0; i  10; i++) 
{
writef(Press key #%d:\t\n, i);
k = cast(char)getchar();
}
}

E.g.:
Press key #0:
a
Press key #1:
Press key #2:
b
Press key #3:
Press key #4:
c
Press key #5:
Press key #6:

I guess I could use scanf() instead.. or maybe something more D-ish perhaps? :)

Someone on the NGs started creating some user-friendly input functions, 
something like getInput!char(variable), or similar. But I can't find the topic, 
anyone know the link perhaps? It was fairly recent that someone posted it.


Re: Understanding isInfinite(Range)

2010-09-06 Thread Philippe Sigaud
On Mon, Sep 6, 2010 at 23:31, Andrej Mitrovic andrej.mitrov...@test.comwrote:

 That still won't work. Observe:



 template isInputRange(R)
 {
 enum bool isInputRange = isValidCode!(
 {
R r;// can define a range object
if (r.empty) {} // can test for empty
r.popFront; // can invoke next
auto h = r.front;   // can get the front of the range
});
 }

 template isValidCode(alias code) { enum bool isValidCode =
 __traits(compiles, code); }

 Instead of returning false, it will give out a compiler error.


That's because the part between the curly braces is evaluated before being
passed to the template. And there is no lazy alias.
As Mafi said, you can use a string, it's still the best way to move code
around in D. With q{ ... }, it's palatable.
And no, before you try it, there is no way to pass the {...} to another
template that would stringify it into a q{...} :-)

Maybe, eventually, something like this:

import std.stdio;


template isValidCode(alias code)
{
template For(T)
{
enum bool For = __traits(compiles, code(T.init));
}
}

void main()
{
   // use an anonymous templated function:
alias isValidCode!((r)
{
if (r.empty) {} // can test for empty
r.popFront; // can invoke next
auto h = r.front;   // c
}
) isInputRange;

//writeln(isInputRange.For!(int[]));
}

Except DMD doesn't like the commented-out line. Whaoh!



Philippe


Re: Using getchar

2010-09-06 Thread Stanislav Blinov

Andrej Mitrovic wrote:



Someone on the NGs started creating some user-friendly input functions, 
something like getInput!char(variable), or similar. But I can't find the topic, 
anyone know the link perhaps? It was fairly recent that someone posted it.


It was Jesse Phillips: 
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.comgroup=digitalmars.Dartnum=115546


Re: Understanding isInfinite(Range)

2010-09-06 Thread bearophile
Andrej Mitrovic:

 enum a = test;
 a = test2;
 
 Because it seems to compile. But that shouldn't work afaik..?

I have two open bug reports on this (and a third one was open by Don).

Bye,
bearophile


Re: Understanding isInfinite(Range)

2010-09-06 Thread Andrej Mitrovic
I'm sorry, but what does q{..} mean?

Philippe Sigaud Wrote:

 On Mon, Sep 6, 2010 at 23:31, Andrej Mitrovic 
 andrej.mitrov...@test.comwrote:
 
  That still won't work. Observe:
 
 
 
  template isInputRange(R)
  {
  enum bool isInputRange = isValidCode!(
  {
 R r;// can define a range object
 if (r.empty) {} // can test for empty
 r.popFront; // can invoke next
 auto h = r.front;   // can get the front of the range
 });
  }
 
  template isValidCode(alias code) { enum bool isValidCode =
  __traits(compiles, code); }
 
  Instead of returning false, it will give out a compiler error.
 
 
 That's because the part between the curly braces is evaluated before being
 passed to the template. And there is no lazy alias.
 As Mafi said, you can use a string, it's still the best way to move code
 around in D. With q{ ... }, it's palatable.
 And no, before you try it, there is no way to pass the {...} to another
 template that would stringify it into a q{...} :-)
 
 Maybe, eventually, something like this:
 
 import std.stdio;
 
 
 template isValidCode(alias code)
 {
 template For(T)
 {
 enum bool For = __traits(compiles, code(T.init));
 }
 }
 
 void main()
 {
// use an anonymous templated function:
 alias isValidCode!((r)
 {
 if (r.empty) {} // can test for empty
 r.popFront; // can invoke next
 auto h = r.front;   // c
 }
 ) isInputRange;
 
 //writeln(isInputRange.For!(int[]));
 }
 
 Except DMD doesn't like the commented-out line. Whaoh!
 
 
 
 Philippe
 



Re: Using getchar

2010-09-06 Thread Andrej Mitrovic
Thanks.

Stanislav Blinov Wrote:

 Andrej Mitrovic wrote:
 
  
  Someone on the NGs started creating some user-friendly input functions, 
  something like getInput!char(variable), or similar. But I can't find the 
  topic, anyone know the link perhaps? It was fairly recent that someone 
  posted it.
 
 It was Jesse Phillips: 
 http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.comgroup=digitalmars.Dartnum=115546



Re: Understanding isInfinite(Range)

2010-09-06 Thread bearophile
Andrej Mitrovic:

 I'm sorry, but what does q{..} mean?

q{} is just a different syntax to write  or ``

It's a controversial feature. q{} isn't recognized by editors as a string, so 
they colour the syntax it contains normally as code, and not as a string. So 
it's a bit useful if you want to give a string to a higher order function like 
map, instead of a delegate, and you want to keep the visual illusion of a 
delegate:

map!q{a * a}([1, 2, 3])

The problem comes straight from its purpose: is that it doesn't look like a 
string, so its true nature is a bit hidden; and this may cause some troubles.

Another possible problem was discussed when the q{} syntax was introduced. It's 
not a clean syntax, it's a hack from the point of view of parsing/lexing too.

It's handy, but it may cause troubles too. I am getting used to it, but it's a 
untidy hack and it will keep being nothing more than a hack. And sometimes 
hacks later come back and bite your bum.

Bye,
bearophile


Re: Understanding isInfinite(Range)

2010-09-06 Thread Andrej Mitrovic
Heh. I'd rather want text editors to use syntax highlighting on comments as 
well, but use a different background color. Then I would know it's a comment 
but it would also make any embedded code in the comment actually readable.

bearophile  bearophileh...@lycos.com Wrote:

 Andrej Mitrovic:
 
  I'm sorry, but what does q{..} mean?
 
 q{} is just a different syntax to write  or ``
 
 It's a controversial feature. q{} isn't recognized by editors as a string, so 
 they colour the syntax it contains normally as code, and not as a string. So 
 it's a bit useful if you want to give a string to a higher order function 
 like map, instead of a delegate, and you want to keep the visual illusion of 
 a delegate:
 
 map!q{a * a}([1, 2, 3])
 
 The problem comes straight from its purpose: is that it doesn't look like a 
 string, so its true nature is a bit hidden; and this may cause some troubles.
 
 Another possible problem was discussed when the q{} syntax was introduced. 
 It's not a clean syntax, it's a hack from the point of view of parsing/lexing 
 too.
 
 It's handy, but it may cause troubles too. I am getting used to it, but it's 
 a untidy hack and it will keep being nothing more than a hack. And sometimes 
 hacks later come back and bite your bum.
 
 Bye,
 bearophile



Re: Understanding isInfinite(Range)

2010-09-06 Thread Andrej Mitrovic
I meant string literals. But comments as well.

Andrej Mitrovic Wrote:

 Heh. I'd rather want text editors to use syntax highlighting on comments as 
 well, but use a different background color. Then I would know it's a comment 
 but it would also make any embedded code in the comment actually readable.
 
 bearophile  bearophileh...@lycos.com Wrote:
 
  Andrej Mitrovic:
  
   I'm sorry, but what does q{..} mean?
  
  q{} is just a different syntax to write  or ``
  
  It's a controversial feature. q{} isn't recognized by editors as a string, 
  so they colour the syntax it contains normally as code, and not as a 
  string. So it's a bit useful if you want to give a string to a higher order 
  function like map, instead of a delegate, and you want to keep the visual 
  illusion of a delegate:
  
  map!q{a * a}([1, 2, 3])
  
  The problem comes straight from its purpose: is that it doesn't look like a 
  string, so its true nature is a bit hidden; and this may cause some 
  troubles.
  
  Another possible problem was discussed when the q{} syntax was introduced. 
  It's not a clean syntax, it's a hack from the point of view of 
  parsing/lexing too.
  
  It's handy, but it may cause troubles too. I am getting used to it, but 
  it's a untidy hack and it will keep being nothing more than a hack. And 
  sometimes hacks later come back and bite your bum.
  
  Bye,
  bearophile