Why would you use a proto rule in a Perl 6 grammar? - grammar

Here are two grammars. One uses a proto token and one doesn't. They both get the same done. These are basically the examples in S05 under "Variable (non-)interpolation". In this simple example, they are both able to do the same things.
Which situations justify all the extra typing? The proto tokens have distinct methods in the action class, and maybe there's a small benefit there. However, you have to type some extra stuff to get that benefit.
Is there some feature of proto that makes other parts of the grammar easier?
grammar NoProto {
token variable { <sigil> <identifier> }
token identifier { <ident>+ }
token sigil { < $ # % & :: > }
}
grammar YesProto {
token variable { <sigil> <identifier> }
token identifier { <ident>+ }
proto token sigil { * }
token sigil:sym<$> { <sym> }
token sigil:sym<#> { <sym> }
token sigil:sym<%> { <sym> }
token sigil:sym<&> { <sym> }
token sigil:sym<::> { <sym> }
}
class Proto::Actions {
method variable ($/) {
say "found variable: " ~ $/;
}
method identifier ($/) {
say "found identifier: " ~ $/;
}
method sigil ($/) {
say "found sigil: " ~ $/;
}
method sigil:sym<$> ($/) {
say "found sym sigil: " ~ $/;
}
}
my $variable = '$butterfuly';
say "------No proto parsing";
my $no_proto_match = NoProto.parse(
$variable,
:rule<variable>,
:actions(Proto::Actions),
);
say "------Yes proto parsing";
my $yes_proto_match = YesProto.parse(
$variable,
:rule<variable>,
:actions(Proto::Actions),
);
The output shows that proto calls a different method in the action class:
------No proto parsing
found sigil: $
found identifier: butterfuly
found variable: $butterfuly
------Yes proto parsing
found sym sigil: $
found identifier: butterfuly
found variable: $butterfuly

Technically, a proto will be made for you if you don't specify it yourself. It basically creates the multi-method dispatch handler for that particular token (just as it does with sub and method). Which you usually don't need to care about.
Why would you specify a proto? I can think of a number of reasons:
because you want the tokens to share some traits
because you want to execute some code before or after the dispatch
Yes, the { * } may contain executable code. The bare Whatever indicates the dispatching to the appropriate candidate. Showing this in a simpler situation with sub:
proto a(|) { say "before"; {*}; say "after" }
multi a(Int) { say "Int" }
multi a(Str) { say "Str" }
a 42; a "42"
shows:
before
Int
after
before
Str
after
Hope this helps :-)

Having the method it calls in an actions class can be useful for separating out the logic. It's basically the same sort of idea as multimethods except for grammars.
( I wrote this for evaluating answers to a Code Golf )
grammar Mathemania {
token TOP { <cmd-list> }
token cmd-list { <cmd>+ }
token cmd { <op> <argument>? }
proto token op { * }
token op:sym<exp> { e } # notice that the name doesn't have to match
token op:sym<factorial> { f }
token op:sym<root> { r }
token op:sym<ceil> { c }
token op:sym<floor> { l }
token argument { '(' ~ ')' <cmd-list> }
}
class Calculate {
method TOP ($/) { make $<cmd-list>.made }
method argument ($/) { make $<cmd-list>.made }
method cmd-list ($/) {
my $result = 2;
$result = .made.($result).narrow for #<cmd>;
make $result;
}
method cmd ($/) {
if $<argument> {
make $<op>.made.assuming( *, $<argument>.made );
} else {
make $<op>.made;
}
}
method op:sym<exp> ($/) { make -> \n, \e = 2 { n ** e } }
method op:sym<factorial> ($/) { make -> \n, \k = 2 { [*] n, n - k + 1 ...^ 0 } }
method op:sym<root> ($/) { make -> \n, \r = 2 { n ** (1/r) } }
method op:sym<ceil> ($/) { make &ceiling }
method op:sym<floor> ($/) { make &floor }
}
It also makes it so that a subclassing grammar can add its tokens along side of those that already exist, and a subclassing actions class can do the same. ( try it )
grammar Mathmania-Plus is Mathemania {
token op:sym<negate> { n }
token op:sym<abs> { a }
}
class Calculate-Plus is Calculate {
method op:sym<negate> ($/) { make &prefix:<-> }
method op:sym<abs> ($/) { make &abs }
}

