I don't understand what a YAML tag is - tags

I get it on some level, but I have yet to see an example that didn't bring up more questions than answers.
http://rhnh.net/2011/01/31/yaml-tutorial
# Set.new([1,2]).to_yaml
--- !ruby/object:Set
hash:
1: true
2: true
I get that we're declaring a Set tag. I don't get what the subsequent hash mapping has to do with it. Are we declaring a schema? Can someone show me an example with multiple tag declarations?
I've read through the spec: http://yaml.org/spec/1.2/spec.html#id2761292
%TAG ! tag:clarkevans.com,2002:
Is this declaring a schema? Is there something else a parser has to do in order to successfully parse the file? A schema file of some type?
http://www.yaml.org/refcard.html
Tag property: # Usually unspecified.
none : Unspecified tag (automatically resolved by application).
'!' : Non-specific tag (by default, "!!map"/"!!seq"/"!!str").
'!foo' : Primary (by convention, means a local "!foo" tag).
'!!foo' : Secondary (by convention, means "tag:yaml.org,2002:foo").
'!h!foo': Requires "%TAG !h! <prefix>" (and then means "<prefix>foo").
'!<foo>': Verbatim tag (always means "foo").
Why is it relevant to have a primary and secondary tag, and why does a secondary tag refer to a URI? What problem is being solved by having these?
I seem to see a lot of "what they are", and no "why are they there", or "what are they used for".

I don't know a lot about YAML but I'll give it a shot:
Tags are used to denote types. A tag is declared using ! as you have seen from the "refcard" there. The %TAG directive is kind of like declaring a shortcut to a tag.
I'll demonstrate with PyYaml. PyYaml can parse the secondary tag of !!python/object: as an actual python object. The double exclamation mark is a substitution in itself, short for !tag:yaml.org,2002:, which turns the whole expression into !tag:yaml.org,2002:python/object:. This expression is a little unwieldy to be typing out every time we want to create an object, so we give it an alias using the %TAG directive:
%TAG !py! tag:yaml.org,2002:python/object: # declares the tag alias
---
- !py!__main__.MyClass # creates an instance of MyClass
- !!python/object:__main__.MyClass # equivalent with no alias
- !<tag:yaml.org,2002:python/object:__main__.MyClass> # equivalent using primary tag
Nodes are parsed by their default type if you have no tag annotations. The following are equivalent:
- 1: Alex
- !!int "1": !!str "Alex"
Here is a complete Python program using PyYaml demonstrating tag usage:
import yaml
class Entity:
def __init__(self, idNum, components):
self.id = idNum
self.components = components
def __repr__(self):
return "%s(id=%r, components=%r)" % (
self.__class__.__name__, self.id, self.components)
class Component:
def __init__(self, name):
self.name = name
def __repr__(self):
return "%s(name=%r)" % (
self.__class__.__name__, self.name)
text = """
%TAG !py! tag:yaml.org,2002:python/object:__main__.
---
- !py!Component &transform
name: Transform
- !!python/object:__main__.Component &render
name: Render
- !<tag:yaml.org,2002:python/object:__main__.Entity>
id: 123
components: [*transform, *render]
- !<tag:yaml.org,2002:int> "3"
"""
result = yaml.load(text)
More information is available in the spec

Related

Ontology annotation type is missing in saved ontology file

I'm using OWL API 4.1. I add annotation with type XSD:string like that:
OWLAnnotationProperty annotationProperty = this.getDf().getOWLAnnotationProperty(annotationPropertyIri);
OWLLiteral lit = this.df.getOWLLiteral(annotationValue, range);
OWLAnnotation annotation = df.getOWLAnnotation(annotationProperty, lit);
this.getMng().applyChange(new AddOntologyAnnotation(this.getOnt(), annotation));
... I checked that here lit="test"^^xsd:string. But after I saved ontology (in ttl format) - there in no type ending - ^^xsd:string:
...
<http://semanticweb.rocks/whole-dataset-name/wheat-02> a owl:Ontology ;
dc:description """test""" ;
dc:source """http://mail.ru"""^^xsd:anyURI .
...
If I use other type (e.g. xsd:anyURI ) instead of ^^xsd:string the ending ^^xsd:anyURI is presented.
What is matter with ^^xsd:string?
The xsd:string type can be skipped for string literals, when there is no language tag. A literal typed with xsd:string is identical to a plain literal with no language tag.
If you load the ontology back into an OWLOntology, I expect you to see a test^^xsd:string literal attached to the ontology.

Haxe: Creating a code completion macro for JSON files

