Feed Aggregator Page 689
Rendered on Mon, 28 Feb 2022 12:31:45 GMT
Rendered on Mon, 28 Feb 2022 12:31:45 GMT
via Elm - Latest posts by @system system on Mon, 28 Feb 2022 09:55:31 GMT
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
via Elm - Latest posts by @gorgoroth Gorgoroth on Mon, 28 Feb 2022 07:48:05 GMT
Okay. I have found the issue. Nothing to do with keyed elements.
The problem is mine. I’m using a loading view while loading data but obviously this view ‘erases’ the previous view every time. I need to manage the loading phase in a different way.
via Elm - Latest posts by @jfmengels Jeroen Engels on Mon, 28 Feb 2022 07:28:25 GMT
Tail recursion, but modulo cons
I worked on extending Elm’s tail call optimization so that it applies to more recursive functions. Hope you love the result as much as I do
via Elm - Latest posts by @robin.heggelund Robin Heggelund Hansen on Mon, 28 Feb 2022 02:32:49 GMT
The reason List.map (someFunction apple) bananas
Is faster is because the curried call returns a single-arity function which will be executed directly by List.map, while List.map (\apples banana -> someFunction apples banana) bananas
will have to create a curried version of the lambda (with F2, which has some overhead) and then List.map essentially calls two functions when executing (first the lambda through A2, then someFunction through A2).
via Elm - Latest posts by @jfmengels Jeroen Engels on Sun, 27 Feb 2022 21:53:55 GMT
Hey @john_s!
Very nice work! I know quite a few people are interested in this because I’ve seen asked a number of times whether this existed. Well now it does!
You mention changing performance attributes, so I just want to mention that even the changes that this rule makes can have some performance impacts.
When they have multiple arguments, Elm functions are wrapped in a FX function (F2, F3, F4, …), and when functions are called with multiple argument, they are called with a AX function (A2, A3, A4, …). What the AX functions do is check whether the function to call is wrapped in a FX function of the same number (A2 and F2, A3 and F3, …). If it’s the case, then the function is called with the original functions like f(a, b, c, ...)
. If it isn’t, then the function will be called one argument at a time f(a)(b)(c)...
until all the arguments are passed, which is noticeably slower for a function that is often called.
@robin.heggelund wrote a very nice series of articles on Elm performance, including one article explaining How Elm functions work, and its following articles explain how they got faster (links to those at the end of this article).
That means that List.map (\apples bananas -> someFunction milk apples bananas) list
will be faster than List.map (someFunction milk) list
. Of course, always benchmark instead of making a claim, so I wrote a benchmark.
For Elm 0.19.1, performance is faster with the curried version (I was very surprised to be honest, and I don’t know how to explain) by 5%-10%. However, when run with elm-optimize-level-2
, the curried version is 3.5 times slower (according to this particular benchmark at least).
Of course, this rule can also have the opposite effect. when you have a function defined as someFunction a = \b -> ...
, then having it called like List.map (someFunction 1) list
should be more performant than List.map (\a -> someFunction 1 a) list
. In this case, the rule would push towards the former version which would be a good thing.
These performance impacts is the reason why it didn’t explore this rule further. But I think that there are some cases where it’s always going to be okay or better (on a performance level, not in terms of personal preferences), like for \apples -> someFunction apples
or \apples bananas -> someFunction apples bananas
being reduced to someFunction
.
I think I would see the value in having a setting for the rule that only reports errors when the performance can be estimated to be at least as good as the current version. I see at least 2 scenarios when it could do that:
\apples -> someFunction apples
→ soimeFunction
(that said, this should be benchmarked)someFunction milk = \apples bananas -> ...
, then we can simplify \apples bananas -> someFunction milk apples bananas
to someFunction milk
(and otherwise this should be left untouched). This information can be gathered by looking at the definitions of each function. When the information is missing (code from dependencies, or functions from arguments), then no error should be reported.What do you think?
PS: What does “Eta” mean?
via Elm - Latest posts by @stiff Stiff on Sun, 27 Feb 2022 19:17:58 GMT
Well you don’t have to stop here. Replacing players with
, currentPlayer : Player
, otherPlayer : Player
will give direct access to data necessary and simplify winning condition check.
via Elm - Latest posts by @john_s John Suder on Sun, 27 Feb 2022 16:32:30 GMT
I published a rule that can be used to enforce varying levels of function simplification
elm-review-reducible-lambdas. The default settings are probably a little more aggressive than most in the community would prefer. However, you may be able to tinker with the settings to find a useful sweet spot for your project and so I decided to share in case anyone finds this useful.
This example config will only reduce single argument lambdas that have single letter argument names (thanks to @Arkham for the argument name predicate suggestion).
Error
\a -> someFunction a
will reduce to someFunction
Not Error
\apples -> someFunction apples
due to argument name length\a b -> someFunction a b
due to multiple arguments.config : List Rule
config =
[ NoEtaReducibleLambdas.rule
{ lambdaReduceStrategy = NoEtaReducibleLambdas.OnlyWhenSingleArgument
, argumentNamePredicate = \argumentName -> String.length argumentName == 1
}
]
These are the default settings. These may reduce a little too aggressively for most.
Error
\apples -> someFunction apples
reduces to someFunction
\apples bananas -> someFunction apples bananas
reduces to someFunction
\apples bananas -> someFunction milk apples bananas
reduces to someFunction milk
\apples bananas -> fn (apples 15) bananas
reduces to \apples -> fn (apples 15)
Not Error
\bananas -> fn (apples 15) bananas
because removing the lambda would change performance attributes by immediately evaluating (apples 15)
.config : List Rule
config =
[ NoEtaReducibleLambdas.rule
{ lambdaReduceStrategy = NoEtaReducibleLambdas.RemoveLambdaWhenNoCallsInApplication
, argumentNamePredicate = always True
}
]
via Elm - Latest posts by @axelbdt Axel on Sun, 27 Feb 2022 13:01:42 GMT
Thanks for the feedback!
I implemented your suggestion as follows:
type alias Player =
{ player : Color, tokens : Set Platform }
type alias Model =
{ currentPlayer : Color
, turnPhase : TurnPhase
, board : Board
, players : List Player
, lastMovedPlatform : Platform
, selectedToken : Maybe Token
, selectedPlatform : Maybe Platform
}
In practice I have the following problems with this model:
Dict Color (Set Platform)
would have).The pros being:
Dict
wrangling which is quite nice, though.Player
type are nice.I am considering going back to a Dict Platform Color
, but with nice helper functions to get a player’s set of tokens, move the token, etc… And see which I like better
This is clearly overthinking it, but well, I have time and the goal is to improve
The updated code is here : https://ellie-app.com/gNx2FTFYR3za1
via Elm - Latest posts by @system system on Sun, 27 Feb 2022 08:33:41 GMT
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
via Elm - Latest posts by @avh4 on Sat, 26 Feb 2022 22:31:14 GMT
Ah, great
This brings to mind another way you might want to consider organizing it where you make a pair for each card and then combine them instead of making a full set of cards and then copying the full set:
let
makeCardPair card =
[ initializeCards model.selectedCard card
, initializeCards model.selectedCard card
]
-- or instead you could use:
-- List.repeat 2 (initializeCards model.selectedCard card)
in
List.concatMap makeCardPair model.cards
Good luck w/ your game!
via Elm - Latest posts by @Branquinho Pedro Gomes Branquinho on Sat, 26 Feb 2022 22:14:39 GMT
You nailed it. Can you read minds? Because you totally got my point haha
Yeah, so I was trying to instantiate pair of cards, because I’m creating that old memory-game, in which one have to find the matching pairs of cards.
In the future, I plan to incorporate random positions to the cards.
So far, I managed to flip the cards, only.
You can check the entire project here Elm-FlippingCards, or the live version here.
Thank you.
via Elm - Latest posts by @avh4 on Sat, 26 Feb 2022 21:55:20 GMT
Hi!
I’m not sure if I completely understood what you’re trying to accomplish, so let me talk through it a little bit to make sure I understood…
Elm is pure, so “calling a function” doesn’t have side-effects. And Elm, unlike Haskell, also doesn’t have a Monad interface to represent side-effects. So there’s not going to be any purpose to calling a function multiple times unless you are using different arguments. I’m thinking in your examples, you want to produce some values, and then use the values multiple times?
In the case of the ul
example, you want to end up with two displayed copies of each card? If so, I’d do it like this:
let
cardViews = List.map (initializeCards model.selectedCard) model.cards
in
Html.ul []
(List.concat [cardViews, cardViews])
In your initializeN
example, f
would return the same value on every call, right? So then you can use List.repeat
(and in your example, f
isn’t passed an argument, so it’s really just a value, not a “function”):
List.repeat 5 f
Or if there were some arguments to f
:
List.repeat 5 (f arg1 arg2 arg3)
If I’m wrong about the above and you do want different input values passed to each call, then you’d use List.map
if you have a list of input values, possibly with List.range if you need to create a list of indices
cardFromIndex : Int -> Card
cardFromIndex i = ...
List.map cardFromIndex (List.range 1 52)
or List.indexedMap if you have a list of input values and want indices.
via Elm - Latest posts by @Branquinho Pedro Gomes Branquinho on Sat, 26 Feb 2022 21:29:16 GMT
I would like to do a sequential call in a ul
view-statement.
view model =
div [ class "tarot" ]
[ div [ id "counter" ]
[ text "Counter: "
, span [] [ text "0" ]
, text " seconds"
]
, h1 [ class "center" ] [ text "TAROT CARD GAME" ]
, ul []
(List.map (initializeCards model.selectedCard) model.cards)
(List.map (initializeCards model.selectedCard) model.cards)
]
More exactly, in
ul []
(List.map (initializeCards model.selectedCard) model.cards)
(List.map (initializeCards model.selectedCard) model.cards)
]
How can I call a function n times in a row; or, more generally, call a sequence of different functions, as in a Do
statement in Haskell?
As another example,
initializeN n f =
let
stop = 1
in
if stop <= n then
**Do**
f -- Call function
initializeN (decrement n) f -- Recursion with decreased value
in which,
initializeN f 5
Would call f
five times.
via Elm - Latest posts by @gorgoroth Gorgoroth on Sat, 26 Feb 2022 11:28:47 GMT
Unfortunately at the moment I don’t have the code at hand.
The part of the view for log entries is an ElmUI Column with three rows:
It seems that the entire ElmUI column is removed. I removed the second row in Elm but the problem persists. So is not because of the list of entries being updated.
I added DOM breakpoints (removal, subtree modification, attributes modification) in each row but no break occurs.
Adding a DOM removal breakpoint in che ElmUI Column node, breaks so is the column which is removed.
But why?
via Elm - Latest posts by @ni-ko-o-kin Nikolaus Wettstein on Sat, 26 Feb 2022 09:13:07 GMT
It would be easier to help if you could share an example so we can reproduce the problem.
My guess is, that the input field is inside the view where the new data from the server is rendered. So separating the data for the input and the response data should solve the problem.
via Elm - Latest posts by @system system on Sat, 26 Feb 2022 08:02:28 GMT
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
via Elm - Latest posts by @stiff Stiff on Fri, 25 Feb 2022 20:35:28 GMT
In language I’d describe the game as two players having 3 pieces of their (red or black) color. So model like
Player = { color: Color, pieces: List Platform }
feels closer to this description and thus more natural and easy to use.
via Elm - Latest posts by @ChristophP Christoph P on Fri, 25 Feb 2022 20:12:50 GMT
I added some info about those memory leaks to the issues justification for adding app.kill() · Issue #886 · elm/core · GitHub
via Elm - Latest posts by @ChristophP Christoph P on Fri, 25 Feb 2022 20:06:46 GMT
Nice, thanks for the insights
via Elm - Latest posts by @ChristophP Christoph P on Fri, 25 Feb 2022 20:06:26 GMT
Ah thanks, if only that got merged