Re: Why any! with map! is not working here

2019-06-06 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, June 6, 2019 10:21:39 PM MDT rnd via Digitalmars-d-learn wrote:
> On Thursday, 6 June 2019 at 21:32:11 UTC, Jonathan M Davis wrote:
> > If any is not given a predicate, it defaults to just checking
> > whether the element itself is true (requiring that the element
> > be bool), which is why Marco's suggestion works, but it's a
> > rather odd way to write the code and will be less efficient
> > unless the optimizer manages to optimize away the extra work
> > involved with having map.
> >
> > However, in general, with D, you're not going to find that
> > there is only one way to do things. There are going to tend to
> > be many different approaches to solve the same problem. D code
> > is often simple because of the powerful language constructs and
> > standard library, but it makes no attempt to make it so that
> > there's only one way to do things - especially when you start
> > combining stuff to do whatever it is you're trying to do.
> >
> > - Jonathan M Davis
>
> Maybe one of these methods can be made 'official' or 'idiomatic':

If you're looking for the language or library to tell you exactly how you
should be doing things, then you've come to the wrong language. There are
approaches that are more idiomatic than others (e.g. range-based solutions
are usually favored), but D is purposefully designed to be multi-paradigm,
and there are going to be very different approaches to a problem where each
approach is equally viable or where one approach is better in some
situations, whereas another is better in others. And once we're dealing with
combining functions to get a job done, it would actually be very difficult
to try to claim that a particular combination of them is the correct way.
Which functions make sense is going to depend on the task, and it's
naturally going to be possible to combine functions in different ways to get
the same result.

> > any!pred(ss);
> > ss.any!pred();
> > ss.any!pred;
>
> This will reduce learning burden on beginners.

