Jump to page: 1 2 3
Thread overview
Looking for an equivalent to C++ std::getline in D
May 05, 2017
k-five
May 05, 2017
Stanislav Blinov
May 06, 2017
k-five
May 06, 2017
Jonathan M Davis
May 06, 2017
k-five
May 06, 2017
Stanislav Blinov
May 06, 2017
k-five
May 07, 2017
Patrick Schluter
May 07, 2017
k-five
May 07, 2017
Stanislav Blinov
May 07, 2017
Patrick Schluter
May 07, 2017
bachmeier
May 07, 2017
Patrick Schluter
May 08, 2017
k-five
May 08, 2017
Daniel N
May 09, 2017
Jonathan M Davis
May 09, 2017
Moritz Maxeiner
May 10, 2017
Jonathan M Davis
May 06, 2017
Stanislav Blinov
May 08, 2017
Ali Çehreli
May 09, 2017
k-five
May 10, 2017
Ali Çehreli
May 10, 2017
k-five
May 05, 2017
Hi all.
I have a simple command-line program utility in C++ that can rename or remove files, based on regular expression.
After finding D that is more fun than C++ is, I want to port the code, but I have problem with this part of it:

        std::getline( iss, match, delimiter );
        std::getline( iss, substitute, delimiter );

I need to read from iss ( = std::istringstream iss( argv[ 1 ] ) and separate them by delimiter.

Since the program gets the input from a user, and it can be something like: 's/\d+[a-z]+@(?=\.)//g'  or '/[A-Za-z0-9]+//'

So for: s/\d+[a-z]+@(?=\.)//g
I need:
s
\d+[a-z]+@(?=\.)
g

and for: /[A-Za-z0-9]+/
It should be:
[A-Za-z0-9]+

---

I tired ( std.string: split or format ) or ( std.regex split ). In fact I need to read from a stream up to a delimiter.

Does someone knows a way to do this in D? Thanks
May 05, 2017
On Friday, 5 May 2017 at 09:54:03 UTC, k-five wrote:
> Hi all.
> I have a simple command-line program utility in C++ that can rename or remove files, based on regular expression.
> After finding D that is more fun than C++ is, I want to port the code, but I have problem with this part of it:
>
>         std::getline( iss, match, delimiter );
>         std::getline( iss, substitute, delimiter );
>
> I need to read from iss ( = std::istringstream iss( argv[ 1 ] ) and separate them by delimiter.
>
> Since the program gets the input from a user, and it can be something like: 's/\d+[a-z]+@(?=\.)//g'  or '/[A-Za-z0-9]+//'
>
> So for: s/\d+[a-z]+@(?=\.)//g
> I need:
> s
> \d+[a-z]+@(?=\.)
> g
>
> and for: /[A-Za-z0-9]+/
> It should be:
> [A-Za-z0-9]+
>
> ---
>
> I tired ( std.string: split or format ) or ( std.regex split ). In fact I need to read from a stream up to a delimiter.
>
> Does someone knows a way to do this in D? Thanks

So, you need to consume input one element at a time (delimited), dropping empty elements? Try std.algorithm.iteration splitter and filter:

auto advance(Range)(ref Range r)
{
    assert(!r.empty);
    auto result = r.front;
    r.popFront();
    return result;
}

void main(string[] args)
{
    import std.algorithm.iteration : splitter, filter;
    import std.range : empty;

    auto input = args[1].splitter('/').filter!"!a.empty"();

    import std.stdio : writeln;
    while (!input.empty)
        writeln(input.advance());
}

The advance() function reads the next delimited element and pops it from the range.
May 06, 2017
On Friday, 5 May 2017 at 17:07:25 UTC, Stanislav Blinov wrote:
> On Friday, 5 May 2017 at 09:54:03 UTC, k-five wrote:

======================================================

Thanks.
I only needed this part since it filters the empty elements and this is enough for me:
auto input = args[1].splitter('/').filter!"!a.empty"();

but if your are wailing please explain what is the type of "input" since I think this is an array but after testing it has no [] - index operator ( imput[ 0 ] is fail )

Also what is the parameter "a.empty" for template filter
May 06, 2017
On Saturday, May 6, 2017 8:34:11 AM CEST k-five via Digitalmars-d-learn wrote:
> On Friday, 5 May 2017 at 17:07:25 UTC, Stanislav Blinov wrote:
> > On Friday, 5 May 2017 at 09:54:03 UTC, k-five wrote:
> ======================================================
>
> Thanks.
> I only needed this part since it filters the empty elements and
> this is enough for me:
> auto input = args[1].splitter('/').filter!"!a.empty"();
>
> but if your are wailing please explain what is the type of "input" since I think this is an array but after testing it has no [] - index operator ( imput[ 0 ] is fail )
>
> Also what is the parameter "a.empty" for template filter

It's a range. The exact type is a "voldemort" type in that its declared internally to filter, and you can't reference it by name. Rather, it has a known API, so you don't need to name it. You just use it. But that does require that you know about D ranges (since you can't use the API if you're not familiar with it).

If you're not familiar with D's ranges, I would suggest reading this:

http://ddili.org/ders/d.en/ranges.html

There's also this talk from dconf 2015:

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

But if you don't have at least a basic understanding of what ranges are, a good chunk of D's standard library (std.algorithm in particular) is likely to be confusing.

Now, if you want to get a dynamic array out of a range, then you can call std.array.array on it, and array will allocate a dynamic array. So, if you call array on input, then you'll have a dynamic array to operate on instead.

In general though, if you're able to operate on ranges rather than dynamic arrays specifically, the code will be more efficient (e.g. both splitter and filter return lazy ranges, so they're not actually doing any work until you iterate over the range, and converting the range to a dynamic array would mean iterating through the entire range as well as allocating memory). So, while converting to a dynamic array is often the right solution, it's usually better to avoid it if you don't need it. But obviously, you'll need to be familiar with ranges first.

- Jonathan M Davis

May 06, 2017
On Saturday, 6 May 2017 at 08:34:11 UTC, k-five wrote:

> Also what is the parameter "a.empty" for template filter

Jonathan covered the type part. As for that last bit, the filter template takes a predicate as parameter. This predicate is called for each input element, and if returns false, the element is ignored. The predicate can be a function, or, for example, a lambda:

auto input = args[1].splitter('/').filter!((string s) { return !s.empty; })();

or a template lambda:

auto input = arga[1].splitter('/').filter!((s) => !s.empty)();

By convention, predicates in Phobos can also be compile-time strings. In that case, std.functional.unaryFun is used to turn that string into a function. By default, unaryFun names the argument 'a', so the "!a.empty" will be expanded by unaryFun into (a) => !a.empty.
May 06, 2017
On Saturday, 6 May 2017 at 08:53:12 UTC, Jonathan M Davis wrote:
> On Saturday, May 6, 2017 8:34:11 AM CEST k-five via Digitalmars-d-learn wrote:
>> On Friday, 5 May 2017 at 17:07:25 UTC, Stanislav Blinov wrote:
>> > On Friday, 5 May 2017 at 09:54:03 UTC, k-five wrote:

---------------------------------------------------------

Although I am not sure but it may Range in D, has the same concept that C++ has on iterator, like InputIterator or OutputIterator, since I realized that the output of [ filter ] does not have RandomAccessRange so I can not use input[ 0 ]. But I can use input.front().

Also thank you @Stanislav Blinov, I am familiar with lambda but have never seen a lambda in shape of string :)

