CONTROL or once messes with last? - exception

This loop never stops:
class CX::Vaya does X::Control {
has $.message
}
loop {
once {
CX::Vaya.new( message => "I messed up!" ).throw;
}
last;
CONTROL {
default {
say "Controlled { .^name }: { .message }"
}
}
}
It keeps writing
Controlled CX::Last: <last control exception>
Controlled CX::Last: <last control exception>
Controlled CX::Last: <last control exception>
Controlled CX::Last: <last control exception>
Controlled CX::Last: <last control exception>
Controlled CX::Last: <last control exception>
Controlled CX::Last: <last control exception>
Controlled CX::Last: <last control exception>
...
It could be the once bit, because CONTROL phaser with last does finish:
loop { say "Hey"; last; CONTROL { default: .message.say } }
# OUTPUT: «Hey␤<last control exception>␤»
But I'm not really sure.

Loop flow control in Perl 6 is implemented using control exceptions. Thus, last is actually throwing a CX::Last control exception. Since the CONTROL block uses default, it is therefore catching the CX::Last thrown by last, meaning that control is never transferred out of the loop.
The fix is to instead specify which control exception to catch, using when:
loop {
once {
CX::Vaya.new( message => "I messed up!" ).throw;
}
last;
CONTROL {
when CX::Vaya {
say "Controlled { .^name }: { .message }"
}
}
}