I am trying to implement a code completion macro for JSON files by generating field definitions
var classOfChild = Type.getClass(child); // `child` may look like this array: [[1,2,3],[0.1,0.2,0.3]]
fields.push({
"name": childName,
"pos" : _pos,
"kind": childType,
});
I already watched some videos and read some tutorials on this, but there is no information how to get ComplexType from a Type.typeof(object) result.
I have tried code that doesn't work like:
//"kind": childType,
//"kind": childType.toString(),
//"kind": FVar(macro {childType.toString(); }),
//"kind": FVar(macro Array<$v{arrType}>)
but none of them worked (all of them raise some Error or )
Edit 1: here is my json data:
{"floatVar1":0.1, "str":"some string", "nullValueObject":null, "arrayOfInts":[11,20,9], "matrixLikeArray":[[14, 12, 13, 11, 18]], "floatMatrix":[[14.4, 12.3, 13.7, 11.9, 18.0]], "symbolPayouts":[0.05], "objectInObject":{"prop1":"some str", "prop2": "some str2", "prop3":10.17, "prop4":[[1,2,3],[19.3,20.4]]}}
I would like to create Definitions for prop4, ("prop4":[[1,2,3],[19.3,20.4]])
Edit 2: I have already figured out how to create the "kind" for the simple types ("kind": FVar(macro:Dynamic)) and the object (kind : FVar(TAnonymous( jsonFields ))). But how to do that for arrays, arrays of arrays, etc.
Edit 3: code in gist.github.com
When generating code with macros it is easy to attempt to generate something which isn't efficient and you did get side tracked by trying to define explicit types.
Based on your gist, you just need to define a json field and give it the content of your JSON file as the field's value as if you were defining the value as a Haxe literal object.
Your goal is then to generate something you could have written as:
private var json = { prop1:'hello', prop2:42, prop3:[1,2,3] };
The haxe compiler will strongly type this json field.
To achieve that, your macro just need to add one field with an initial value obtained from the JSON file; and likewise, the Haxe compiler will strictly type it.
Creating a variable with a type to be inferred by the compiler is simply FVar(null, valueExpr), which means your entire macro can be reduced to:
var fields = Context.getBuildFields();
var json = Json.parse(src);
fields.push({
name : "json",
pos : Context.currentPos(),
kind : FVar(null, macro $v{json}),
access: [APrivate],
});
return fields;
For a more elaborated version I can point you on the following gist: ResourceGenerator.hx which will generate recursively "inlinable" and dce-friendly objects.
PS: sadly your "prop4":[[1,2,3],[19.3,20.4]] is impossible because it will be seen by the compiler as an Array of incompatible types ([Array<Int>, Array<Float>]).

Supporting "recursive objects" in lua