---------------------------------------------------------

Solving the problem by using
split and empty in std.string
or splitter in std.algorithm or splitter in std.regex

plus
filter in std.algorithm,
and accessing the elements by:
input.front()
input.popFront()

---------------------------------------------------------

for input:
import std.stdio : print = writeln;
import std.algorithm: filter;
import std.string: split, empty;

void main() {

	immutable (char)[] str = "one//two//three";
	
	auto input = str.split( '/' ).filter!( element => !element.empty  )();
	
	print( input.front );
	input.popFront();
	print( input.front );
	input.popFront();
	print( input.front );

}

the output is:
one
two
three


May 06, 2017
On Saturday, 6 May 2017 at 10:15:03 UTC, k-five wrote:
> On Saturday, 6 May 2017 at 08:53:12 UTC, Jonathan M Davis wrote:
>> On Saturday, May 6, 2017 8:34:11 AM CEST k-five via Digitalmars-d-learn wrote:
>>> On Friday, 5 May 2017 at 17:07:25 UTC, Stanislav Blinov wrote:
>>> > On Friday, 5 May 2017 at 09:54:03 UTC, k-five wrote:
>
> ---------------------------------------------------------
>
> Although I am not sure but it may Range in D, has the same concept that C++ has on iterator, like InputIterator or OutputIterator, since I realized that the output of [ filter ] does not have RandomAccessRange so I can not use input[ 0 ]. But I can use input.front().
>
> Also thank you @Stanislav Blinov, I am familiar with lambda but have never seen a lambda in shape of string :)
>
> ---------------------------------------------------------
>
> Solving the problem by using
> split and empty in std.string
> or splitter in std.algorithm or splitter in std.regex
>
> plus
> filter in std.algorithm,
> and accessing the elements by:
> input.front()
> input.popFront()
>
> ---------------------------------------------------------
>
> for input:
> import std.stdio : print = writeln;
> import std.algorithm: filter;
> import std.string: split, empty;
>
> void main() {
>
> 	immutable (char)[] str = "one//two//three";
> 	
> 	auto input = str.split( '/' ).filter!( element => !element.empty
>  )();
> 	
> 	print( input.front );
> 	input.popFront();
> 	print( input.front );
> 	input.popFront();
> 	print( input.front );
>
> }
>
> the output is:
> one
> two
> three

