I am new to OCL, and I just came across this expression:
context Person::descendants(): Set
body: result = self.children -> union(
self.children -> collect(c | c.descendants()))
I now that it's trying to obtain the direct and indirect descendants of a person, but how is that written here, what each sentence is trying to say?
Also this one,
context Person::income(): Integer
body: self.job.salary -> sum()
Is this recursive?
result =
is gratuitous fluff to convert an OCL query into the narrow UML requirements for a Boolean valued body condition. IMHO it should be deleted, and some tools may do so for you.
self.children
is the direct children
x->union(y)
combines two sets
c.descendants()
is a recursion invocation of the descendants()
self.children -> collect(c | c.descendants())
is the recursion applied to each child and with the result accumulated as a Bag
There is now a closure() iteration so I would write
context Person::descendants(): Set(Person)
body: children->closure(children)
Regards
Ed Willink
Related
I now have a function called processor, inside the processor function, a list will be matched to different patterns. In some patterns I wish it to return a tuple while the rest calls processor again.
Suppose I now have a custom type to wrap two types of processor:
type processor_return_type =
| REC of unit
| INFO of (string list * bool)
My processor basically looks like this:
let rec processor cmds stack env =
match (cmds, stack) with
| (ADD::rest_cmds, first_list::rest_stack) -> ... processor a b c
...
| (FUN::...) -> ... let (sl, b) = processor a b c in processor d e f
| (RETURN::...) -> (string list, a bool)
| _ -> REC()
...
in
Then I invoke this function with (you can assume I give correct arguments):
processor cmd_list [[]] [[]];;
The error emerges:
664 | processor cmd_list [[]] [[]];;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type processor_return_type
but an expression was expected of type unit
How could I fix this issue?
Thanks for including the error message and the indicated erroneous part of the code.
The expression that the compiler is complaining about is the entire call to processor. In other words, the reason the compiler is expecting something of type unit is because of the context of the call, which you unfortunately don't show.
Generally your code should expect to get a result back from the call to processor and should handle the result appropriately. If there are other branches of your code (the else part of an if, say), they have to be of the same type also.
Here's an example of an erroneous call context:
if some_test () then
Printf.printf "did not want to call processor\n"
else
proceessor ...
If you show more of the context of the call, people can give you a more helpful answer maybe.
Hey guys I am having a bit of trouble i have a general idea what the code should be but not to sure what to do from here.
The question is: Define a function remove_elts taking a list of items as well as a list of items to
remove from the first list, and returning a list with all occurrences of the items
to be removed gone.
My code is :
let remove_elts l reml =
match l with
[] -> false
| hd :: tl -> if hd = l then reml
else hd :: remove_elts l tl;;
Any filtering function, i.e., a function that takes a container and returns another container that contains elements of the input container that satisfy some property, is implemented using the following algorithm:
output-sequence = []
foreach element in the input-sequeunce:
if element satisfies condition:
output-sequence := output-sequence + element
This iteration has two elements which differ with each step, the element variable that takes in order the elements of the input-sequence and the output-sequence that grows every time, the <element> satisfies the condition.
In functional programming, iteration is commonly represented with recursion which is more natural from the mathematical point of view. Anything that changes in the iteration will become a parameter of the recursive function, and each step is represented as a recursive call with the new values of the variables. So the same iteration in the functional style (pseudocode)
filter input-sequence output-sequence =
if is-empty input-sequence then output-sequence
else
let element = first-element-of input-sequence in
let rest = drop-first-element input-sequence in
if element satisfies condition
then filter rest (output-sequence + element)
else filter rest output-sequence
And the iteration is called as
filter input-sequence []
So it is a little bit more verbose then the foreach but this is because foreach is basically a syntactic sugar.
Now, your task is to implement this in OCaml, keeping in mind two things:
1) In OCaml you can use pattern matching, instead of is-empty,first-element-of, and drop-first-element primitives.
2) You're using a singly-linked list as the sequence, so appending an element to the end of it is very expensive, it is O(N) (as you have to go through all elements, until you reach the end), and doing this in cycle will make your algorithm O(N^2), so instead you should prepend to the beginning (which is O(1)) and at the end of recursion, reverse the list.
I'd like to track SyntaxNodes and SyntaxTrivias across
different versions of a Solution/Workspace.
I tried annotating some nodes with SyntaxAnnotations.
This works well as long as I don't update the workspace.
Calling Workspace.TryApplyChanges (successfully) seems to remove
all SyntaxAnnotations.
This surprised me. Why does this happen?
How can I track SyntaxNodes across workspace updates?
Example code follows:
var workspace = new AdhocWorkspace();
var project = workspace.AddProject("TestProject", LanguageNames.CSharp);
var klass = SyntaxFactory
.ClassDeclaration("Klass")
.WithAdditionalAnnotations(new SyntaxAnnotation("Foo"));
var compUnit = SyntaxFactory.CompilationUnit().AddMembers(klass);
var document = project.AddDocument("TestFile.cs", compUnit);
var docId = document.Id;
var solution = document.Project.Solution;
var root1 = document.GetSyntaxRootAsync().Result;
var klass1 = root1.GetAnnotatedNodes("Foo").FirstOrDefault();
var eq1 = klass1.IsEquivalentTo(klass); // returns true
var apply = workspace.TryApplyChanges(solution); // returns true
var root2 = workspace.CurrentSolution.GetDocument(docId).GetSyntaxRootAsync().Result;
var klass2 = root2.GetAnnotatedNodes("Foo").FirstOrDefault(); // returns null, why?
This happens because TryApplyChanges doesn't actually re-use your nodes as is. Instead it "replays" the same changes as textual changes to the actual solution, and then let's the parser re-parse.
This happens for a few reasons:
To avoid having annotations pile up over time in the trees and interfere with each other (consider something like that formatting or rename annotations used in CodeFixes still being present after the fix was applied).
To protect against trees that don't round-trip from showing up in CurrentSolution. It is possible to construct trees that the parser would never generate (consider changing operator precedence for example).
To ensure the changes are actually applied, requires changing the original representation - the files on disk or the text buffers in memory, not just using the new trees in the workspace.
You could consider using something like the SyntaxPath type from the Roslyn sources to try to find an equivalent node.
I am looking to convert this code to use F# list instead of the C# list implementation.
I am connecting to a database and running a query usually with C# would create a list of a type and keep adding the list while the datareader has values. How would I go about converting this to use an F# list
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
let transactions = new List<string>()
let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
let json = dataReader.GetString(1)
transactions.Add(json)
transactions
The tricky thing here is that the input data source is inherently imperative (you have to call Read which mutates the internal state). So, you're crossing from imperative to a functional world - and so you cannot avoid all mutation.
I would probably write the code using a list comprehension, which keeps a similar familiar structure, but removes explicit mutation:
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
[ let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
yield dataReader.GetString(1) ]
Tomas' answer is a solution to use in product code. But for sake of learning F# and functional programming I present my snippet with tail recursion and cons operator:
let drToList (dr:DataReader) =
let rec toList acc =
if not dr.Read then acc
else toList <| dr.GetString(1) :: acc
toList []
This tail recursion function is compiled into imperative-like code, thus no stack overflow and fast execution.
Also I advice you look at this C# thread and this F# documentation to see how properly dispose your command. Basically, you need to use smth like this:
let queryDb (conn: NpgsqlConnection) (qStr: string) =
use cmd = new NpgsqlCommand(qStr, conn)
cmd.ExecuteReader() |> drToList
And if we go deeper, you should also think about exception handling.
I want a list of Reports. Report can be either Detail or Section types.
module Data
type Section = { Header: string;
Lines: string list;
Total: string }
type Detail = { State: string;
Divisions: string list;
Sections: Section list }
type Summary = { State: string;
Office: string;
Sections: Section list }
type Report = Detail | Summary
Then in my code, I'd like to do the following:
let mutable (reports:Report list) = []
...
reports <- detail::reports
// or
reports <- summary::reports
The compiler complains in the first case: "The expression was expected to have type Report but here has type Detail", and appropriately similarly in the second case.
Am I out of my mind for wanting to do such a thing? Should I be thinking about the problem differently? Because Report is either Detail or Summary, shouldn't a list of Report accept either a Detail or a Summary? What is a Report list if not a list of Detail or Summary?
Thanks.
You've just got your syntax a bit wrong:
type Report = Detail of Detail | Summary of Summary
reports <- (Detail detail)::reports
// or
reports <- (Summary summary)::reports
In your code you've basically just defined the Report type to be an enum with the two possible values Details or Summary (these are like labels, not the types of different subtypes in this context). Discriminated unions in F# are explicitly tagged, so you've also got to use one of the union constructors to create an instance to put into the list.
You need to change your Report type to:
type Report = Detail of Detail | Summary of Summary
since your current definition just names the two cases of your Report type, and these names are not related to the existing Detail and Summary types.
You can then filter the Detail and Summary elements using List.choose e.g.
let details = reports |> List.choose (function Detail(d) -> Some(d) | _ -> None)