What Jonathan says.
In more detail:
The default control flow for P6 is that the next statement follows the current one. So say 42; say 99; defaults to doing the say 42 and then doing the say 99.
P6 has an advanced and pervasive exception system that's used for any exception to this default control flow of one-statement-then-the-immediately-following-statement. It's not just for errors.
Any exception to the default control flow is called an exception. Many are error exceptions. But there's another category, namely control flow exceptions, or control exceptions for short. For example, an explicit or implicit return/leave from a routine/block is a control exception. (In principle. In reality the compiler/optimizer will elide some of this machinery when appropriate.)
A last is a control exception. It throws the control exception CX::Last. Its message payload is "last control exception". You are seeing that message.
A CONTROL block is entered if a control exception applies to its containing block. It can either handle the passed exception or not handle it. If it handles it then control resumes with the statement that follows it. If, as in this example, the CONTROL block is at the end of a loop, then the next statement would be an implicit next (another control exception) and the loop would restart.
The code CONTROL { default { say "Controlled { .^name }: { .message }" } handles all control exceptions, including the one thrown by last. So it prints its message and then the loop continues. (Infinitely.)
In the code loop { say "Hey"; last; CONTROL { default: .message.say } } # OUTPUT: «Hey␤<last control exception>␤», the CONTROL block does display the exception's message but it doesn't handle it. (default: is just a label, no different to, say, I'm-a-label:, and unrelated to default { ... }.) So the last control exception isn't handled by your code and instead is handled by the default language handling which is to break out of the loop.

It is really the combination of CONTROL and CX::Succeed that are preventing the default behaviour of last.
All of the flow control functions are implemented in terms of exceptions.
Rather than lump them in with regular exceptions in CATCH, there is a special handler just for them named CONTROL.
Both CATCH and CONTROL can be thought of as special forms of given.
The two main differences being that the topic is set to the exception, and that something special happens if there was a CX::Succeed.
If there is a CX::Succeed then that indicates the exception or flow-control was successfully handled, and that no further processing needs to happen.
There are two ways to get CX::Succeed to happen inside of CONTROL.
default block
when block
(Technically I think that just plain succeed should also work, but it doesn't seem to.)
If you are in one of those blocks, and you want the processing to actually continue, you can use proceed (CX::Proceed).
loop {
once {
CX::Vaya.new( message => "I messed up!" ).throw;
}
last;
CONTROL {
default {
.^name.say;
proceed if CX::Last;
}
}
}
It is much better to just use a when block that captures exactly what you want to handle specially.
(Note that a postfix when does not throw CX::Succeed, so normal processing would continue in that case.)
default is a block prefix. Meaning it always must be followed by a block.
Adding just : to the end of an identifier is only used to create a label, and on method calls to remove the parentheses.
So default: does absolutely nothing here.
Also once is not a block prefix. It is a statement prefix. (It just so happens that a block can be treated as a statement.)
There is no reason to add a block there unless you are going to write more than one statement inside of it.
loop {
once CX::Vaya.new( message => "I messed up!" ).throw;
last;
CONTROL {
when CX::Vaya {
.^name.say;
}
}
}

Related

How to check the (initial) render state (not the update state) of a component in shadow DOM

Following the question I would like to ask about the appropriate way to check the initial render status of a component (not the update status) in shadow DOM. Is there any similar to document.readyState or a promise?
I have also tried to do:
getItems() {
this.updateComplete
.then(() => {
this.nodesLists = this.shadowRoot.querySelectorAll(".name");
})
.then(...)
}
which also failed.
Tia
await this.updateComplete (or this.updateComplete.then(...)) is the correct way to wait until the element has no pending render work before e.g. querying the state of the element's rendering, so your code should generally work as long as the element is connected to the document before running getItems.
Example: https://jsbin.com/jiquhez/edit?html,console,output
Note however, that if you await updateComplete before the element is connected and the element has no properties set that would trigger a render, then updateComplete currently resolves before the first render. This may be considered an unintended bug, filed at lit-element/#594.
Note you may also want to look into using the firstUpdated lifecycle method, depending on your use case. This is a method you can implement on your class to perform one-time work following the first update/render cycle for the element (useful for e.g. selecting static nodes that won't change based on rendering).
Example: https://jsbin.com/limikas/edit?html,console,output

Can Custom Element names contain Unicode?

Surprisingly can't find this on google...
Can the name of a custom element (a la the Web Components set of W3C specs) contain unicode?
This HTML 5 Custom element names? says that a custom element name must begin with an ASCII character, contain a hyphen, and ANY OTHER characters. Does that mean unicode?
TL;DR This great article explains what characters are permitted in javascript. Unfortunately, those won’t work as expected with elements. At least, at the moment.
The reason is that document.registerElement which is being called on newly created custom elements, will fail:
var a = document.registerElement('a-ℵ');
//⇒ Uncaught SyntaxError: Failed to execute
// 'registerElement' on 'Document':
// Registration failed for type 'a-ℵ'.
// The type name is invalid.
That’s because registerElement tries to create internal constructor, different from generic function HTMLElement()/function HTMLUnknownElement() for registered elements:
console.log(document.registerElement('a-b'));
//⇒ function a-b() { [native code] }
I would suggest the internals of browsers are not yet ready for:
//⇒ function a-ℵ() { [native code] }
though you might easily specify:
var ℵ = function() { console.log('IT WORKS') };
ℵ();
//⇒ IT WORKS
I understand this is not exactly an answer you expected, but I hope it sheds some light.

How to use COMMENTS channel without getting a warning

I read the answer to Why am I getting an error when assigning tokens to a channel?.
The answer is that this is not an error, but a warning.
Well that's all very well, but the Eclipse IDE, https://github.com/jknack/antlr4ide, will not generate code when this warning is present.
Is there a way to not get a warning, when using a COMMENT channel?
You could trick the compiler by defining COMMENT in a tokens{} block instead of in the #members{} block. This would result in a constant value getting automatically assigned to it.
If you are also using the HIDDEN channel, I would include something like this to be safe:
#members {
{
if (HIDDEN == COMMENT) {
throw new IllegalStateException(
"Expected the HIDDEN and COMMENT constants to have different values.");
}
}
}

Scala.swing GUI -- How to separate multiple reaction cases

I am currently in the process of turning a sudoku solving program into a GUI with scala.swing and running into some trouble with the use of different functions. That is to say, I have a function for completely solving the puzzle, another for offering a hint entry, and another that will reset the grid. The interface consists of 81 individual ComboBox'es (see: http://i.imgur.com/45vzpei.png) and three buttons that perform said functions. My problem is that, while the separate reactions/cases involved reference specifically which buttons/functions to listen to, any button will incite all of the functions. My code for each of the listeners/buttons looks something like the following
listenTo(solve,comb11,comb12,comb13,comb14,comb15,comb16,comb17,comb18,comb19,comb21,comb22,comb23,comb24,comb25,comb26,comb27,comb28,comb29,comb31,comb32,comb33,comb34,comb35,comb36,comb37,comb38,comb39,comb41,comb42,comb43,comb44,comb45,comb46,comb47,comb48,comb49,comb51,comb52,comb53,comb54,comb55,comb56,comb57,comb58,comb59,comb61,comb62,comb63,comb64,comb65,comb66,comb67,comb68,comb69,comb71,comb72,comb73,comb74,comb75,comb76,comb77,comb78,comb79,comb81,comb82,comb83,comb84,comb85,comb86,comb87,comb88,comb89,comb91,comb92,comb93,comb94,comb95,comb96,comb97,comb98,comb99)
reactions += {
case ButtonClicked(solve) =>
...[working code for solve function]...
}
(The 'comb##'s are the exhaustive 81 ComboBoxes and the 'solve' is the button that solves the whole puzzle.) If I get rid of all but one of the listener/reaction blocks of code, clicking the remaining button works perfectly. If I try to include two or all of the listener/reaction code blocks, then every button causes ALL functions to be performed, which is clearly confusing and undesirable.
Not sure I understand your problem. But if you use lower case names in pattern matching extraction, these are fresh variables, and have nothing to do with values of the same name defined elsewhere. So to react to the solve button, you need to match against the value solve which you can do by putting it in back ticks:
listenTo(allMyButtons: _*)
reactions += {
case ButtonClicked(`solve`) => // note the back ticks!
...[working code for solve function]...
}
Otherwise, why don't you just keep each reaction with each combo box?
val combos = Vector.tabulate(81) { i =>
new ComboBox(1 to 9) {
listenTo(this)
reactions += {
case ButtonClicked(_) =>
... // not important to check the button - we only listen to one!
}
}
}
There is also a shorter way of defining the reaction to a pressed button.
import swing.{MainFrame, FlowPanel, Button}
val frame = new MainFrame {
contents = new FlowPanel {
contents += Button("solve")(println("solve"))
}
visible = true
}

Grabbing a new Window in Tcl/Tk

I have a GUI, in it I have a properties window that opens in a new window. In some of the times, (randomly and not deterministicly reproducible) when I open the window it gives the fallowing error:
grab failed: window not viewable
It doesn't interfere with the normal function of the program nor doesn't seem to have any affect on anything besides printing that message.
The code for creating the new window is:
proc _prop_menu_make_top {{elem {}}} {
toplevel .prop_menu
#...initialize some variables...
wm title .prop_menu "Properties for $_prop_attr(name)"
#...create and display the window widgets...
bind .prop_menu <Key-KP_Enter> {_prop_menu_ok_button}
bind .prop_menu <Return> {_prop_menu_ok_button}
bind .prop_menu <Escape> {_prop_menu_cancel_button}
# catch presses on the window's `x` button
wm protocol .prop_menu WM_DELETE_WINDOW {
_prop_menu_cancel_button
}
# make the top window unusable
center_the_toplevel .prop_menu
focus .prop_menu.main_frame.model_name.entry
grab release .
grab set .prop_menu
}
proc center_the_toplevel { window } {
if { [string equal $window [winfo toplevel $window]] } {
set width [winfo reqwidth $window]
set height [winfo reqheight $window]
set x [expr {([winfo vrootwidth $window] - $width) / 2}]
set y [expr {([winfo vrootheight $window] - $height) / 2 }]
wm geometry $window +${x}+${y}
}
return
}
proc _prop_menu_ok_button {} {
#....saving the needed data...
_prop_menu_cancel_button
}
proc _prop_menu_cancel_button {} {
destroy .prop_menu
# make the top window usable again
grab set .
# redraw the canvas
nlv_draw
}
Does anyone has any idea as to what may be causing this problem?
Does anyone has any advice as to how make the bug easier to reproduse?
EDIT:
running Tcl version 8.4.6 for 64bit, don't know which tk version.
Explanation
For various reasons (some technical, some design principles), Tk only permits grabs to be set on windows that are mapped onto the screen. This is almost certainly what you want; mouse clicks should be going to a window you can see after all.
The problem you've got is that you're trying to do the grab too early. In particular, Tk postpones the creation of the underlying X11/OS window (depending on platform) for each widget until it has finished deciding what the configuration of that widget will be, which is taken to be when Tk becomes “idle”. Idle is defined to be when the event loop is entered and there are no pending events to be serviced. At that point, Tk tells the basic system graphics engine to allocate a rectangular chunk of screen estate (the window) and to put it on the screen. That in turn triggers a whole cascade of events and processing (there's a lot going on at that point) that ends up with the window being shown to you; it's only once the window is shown that you can set a grab on it.
So how do you know when you can set a grab? Well, you've got to wait for the window to turn up. That means waiting for an event: the key ones that you might care about for this task are <Map>, <Visibility> and <Expose>. They indicate respectively when the window is logically present within the root window, when there is a change in what is actually viewable, and when there is something to redraw. (There are equivalents on Windows to the first and last, which Tk remaps internally, but Windows doesn't tell you about actual visibility changes at all. Ever.)
Solution
The simplest way to wait for a widget to become grabbable (and then do the grabbing) is to use:
tkwait visibility $theWidget
grab set $theWidget
That just waits in the event loop for a <Visibility> event to turn up on that window. (It doesn't work on Windows though because of the absence of the event type on that platform.) You could rewrite the above as this:
bind $theWidget <Visibility> [list set waiting($theWidget) gotit]
vwait waiting($theWidget)
bind $theWidget <Visibility> {} ;# remove the binding again!
grab set $theWidget
If you're on Windows[*], you'll have to use that second technique, but replacing <Visibility> with <Map>.
bind $theWidget <Map> [list set waiting($theWidget) gotit]
vwait waiting($theWidget)
bind $theWidget <Map> {} ;# remove the binding again!
grab set $theWidget
I can't remember if <Expose> is available to scripts in Tk 8.4; that's an event that Tk handles for you normally. In any case, <Map> works and <Visibility> is perfect on X11.
You should also be aware that both tkwait and vwait can cause problems with reentrant event handling — you don't want it if you can help it! — so take care. You can deal with the problems by rewriting it all into continuation-passing style, which happens to be fairly easy in this case:
bind $theWidget <Map> {
bind %W <Map> {}
grab set %W
}
But if you're doing anything more than setting a grab, it can become really complex. (Tcl 8.6's coroutines can help untangle this mess, but they're definitely not portable to 8.4.)
[*] I forget whether there are issues round here with OSX with a non-X11 build of Tk. Check for yourself if you care.