Raku cloned object not sunk - clone

class A {
has $.n;
# If this method is uncommented then the clone won't be sunk
# method clone {
# my $clone = callwith(|%_);
# return $clone;
# }
method sink(-->Nil) { say "sinking...$!n" }
}
sub ccc(A:D $a) { $a.clone(n=>2) }
ccc(A.new(n=>1));
say 'Done';
Above prints:
sinking...2
Done
However, if the custom clone method is used, then the returned clone from ccc won't be sunk for some reason. It works if I sink it explicitly at call site or if I change the my $clone = callwith(|%_) line to my $clone := callwith(|%_). Is this expected? What's the reason that it's working this way?
Thanks!

There are lots of filed-and-still-open-years-later sink bugs (and, I suspect, loads that have not been filed).
As touched on in my answer to Last element of a block thrown in sink context:
someone needs to clean the kitchen sink, i.e. pick up where Zoffix left off with his Flaws in implied sinkage / &unwanted helper issue.
Zoffix's conclusion was:
So given there are so many issues with the system, I'm just wondering if there isn't a better one that can be used to indicate whether something is wanted or not.
Fast forward 2 years, and a better system is hopefully going to land. In a recent grant report jnthn writes:
The current code doing this work in Rakudo is difficult to follow and not terribly efficient. ... Since RakuAST models the language at a higher level and defers producing QAST until much later, a far cleaner solution to the sink analysis problem is possible. ... I'm optimistic that the model I've created will be flexible enough to handle all the sinking-related requirements

I'm not sure what is going on yet, but removing the return statement makes the cloned object call the right sink method.
I've created an issue for it: https://github.com/rakudo/rakudo/issues/3855

Related

Angular 6 avoid callback hell

Coming from AngularJS I'm struggling trying to solve the next problem. I need a function that returns an object (lets call it A, but this object cannot be returned till all the requests that are contained in that function are resolved. The process should be like:
The object A is downloaded from a remote server
Using A, we do operations over another object (B)
B is downloaded from the server
B is patched using some attributes from A
Using A and the result of B we do operations over a third object, C
C is downloaded from the server
C is patched using some attributes from A and B
After B and C are processed, the function must return A
I'd like to understand how to do something like this using rxjs, but with Angular 6 most of the examples around the internet seem to be deprecated, and the tutorials out there are not really helping me. And I cannot modify the backend to make this a bit more elegant. Thanks a lot.
Consider the following Observables:
const sourceA = httpClient.get(/*...*/);
const sourceB = httpClient.get(/*...*/);
const sourceC = httpClient.get(/*...*/);
Where httpClient is Angular's HTTPClient.
The sequence of the operations you described may look as follows:
const A = sourceA.pipe(
switchMap(a => sourceB.pipe(
map(b => {
// do some operation using a and b.
// Return both a and b in an array, but you can
// also return them in an object if you wish.
return [a,b];
})
)),
switchMap(ab => sourceC.pipe(
map(c => {
// do some operations using a, b, and/or c.
return a;
})
))
);
Now you just need to subscribe to A:
A.subscribe(a => console.log(a));
You can read about RxJs operators here.
Well, first of all, it appears to me that this function-call, as described, would be somehow expected to block the calling process until all of the specified events have occurred – which of course is unreasonable in JavaScript.
Therefore, first of all, I believe that your function should require, as its perhaps-only parameter, a callback that will be invoked when everything has finally taken place.
Now – as to "how to handle steps 1, 2, and 3 elegantly" ... what immediately comes to mind is the notion of a finite-state machine (FSM) algorithm.
Let's say that your function-call causes a new "request" to be placed on some request-table queue, and, if necessary, a timer-request (set to go off in 1 millisecond) to service that queue. (This entry will contain, among other things, a reference to your callback.) Let's assume also that the request is given a random-string "nonce" that will serve to uniquely identify it: this will be passed to the various external requests and must be included in their corresponding replies.
The FSM idea is that the request will have a state, (attribute), such as: DOWNLOADING_FROM_B, B_DOWNLOADS_COMPLETE, DOWNLOADING_FROM_C, C_REQUESTS_COMPLETE, and so on. Such that each and every callback that will play a part in this fully-asynchronous process will (1) be able to locate a request-entry by its nonce, and then (2) unambiguously "know what to do next," and "what new-state (if any) to assign," based solely upon examination of the entry's state.
For instance, when the state reaches C_REQUESTS_COMPLETE, it would be time to invoke the callback that you originally provided, and to delete the request-table entry.
You can easily map-out all of the "state transitions" that might occur in an arbitrarily-complex scenario (what states can lead to what states, and what to do when they do), whether or not you actually create a data-structure to represent that so-called "state table," although sometimes it is even-more elegant(!) when you do. (Possibly-messy decision logic is simply pushed to a simple table-lookup.)
This is, of course, a classic algorithm that is applicable to – and, has been used in – "every programming language under the sun." (Lots of hardware devices use it, too.)