One benefit of splitting your alternatives into a proto and multis is that you can extend it more reliably. You can add multis to the existing proto in a grammar that inherits from the grammar that declares the proto, and you don't need to list all the possible alternatives (which you'd have to do in case a of a single rule).
This means that you can even have multiple independent extensions to the same grammar, for example by mixing in several rules that supply multis for different symbols to match.
This is basically the mechanism that Perl 6 itself uses when you define a custom operator: there are rules for matching the different kinds of operators (like infix, prefix, postfix, ...), and declaring a new operator derives a new grammar from the currently active one, with a multi candidate added for the new operator. A script can import operators from several modules that don't know of each other thanks to the extensibility of proto token mechanism.

Related

listop operator causing infinite recursion, any way to fix?

I'm looking to possibly help update the File::HomeDir module which was never finished. While inspecting it, I noticed that stubbed out methods were causing infinite loops:
In the File::HomeDir role:
unit class File::HomeDir;
use File::HomeDir::Win32;
use File::HomeDir::MacOSX;
use File::HomeDir::Unix;
my File::HomeDir $singleton;
method new
{
return $singleton if $singleton.defined;
if $*DISTRO.is-win {
$singleton = self.bless does File::HomeDir::Win32;
} elsif $*DISTRO.name.starts-with('macos') {
$singleton = self.bless does File::HomeDir::MacOSX;
} else {
$singleton = self.bless does File::HomeDir::Unix;
}
return $singleton;
}
method my-home {
return File::HomeDir.new.my-home;
}
method my-desktop {
return File::HomeDir.new.my-desktop;
}
<snip>
In the File::HomeDir::MacOSX module:
use v6;
unit role File::HomeDir::MacOSX;
method my-home {
# Try HOME on every platform first, because even on Windows, some
# unix-style utilities rely on the ability to overload HOME.
return %*ENV<HOME> if %*ENV<HOME>.defined;
return;
}
method my-desktop {
!!!
}
<snip>
With this code, calling say File::HomeDir.my-desktop; results in an infinite loop.
This module was first written about 5 1/2 years ago. I'm assuming it worked at the time. But it appears now that if a role method has a listop operator, it causes the parent's class to be called which then called the role method which then calls the parent class, etc.
I'd do it like this, staying close to the original design:
role File::HomeDir::Win32 {
method my-home() { dd }
method my-desktop() { dd }
}
role File::HomeDir::MacOSX {
method my-home() { dd }
method my-desktop() { dd }
}
role File::HomeDir::Unix {
method my-home() { dd }
method my-desktop() { dd }
}
class File::HomeDir {
my $singleton;
# Return singleton, make one if there isn't one already
sub singleton() {
without $singleton {
$_ = File::HomeDir but $*DISTRO.is-win
?? File::HomeDir::Win32
!! $*DISTRO.name.starts-with('macos')
?? File::HomeDir::MacOSX
!! File::HomeDir::Unix;
}
$singleton
}
method my-home() { singleton.my-home }
method my-desktop() { singleton.my-desktop }
}
File::HomeDir.my-home;
File::HomeDir.my-desktop;

Optional route authentication in Ktor

