I've got a small problem.
I made calculations and all my ids are not following each other anymore (because of some delete during the calculus). Unfortunately, to make my result valid, I need this order... :/
So in order to simply the task, I made an external function, that will "rename" all the IDs but I do not know how to perform this.
Here is the function that I've got :
fun setId (W {id, ...}) =
let
in
print( "[" ^ Int.toString (id) ^ "]");
print( "[" ^ Int.toString (!nextId) ^ "]\n");
Ref.incr nextId
end
(for the one who are wandering appis just a homemade function to perform the same calcul on each element of a list, but it's not important.)
When I'm execute this code, I obtain in output :
[0][0]
[1][1]
[2][2]
[3][3]
[4][4]
[5][5]
[6][6]
[7][7]
[8][8]
[9][9]
[10][10]
[11][11]
[12][12]
[13][13]
[14][14]
[15][15]
[16][16]
[17][17]
[18][18]
[19][19]
[20][20]
[21][21]
[22][22]
[39][23]
[40][24]
[41][25]
[42][26]
[43][27]
[44][28]
[45][29]
[46][30]
[47][31]
[48][32]
[49][33]
[50][34]
[51][35]
[52][36]
[53][37]
as you can see there is a big problem [23] [39] the list does not have following numbers. :/
Basically, I would like the function setIdto be able to modify the ID of the Node. But I don't know how :/
Here is the datatype Node for understanding purposes :
datatype node =
W of {
id : int
, predId : int option
, creationDepcy : Dependency.depcy
, nominalDepcies : Dependency.depcy list ref
, pattern : Termstore.store
, propositions : Propstore.pstore
, nominals : Propstore.pstore
, diamonds : Termstore.store
, boxes : Termstore.store
, disjunctions : Termstore.store
, nglstore : Termstore.store
, lazyProps : Lazystore.store
, lazyNoms : Lazynomstore.store
, lazyBoxes : Lazyboxstore.store
, blockedDiamonds : (Term.index * int) list ref
, branchPoints : int list ref
}
Thanks in advance for your help !
Best Regards.
Since id is typed int it cannot be modified. If you change it to int ref then you can modify it, but you will also have to change the accessors to dereference the ref.
An alternative solution is to create an array that maps from old IDs to new IDs and use this array for presentation, but that seems even more complicated.
Since ints are immutable -- you could take your list of nodes and replace it with a new list of nodes:
fun newID (W(x), i) =
W({
id = i
, predId = #predId x
, creationDepcy = #creationDepcy x
, nominalDepcies = #nominalDepcies x
, pattern = #pattern x
, propositions = #propositions x
, nominals = #nominals x
, diamonds = #diamonds x
, boxes = #boxes x
, disjunctions = #disjunctions x
, nglstore = #nglstore x
, lazyProps = #lazyProps x
, lazyNoms = #lazyNoms x
, lazyBoxes = #lazyBoxes x
, blockedDiamonds = #blockedDiamonds x
, branchPoints = #branchPoints x
});
fun imap _ [] _ = []
| imap f (x::xs) i = f(x,i):: (imap f xs (i+1));
(imap stands for "increment map")
Then if xs is a list of nodes the function call
imap newID xs 0
will yield a new list of nodes with the id fields consecutive ints starting with 0
Disclaimer: I didn't try this on your setup of course, by I created a datatype of records which had an id field and successfully used this approach. Obviously this isn't something you would want to do a lot of because of all the copying, but if it is at one specific point in your code it should be okay.
Mostly equivalent to John's solution, here is how one would update a list of nodes without using references, using a fold instead. The function setId is the same.
fun setIds firstId ws =
#1 (foldr (fn (w,(ws',nextId)) => (setId w nextId::ws', nextId+1)) ([],firstId) ws)
Running setIds 1 [w1, w2, w3, ...] would yield [w1', w2', w3', ...].
Related
I want to create a function that gets the first value of a table field if two other field values match the two given function parameters.
I thought this would be easy. But I found nothing in the internet or M documentation that could solve this.
I don't know if I have to loop through a record or if there is a top level function.
= (val1 as text, val2 as text) as text =>
let
result = if [Field1] = val1 and [Field2] = val2 then [Field3] else ""
in
result
As far as I understand your wish, table and column names are hard coded (i.e. you intend to apply the function only for specific table). Then you may use following approach:
// table
let
t1 = #table({"Field1"}, List.Zip({{"a".."e"}})),
t2 = #table({"Field2"}, List.Zip({{"α".."ε"}})),
join = Table.Join(t1&t1,{}, t2&t2,{}),
add = Table.AddIndexColumn(join, "Field3", 0, 1)
in
add
// func
(val1 as text, val2 as text) => Table.SelectRows(table, each [Field1] = val1 and [Field2] = val2)[Field3]{0}
// result
func("d","β") //31
I'm working on a custom query provider and would like to support SQL Server's recursive CTEs. I have something that I think will work, but there are two improvements I'd like to make.
First, here's the signature of my query operator (mostly based on GroupJoin).
type QueryBuilder with
[<CustomOperation("recurse", IsLikeGroupJoin = true, JoinConditionWord = "on")>]
member x.Recurse(
anchorSource: QuerySource<'Anchor, 'Q>,
recursiveSource: QuerySource<'Recursive, 'Q>,
anchorKeySelector: ('Anchor -> 'Key),
recursiveKeySelector: ('Recursive -> 'Key),
resultSelector: ('Anchor -> IQueryable<'Recursive> -> 'Result)) =
Unchecked.defaultof<QuerySource<'Result, 'Q>>
And here's a sample query. Note the comment. The first improvement I'd like to make is prior range variables shouldn't be accessible afterwards. Is this possible?
query {
for x in customQueryable do
where (x.Day = 5)
recurse y in customQueryable
on (x.Subtract(TimeSpan.FromDays 1.0) = y) into g
for z in g do
//NOTE: `x` shouldn't be in scope here
select x
}
The second improvement is, I'd prefer to use the query syntax below, but couldn't figure out how to pull it off.
query {
for x in customQueryable do
where (x.Day = 5)
for y in customQueryable do
recurseOn (x.Subtract(TimeSpan.FromDays 1.0) = y) into g
for z in g do
select z
}
I'm also wondering if this is possible.
This is another take on accessing dynamic objects in F# There I'm using let y = x.Where(fun x -> x.City ="London").Select("new(City,Zip)") to parametrize the query and extract the necessary items. These would correspond to columns in an SQL query, and be represented by a property of the datacontext. This is the part that I would like to pass in as a parameter.
type Northwind = ODataService<"http://services.odata.org/Northwind/Northwind.svc">
let db = Northwind.GetDataContext()
let query2 = query { for customer in db.Customers do
select customer} |> Seq.toArray
let qryfun (x:Northwind.ServiceTypes.Customer) =
query { for x in query2 do
select (x.City,x.CompanyName,x.Country)}
Basically I would like to pass in not only x but also x.*. As I'm accessing one database that is fixed, I can factor out x. However I now have 40 small functions extracting the different columns. Is it possible to factor it out to one function and pass the property as an argument? So sometimes I extractx.City but other times x.Country. I have tried using quotations however cannot splice it properly and maybe that is not the right approach.
Regarding quotation splicing, this works for me:
open System.Linq
type record = { x:int; y:string }
let mkQuery q =
query {
for x in [{x=1;y="test"}].AsQueryable() do
select ((%q) x)
}
mkQuery <# fun r -> r.x, r.y #>
|> Seq.iter (printfn "%A")
I have a view and entity
var q = from stud in context.CollegePlans
where stud .Meta.Active == true &&
stud .CreatedBy_Id == user.Id
select stud ;
var k = from nv in context.vw_Year_Plans
where ( nv.StudentId == q.Where( p => p.Section.StudentId))
select nv;
studenId is Guid in both view and in entity..when i do the above it says cannot implictly convert system.Guid ? to bool ..how to overcome this ?
The expression evaluated by Where needs to evaluate to a boolean value.
where ( nv.StudentId = q.Where( p => p.Section.StudentId))
In this case, you have given it a Guid. That is where the error is coming from. I think you would have problems with that line even if the Where predicate was valid. From the looks of it, you want to want all of the StudentIds in context.vw_Year_Plans that are also in q.
A simple way to do that is to create an intermediate collection of the ids in q for comparison purposes.
var temp = q.Select(a => a.Section.StudentId);
Then see if each StudentId is also in context.vw_Year_Plans
var k = from nv in context.vw_Year_Plans
where (temp.Contains(nv.StudentId))
select nv;
There are better ways to solve this issue, but this should get you going.
EDIT
You mentioned using join in your comment. I haven't tested either of these solutions but this should be what you need. If you are still having problems, update your question with more specific details on the issues you are facing.
var k = from nv in context.vw_Year_Plans
join p in q on nv.StudentId equals p.Section.StudentId
select nv;
I have a table that is filled with random content that a user enters. I want my users to be able to rapidly search through this table, and one way of facilitating their search is by sorting the table alphabetically. Originally, the table looked something like this:
myTable = {
Zebra = "black and white",
Apple = "I love them!",
Coin = "25cents"
}
I was able to implement a pairsByKeys() function which allowed me to output the tables contents in alphabetical order, but not to store them that way. Because of the way the searching is setup, the table itself needs to be in alphabetical order.
function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do
table.insert(a, n)
end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then
return nil
else
return a[i], t[a[i]]
end
end
return iter
end
After a time I came to understand (perhaps incorrectly - you tell me) that non-numerically indexed tables cannot be sorted alphabetically. So then I started thinking of ways around that - one way I thought of is sorting the table and then putting each value into a numerically indexed array, something like below:
myTable = {
[1] = { Apple = "I love them!" },
[2] = { Coin = "25cents" },
[3] = { Zebra = "black and white" },
}
In principle, I feel this should work, but for some reason I am having difficulty with it. My table does not appear to be sorting. Here is the function I use, with the above function, to sort the table:
SortFunc = function ()
local newtbl = {}
local t = {}
for title,value in pairsByKeys(myTable) do
newtbl[title] = value
tinsert(t,newtbl[title])
end
myTable = t
end
myTable still does not end up being sorted. Why?
Lua's table can be hybrid. For numerical keys, starting at 1, it uses a vector and for other keys it uses a hash.
For example, {1="foo", 2="bar", 4="hey", my="name"}
1 & 2, will be placed in a vector, 4 & my will be placed in a hashtable. 4 broke the sequence and that's the reason for including it into the hashtable.
For information on how to sort Lua's table take a look here: 19.3 - Sort
Your new table needs consecutive integer keys and needs values themselves to be tables. So you want something on this order:
SortFunc = function (myTable)
local t = {}
for title,value in pairsByKeys(myTable) do
table.insert(t, { title = title, value = value })
end
myTable = t
return myTable
end
This assumes that pairsByKeys does what I think it does...