str.split('/') is eager, that is, it will iterate the input and return the array of delimited elements. So in fact you're getting an array of all elements (even empty ones), and then filtering it, ignoring empty elements.
If you want to get the output as an array, it's better to use std.array as Jonathan mentioned:

import std.array : array;
auto inputArray = str.splitter('/').filter!(a => !a.empty)().array;

This will eagerly consume the results of filter and put them into an array.
May 06, 2017
On Saturday, 6 May 2017 at 10:35:05 UTC, Stanislav Blinov wrote:
> On Saturday, 6 May 2017 at 10:15:03 UTC, k-five wrote:
>> On Saturday, 6 May 2017 at 08:53:12 UTC, Jonathan M Davis wrote:
>>> On Saturday, May 6, 2017 8:34:11 AM CEST k-five via Digitalmars-d-learn wrote:
>>>> On Friday, 5 May 2017 at 17:07:25 UTC, Stanislav Blinov wrote:
>>>> > On Friday, 5 May 2017 at 09:54:03 UTC, k-five wrote:

-----------------------------------------------------------

Oh! So much better, Many thanks. I am only reading about D for two weeks.
To be honest I did not understand what Jonathan M Davis mentioned, but your example clarified it to me.

May 07, 2017
On Saturday, 6 May 2017 at 10:15:03 UTC, k-five wrote:
>
> Although I am not sure but it may Range in D, has the same concept that C++ has on iterator, like InputIterator or OutputIterator, since I realized that the output of [ filter ] does not have RandomAccessRange so I can not use input[ 0 ]. But I can use input.front().
>

If you want to learn the basis of the range concept and their link to C++ Iterators, you should definitively read Andrei's article on them in the InformIT magazine. Here is the link
http://www.informit.com/articles/printerfriendly/1407357
required read for every aspiring D programmer ;-)
May 07, 2017
On Sunday, 7 May 2017 at 09:46:22 UTC, Patrick Schluter wrote:
> On Saturday, 6 May 2017 at 10:15:03 UTC, k-five wrote:

> If you want to learn the basis of the range concept and their link to C++ Iterators, you should definitively read Andrei's article on them in the InformIT magazine. Here is the link
> http://www.informit.com/articles/printerfriendly/1407357
> required read for every aspiring D programmer ;-)

---------------------------------------------------

Thanks for the article.

Although I found D for being more better, nicer,and fun than C++ is, but there is a few questions on Stack-Over-Flow, videos on Youtube, and  some other forums in my country. So, why D is not popular?

I am a big fan of Perl-one-liner and after seeing
rdmd --evel='one-line-code'
I gasped! Oh, really? a one-liner with D!

Or even Unix Command Line, that D has Uniform Function Call Syntax.
line.sort.uniq.writeln();

It may you know about the future of D or may introduce some other articles about the future of D to me. Since after learning C++ I am not very comfortable with.
« First   ‹ Prev
1 2 3