The WhenAnyValue method is overloaded for up to 12 properties.
What is the recommended way of handling an arbitrarily large number of properties, more than can be handled by the defined overloads of WhenAnyValue?
Thanks
If you really must handle that many properties at once (omg, why?), I would suggest breaking up the properties into multiple calls to WhenAnyValue and combining them with CombineLatest. Since you're combining them all with WhenAnyValue anyway, I imagine this should work fine.
Example:
var group1 = this.WhenAnyValue(#this => #this.Prop1, ..., (prop1, ...) => ...);
var group2 = this.WhenAnyValue(#this => #this.Prop13, ..., (prop13, ...) => ...);
group1.CombineLatest(group2, (g1, g2) => ...);
WhenAnyValue just uses CombineLatest under the hood anyway.
Alternatively, you could create additional overloads to support more values. There isn't really a limit on the number of type parameters.
Related
One very common parsing scenario in programming languages is an arbitrary-length nonempty list of elements with a separator, for example:
[1, 2, 3, 4, 5]
f(a, b, c)
I've been parsing this in treesitter as follows:
list: $ => seq(
repeat(seq($.element, ',')),
$.element
)
This works, but it's common enough that I wonder whether treesitter has a built-in construct for it. Does it?
In several grammars, (e.g. Rust, Go), we define helper functions for this.
function commaSep1(rule) {
return seq(rule, repeat(seq(',', rule)))
}
function commaSep(rule) {
return optional(commaSep1(rule))
}
We could include these functions as part of the Tree-sitter DSL, but since it's so easy to
define your own helper functions like this, I think it's best to keep the DSL small.
I'd like to get values from map like that
user_TopicResponses.put(
"3"+"_"+topicid,
Access.useradVectorMap.getOrElse(
"3"+"_"+topicid,
Access.useradVectorMap.getOrElse("3"+"_"+"0"),
Array(0.0)
)
)
What means if key in map value will be get, of else key is set to "3+"0" and value will also be get.
but it will be reported that:
too many arguments for method getOrElse: (key: String, default: => B1)B
You mixed up parentheses a bit :
Access.useradVectorMap.getOrElse("3"+"_"+"0"),Array(0.0) shoud in fact be
Access.useradVectorMap.getOrElse("3"+"_"+"0",Array(0.0))
It should be ok after that !
First off, I would suggest, at least for debugging purposes, to break your one statement into multiple statements. Your problem stems from a missing/misplaced parentheses. This would be much easier to see if you split your code up.
Secondly, it's good practice to use a variable or function for any repeated code, it makes it far easier to change and maintain (I like to use them for any hard coded value that might change later as well).
In order to only calculate the secondaryValue only if the primaryValue.getOrElse(...) goes to the "else" value, you can use a lazy val, which only evaluates if needed:
val primaryKey = "3_" + topicid
val secondaryKey = "3_0"
val secondaryDefaultValue = Array(0.0)
lazy val secondaryValue = Access.useradVectorMap.getOrElse(secondaryKey, secondaryDefaultValue )
val primaryValue = Access.useradVectorMap.getOrElse(primaryKey, secondaryValue)
user_TopicResponses.put(primaryKey, primaryValue)
This code is far easier to read and, more importantly, far easier to debug
I wanted a list of numbers:
auto nums = iota(0, 5000);
Now nums is of type Result. It cannot be cast to int[], and it cannot be used as a drop-in replacement for int[].
It's not very clear from the docs how to actually use an iota as a range. Am I using the wrong function? What's the way to make a "range" in D?
iota, like many functions in Phobos, is lazy. Result is a promise to give you what you need when you need it but no value is actually computed yet. You can pass it to a foreach statement for example like so:
import std.range: iota;
foreach (i ; iota(0, 5000)) {
writeln(i);
}
You don't need it for a simple foreach though:
foreach (i ; 0..5000) {
writeln(i);
}
That aside, it is hopefully clear that iota is useful by itself. Being lazy also allows for costless chaining of transformations:
/* values are computed only once in writeln */
iota(5).map!(x => x*3).writeln;
// [0, 3, 6, 9, 12]
If you need a "real" list of values use array from std.array to delazify it:
int[] myArray = iota(0, 5000).array;
As a side note, be warned that the word range has a specific meaning in D that isn't "range of numbers" but describes a model of iterators much like generators in python. iota is a range (so an iterator) that produced a range (common meaning) of numbers.
I have a wrapper template that looks like this:
#(first: Html, second:Html, third:Html)
<div class="wrapper">
#first
#second
#third
</div>
I have three templates I want to shuffle and place as first, second and third.
Let's name them: views.html.a, views.html.b, views.html.c.
The controller code:
val a = views.html.a
val b = views.html.b
val c = views.html.c
val list = Random.shuffle(List(a, b, c)) // Will use Random.shuffle here but it fails complication either way
Ok(views.html.wrapper(list(0)(), list(1)(), list(2)()))
The complication error:
play.templates.BaseScalaTemplate[play.api.templates.HtmlFormat.Appendable,play.templates.Format[play.api.templates.HtmlFormat.Appendable]] does not take parameters
It appears as entering the object to the List and getting it out tricks the compiler.
If I don't use list and do:
Ok(views.html.wrapper(a(), b(), c()))
it works as expected and renders the page.
I know I can move the random logic to the wrapper template but I prefer to understand / fix the current implementation and learn some Scala in the process.
Thanks
EDIT
After reading serejja's answer, I'll add complexity to the question since this better represents the problem I'm facing.
The three templates need to take a boolean so views.html.a looks like:
#(checkMe:Boolean)
<div ...
So I can't use parentheses before the shuffle. Only after the shuffle occur I wish to send true false true as the booleans.
Using this approach:
Ok(views.html.wrapper(list(0)(true), list(1)(false), list(2)(true)))
gives the following compilation error:
play.templates.BaseScalaTemplate[play.api.templates.Html,play.templates.Format[play.api.templates.Html]] with play.api.templates.Template1[Boolean,play.api.templates.Html] does not take parameters
You were almost there :)
val a = views.html.a()
val b = views.html.b()
val c = views.html.c()
Notice the parentheses. The type of a, b and c now is play.api.templates.HtmlFormat.Appendable instead of the one before.
Now you can pass it as you wanted:
Ok(views.html.wrapper(list(0), list(1), list(2)))
EDIT:
Ok, I cannot imagine what you are up to (so that the solution could be simplified if possible) but I found a workaround.
First, consider that views a, b and c are on the one level of hierarchy:
/ a
BaseScalaTemplate - b
\ c
For this solution to work, these views must have the same number of parameters (a(check: Boolean), b(check: Boolean), c(check: Boolean)) so that they make a List[play.templates.BaseScalaTemplate[play.api.templates.Html,play.templates.Format[play.api.templates.Html]]
with play.api.templates.Template1[Boolean,play.api.templates.Html]] (which means "a generic template with one Boolean parameter").
play.api.templates.Template1 has a method render which takes that parameter and returns you a HtmlFormat.Appendable (which I mentioned earlier).
Considering this your solution might be like this:
val a = views.html.a
val b = views.html.b
val c = views.html.c
val randomizedViews = Random.shuffle(List(a, b, c))
Ok(views.html.wrapper(list(0).render(true), list(1).render(false), list(2).render(true)))
Note that this solution is far from being perfect and I'd suggest you not to use it in real life. I dont think views are intended to be used this way.
I have been looking at various discussions here on SO and other places, and the general consensus seems that if one is returning multiple non-similar data structures from an R function, they are best returned as a list(a, b) and then accessed by the indexes 0 and 1 and so on. Except, when using an R function via PL/R inside a Perl program, the R list function flattens the list, and also stringifies even the numbers. For example
my $res = $sth->fetchrow_arrayref;
# now, $res is a single, flattened, stringified list
# even though the R function was supposed to return
# list([1, "foo", 3], [2, "bar"])
#
# instead, $res looks like c(\"1\", \""foo"\", \"3\", \"2\", \""bar"\")
# or some such nonsense
Using a data.frame doesn't work because the two arrays being returned are not symmetrical, and the function croaks.
So, how do I return a single data structure from an R function that is made up of an arbitrary set of nested data structures, and still be able to access each individual bundle from Perl as simply $res->[0], $res->[1] or $res->{'employees'}, $res->{'pets'}? update: I am looking for an R equiv of Perl's [[1, "foo", 3], [2, "bar"]] or even [[1, "foo", 3], {a => 2, b => "bar"}]
addendum: The main thrust of my question is how to return multiple dissimilar data structures from a PL/R function. However, the stringification, as noted above, and secondary, is also problematic because I convert the data to JSON, and all those extra quotes just add to useless data transferred between the server and the user.
I think you have a few problems here. The first is you can't just return an array in this case because it won't pass PostgreSQL's array checks (arrays must be symmetric, all of the same type, etc). Remember that if you are calling PL/R from PL/Perl across a query interface, PostgreSQL type constraints are going to be an issue.
You have a couple of options.
You could return setof text[], with one data type per row.
you could return some sort of structured data using structures PostgreSQL understands, like:
CREATE TYPE ab AS (
a text,
b text
);
CREATE TYPE r_retval AS (
labels text[],
my_ab ab
);
This would allow you to return something like:
{labels => [1, "foo", 3], ab => {a => 'foo', b => 'bar'} }
But at any rate you have to put it into a data structure that the PostgreSQL planner can understand and that is what I think is missing in your example.