I'm fairly new to lua and have the following problem with an assignment from a class:
We currently extend lua to support objects and inheritance. The Syntax for that is
Class{'MyClass',
attribute1 = String,
attribute2 = Number
}
Class{'MySubClass', MyClass,
attribute3 = Number
}
This works perfectly fine. The real problem lies within the next task: We should support "recursive types", that means a call like
Class{'MyClass', attribute = MyClass}
should result in an class with a field of the same type as the class. When this "class-constructor" is called the variable MyClass is nil, thats why the parameter table doesnt't have an entry attribute. How is it possible to access this attribute?
My first thought was using some kind of nil-table which gets returned every time the global __index is called with an unset key. This nil-table should behave like the normal nil, but can be checked for in the "class-constructor". The problem with this approach are comparisons like nil == unknown. This should return true, but as the __eq meta method of the nil-table is never called we cannot return true.
Is there another approach I'm currently just ignoring? Any hint is greatly appreciated.
Thanks in advance.
Edit:
Here the relevant part of the "testfile". The test by which the code is rated in class is another one and gets published later.
three = 3
print( three == 3 , "Should be true")
print( unknown == nil , "Should be true" )
Class{'AClass', name = String, ref = AClass}
function AClass:write()
print("AClass:write(), name of AClass:", self.name)
end
aclass = AClass:create("A. Class")
aclass:write()
Since MyClass is just a lookup in the global table (_G), you could mess with its metatable's __index to return a newly-defined MyClass object (which you would later need to fill with the details).
However, while feasible, such an implementation is
wildly unsafe, as you could end up with an undefined class (or worse, you may end up inadvertantly creating an infinite lookup loop. Trust me, I've been there)
very hard to debug, as every _G lookup for a non-existing variable will now return a newly created class object instead of nil (this problem could somewhat be reduced by requiring that class names start with an uppercase character)
If you go that route, be sure to also override __newindex.
How about providing the argument in string form?
Class{'MyClass', attribute = 'MyClass'}
Detect strings inside the implementation of Class and process them with _G[string] after creating the class
Or alternatively, use a function to delay the lookup:
Class{'MyClass', attribute = function() return MyClass end}

How to pass parameters to a Progress program using database field dynamic-based rules?

I have in my database a set of records that concentrates information about my .W's, e.g. window name, parent directory, file name, procedure type (for internal treatments purposes), used to build my main menu. With this data I'm developing a new start procedure for the ERP that I maintain and using the opportunity in order to rewrite some really outdated functions and programs and implement new functionalities. Until now, I hadn't any problems but when I started to develop the .P procedure which will check the database register of a program that was called from the menu of this new start procedure - to check if it needs to receive fixed parameters to be run and its data types - I found a problem that I can't figure out a solution.
In this table, I have stored in one of the fields the parameters needed by the program, each with his correspondent data type. The problem is on how to pass different data types to procedures based only on the stored data. I tried to pre-convert data using a CASE clause and an include to check the parameter field for correct parameter sending but the include doesn't work as I've expected.
My database field is stored as this:
Description | DATATYPE | Content
I've declared some variables and converted properly the stored data into their correct datatype vars.
DEF VAR c-param-exec AS CHAR NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-param-exec AS INT NO-UNDO EXTENT 9 INIT ?.
DEF VAR de-param-exec AS DEC NO-UNDO EXTENT 9 INIT ?.
DEF VAR da-param-exec AS DATE NO-UNDO EXTENT 9 INIT ?.
DEF VAR l-param-exec AS LOG NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-count AS INT NO-UNDO.
blk-count:
DO i-count = 0 TO 8:
IF TRIM(programa.parametro[i-count]) = '' THEN
LEAVE blk-count.
i-count = i-count + 1.
CASE ENTRY(2,programa.parametro[i-count],CHR(1)):
WHEN 'CHARACTER' THEN
c-param-exec[i-count] = ENTRY(3,programa.parametro[i-count],CHR(1)).
WHEN 'INTEGER' THEN
i-param-exec[i-count] = INT(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'DECIMAL' THEN
de-param-exec[i-count] = DEC(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'DATE' THEN
da-param-exec[i-count] = DATE(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'LOGICAL' THEN
l-param-exec[i-count] = (ENTRY(3,programa.parametro[i-count],CHR(1)) = 'yes').
OTHERWISE
c-param-exec[i-count] = ENTRY(3,programa.parametro[i-count],CHR(1)).
END CASE.
END.
Then I tried to run the program using an include to pass parameters (in this example, the program have 3 INPUT parameters).
RUN VALUE(c-prog-exec) ({util\abrePrograma.i 1},
{util\abrePrograma.i 2},
{util\abrePrograma.i 3}).
Here is my abrePrograma.i
/* abrePrograma.i */
(IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'CHARACTER' THEN c-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'INTEGER' THEN i-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DECIMAL' THEN de-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DATE' THEN da-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'LOGICAL' THEN l-param-exec[{1}] ELSE
c-param-exec[{1}])
If I suppress the 2nd, 3rd, 4th and 5th IF's from the include or use only one data type in all IF's (e.g. only CHAR, only DATE, etc.) the program works properly and executes like a charm but I need to call some old programs, which expects different datatypes in its INPUT parameters and using the programs as described OpenEdge doesn't compile the caller, triggering the error number 223.
---------------------------
Erro (Press HELP to view stack trace)
---------------------------
** Tipos de dados imcompativeis em expressao ou atribuicao. (223)
** Nao entendi a linha 86. (196)
---------------------------
OK Ajuda
---------------------------
Can anyone help me with this ?
Thanks in advance.
Looks as if you're trying to use variable parameter definitions.
Have a look at the "create call" statement in the ABL reference.
http://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/dvref/call-object-handle.html#wwconnect_header
Sample from the documentation
DEFINE VARIABLE hCall AS HANDLE NO-UNDO.
CREATE CALL hCall.
/* Invoke hello.p non-persistently */
hCall:CALL-NAME = "hello.p".
/* Sets CALL-TYPE to the default */
hCall:CALL-TYPE = PROCEDURE-CALL-TYPE
hCall:NUM-PARAMETERS = 1.
hCall:SET-PARAMETER(1, "CHARACTER", "INPUT", "HELLO WORLD").
hCall:INVOKE.
/* Clean up */
DELETE OBJECT hCall.
The best way to get to the bottom of those kind of preprocessor related issues is to do a compile with preprocess listing followed by a syntax check on the preprocessed file. Once you know where the error is in the resulting preprocessed file you have to find out which include / define caused the code that won't compile .
In procedure editor
compile source.w preprocess source.pp.
Open source.pp in the procedure editor and do syntax check
look at original source to find include or preprocessor construct that resulted in the code that does not compile.
Okay, I am getting a little bit lost (often happens to me with lots of preprocessors) but am I missing that on the way in and out of the database fields you are storing values as characters, right? So when storing a parameter in the database you have to convert it to Char and on the way out of the database you have convert it back to its correct data-type. To not do it one way or the other would cause a type mismatch.
Also, just thinking out loud (without thinking it all the way through) wonder if using OOABL (Object Oriented ABL) depending on if you Release has it available wouldn't make it easier by defining signatures for the different datatypes and then depending on which type of input or output parameter you call it with, it will use the correct signature and correct conversion method.
Something like:
METHOD PUBLIC VOID storeParam(input cParam as char ):
dbfield = cParam.
RETURN.
END METHOD.
METHOD PUBLIC VOID storeParam(input iParam as int ):
dbfield = string(iParam).
RETURN.
END METHOD.
METHOD PUBLIC VOID storeParam(input dParam as date ):
dbfield = string(dParam).
RETURN.
END METHOD.
just a thought.

Dynamic property names in VBA

I have a custom class module in VBA (Access) that is supposed to handle a large amount of external data. Currently I have two functions Read(name) and Write(name, value) that allows to read and set dynamic properties.
Is there a way to define a more syntactic way to read and write those data? I know that some objects in VBA have a special way of accessing data, for example the RecordSet, which allows to read and set data using myRS!property_name. Is there a way to do exactly the same for custom class modules?
The exclamation mark syntax is used to access members of a Scripting.Dictionary instance(you'll need to add a reference to Microsoft Scripting Runtime through Tools > References first). To use this syntaxyou'll need to be storing the information internally in a dictionary.
The quickest way to use it in a class is to give your class an object variable of type Scripting.Dictionary and set it up as follows:
Option Explicit
Dim d As Scripting.Dictionary
Private Sub Class_Initialize()
Set d = New Scripting.Dictionary
End Sub
Private Sub Class_Terminate()
Set d = Nothing
End Sub
Public Property Get IntData() As Scripting.Dictionary
Set IntData = d
End Property
Now you can access properties using myinstance.IntData!MyProperty = 1... but to get to where you want to be you need to use Charlie Pearson's technique for making IntData the default member for your class.
Once that's done, you can use the following syntax:
Dim m As MyClass
Set m = New MyClass
Debug.Print "Age = " & m!Age ' prints: Age =
m!Age = 27
Debug.Print "Age = " & m!Age ' prints: Age = 27
Set m = Nothing
Okay, thanks to Alain and KyleNZ I have now found a working way to do this, without having a collection or enumerable object below.
Basically, thanks to the name of the ! operator, I found out, that access via the bang/pling operator is equivalent to accessing the default member of an object. If the property Value is the default member of my class module, then there are three equivalent statements to access that property:
obj.Value("param")
obj("param")
obj!param
So to make a short syntax working for a custom class module, all one has to do is to define a default member. For example, I now used the following Value property:
Property Get Value(name As String) As String
Value = SomeLookupInMyXMLDocument(name)
End Property
Property Let Value(name As String, val As String) As String
SetSomeNodeValueInMyXMLDocument(name, val)
End Property
Normally, you could now access that like this:
obj.Value("foo") = "New value"
MsgBox obj.Value("foo")
Now to make that property the default member, you have to add a line to the Property definition:
Attribute Value.VB_UserMemId = 0
So, I end up with this:
Property Get Value(name As String) As String
Attribute Value.VB_UserMemId = 0
Value = SomeLookupInMyXMLDocument(name)
End Property
Property Let Value(name As String, val As String) As String
Attribute Value.VB_UserMemId = 0
SetSomeNodeValueInMyXMLDocument(name, val)
End Property
And after that, this works and equivalent to the code shown above:
obj("foo") = "New value"
MsgBox obj("foo")
' As well as
obj!foo = "New value"
MsgBox obj!foo
' Or for more complex `name` entries (i.e. with invalid identifier symbols)
obj![foo] = "New value"
MsgBox obj![foo]
Note that you have to add the Attribute Value.VB_UserMemId = 0 in some other editor than the VBA editor that ships with Microsoft Office, as that one hides Attribute directives for some reason.. You can easily export the module, open it in notepad, add the directives, and import it back in the VBA editor. As long as you don't change too much with the default member, the directive should not be removed (just make sure you check from time to time in an external editor).
See this other question: Bang Notation and Dot Notation in VBA and MS-Access
The bang operator (!) is shorthand for
accessing members of a Collection or
other enumerable object
If you make your class extend the Collection class in VBA then you should be able to take advantage of those operators. In the following question is an example of a user who extended the collection class:
Extend Collections Class VBA