www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is there a standard function that combines take() and

reply realhet <real_het hotmail.com> writes:
Hi,

I've just made this unicode wordreplacer function working, but It 
seems not too nice and functional-ish.
Are there ways to make it more simple?


import std.stdio, std.range, std.algorithm, std.uni, std.utf, 
std.conv;

bool isWordChar(dchar ch){
     return isAlphaNum(ch) || ch=='_';
}

string replaceWords(alias fun = isWordChar)(string str, string 
from, string to){
     auto res = appender!string();
     auto src = str.byCodePoint;
     foreach(isWord, len; str.map!fun.group){
         auto act = src.take(len).text;
         src.popFrontExactly(len);

         res.put(isWord && act==from ? to : act);
     }
	return(res[]);
}

void main(){
     immutable str = "Type=FunctionType Type; éType Type2: Type 
aTypeb Type";
     str.replace("Type", "AsmType").writeln;
     str.replaceWords("Type", "AsmType").writeln;
}

Thanks in advance!
Dec 11 2020
parent reply Dukc <ajieskola gmail.com> writes:
On Friday, 11 December 2020 at 19:07:23 UTC, realhet wrote:
 I've just made this unicode wordreplacer function working, but 
 It seems not too nice and functional-ish.
 Are there ways to make it more simple?
To answer the title, yes there is: ``` foreach(isWord, len; str.map!fun.group){ auto act = (&src).refRange.take(len).text; res.put(isWord && act==from ? to : act); } ``` But personally I think it does not pay to try to be more functional than what this snippet already is. The most important thing is that the program is functional on the high level. This means avoiding globals and static variables (`pure` may help), big monolithic functions, god classes and functions which get needless info by their parameters. Being functional in the low level is secondary and not always worth it.
Dec 14 2020
parent realhet <real_het hotmail.com> writes:
On Monday, 14 December 2020 at 14:16:41 UTC, Dukc wrote:
 On Friday, 11 December 2020 at 19:07:23 UTC, realhet wrote:
 I've just made this unicode wordreplacer function working, but 
 It seems not too nice and functional-ish.
 Are there ways to make it more simple?
To answer the title, yes there is:
Thanks for ideas! Yesterday I ended up making this helper funct: auto fetchFrontExactly(R)(ref R r, size_t n) if(isInputRange!R){ auto res = r.takeExactly(n); r.popFrontExactly(n); return res; } Now I leaned from you: refRange and take-s ability to pop elements from a refRange. That's what I was needed! Now the 2 aproach looks like: string replaceWords(alias fun = isWordChar)(string str, string from, string to){ if(1){ auto fetchAndReplace(Tuple!(bool, uint) p){ auto act = refRange(&str).take(p[1]).text; return p[0] && act==from ? to : act; } return str.map!fun .group .map!fetchAndReplace .join; }else{ string res; foreach(isWord, len; str.map!fun.group){ auto act = (&str).refRange.take(len).text; res ~= (isWord && act==from ? to : act); } return(res); } } They are the same thing, but the first looks nicer because it is a processing pipe with the state modifying thing extracted to a named function (so that's makes the pipe more understandable). However in the foreach version I can have meaningful parameter names: (isWord, len) instead of a tuple. I don't want to do functional programming just for itself. I'm just learning it, and want to understand it better. I already found a lot of good uses of it for my tasks and I still discover a lot of cool stuff. Thanks again!
Dec 14 2020