I have a route in my Ktor application that I want to optionally authenticate. What is the best way to go about this? If I put two routing blocks in, both calls default to the unauthenticated one.
e.g.
routing {
post("/my-route") {
val request = call.receive<MyRouteRequest>()
...
}
authenticate(Constants.myAuthScope) {
post("/my-route") {
val request = call.receive<MyRouteRequest>()
val user = call.principal<User>()
...
}
}
It should be possible using more explicit models combined with validation of those either in the route or perhaps in the underlying service (depends if this is seen as domain logic or API logic)
For basic auth it looks a bit like:
sealed interface PrincipalResult {
data class User(/* ... */): PrincipalResult
object NoUserProvided: PrincipalResult
// This might be replaced with a null result to conform with the Ktor API
// I prefer making it explicit and communicate what's going on
// and not just accept a null that means everything and nothing.
//
// This can also be made into a data class and expanded
// with additional information, allowing for better errors and richer debugging
object InvalidUserCredentials: PrincipalResult
}
install(Authentication) {
basic("stuart-auth") {
realm = "Access to the '/' path"
validate { credentials ->
if (credentials.isMissing()) {
PrincipalResult.NoUserProvided
} else if (credentials.isValid() {
PrincipalResult.User(/* ... */)
} else {
PrincipalResult.InvalidUserCredentials
}
}
}
}
now one can do:
authenticate(Constants.myAuthScope) {
post("/my-route") {
val request = call.receive<MyRouteRequest>()
val principalResult = call.principal<PrincipalResult>()
when (principalResult) {
is PrincipalResult.User ->
is PrincipalResult.NoUserProvided ->
is PrincipalResult.InvalidUserCredentials ->
}
// ...
}
}
This pattern should of course be applied to whichever authentication scheme you actually use, such as JWT, OAuth, LDAP etc.

Default string values for union types in Yang Schema

Why can't the leaf wibble be assigned a default value "-"in the following schema (comments not in schema, added to post for clarity)
module type
{
namespace "example.com";
prefix "foo";
typedef optional-value {
type union {
type uint8 {
range "0 .. 99";
}
type string {
pattern "^-$";
}
}
}
container bar {
leaf wibble {
type optional-value;
default "-"; ### NOT OKAY
}
leaf wobble {
type optional-value;
default 42; ### OKAY
}
}
}
yanglint (version 0.16.105) does not validate the above schema and returns the error message:
err : Invalid value "-" in "wibble" element. (/type:wibble)
err : Module "type" parsing failed.
Done some more experimenting and it appears that strings with patterns cannot be assigned default values
module tmp
{
namespace "example.com";
prefix "foo";
container bar {
leaf wibble {
type string {
pattern "^x$";
}
default "x"; ### NOT OKAY
}
leaf wobble {
type string;
default "y"; ### OKAY
}
}
}
yanglint output:
err : Value "x" does not satisfy the constraint "^x$" (range, length, or pattern). (/tmp:wibble)
err : Module "tmp" parsing failed.
In YANG one uses the regex flavor from XML Schema which doesn't require ^$ to anchor expressions so that they math the entire value. All XSD expressions are implicitly anchored. You could try to remove these characters from your patterns and give it another try.

Is there any concern about returning generic type object in Dart?

I want to implement a different error handling approach in a project without chaining exceptions.
To make it simple as possible, I am tend to write my own basic either-like model.
class Either<F, T> {
final F failure;
final T value;
const Either(this.failure, this.value);
Object check (){
if (failure != null) return failure;
return value;
}
}
I am concerning about returning the type Object, is there any problem or considerations with that in Dart or any other language?
Edit:
or returning dynamic type...
dynamic check(){
if (failure != null) return failure;
return value;
}
I think in your case, it's kind of a wired implementation. The question is, what do you want to do with the actual implementation ? Do you want to replace an if else that will appear over and over? In that case, what would you do if you have to handle the error (failure) ? I think a better approach is to use functions as parameters. Here's a short suggestion.
class Either<T, F> {
T value;
F fail;
Either(this.value, this.fail);
void check(success(T value), {failure(F fail)}) {
if (fail != null && failure != null) {
failure(fail);
} else if (value != null) {
success(value);
}
}
}
class SomeClass {
void checkTheImplementation() {
Either<String, Error> maybeString = Either("testing", null);
// if you don't want to handle the error.
maybeString.check((value) => print(value));
// if you want to handle the error
maybeString.check((value) => print(value), failure: (err) {
print(err.toString());
});
}
}
I have looked over and decided to go with baihu92's either_type way. It's much more clear and comprehensible than either in the dartz package. Here is my implementation:
and the usage is like:

can not read get property of undefined angular 2 error

hi I am trying to get city name from google api but getting that error below is my code
appcomponent class
import {Component, OnInit} from 'angular2/core';
import {marketComponent} from './market.component';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {introComponent} from './intro.component';
import {geoService} from './service.geo';
import {JSONP_PROVIDERS} from 'angular2/http';
declare var google: any;
#Component({
selector: 'my-app',
templateUrl: 'app/app.component.html',
directives: [ROUTER_DIRECTIVES],
providers: [JSONP_PROVIDERS, geoService]
})
#RouteConfig([
{ path: '/intro', name: 'Intro', component: introComponent, useAsDefault: true },
{ path: '/market', name: 'Market', component: marketComponent },
])
export class AppComponent {
constructor(private _http: geoService) { }
public maps;
public cat_error: Boolean = false;
public xml_Latitude :string;
public xml_Lang: string;
ngOnInit() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(this.showPosition);
} else {
alert("Geolocation is not supported by this browser.");
}
var input: any = document.getElementById('google_places_ac');
var autocomplete = new google.maps.places.Autocomplete(input, {});
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var place = autocomplete.getPlace();
console.log(place)
});
}
showPosition(position) {
this.xml_Latitude = position.coords.latitude;
this.xml_Lang = position.coords.longitude;
this._http.getPlaces(this.xml_Latitude, this.xml_Lang).subscribe(
data => { this.maps = data },
err => { this.cat_error = true }
);
var result = this.maps.results;
var city = result[0].address_components[4].long_name + "," + result[0].address_components[6].long_name;
alert(city);
}
}
and geoservice file
import {Injectable} from 'angular2/core';
import { Response, Jsonp} from 'angular2/http';
import 'rxjs/add/operator/map';
#Injectable()
export class geoService {
constructor(private http: Jsonp) { }
public xml_Latitude: string;
public xml_Lang: string;
public getPlaces(xml_Latitude, xml_Lang) {
return this.http.get(`http://maps.googleapis.com/maps/api/geocode/json?latlng=
'${this.xml_Latitude}','${this.xml_Lang}'&sensor=true`)
.map((res: Response) => res.json())
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return error.json().error || 'Server error';
}
}
error also says getplaces is not a function, I think I am missing something but don't know what....
In addition to the callback ordering problem identified by Thierry, you have a lost this context on this line:
navigator.geolocation.getCurrentPosition(this.showPosition);
The Problem
You have the classic JavaScript problem known as the incorrect this context.
The this keyword in JavaScript behaves differently than in does in other languages like C# and Java.
How this works
The this keyword, in a function, is determined as follows:
* If the function was created through a call to .bind, the this value is the argument provided to bind
* If the function was invoked through a method call, e.g. expr.func(args), then this is expr
* Otherwise
* If the code is in strict mode, this is undefined
* Otherwise, this is window (in a browser)
Let's look at how this works in practice:
class Foo {
value = 10;
doSomething() {
// Prints 'undefined', not '10'
console.log(this.value);
}
}
let f = new Foo();
window.setTimeout(f.doSomething, 100);
This code will print undefined (or, in strict mode, throw an exception).
This is because we ended up in the last branch of the decision tree above.
The doSomething function was invoked, the function wasn't a result of a bind call, and it wasn't invoked in a method syntax position.
We can't see the code for setTimeout to see what its invocation looks like, but we don't need to.
Something to realize is that all doSomething methods point to the same function object.
In other words:
let f1 = new Foo();
let f2 = new Foo();
// 'true'
console.log(f1.doSomething === f2.doSomething);
We know that setTimeout can only see the function we passed it, so when it invokes that function,
there's no way for it to know which this to provide.
The this context has been lost due to our referencing the method without invoking it.
The Red Flag
Once you know about this problems, they're easy to spot:
class Foo {
value = 10;
method1() {
doSomething(this.method2); // DANGER, method reference without invocation
}
method2() {
console.log(this.value);
}
}
The Solution
You have a few options here, each with its own trade-offs.
The best option depends on how often the method in question is invoked from differing call sites.
Arrow Function in Class Definition
Instead of using the normal method syntax, use an arrow function to initialize a per-instance member.
class DemonstrateScopingProblems {
private status = "blah";
public run = () => {
// OK
console.log(this.status);
}
}
let d = new DemonstrateScopingProblems();
window.setTimeout(d.run); // OK
Good/bad: This creates an additional closure per method per instance of your class. If this method is usually only used in regular method calls, this is overkill. However, if it's used a lot in callback positions, it's more efficient for the class instance to capture the this context instead of each call site creating a new closure upon invoke.
Good: Impossible for external callers to forget to handle this context
Good: Typesafe in TypeScript
Good: No extra work if the function has parameters
Bad: Derived classes can't call base class methods written this way using super.
Bad: The exact semantics of which methods are "pre-bound" and which aren't create an additional non-typesafe contract between your class and its consumers.
Function Expression at Reference Site
Shown here with some dummy parameters for explanatory reasons:
class DemonstrateScopingProblems {
private status = "blah";
public something() {
console.log(this.status);
}
public run(x: any, y: any) {
// OK
console.log(this.status + ': ' + x + ',' + y);
}
}
let d = new DemonstrateScopingProblems();
// With parameters
someCallback((n, m) => d.run(n, m));
// Without parameters
window.setTimeout(() => d.something(), 100);
Good/bad: Opposite memory/performance trade-off compared to the first method
Good: In TypeScript, this has 100% type safety
Good: Works in ECMAScript 3
Good: You only have to type the instance name once
Bad: You'll have to type the parameters twice
Bad: Doesn't easily work with variadic parameters
I think that you should move the result block into the subscribe callback associated the getPlaces method call:
showPosition(position) {
this.xml_Latitude = position.coords.latitude;
this.xml_Lang = position.coords.longitude;
this._http.getPlaces(this.xml_Latitude, this.xml_Lang).subscribe(
data => {
this.maps = data;
var result = this.maps.results; // <----------
var city = result[0].address_components[4].long_name + "," + result[0].address_components[6].long_name;
alert(city);
},
err => { this.cat_error = true }
);
}
It's because this.maps is undefined before the callback is called. And you try tyo get the result attribute before (this.maps.results).
Edit
I also see a problem at the line navigator.geolocation.getCurrentPosition. You could refactor your code this way:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => { // <----
this.showPosition(position);
});
} else {
alert("Geolocation is not supported by this browser.");
}