We're not going to make requirements over that sort of thing any more than
we're going to require that all D code use a particular bracing style. D
provides the tools needed to get stuff done, but for the most part, it
doesn't try to tell you how to use them. There are some best practices for
how to go about things in D, but that's not usually about stuff like coding
style, and it really covers a fairly small number of the decisions that a D
programmer has to make. The closest that you're going to get on coding style
is the official style guide ( https://dlang.org/dstyle.html ), and aside
from some Phobos-specific requirements at the bottom, it's mostly just about
how you name public symbols so that there's some consistency when using
other people's libraries.

For best practices, you're going to get things like "use ranges" and "make
your imports local." You're not going to be told how to format your code or
which set of functions you should be using to solve a particular problem.

- Jonathan M Davis





Re: Why any! with map! is not working here

2019-06-06 Thread rnd via Digitalmars-d-learn

On Thursday, 6 June 2019 at 21:32:11 UTC, Jonathan M Davis wrote:
If any is not given a predicate, it defaults to just checking 
whether the element itself is true (requiring that the element 
be bool), which is why Marco's suggestion works, but it's a 
rather odd way to write the code and will be less efficient 
unless the optimizer manages to optimize away the extra work 
involved with having map.


However, in general, with D, you're not going to find that 
there is only one way to do things. There are going to tend to 
be many different approaches to solve the same problem. D code 
is often simple because of the powerful language constructs and 
standard library, but it makes no attempt to make it so that 
there's only one way to do things - especially when you start 
combining stuff to do whatever it is you're trying to do.


- Jonathan M Davis


Maybe one of these methods can be made 'official' or 'idiomatic':


any!pred(ss);
ss.any!pred();
ss.any!pred;


This will reduce learning burden on beginners.



Re: Why any! with map! is not working here

2019-06-06 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, June 6, 2019 5:50:36 AM MDT rnd via Digitalmars-d-learn wrote:
> On Thursday, 6 June 2019 at 09:49:28 UTC, Jonathan M Davis wrote:
> > So, to start, the any portion should be something more like
> >
> > any!pred(ss);
> >
> > or
> >
> > ss.any!pred();
> >
> > or
> >
> > ss.any!pred;
> >
> > where pred is whatever the predicate is.
>
> Apparently, following also works:
>
>
> any(ss.map!(a => a > 127))   // as written by Marco de Wild
> or
> any(map!(a => a > 127)(ss))
>
>
> Thanks for detailed explanations.
> Philosophically, I personally think, there should be only one way
> to do such things since that will add to simplicity, as in C.
> Apparently, smallness and simplicity of C contributed greatly to
> its success.
> Only drawbacks of C, like its unsafe parts, should be removed and
> clearly advantages newer concepts should be added in a clearly
> defined manner.
> Just thinking loudly!

If any is not given a predicate, it defaults to just checking whether the
element itself is true (requiring that the element be bool), which is why
Marco's suggestion works, but it's a rather odd way to write the code and
will be less efficient unless the optimizer manages to optimize away the
extra work involved with having map.

However, in general, with D, you're not going to find that there is only one
way to do things. There are going to tend to be many different approaches to
solve the same problem. D code is often simple because of the powerful
language constructs and standard library, but it makes no attempt to make it
so that there's only one way to do things - especially when you start
combining stuff to do whatever it is you're trying to do.

- Jonathan M Davis





Re: Why any! with map! is not working here

2019-06-06 Thread rnd via Digitalmars-d-learn

On Thursday, 6 June 2019 at 09:49:28 UTC, Jonathan M Davis wrote:


So, to start, the any portion should be something more like

any!pred(ss);

or

ss.any!pred();

or

ss.any!pred;

where pred is whatever the predicate is.


Apparently, following also works:


any(ss.map!(a => a > 127))   // as written by Marco de Wild
or
any(map!(a => a > 127)(ss))


Thanks for detailed explanations.
Philosophically, I personally think, there should be only one way 
to do such things since that will add to simplicity, as in C.
Apparently, smallness and simplicity of C contributed greatly to 
its success.
Only drawbacks of C, like its unsafe parts, should be removed and 
clearly advantages newer concepts should be added in a clearly 
defined manner.

Just thinking loudly!




Re: Why any! with map! is not working here

2019-06-06 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, June 6, 2019 3:01:11 AM MDT rnd via Digitalmars-d-learn wrote:
> I am trying to check if any character in the string is > 127 by
> following function:
>
> import std.algorithm.searching;
> import std.algorithm.iteration;
> bool isBinary(char[] ss){
>return (any!(map!(a => a > 127)(ss)));
> }
>
> However, I am getting this error:
>
> Error: variable ss cannot be read at compile time
>
> I also tried:
>
> bool isBinary(char[] ss){
>   return (any!(ss.map!(a => a > 127)));
> }
>
>
> But I get error:
>
> Error: template identifier map is not a member of variable
> mysrcfile.isBinary.ss
>
>
> How can this be corrected?

Well, it might be easier to see the problem if you removed the outer layer
of parens, since they do nothing and just clutter up the code further.

bool isBinary(char[] ss){
   return any!(map!(a => a > 127)(ss));
}

Now, let's add the parens for the function call for clarity.

bool isBinary(char[] ss){
   return any!(map!(a => a > 127)(ss))();
}

So, as should now be obvious, the first problem here is that you're not
passing any function arguments to any - neither through UFCS or through the
normal function call syntax. any takes a predicate as a template argument
and a range as a runtime argument. Presumably, you want to be passing ss to
any. However, you're passing it to map, which is part of the predicate for
any, and the way that you're doing it results in the compiler trying to
evaluate ss at compile-time, which isn't going to work, because it's a
runtime variable - hence the compiler error that you're seeing.

So, to start, the any portion should be something more like

any!pred(ss);

or

ss.any!pred();

or

ss.any!pred;

where pred is whatever the predicate is. That would then iterate through ss
and return whether the predicate returned true for any element. So, you'd
want something like

bool isBinary(char[] ss){
   return any!pred(ss);
}

That then leaves the question of what the predicate should be (since, you're
obviously not going to just put the value pred there). The predicate needs
to be something that's callable - be it a function, a delegate, a lambda,
etc. Most typically, it's a lambda.

map!(a => a > 127)(ss);

is not a lambda. It's simply a function call to map. The a => a > 127 is a
lambda for map, but the overall expression is not a lambda. It calls map on
ss and converts it to a range of bool where each element is true if the
corresponding element of ss was greater than 127. It could be turned into a
lambda by doing something like

b => map!(a => a > 127)(ss)

but the return value isn't bool (which is what's necessary for a predicate),
and it really doesn't make sense to be using ss in the predicate anyway.
You're already iterating over ss with any. What you want is a predicate
that's going to be true for an element of ss that matches the condition
you're testing for. What you said about that is

