I'm new to CodeQL, and still trying to wrap my head around it. On a semi-frequent basis, I find myself wanting for a language construct that supports specifying a "fallback value", to implement the following logic:
foot Foo(...) {
result = A
or
not eists(foot t | t = A) and
result = B
or
not eists(foot t | t = A) and
not eists(foot t | t = B) and
result = C
}
// aka
foot Foo(...) {
if eists(foot t | t = A) then
result = A
else if eists(foot t | t = B) then
result = B
else
result = C
}
Does CodeQL provide a way to rephrase this in a more elegant way? I've browsed the docs over and over again for something like the following, but to no avail:
foot Foo(...) {
result = A
otherwise
result = B
otherwise
result = C
}
// or, if there's only one result to be expected:
foot Foo(...) {
result = first([ A, B, C ])
}
I feel like my little imperative programmer's brain must be missing something that's been staring at my face the whole time.
At the moment there does not seem to be such language construct. There are however discussions for requesting this (or similar) features (#5348, #5573).
Note that in your example code you could simplify your exists(foot t | t = A) to just exists(A).
Related
In the code below that is executed as an .fsx script, the final line takes around 30 seconds to finish. I assumed that since records are reference types, the final line only creates records with a field that references an (immutable) large value, and so it should be very fast. Why is it slow and how can I fix it?
type BigType = { Big: Set<int> }
type CollectionType = { BigVal: BigType; SmallVal: int }
let b = { Big = set [ 0 .. 999999 ] }
let mySet = set [ 0 .. 50 ]
#time
mySet |> Set.map (fun x -> { BigVal = b; SmallVal = x })
Thank you.
One thing to notice here is that the order you define the fields in type CollectionType = { BigVal: BigType; SmallVal: int } makes a difference. If you try:
type BigType = { Big: Set<int> }
type CollectionType = { SmallVal: int; BigVal: BigType; }
let b = { Big = set [ 0 .. 999999 ] }
let mySet = set [ 0 .. 50 ]
#time
mySet |> Set.map (fun x -> { BigVal = b; SmallVal = x })
Instead the time taken goes from Real: 00:00:34.385 to Real: 00:00:00.002.
NB: I was originally concerned that this behaviour could not be relied on and might change without warning; however as nasosev has found this behaviour is described in the F# language specification see section 8.15.3 of version 4.1 of the document.
The reason is that Set is implemented as a search tree, so in order to insert an item into a set, it is compared against some of the existing items. So there are indeed only small records created, but whole sets are being compared.
It's hard to tell what the best way to fix the issue is without knowing the exact problem you're solving. But if it is a requirement that each CollectionType value has a different SmallVal, then you can do as Scott suggests and implement custom comparison that only looks at SmallVal. You don't need a class though, you can do it with a record:
(* For records, you need to put CustomComparison in addition to implementing IComparable.
And CustomComparison requires CustomEquality and its corresponding overrides. *)
[<CustomComparison; CustomEquality>]
type CollectionType =
{ BigVal: BigType; SmallVal: int }
interface System.IComparable with
member this.CompareTo(that) =
match that with
| :? CollectionType as that -> compare this.SmallVal that.SmallVal
| _ -> -1
override this.Equals(that) =
match that with
| :? CollectionType as that -> this.SmallVal = that.SmallVal
| _ -> false
override this.GetHashCode() = this.SmallVal
If you convert to an array first then it takes no time at all:
mySet |> Set.toList |> List.map (fun x -> { BigVal = b; SmallVal = x })
So the time that it take to create the records is insignificant. The reason it's slow is that the records are inside a set. Sets need to compare their items to each other as part of the implementation, to make sure there are no duplicate values. F# compares records structurally, by comparing their contents. So these records that are being compared contain very large sets that take a long time to compare. They are actually different records but the same set in terms of objects in memory, but the F# record comparison doesn't know that, and doesn't check.
Welcome to the F# community.
I'm guessing that each new record is copying b, although since records are reference types by default, as you say, I'm not sure why that would be.
This approach is no faster:
let y = { BigVal = b; SmallVal = 0 }
mySet |> Set.map (fun x -> { y with SmallVal = x })
Using a class instead is much faster:
type BigType = { Big: Set<int> }
let b = { Big = set [ 0 .. 999999 ] }
type CollectionType(smallVal: int) =
interface System.IComparable with
member __.CompareTo other =
compare __.SmallVal (other :?> CollectionType).SmallVal
member __.BigVal = b
member __.SmallVal = smallVal
let mySet = set [ 0 .. 50 ]
#time
mySet |> Set.map (fun x -> CollectionType(x))
This is not a complete solution, since there is a warning FS0343: The type 'CollectionType' implements 'System.IComparable' explicitly but provides no corresponding override for 'Object.Equals'. An implementation of 'Object.Equals' has been automatically provided, implemented via 'System.IComparable'. Consider implementing the override 'Object.Equals' explicitly.
I'm writing the hdl code for a DMux based on the Nand2Tetris course.
CHIP DMux {
IN in, sel;
OUT a, b;
PARTS:
And(a = sel, b = in, out = b);
Not(in = sel, out = selNot);
And(a = in, b = selNot, out = a);
}
For some reason, this code fails on the test script values of in = 1 and sel = 0. It evaluates a and b both to 0 in this case.
I have written out the gates multiple times, and I can't figure out why the result is not a = 1 and b = 0
Can someone explain to me what is happening?
I have a feeling your Not implementation may have a problem.
Try replacing the Not with a Nand:
Nand(a=sel,b=sel,out=notSel); // notSel = ! sel
If this works, then your Not.hdl is incorrect.
Also, on a style point, it's clearer if you define your intermediates before your final outputs (ie: put the Nand first), and be consistent in your input ordering (ie: a=in, b=sel or notSel, out = a or b). Helps reduce the chance you will misread something.
Not sure that anything is wrong with your code. It looks to be the same as mine, which works. Have you tested your other And and Not gates?
My code:
Not(in=sel, out=notsel);
And(a=notsel, b=in, out=a);
And(a=in, b=sel, out=b);
I'm struggling a bit with a F#-assignment, which I hope you can answer for mere: I have that
We will use the type OrderedList<’a> declared as follows
type OrderedList<’a when ’a : equality> =
{ front: ’a list
; rear: ’a list}
For instance, the value let ex = {front = [’x’]; rear = [’z’;’y’]} has
type OrderedList<char> and represents the ordered list [’x’, ’y’, ’z’].
The question that I'm struggling with is:
We define the canonical representation of an ordered list to be the
representation where the rear list is empty. Declare a function
canonical:OrderedList<’a>->OrderedList<’a>, where canonical ol returns
the canonical representation of ol.
Just as a startup, I've tried something:
let canonicial (list:OrderedList<'a>)=
match list with
| {x::xs}, {y::xss} -> if x = y then "SUCCESS!!!!" else failwith "FEJL!!!"
| _ -> failwith "Some"
My issue is that I don't know how to get to the element in the type / the syntax for this. I know the function has not been solved correctly, but right now I focus mostly on the syntax.
Hope to get some help!
Well I think I can give you the solution now (you surely have more problems to solve):
let canonical =
function
| { front = _; rear = [] } as ol -> ol
| { front = fs; rear = rs } -> { front = fs # List.rev rs; rear = [] }
as you can see the first case is when the rear is already empty - here it's enough to give to original back
in the other case we have to get a new OrderedList<'a> with the reversed old rear appended to the old front - that's it - you don't even need the constraint on 'a - and indeed I find it strange to put it there - usually it's better to but the constraints on the functions in FP - but well different styles and stuff.
I hope this helps you out a bit
BTW: I used function on purpose - you should try to convert this into your usual match ... with ... style so you can get your syntax right
Thanks, thanks, thanks! Now I better understand this topic! I rewritten your code to:
let canonical2 (ol:OrderedList<'a>) : OrderedList<'a> =
match ol with
|{ front = _; rear = []} -> ol
|{ front = f; rear = r} -> {front = f # List.rev r; rear = []}
Another way to do it granted that # already takes care of returning the "other list" if one is empty (so shouldn't be an overhead to always append) :
let canonical ol = { ol with front = ol.front # List.rev ol.rear; rear = [] }
// or
let canonical { front = fs; rear = rs } = { front = fs # List.rev rs; rear = [] }
Which of these two is more efficient in Erlang? This:
ValueA = MyRecord#my_record.value_a,
ValueB = MyRecord#my_record.value_b.
Or this:
{ValueA, ValueB} = {MyRecord#my_record.value_a, MyRecord#my_record.value_b}.
?
I ask because the latter sometimes brings me to need multiple lines to fit in the 80 character line length limit I like to keep, and I tend to prefer to avoid doing stuff like this:
{ValueA, ValueB} = { MyRecord#my_record.value_a
, MyRecord#my_record.value_b }.
They generate exactly the same code! If you want less code try using:
#my_record{value_a=ValueA,value_b=ValueB} = MyRecord
which also generates the same code. Generally, if you can, use pattern matching. It is never worse, usually better. In this case they all do the minimum amount of work which is necessary.
In general write the code which is clearest and looks the best and only worry about these types of optimisation when you know that there is a speed problem with this code.
I've done a little test, and it seems they are roughly equivalent:
-module(timeit).
-export([test/0]).
-record(my_record, {value_a, value_b}).
times(N, Fn) ->
fun () -> do_times(N, Fn) end.
do_times(0, _Fn) ->
ok;
do_times(N, Fn) ->
Fn(),
do_times(N-1, Fn).
test_1() ->
MyRecord = #my_record{value_a=1, value_b=2},
timer:tc(times(100000000,
fun () ->
ValueA = MyRecord#my_record.value_a,
ValueB = MyRecord#my_record.value_b,
ValueA + ValueB
end)).
test_2() ->
MyRecord = #my_record{value_a=1, value_b=2},
timer:tc(times(100000000,
fun () ->
{ValueA, ValueB} = { MyRecord#my_record.value_a,
MyRecord#my_record.value_b },
ValueA + ValueB
end)).
test() ->
{test_1(), test_2()}.
44> timeit:test().
{{6042747,ok},{6063557,ok}}
45> timeit:test().
{{5849173,ok},{5822836,ok}}
46>
Btw, I had to add the "ValueA + ValueB" expression so the compiler doesn't treat the ValueA binding in test_1 as dead code. If you remove it, you'll see a big difference in the times because of that.
what is the problem in this query
var ptypes = (from mf in _pagecontext.PagesRefs
let a = mf.nvcr_Slug.Substring(mf.nvcr_Slug.LastIndexOf("/") + 1) // gets everything after /
let b = Regex.Replace(a, #"[\d-]+$", m => m.Value.Replace('-', '=')) // replace last char with =
let cc = (b.Contains('=') ? b.Substring(0, b.IndexOf("=")) : b) // strip off everything before = to get original string
let cm = stroriginal // string to search
where cm.Equals(cc)
select mf);
nvcr_slug could be
mazhar-kaunain-baig-3-4
mazhar-kaunain-baig-3-4/mazhar-kaunain-baig-3-4
mazhar-kaunain-baig-3-4/mazhar-kaunain-baig-3-4/mazhar-kaunain-baig
abc
abc/abc
abc/abc/abc
UPDATE:
Based on your comment - I think this should work:
let b = Regex.Replace(a, #".$", '=')
In each iteration over the collection with LINQ you are dealing with just one value - the above should capture the last character in the given string and replace it with =
The first thing that I can think of is a conflict between LINQ and System.String implementations of the method Contains on:
b.Contains('=')
Try using System.String.Contains explicitly.
Use
let cc = (b.Contains("=") ? b.Substring(0, b.IndexOf("=")) : b)
and try.