Is there precedence for object oriented syntax for a relative path? - oop

I'm creating my own extended version of JSON for various reasons. One thing that I'm adding is the ability to self reference and I'm trying to come up with an OO syntax for relative paths.
To illustrate, lets say I have a nested object that is supposed to reference its parent object
{ my_item: { parent: ??? } }
??? symbolizes the missing syntax.
Now in most operating systems, going up one level is notated as .. so we could try doing the same
{ my_item: { parent: .. } }
Looks pretty neat, however, if I tried to reference anything else in the parent, I'd end up with
{ my_item_sibling: {}, my_item: { sibling_of_parent: ...my_item_sibling } }
Which is not as neat as its the same as spread syntax ... which I'm also adding
I could do something with parentheses, like so
{ my_item_sibling: {}, my_item: { sibling_of_parent: (..).my_item_sibling } }
Which is not terrible but I'd prefer something cleaner.
Maybe I'll reserve a symbol?
{ my_item_sibling: {}, my_item: { sibling_of_parent: #.my_item_sibling } }
In any case, these examples are just to illustrate what I'm doing. If there is an established or a particularly nice looking way to do it, I'll just copy that.
The question is: Is there a precedence to this? A relative path implemented in a c-like language?

Related

Enforcing read-only attributes from the metaclass

Yes, still going with this. My impression is that there's this powerful facility in Raku, which is not really easy to use, and there's so little documentation for that. I'd like to kind of mitigate that.
In this case, I'm trying to force attributes to be read-only by default, to make immutable classes. Here's my attempt:
my class MetamodelX::Frozen is Metamodel::ClassHOW {
method compose_attributes($the-obj, :$compiler_services) {
my $attribute-container = callsame;
my $new-container = Perl6::Metamodel::AttributeContainer.new(
:attributes($attribute-container.attributes),
:attribute_lookup($attribute-container.attribute_table),
:0attr_rw_by_default
);
$new-container.compose_attributes($the-obj, $compiler_services);
}
}
my package EXPORTHOW {
package DECLARE {
constant frozen = MetamodelX::Frozen;
}
}
I'm calling that from a main function that looks like this:
use Frozen;
frozen Foo {
has $.bar;
method gist() {
return "→ $!bar";
}
}
my $foo = Foo.new(:3bar);
say $foo.bar;
$foo.bar(33);
I'm trying to follow the source, that does not really give a lot of facilities to change attribute stuff, so there seems to be no other way that creating a new instance of the container. And that might fail in impredictable ways, and that's what it does:
Type check failed in binding to parameter '$the-obj'; expected Any but got Foo (Foo)
at /home/jmerelo/Code/raku/my-raku-examples/frozen.raku:7
Not clear if this is the first the-obj or the second one, but any way, some help is appreciated.

How to use `.kind()` on my custom errors?

I'm wondering how I can do some pattern-matching on my custom errors, to have a specific behaviour for a few errors and a generic behaviour for the others.
I have the following custom error, defined using thiserror as it seems to be the latest recommended crate for custom errors in July 2020.
#[derive(thiserror::Error, Debug)]
pub enum MyError{
#[error("Error while building the query")]
Builder(#[source] hyper::http::Error),
#[error("Generic error")]
Fuck,
#[error("Not OK HTTP response code")]
NotOK,
#[error("Request error")]
Request(#[source] hyper::Error),
}
pub async fn do_http_stuff() -> Result<Vec<u8>, MyError> {
...
}
And:
match do_http_stuff().await {
Ok(data) => ...,
Err(error) => match error.kind() {
MyError::NotOK => {
println!("not ok");
},
_ => {
println!("{}", error.to_string());
},
},
},
But .kind() is not implemented. When I search about how to manage errors in rust, kind is often in the examples. What kind of incantations should I do to have this .kind() method or something equivalent in my project too ?
Thanks.
I expect you're referring to the std::io::Error:kind method. It's specifically for IO errors. Because it needs to be able to represent OS errors, io::Error isn't defined as an enum, and we can't match on it. The kind method allows us to get an ErrorKind representing the generic cause of the error in a platform independent way.
This workaround is completely unnecessary in a normal Rust library, as all of your error cases can be expressed simply (as the variants of your enum). All you need to do is match on the error value directly

Writing an attribute trait

I'm about to choose what language to use for a new project: Perl5 or Perl6. 6 wins so far except that it is missing Moo's lazy attributes. The two implementations I found in modules are missing the key functionality. Hence, my attempt write my own implementation.
Role vs. Class
First problem I've got into is the content of attribute's .package for one declared in a role. Consider the followin:
role HOW1 {
method compose ( Mu $class ) {
note "HOW1.compose";
nextsame;
}
}
role HOW2 {
method compose ( Mu $class ) {
note "HOW2.compose";
nextsame;
}
}
multi trait_mod:<is> (Attribute:D $attr, :$mooish!) {
note "Attribute's package.HOW: ", $attr.package.HOW;
note '$*PACKAGE.HOW: ', $*PACKAGE.HOW;
$attr.package.HOW does HOW1;
$*PACKAGE.HOW does HOW2;
}
class Foo {
has $.bar is mooish;
}
role FooRole {
has $.baz is mooish;
}
The output of the script follows:
Attribute's package.HOW: Perl6::Metamodel::ClassHOW.new
$*PACKAGE.HOW: Perl6::Metamodel::ClassHOW.new
HOW2.compose
HOW1.compose
Attribute's package.HOW: Perl6::Metamodel::GenericHOW.new
$*PACKAGE.HOW: Perl6::Metamodel::ParametricRoleHOW.new
HOW2.compose
As it is clearly seen from the output, applying a role to a metaclass always works for classes and only works for $*PACKAGE.HOW with roles. Use of $*PACKAGE instead of .package could be considered a solution, but not the one I'd really like to use. (Though, if there is no better way...)
Accessor
I would like to provide lazy functionality for private attributes too. Yes, this will be availabe with self!bar syntax only, but this is a sacrifice I'm willing to make. 😉 The problem is that all the examples of custome-made accessor I found so far are using Attribute.set_value() method which is way too low-level. I'd like to have something like this:
role MooishHOW {
method compose ( Mu $class ) {
my $accessor = $class.^add_private_method( 'bar1',
method () is rw {
note self.WHO, ".bar1";
Proxy.new(
FETCH => -> $o {
$!bar1;
},
STORE => method ( $val ) {
note "Storing";
$!bar1 = $val;
}
);
}
);
callsame;
}
}
multi trait_mod:<is> (Attribute:D $attr, :$mooish!) {
$attr.package.HOW does MooishHOW unless $attr.package.HOW ~~ MooishHOW;
}
class Foo {
has $.bar is mooish;
has $!bar1 is mooish;
method to-bar1 {
note "bar1 val:",self!bar1;
}
}
my $inst = Foo.new;
$inst.to-bar1;
But $!bar1 notation doesn't compile because of the scope (MooishRole). Are there a trick I'm missing which would allow referencing a private attribute on self?
Tricky one
Perhaps it is possible to make an attribute to be a Proxy container? This would greatly simplify the overall logic of laziness implementation.
I have answered all my questions by finally achieving the target and released AttrX::Mooish module.
So far, the answer for the first question is: no. $*PACKAGE is currently the only way.
Second question: have no answer, but the final code has to rely on set_value() anyway.
The tricky one happened to be possible: set_value() does binding of an attribue to a container making it possible to bind to a Proxy object. No need to for sacrifices, private attributes can be accessed directly with lazyness working on them.
Thanks everybody, your answers let me work around some rough edges!

Object oriented design patterns for parsing text files?

As part of a software package I'm working on, I need to implement a parser for application specific text files. I've already specified the grammar for these file on paper, but am having a hard time translating it into easily readable/updatable code (right now just it passes each line through a huge number of switch statements).
So, are there any good design patterns for implementing a parser in a Java style OO environment?
Any easy way to break a massive switch into an OO design would be to have
pseudo code
class XTokenType {
public bool isToken(string data);
}
class TokenParse {
public void parseTokens(string data) {
for each step in data {
for each tokenType in tokenTypess {
if (tokenType.isToken(step)) {
parsedTokens[len] = new tokenType(step);
}
...
}
}
...
}
}
Here your breaking each switch statement into a method on that token object to detect whether the next bit of the string is of that token type.
Previously:
class TokenParse {
public void parseTokens(string data) {
for each step in data {
switch (step) {
case x:
...
case y:
...
...
}
}
...
}
}
One suggestion is to create property file where you define rules. Load it during run time and use if else loop (since switch statements also does the same internally). This way if you want to change some parsing rules you have to change .property file not code. :)
You need to learn how to express context free grammars. You should be thinking about the GoF Interpreter and parser/generators like Bison, ANTRL, lex/yacc, etc.

Optimizing a method with boolean flag

I have a method whose purpose is to retrieve collection items.
A collection can contain a mix of items, let's say: pens, pencils, and papers.
The 1st parameter allows me to tell the method to retrieve only the itemTypes I pass (e.g, just pens and pencils).
The 2nd parameter flags the function to use the collection's default item types, instead.
getCollectionItems($itemTypes,$useCollectionDefaultItemTypes) {
foreach() {
foreach() {
foreach() {
// lots of code...
if($useCollectionDefaultItemTypes) {
// get collection's items using collection->itemTypes
}
else {
// get collection's items using $itemTypes
}
// lots of code...
}
}
}
}
What feels odd is that if I set the $useCollectionDefaultItemTypes to true, there is no need for the function to use the first parameter. I was considering refactoring this method into two such as:
getCollectionItems($itemTypes); // get the items using $itemTypes
getCollectionItems(); // get the items using default settings
The problem is that the methods will have lots of duplicate code except for the if-statement area.
Is there a better way to optimize this?
Pass in $itemTypes as null when you're not using it. Have your if statement check if $itemTypes === null; if it is, use default settings.
If this is php, which I assume it is, you can make your method signature function getCollectionItems($itemTypes = null) and then you can call getCollectionItems() and it will call it as if you had typed getCollectionItems(null).
It's generally a bad idea to write methods that use flags like that. I've seen that written in several places (here at #16, Uncle Bob here and elsewhere). It makes the method hard to understand, read, and refactor.
An alternative design would be to use closures. Your code could look something like this:
$specificWayOfProcessing = function($a) {
//do something with each $a
};
getCollectionItems($processer) {
foreach() {
foreach() {
foreach() {
// lots of code...
$processor(...)
// lots of code...
}
}
}
}
getCollectionItems($specificWayOfProcessing);
This design is better because
It's more flexible. What happens when you need to decide between three different things?
You can now test the code inside the loop much easier
It is now easier to read, because the last line tells you that you are "getting collection items using a specific way of processing" - it reads like an English sentence.
Yes, there is a better way of doing this -- though this question is not an optimization question, but a style question. (Duplicated code has little effect on performance!)
The simplest way to implement this along the lines of your original idea is to make the no-argument form of getCollectionItems() define the default arguments, and then call the version of it that requires an argument:
getCollectionItems($itemTypes) {
foreach() {
foreach() {
foreach() {
// lots of code...
// get collection's items using $itemTypes
}
// lots of code...
}
}
}
getCollectionItems() {
getCollectionItems(collection->itemTypes)
}
Depending on what language you are using, you may even be able to collapse these into a single function definition with a default argument:
getCollectionItems($itemTypes = collection->itemTypes) {
foreach() {
foreach() {
foreach() {
// lots of code...
// get collection's items using $itemTypes
}
// lots of code...
}
}
}
That has the advantage of clearly expressing your original idea, which is that you use $itemTypes if provided, and collection->itemTypes if not.
(This does, of course, assume that you're talking about a single "collection", rather than having one of those foreach iterations be iterating over collections. If you are, the idea to use a null value is a good one.)