Ramda: pass predicate equality argument last - ramda.js

I heve a static collection. And I want to check for any match by value each time, the value is changed.
Now I have:
var isOk = R.any(item => item.test(value), items);
What I want:
To store a function in other place and to call it like:
var isOk = checkMatch(value);
Any ideas? Thx.
UPDATE
I'm looking for solution in Ramda way. Something with changind call order of R.__

Wrap it in a closure that takes value.
var isOk = (value) => R.any(item => item.test(value), items);
var isOk_foobar = isOk('foobar');

I don't know for sure that your test items are regular expressions to use on
Strings, but if they are, you might try something like this:
const anyMatch = curry((regexes, val) => any(regex => test(regex, val), regexes))
const testFiles = anyMatch([/test\/(.)+\.js/i, /\.spec\.js/i])
testFiles('foo.js') //=> false
testFiles('test/foo.js') //=> true
testFiles('foo.spec.js') //=> true
And this looks clean to me, and very much in the spirit of Ramda. If you wanted to make it point-free, you could do this:
const anyMatch = useWith(flip(any), [identity, flip(test)])
But I find that much less readable. To me, point-free is a tool worth using when it improves readability, and to avoid when it doesn't.
You can see this in action on the Ramda REPL.

Related

What are some other ways this loop can be rewritten?

Got this simple loop:
use Config::Simple:from<Perl5>;
my $cfg = Config::Simple.new(syntax => 'ini');
%config{'short_name'} = 'blah';
for %config.kv -> $k, $v {
$cfg.param("%config{'short_name'}.$k", $v);
}
Works fine. But I want to get more familiar with other ways to achieve the same goal, if only to get comfortable reading other people's code. Plus, loops seem to be the "old" school way of doing things and not very "Raku-like" and I need to get more comfortable working with using functions in more advanced ways.
Anyway, to stretch my new Raku muscles, I came up with this one-liner as an alternative:
map(-> $k, $v { $cfg.param("%config{'short_name'}.$k", $v) }, %config.kv);
It's less readable (at least to my untrained eye), but it works.
My hunch is there is some good way of making this code both more concise and readable. Interested in seeing if I might be right.
rewritten (IMHO, for is more suitable than map, if a variable is changed)
use Config::Simple:from<Perl5>;
my $cfg = Config::Simple.new: syntax => 'ini';
my %config := short_name => 'blah';
$cfg.param: "%config<short_name>\.{.key}", .value for %config;
print $cfg.as_string();
by set_block
use Config::Simple:from<Perl5>;
my $cfg = Config::Simple.new: syntax => 'ini';
my %config = short_name => 'blah';
$cfg.set_block: %config<short_name>, %config;
print $cfg.as_string();

Can We Get Vue to 'Detect Changes' to an Array If We Use `Filter()`?

First, I had this: parts = parts.filter(part => part.id !== change.doc.id);
So, data is an Array and it gets 'clobbered' with a new 'filtered' Array.
Vue didn't seem keen on detecting the change and updating my DOM.
So, I saw this. Specifically: To deal with caveat 2, you can use splice:
I refactored (or is it 'de-factored' b/c my code 'grew'?) to this:
// Get index of part removed
const index = parts.forEach((part, i) => {
if (part.id === change.doc.id) {
return i;
}
});
parts.splice(index, 1);
She works...but really? Do I have to do this way? 😬
parts.splice(parts.findIndex(part => part.id === change.doc.id), 1);
I got the splice in there while still keeping as 1 line, so m happy! 🤓

Why does R.all with R.both does not equal R.allPass with the same arguments?

I'm just learning while doing ramda.js. Well, there are many ways to reach a goal with ramda, but there is on thing I do not understand.
I would like to check the input for an array of strings that all match one regular expression. I thought I could do it R.all(R.both(isString, isRegExp)), but it seems to deliver a true when the input is a number.
As expected R.allPass([isString, isRegExp]) gives a false with a number input.
But can anyone please explain me why R.all is returning a true? Or what and where is mistake (in thinking)?
Complete code:
var isString = R.is(String),
isMyRegExp = R.test(/^[a-z]+$/),
isMyRegExpString = R.both(isString, isMyRegExp),
isArrayOfMyRegExpStrings = R.all(isMyRegExpString),
isArrayOfMyRegExpStringsPass = R.allPass([isString, isMyRegExp]),
result = {
'all': isArrayOfMyRegExpStrings(9),
'allPass': isArrayOfMyRegExpStringsPass(9)
};
console.log(result);
// {
// all: true,
// allPass: false
// }
https://codepen.io/Eisenhardt/pen/PKLZqj
PS:
I know that I could shorten conditions with just the regexp, but there could be other situations where I need both conditions to be true. eg. isArrayOfNumber and sumOfNumbersOver50.
The second argument to R.all is expecting a list of values to test. Due to the way the function is implemented it is treating the 9 in your example as an empty list, resulting in a vacuous truth and evaluating to true.

Is is possible to autorun even when value doesn't change?

For example
var x = observable({lastPressedKey:""});
autorun(() => console.log(x.lastPressedKey));
x.lastPressedKey = "spacebar"
x.lastPressedKey = "spacebar"
x.lastPressedKey = "spacebar"
I want that console.log prints "spacebar" three times.
I can do something like this
x.lastPressedKey = ["space", Date.now()]
x.lastPressedKey = ["space", Date.now()]
x.lastPressedKey = ["space", Date.now()]
Is there a better way?
The whole point of an observable is to actually avoid what you are trying to achieve. However, you could change the lastPressedKey from a string to an object that includes the datetime, so it would trigger a rerender when the datetime changes even if the string stays the same.

How to check if a TypedPipe or a ValuePipe are empty in Scalding?

In Scalding, suppose you have a TypedPipe[Long] or ValuePipe[Long]. How would you go about checking whether they are empty in the most elegant/efficient way?
Currently testing the following:
val isTPEmpty: Boolean = typePipe.equals(TypedPipe.empty)
val isVPEmpty: Boolean = valuePipe.equals(EmptyValue)
Or, to make it more generic:
def isTypedPipeEmpty[A](typedPipe: TypedPipe[A]): Boolean = {
val emptyTP: TypedPipe[A] = TypedPipe.empty
typedPipe.equals(emptyTP)
}
UPDATE: this doesn't work (will return false for an empty TypedPipe). Appreciate any inputs.
After speaking to several people on this, there is no straight solution simply because a TypedPipe is distributed, and checking whether it is empty is "expensive", therefore one should avoid this as much as possible.
If you absolutely have no choice, what worked for me was something "ugly" as creating a temporary empty TypedPipe, then calling mapWithValue on my ValuePipe, and if it is empty do X, otherwise do Y. Something like:
TypedPipe.from(List()).mapWithValue(valuePipe) { case (temp, valuePipe) => if (valuePipe.isEmpty) doX else doY }
But again, cumbersome.