How can I temporarily disable PaperTrail when reifying a version?

I am using paper_trail for undo/redo functionality in my site and am having a problem when I call reify.save on a version in that on save and new PaperTrail::Version gets created.
Is there a way to turn off PaperTrail during the saving of a reified object?
I understand that PaperTrail.enabled = false is possible, but I don't want other changes being made a the same time to not be recorded.
My ideal solution would be something along the lines of:
PaperTrail.disable { version.reify.save }
I once accomplished something similar by mixing in something like this:
def without_papertrail
PaperTrail.disable
yield if block_given?
PaperTrail.enable
end
Then you can do something similar to your objective
without_papertrail { version.reify.save }
You can disable paper trail for a particular model, using either of two syntaxes:
m = MyModel.find(123)
m.paper_trail.without_versioning do
# No versioning of `m` happens in this block
end
Note: Since it is called on a model instance, it seems as though this might naturally disable versioning on just that instance, but this syntax disables versioning on the entire model.
The other syntax:
MyModel.paper_trail.disable
# No versioning of MyModel happens here
MyModel.paper_trail.enable
As of today, gem version 10.3.0, the correct way to achieve this is, as per the gem documentation:
PaperTrail.request.disable_model(Banana)
# changes to Banana model do not create versions,
# but eg. changes to Kiwi model do.
PaperTrail.request.enable_model(Banana)
from the readme: https://github.com/paper-trail-gem/paper_trail#7-testing
PaperTrail.enabled = false

Why is ReactiveList with ChangeTrackingEnabled slow when I Clear inside SuppressChangeNotifications?

Why is ReactiveList with ChangeTrackingEnabled slow when I Clear inside SuppressChangeNotifications?
With 10,000 entries it takes about 2 seconds for the Clear method to return.
Shouldn't SuppressChangeNotifications bypass the change tracking code?
Or how can I improve the performance here?
ReactiveList<Person> _personList = new ReactiveList<Person> { ChangeTrackingEnabled = true };
using (_personList.SuppressChangeNotifications())
{
_personList.Clear();
}
Thanks a lot.
Change tracking code is bypassed, but still ReactiveList needs to cleanup its internal stuff when you clear the list. And the method used to do so is extremely inefficient ( O(n2) ), as detailed in this SO answer.
The Clear implementation with change tracking enabled can definitely be improved, I'll send a PR to RxUI if I get the chance.
E.g. replacing this code by foreach (var foo in _propertyChangeWatchers.Values.ToList()) foo.Release(); makes the Clear immediate, w/o altering the behavior.
EDIT :
You can work around this performance issue by writing instead:
using (_personList.SuppressChangeNotifications())
_personList.RemoveRange(0, _personList.Count);

Language Service: ParseReason.Check never called after migrating to VS2010

