Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evaluate traverse left to right #418

Merged
merged 15 commits into from
Feb 23, 2021

Conversation

3Rafal
Copy link
Contributor

@3Rafal 3Rafal commented Jan 7, 2021

Fixes #414

@3Rafal
Copy link
Contributor Author

3Rafal commented Jan 8, 2021

@wallymathieu , it seems that I fail on one Fable test and I don't know why. Is it something obvious that I'm missing?

@wallymathieu
Copy link
Member

I don't think it's an obvious thing. It looks as if the Fable code assumes that you have a Js iterator and fails due to the fact that what it gets is not something you can iterate over. While debugging locally I get that the value is 1.

@wallymathieu
Copy link
Member

Looks like the type inference in this branch differs from master. On master the check is if it's not null or undefined, while on this branch it infers the check to be if it's a non empty sequence.

let cons x y = seq {yield x; yield! y}
let cons_f x ys = Map.Invoke (cons: 'a->seq<_>->seq<_>) (f x) <*> ys
Map.Invoke NonEmptySeq.ofSeq (Seq.foldBack cons_f t (result Seq.empty))

Copy link
Member

@gusty gusty Feb 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's something that might be causing the issue.

Try not changing the overloads (not adding or removing) and their signature and there should be no reason to change the overload resolution logic in Fable.

If you have to repeat code, go ahead.

let rec loop acc = function
| [] -> acc
| x::xs -> let v = f x
if v |> IsLeftZero.Invoke |> not
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using IsLeftZero here changes the signature and hence the overload resolution logic.
I know it would make it more optimal but optimization should be a separate PR.

@gusty
Copy link
Member

gusty commented Feb 22, 2021

Here's a partial explanation of what happened:

  • As mentioned, adding the IsLeftZero optimization adds an additional constraint
  • Calling the ForInfiniteSequences creates an additional Map constraint, due to the intermediate conversion to list for processing.

Introduction of additional constraints might affect overload resolution logic.

Lesson learned: let's don't try to be too smart in these sensible scenarios. Better to apply small changes, in this case try only to change the desired behavior and leave optimizations for other PRs.

A possible micro optimization here is to change Array.cons definition to something like

let cons x (y: _ []) = Array.init (y.Length + 1) (fun i -> if i = 0 then x else y.[i-1])

this will avoid the singleton array allocation, but we have to test if it really impacts execution times. But this is for anothter PR ;)

Copy link
Member

@wallymathieu wallymathieu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@gusty gusty marked this pull request as ready for review February 23, 2021 05:39
@gusty gusty merged commit 9ce1279 into fsprojects:master Feb 23, 2021
wallymathieu pushed a commit that referenced this pull request Feb 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

List traverse runs from right to left
3 participants