> I am trying to check if any character in the string is > 127

So, let's build something that does that. The simplest would be

a => a > 127

This would then give you

bool isBinary(char[] ss){
   return any!(a => a > 127)(ss);
}

map is neither necessary nor useful here. map is for converting the elements
from one type to another, which you don't need to do here.

Now, that solution _does_ unfortunately autodecode, so it's actually
decoding sequences of char to dchar and then testing them - which will work
in this case but is unnecessary work. To avoid that, either
std.string.representation or std.utf.byCodeUnit would work. e.g.

bool isBinary(char[] ss){
   return any!(a => a > 127)(ss.representation());
}

or

bool isBinary(char[] ss){
   return any!(a => a > 127)(ss.byCodeUnit());
}

representation would convert string[] to immutable(ubyte)[], and byCodeUnit
converts string[] to a range of code units instead of a range of code points
(so a range of char instead of a range of dchar).

Of course, you could also do something like

bool isBinary(char[] ss){
   return any!isASCII(ss.byCodeUnit());
}

using std.ascii.isASCII, which makes what you're testing for more explicit.
And if you prefer UFCS, then

bool isBinary(char[] ss){
   return ss.byCodeUnit().any!isASCII();
}

or

bool isBinary(char[] ss){
   return ss.byCodeUnit.any!isASCII;
}

- Jonathan M Davis





Re: Why any! with map! is not working here

2019-06-06 Thread Marco de Wild via Digitalmars-d-learn

On Thursday, 6 June 2019 at 09:01:11 UTC, rnd wrote:
I am trying to check if any character in the string is > 127 by 
following function:


import std.algorithm.searching;
import std.algorithm.iteration;
bool isBinary(char[] ss){
  return (any!(map!(a => a > 127)(ss)));
}

However, I am getting this error:

Error: variable ss cannot be read at compile time

I also tried:

bool isBinary(char[] ss){
return (any!(ss.map!(a => a > 127)));
}


But I get error:

Error: template identifier map is not a member of variable 
mysrcfile.isBinary.ss



How can this be corrected?


Removing the ! makes it work:
```
import std.algorithm.searching;
import std.algorithm.iteration;
bool isBinary(char[] ss){
  return (any(map!(a => a > 127)(ss)));
}
```

`any` takes a runtime argument (a range) and optionally a 
template argument.


You can also use UFCS[0]
```
import std.algorithm.searching;
import std.algorithm.iteration;
bool isBinary(char[] ss){
  return ss.map!(a => a > 127).any;
}
```
to make it more obvious to see what is happening. It can be quite 
confusing to mix chains of template and runtime arguments.


[0] 
https://tour.dlang.org/tour/en/gems/uniform-function-call-syntax-ufcs


Why any! with map! is not working here

2019-06-06 Thread rnd via Digitalmars-d-learn
I am trying to check if any character in the string is > 127 by 
following function:


import std.algorithm.searching;
import std.algorithm.iteration;
bool isBinary(char[] ss){
  return (any!(map!(a => a > 127)(ss)));
}

However, I am getting this error:

Error: variable ss cannot be read at compile time

I also tried:

bool isBinary(char[] ss){
return (any!(ss.map!(a => a > 127)));
}


But I get error:

Error: template identifier map is not a member of variable 
mysrcfile.isBinary.ss



How can this be corrected?