I just migrated my language service from VS2008 to VS2010. Everything works fine except for one important thing: I no longer get LanguageService.ParseSource invoked for ParseReason.Check. It do get a single invoke after opening a file. But after editing code, it no longer gets invoked.
Any ideas what could be causing that?
I also migrated a language service from 2008 to 2010. Can you check if you've fallowed all of these steps?
http://msdn.microsoft.com/en-us/library/dd885475.aspx
I didn't have to do anything else, which I verified by diffing the important files in our depot before and after the change.
I don't know if you ever figured your question out, but have you tried making sure that your Source class' LastParseTime is set to 0 when creating it? I seem to recall some issues with Check not happening unless you manually set LastParseTime to 0 when creating your Source object.
Protip: If you use .NET Reflector, you can disassemble all of the base classes for the LanguageService framework and get a pretty good understanding of how it all works under the hood. The classes you'd be interested in live in Microsoft.VisualStudio.Package.LanguageService.10.0.dll, which should be installed in the GAC. I've found this to be unimaginably helpful when trying to figure out why things weren't working in my own Language Service, and being able to step through the source code in the debugger mitigates almost all the pain of working with these frameworks!
When your Source object is initialized, it starts off with a LastParseTime of Int32.MaxValue. The code that causes fires off a ParseRequest with ParseReason.Check checks the LastParseTime value to see if the time since the last change to the text is less than the time it takes to run a parse (or the CodeSenseDelay setting, whichever is greater).
The code that handles the response from ParseSource is supposed to set the LastParseTime, but as far as I can tell, it only does that if the ParseReason is Check.
You can get around this issue by setting Source.LastParseTime = 0 when you initialize your Source. This has the side-effect of setting CompletedFirstParse to true, even if the first parse hasn't finished yet.
Another way to fix this issue is to override Source.OnIdle to fire off the first call to BeginParse() This is the way I would recommend.
public override void OnIdle(bool periodic)
{
// Once first "Check" parse completes, revert to base implementation
if (this.CompletedFirstParse)
{
base.OnIdle(periodic);
}
// Same as base implementation, except we don't check lastParseTime
else if (!periodic || this.LanguageService == null || this.LanguageService.LastActiveTextView == null || (this.IsCompletorActive) || (!this.IsDirty || this.LanguageService.IsParsing))
{
this.BeginParse();
}
}

Adding custom code to mootools addEvent

Even though I've been using mootools for a while now, I haven't really gotten into playing with the natives yet. Currently I'm trying to extend events by adding a custom addEvent method beside the original. I did that using the following code(copied from mootools core)
Native.implement([Element, Window, Document], {
addMyEvent:function(){/* code here */}
}
Now the problem is that I can't seem to figure out, how to properly overwrite the existing fireEvent method in a way that I can still call the orignal method after executing my own logic.
I could probably get the desired results with some ugly hacks but I'd prefer learning the elegant way :)
Update: Tried a couple of ugly hacks. None of them worked. Either I don't understand closures or I'm tweaking the wrong place. I tried saving Element.fireEvent to a temporary variable(with and without using closures), which I would then call from the overwritten fireEvent function(overwritten using Native.implement - the same as above). The result is an endless loop with fireEvent calling itself over and over again.
Update 2:
I followed the execution using firebug and it lead me to Native.genericize, which seems to act as a kind of proxy for the methods of native classes. So instead of referencing the actual fireEvent method, I referenced the proxy and that caused the infinite loop. Google didn't find any useful documentation about this and I'm a little wary about poking around under the hood when I don't completely understand how it works, so any help is much appreciated.
Update 3 - Original problem solved:
As I replied to Dimitar's comment below, I managed to solve the original problem by myself. I was trying to make a method for adding events that destroy themselves after a certain amount of executions. Although the original problem is solved, my question about extending natives remain.
Here's the finished code:
Native.implement([Element, Window, Document], {
addVolatileEvent:function(type,fn,counter,internal){
if(!counter)
counter=1;
var volatileFn=function(){
fn.run(arguments);
counter-=1;
if(counter<1)
{
this.removeEvent(type,volatileFn);
}
}
this.addEvent(type,volatileFn,internal);
}
});
is the name right? That's the best I could come up with my limited vocabulary.
document.id("clicker").addEvents({
"boobies": function() {
console.info("nipple police");
this.store("boobies", (this.retrieve("boobies")) ? this.retrieve("boobies") + 1 : 1);
if (this.retrieve("boobies") == 5)
this.removeEvents("boobies");
},
"click": function() {
// original function can callback boobies "even"
this.fireEvent("boobies");
// do usual stuff.
}
});
adding a simple event handler that counts the number of iterations it has gone through and then self-destroys.
think of events as simple callbacks under a particular key, some of which are bound to particular events that get fired up.
using element storage is always advisable if possible - it allows you to share data on the same element between different scopes w/o complex punctures or global variables.
Natives should not be modded like so, just do:
Element.implement({
newMethod: function() {
// this being the element
return this;
}
});
document.id("clicker").newMethod();
unless, of course, you need to define something that applies to window or document as well.

Resources