How does FreeMarker implement .iterator()?has_content for Iterator ?
Does it attempt to get the first item to decide whether to render,
and does it keep it for the iteration? Or does it start another iteration?
I have found this
static boolean isEmpty(TemplateModel model) throws TemplateModelException
{
if (model instanceof BeanModel) {
...
} else if (model instanceof TemplateCollectionModel) {
return !((TemplateCollectionModel) model).iterator().hasNext();
...
}
}
But I am not sure what Freemarker wraps the Iterator type to.
Is it TemplateCollectionModel?
It doesn't get the first item, it just calls hasNext(), and yes, with the default ObjectWrapper (see the object_wrapper configuration setting) it will be treated as a TemplateCollectionModel, which can be listed only once though. But prior to 2.3.24 (it's unreleased when I write this), there are some glitches to look out for (see below). Also if you are using pure BeansWrapper instead of the default ObjectWrapper, there's a glitch (see below too).
Glitch (2.3.23 and earlier): If you are using the default ObjectWrapper (you should), and the Iterator is not re-get for the subsequent listing, that is, the same already wrapped value is reused, then it will freak out telling that an Iterator can be listed only once.
Glitch 2, with pure BeansWrapper: It will just always say that it has content, even if the Iterator is empty. That's also fixed in 2.3.24, however, you need to create the BeansWrapper itself (i.e., not (just) the Configuration) with 2.3.24 incompatibleImprovements for the fix to be active.
Note that <#list ...>...<#else>...</#list> has been and is working in all cases (even before 2.3.24).
Last not least, thanks for bringing this topic to my attention. I have fixed these in 2.3.24 because of that. (Nightly can be built from here: https://github.com/apache/incubator-freemarker/tree/2.3-gae)
Related
Kotlin has nice wrappers and shortcuts, but sometimes I get caught not understanding them.
I have this simplified code:
class PipeSeparatedItemsReader (private val filePath: Path) : ItemsReader {
override fun readItems(): Sequence<ItemEntry> {
return filePath.useLines { lines ->
lines.map { ItemEntry("A","B","C","D",) }
}
}
And then I have:
val itemsPath = Path(...).resolve()
val itemsReader = PipeSeparatedItemsReader(itemsPath)
for (itemEntry in itemsReader.readItems())
updateItem(itemEntry)
// I have also tried itemsReader.readItems().forEach { ... }
Which is quite straightforward - I expect this code to give me a sequence which opens a file and reads the lines, parses them, and gives ItemEntrys, and when used up, close the file.
What I get, however, is IOException("Stream closed").
Somehow, even before the first item is read (I have debugged), somewhere within Kotlin's wrappers, the reader.in becomes null, so this exception is thrown in hasNext().
I have seen a similar question here: Kotlin to chain multiple sequences from different InputStream?
That one includes a lot of Java boilerplate which I would like to avoid.
How should I code this sequence using Path.useLines()?
Every Kotlin helper with "use" in the name closes the underlying resource at the end of the lambda you pass (at least that's a convention in the stdlib as far as I know). The most common example being AutoCloseable.use.
The Path.useLines extension is no exception:
Calls the block callback giving it a sequence of all the lines in this file and closes the reader once the processing is complete. [emphasis mine]
This means useLines closes the sequence of lines once the block is done, and thus you cannot return a lazy sequence out of it because you can't use it after the useLines function returns.
So, if you want to return a sequence of lines for later use, you cannot return a transformed sequence from that of useLines directly. Sequences actually cannot detect when someone is done using them, hence why useLines needs a lambda to give a "scope" or "lifetime" to the sequence and know when to close the underlying reader.
If you want to wrap this, you have 2 major options: either split the sequence operation and the close operation (make your PipeSeparatedItemsReader closeable), or use a lambda to process things in-place in readItems() the same way useLines does.
I want to build a class in Raku. Here's what I have so far:
unit class Vimwiki::File;
has Str:D $.path is required where *.IO.e;
method size {
return $.file.IO.s;
}
I'd like to get rid of the size method by simply making my class inherit the methods from IO::Path but I'm at a bit of a loss for how to accomplish this. Trying is IO::Path throws errors when I try to create a new object:
$vwf = Vimwiki::File.new(path => 't/test_file.md');
Must specify a non-empty string as a path
in block <unit> at t/01-basic.rakutest line 24
Must specify a non-empty string as a path
I always try a person's code when looking at someone's SO. Yours didn't work. (No declaration of $vwf.) That instantly alerts me that someone hasn't applied Minimal Reproducible Example principles.
So I did and less than 60 seconds later:
IO::Path.new
Yields the same error.
Why?
The doc for IO::Path.new shows its signature:
multi method new(Str:D $path, ...
So, IO::Path's new method expects a positional argument that's a Str. You (and my MRE) haven't passed a positional argument that's a Str. Thus the error message.
Of course, you've declared your own attribute $path, and have passed a named argument to set it, and that's unfortunately confused you because of the coincidence with the name path, but that's the fun of programming.
What next, take #1
Having a path attribute that duplicates IO::Path's strikes me as likely to lead to unnecessary complexity and/or bugs. So I think I'd nix that.
If all you're trying to do is wrap an additional check around the filename, then you could just write:
unit class Vimwiki::File is IO::Path;
method new ($path, |) { $path.IO.e ?? (callsame) !! die 'nope' }
callsame redispatches the ongoing routine call (the new method call), with the exact same arguments, to the next best fitting candidate(s) that would have been chosen if your new one containing the callsame hadn't been called. In this case, the next candidate(s) will be the existing new method(s) of IO::Path.
That seems fine to get started. Then you can add other attributes and methods as you see fit...
What next, take #2
...except for the IO::Path bug you filed, which means you can't initialize attributes in the normal way because IO::Path breaks the standard object construction protocol! :(
Liz shows one way to workaround this bug.
In an earlier version of this answer, I had not only showed but recommended another approach, namely delegation via handles instead of ordinary inheritance. I have since concluded that that was over-complicating things, and so removed it from this answer. And then I read your issue!
So I guess the delegation approach might still be appropriate as a workaround for a bug. So if later readers want to see it in action, follow #sdondley's link to their code. But I'm leaving it out of this (hopefully final! famous last words...) version of this answer in the hope that by the time you (later reader) read this, you just need to do something really simple like take #1.
class Notification(val context: Context, title: String, message: String) {
private val channelID = "TestMessages"
companion object ID {
var s_notificationID = -1
}
init {
var notificationID = -1
synchronized(s_notificationID) {
if (++s_notificationID == 0)
createNotificationChannel()
notificationID = s_notificationID
}
The above is being called simultaneously from two threads. A breakpoint in createNotificationChannel() clearly showed that sometimes s_notificationID equals 1.
However, if I change
synchronized(s_notificationID)
to synchronized(ID)
then it seems to lock fine.
Is synchronized() not locking basic types? And if so, why does it compile?
A look at the generated JVM bytecode indicates that the ID example looks like
synchronized(ID) { ... }
which is what you'd expect. However, the s_notificationID example looks more like
synchronized(Integer.valueOf(s_notificationID)) { ... }
In Java, we can only synchronize on objects, not on primitives. Kotlin mostly removes this distinction, but it looks like you've found one place where the implementation still seeps through. Since s_notificationID is an int as far as the JVM is concerned (hence, not an object) but synchronized expects an object, Kotlin is "smart" enough to wrap the value in Integer.valueOf on demand. Unfortunately for you, that produces wildly inconsistent results, because
This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
So for small numbers, this is guaranteed to lock on some cached object in memory that you don't control. For large ones, it may be a fresh object (hence always unlocked) or it might again end up on a cached object out of your hands.
The lesson here, it seems, is: Don't synchronize on primitive types.
Silvio Mayolo explained why it is not a good idea to synchronize on primitives (actually, I think the compiler should warn about this). But I believe there is another problem with this code, probably the main one that makes your synchronized blocks work in parallel.
The problem is that you replace the value of s_notificationID. Even if it would be an object, not a primitive, your synchronized blocks would still run in parallel, because each call to synchronized uses a different object. This is why in Java we usually synchronize on this and not on a field that we need to modify.
TL;DR The lesson here, it seems, is: Don't synchronize on primitive types.
synchronized(i) where i is Int, is actually synchronized(Integer.valueOf(i)).
Only in the range -128 to 127 this value is guaranteed to be a cached value.
Another fact is that ++i cannot be looked at as a mutation of the "object" i, but rather as replacing i by a new "object" with the value i+1.
Thank you broot & Silvio Mayolo for the above.
Experiments I did prove the above.
In my original code I have removed the ++ from
++s_notificationID. Amazingly or not, the lock worked now.
Now with that change I changed var s_notificationID = -1 to be var s_notificationID = -1000. Even more amazing, now the lock again stopped working.
Still, I think this anomaly of basic types undermines the attempt of Kotlin to see basic types as objects, and I think this should have been mentioned clearly in Kotlin documentation.
Let's say I want to connect to two package repositories, make a query for a package name, combine the result from the repos and process it (filter, unique, prioritize,...), What is a good way to do that?
What I though about is creating Array of two Cro::HTTP::Client objects (with base-uri specific to each repo), and when I need to make HTTP request I call #a>>.get, then process the result from the repos together.
I have attached a snippet of what I'm trying to do. But I would like to see if there is a better way to do that. or if the approach mention in the following link is suitable for this use case! https://perl6advent.wordpress.com/2013/12/08/day-08-array-based-objects/
use Cro::HTTP::Client;
class Repo {
has $.name;
has Cro::HTTP::Client $!client;
has Cro::Uri $.uri;
has Bool $.disable = False;
submethod TWEAK () {
$!client = Cro::HTTP::Client.new(base-uri => $!uri, :json);
}
method get (:$package) {
my $path = <x86_64?>;
my $resp = await $!client.get($path ~ $package);
my $json = await $resp.body;
return $json;
}
}
class AllRepos {
has Repo #.repo;
method get (:$package) {
# check if some repos are disabled
my #candidate = #!repo>>.get(:$package).unique(:with(&[eqv])).flat;
# do furthre processign of the data then return it;
return #candidate;
}
}
my $repo1 = Repo.new: name => 'repo1', uri => Cro::Uri.new(:uri<http://localhost:80>);
my $repo2 = Repo.new: name => 'repo2', uri => Cro::Uri.new(:uri<http://localhost:77>);
my #repo = $repo1, $repo2;
my $repos = AllRepos.new: :#repo;
#my #packages = $repos.get: package => 'rakudo';
Let's say I want to connect to two package repositories, make a query for a package name, combine the result from the repos and process it (filter, unique, prioritize,...), What is a good way to do that?
The code you showed looks like one good way in principle but not, currently, in practice.
The hyperoperators such as >>:
Distribute an operation (in your case, connect and make a query) ...
... to the leaves of one or two input composite data structures (in your case the elements of one array #!repo) ...
... with logically parallel semantics (by using a hyperoperator you are declaring that you are taking responsibility for thinking that the parallel invocations of the operation will not interfere with each other, which sounds reasonable for connecting and querying) ...
... and then return a resulting composite data structure with the same shape as the original structure if the hyperoperator is a unary operator (which applies in your case, because you applied >>, which is an unary operator which takes a single argument on its left, so the result of the >>.get is just a new array, just like the input #!repo) or whose shape is the hyper'd combination of the shapes of the pair of structures if the hyperoperator is a binary operator, such as >>op<< ...
... which can then be further processed (in your case it is, with .unique, which will produce a resulting Seq) ...
... whose elements you then assign back into another array (#candidate).
So your choice is a decent fit in principle, but the commitment to parallelism is only semantic and right now the Rakudo compiler never takes advantage of it, so it will actually run your code sequentially, which presumably isn't a good fit in practice.
Instead I suggest you consider:
Using map to distribute an operation over multiple elements (in a shallow manner; map doesn't recursively descend into a deep structure like the hyperoperators, deepmap etc., but that's OK for your use case) ...
... in combination with the race method which parallelizes the method it proceeds.
So you might write:
my #candidate =
#!repo.hyper.map(*.get: :$package).unique(:with(&[eqv])).flat;
Alternatively, check out task 94 in Using Perl 6.
if the approach mention in the following link is suitable for this use case! https://perl6advent.wordpress.com/2013/12/08/day-08-array-based-objects/
I don't think so. That's about constructing a general purpose container that's like an array but with some differences to the built in Array that are worth baking into a new type.
I can just about imagine such things that are vaguely related to your use case -- eg an array type that automatically hyper distributes method calls invoked on it, if they're defined on Any or Mu (rather than Array or List), i.e. does what I described above but with the code #!repo.get... instead of hyper #!repo.map: *.get .... But would it be worth it (assuming it would work -- I haven't thought about it beyond inventing the idea for this answer)? I doubt it.
More generally...
It seems like what you are looking for is cookbook like material. Perhaps a question posted at the reddit sub /r/perl6 is in order?
OK, this should be an interesting one I think. I want to minimize the number of invocations to my Seam component inside an iteration. I am using Seam 2.2.1.CR1, Richfaces 3.3.3.Final, JSF 1.2 and Facelets.
Please take a look the following Facelet snippet:
<rich:datatable value="#{myBean.products}" var="prod">
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.name}
</rich:column>
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.number}
</rich:column>
...
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.somethingElse1}
</rich:column>
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.somethingElse2}
</rich:column>
...
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.somethingElse3}
</rich:column>
</rich:datatable>
In the above code I am computing an attribute (here the rowspan, but that doesn't really matter, it could be any attribute or value at all, so please don't focus on that) by evaluating an EL expression. As you can see, the method that calculates the value takes the current prod as an argument.
I have made an internal optimization in the rowspan Seam component, and it keeps in a HashMap all the already computed values for products. So, when the the EL expression is evaluated at the second rich:column, the rowspan first looks up in the HashMap the already computed value, and returns that, instead of re-computing all over again.
Although this is better that re-computing all over again, I still have to make an invocation to a Seam component. Is there a way to somehow invoke the Seam component only once, and somehow retain the computed value for the current iteration?
The analogous to Java would be to define a variable inside the loop at each iteration, and reuse it throughout the iteration.
Note: I have already made other Seam-oriented optimizations such as #BypassInterceptors, the Seam component is in the EVENT scope, so no hierarchical lookups take place etc.
Is there a way to somehow invoke the Seam component only once, and somehow retain the computed value for the current iteration?
Sure, in theory.
But I am not sure I fully understand your question. Which seam component are you talking about? rowspan?
If that is the case, then yeah, its invoked each time you call it, which makes sense. You are looping through a dataTable, and for each row you call it.
Without knowing more details about what you are trying to do, its difficult to suggest an answer. Is the code slow? Is that why you need to optimize further?
Update
Try this, though I am not sure if it works
<rich:dataTable value="#{myBean.products}" var="prod">
<ui:param name="myrowspan" value="#{rowspan.calcHomePageProductRowspan(prod)}"/>
<rich:column rowspan="#{myrowspan}">
#{prod.name}
</rich:column>
</rich:dataTable>
Second update
So if you don't change your code to be a #Out, #Factory, #Unwrap or similar, then this will always be evaluated each time it runs. This is just how JSF works.
That's why they say that you should do this in your getters, because JSF will call this for each JSF Phase.
public List<Foo> getFoo() {
if(this.field != null) {
field = (List)entityManager.createQuery("from Foo").getResultList();
}
return this.field;
}
If you wouldn't have cached the list, and checking for null, JSF would hit the database for each phase and for each row in the data table.
Thus this is just something you have to live with.