Lisplog

Blogging in Lisp

Search

Feed Aggregator Page 688

Rendered on Fri, 25 Feb 2022 20:31:22 GMT  newer latest older 

IntelliJ Elm Plugin future

via Elm - Latest posts by @clojj on Fri, 25 Feb 2022 16:56:31 GMT

work continues here

Keep cursor position and focus on input field while typing after a backend request

via Elm - Latest posts by @gorgoroth Gorgoroth on Fri, 25 Feb 2022 14:31:39 GMT

I am using ElmUI and ELMUI Table. I have tried to put Element.Keyed everywhere with no success, at the moment.

Keep cursor position and focus on input field while typing after a backend request

via Elm - Latest posts by @rupert Rupert Smith on Fri, 25 Feb 2022 14:28:16 GMT

You might need to put more Html.keyed in?

So cover the input control itself, anything else that is at the same level inside whatever is the parent of the input control, and similarly all the way up to the root of your Html.

Keep cursor position and focus on input field while typing after a backend request

via Elm - Latest posts by @gorgoroth Gorgoroth on Fri, 25 Feb 2022 13:25:21 GMT

Thanks, I was able to make it work in the Ellie. In my case it seems a little more complex. I try to investigate with your suggestion.

Keep cursor position and focus on input field while typing after a backend request

via Elm - Latest posts by @rupert Rupert Smith on Fri, 25 Feb 2022 13:05:28 GMT

If you wrap your Elm Html in Html.keyed, it will avoid overwriting the DOM every time your view function is called.

To absoluately ensure this works, you may need to add Html.keyed all the way up to the root of your Html. Often just wrapping the input and everything at its level is fine.

A fairly recent discussion on the subject:

You can try it out by adding Html.keyed into this Ellie:

https://ellie-app.com/g85Cv3rQY2ya1

Keep cursor position and focus on input field while typing after a backend request

via Elm - Latest posts by @gorgoroth Gorgoroth on Fri, 25 Feb 2022 12:58:28 GMT

Hi,

I have a list of log entries served by the backend. I want to add a filtering feature which allows to restrict results while typing, requesting the new filtered list to the backend passing the typed filter string.

The problem is that when the result is returned and the View is updated, the inpunt field lose focus and this force the user to click on the input field to continue typing the filter. This is not very smooth.

Is there a way to avoid (o restore) the focus and the cursor position on the input field after a view repaint?

Multiple Debuggers on page?

via Elm - Latest posts by @klaftertief Jonas Coch on Fri, 25 Feb 2022 06:40:23 GMT

Yes, we only set the CSS in development mode.
We do not have client side routing on the page, so I can’t really comment on the route change behaviour. My guess is that the debugger will disappear when the React app removes the wrapping Elm app element, but you might have memory leaks if you do not clean up ports and other things of the Elm app.

Multiple Debuggers on page?

via Elm - Latest posts by @rupert Rupert Smith on Thu, 24 Feb 2022 22:04:51 GMT

This PR might interest you - adds a CSS class to the debugger so that you have somewhere to hook alternative styling onto:

The idea seems reasonable enough, but if it were adopted would need to be documented somewhere so that people know it is available.

If you are really keen to try it, you can fork and merge in the PR, then copy over the elm/browser in your $ELM_HOME cache.

Multiple Debuggers on page?

via Elm - Latest posts by @ChristophP Christoph P on Thu, 24 Feb 2022 21:15:44 GMT

Hey @klaftertief thanks for sharing this tip. Wow, I never would’ve come up with that. I gave contain a check on caniuse and it has surprisingly good browser support.
I guess I could even set the contain to be set only when I’m in dev mode or so.

Another question that popped into my head was this:
Say I have some routing on the page, route A and route B. When I show route A there’s one element, when i navigate to route B there’s another. Will route A’s debugger still be visible when I’m on route B, since there’s no way to do somehting like app.kill()?. Or maybe even more generally? What will happen if Elm.ModuleA.init() is called multiple times as I navigate back and forth? Will new debugger’s be spawned every time?

Multiple Debuggers on page?

via Elm - Latest posts by @klaftertief Jonas Coch on Thu, 24 Feb 2022 21:01:07 GMT

There will be multiple debuggers, one for each app. Because the debuggers have a fixed position, they will overlap and you can only easily interact with the top most one. But each debugger works as normal.

You could contain - CSS: Cascading Style Sheets | MDN on the parent element of each of the apps to create a new containing block so that the fixed position is not relative to the viewport but the to the parent element.

This works well, but only when the CSS in the apps to not depend on the viewport to be the containing block.

Multiple Debuggers on page?

via Elm - Latest posts by @ChristophP Christoph P on Thu, 24 Feb 2022 20:43:39 GMT

I’m thinking of introducing Elm into a React project with Browser.element.
It’ll only be one element for now but I am wondering what’s gonna happen with the debugger when a second element is added?
Are there two debuggers? Is there a way to switch between them? What’s a good way to deal with it?

Would love to hear some experiences.

NoMissingTypeConstructor elm-review rule fix

via Elm - Latest posts by @absynce Jared M. Smith on Thu, 24 Feb 2022 16:19:32 GMT

Good question! From this GitHub issue I believe the intention is for the rule to only be useful for simple variants without arguments.

So I made this other game... (Nonaga)

via Elm - Latest posts by @axelbdt Axel on Thu, 24 Feb 2022 13:37:35 GMT

Thanks for the kind words, and for your answers as well :slight_smile:

I’ve thought a bit about having event handlers at the wrong time and actually expect the approach to be cleaner after all: it would gather the logic in the update function and allow it to be checked by the compiler to some extent (e.g exhaustive pattern matching). I think removing the event handlers makes the view code a bit hairy and might create an “implicit state machine” problem.

I’ll try it out!

Celebrating the next ten years!

via Elm - Latest posts by @system system on Thu, 24 Feb 2022 12:27:58 GMT

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.

Debounce as an effect

via Elm - Latest posts by @system system on Thu, 24 Feb 2022 10:02:12 GMT

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.

So I made this other game... (Nonaga)

via Elm - Latest posts by @wolfadex Wolfgang Schuster on Wed, 23 Feb 2022 22:26:42 GMT

First, this is really awesome and I really enjoyed playing it!

As for your questions:

  • I sometimes use alternatives to Dict that allow for custom keys. Other times I just accept changing my data structures around. I personally haven’t found a singular solution that I prefer yet.
  • I don’t mind code duplication, unless it’s causing issues somewhere. Clarity is always greater than code duplication/de-duplication for me. However you also don’t have to always be piping everything, unless you want to. E.g. line 384-385 doesn’t need to be a pipe.
  • I tend to not worry too much about messages being sent at the wrong time unless it’s a performance concern.
  • My limit is around 2k - 3k loc. In my current side project I have space-sim/Playing.elm at main · wolfadex/space-sim · GitHub which I think was close to 3k loc at one point before I broke it up. Not sure if I’ve hit 4k loc in a single file yet but I wouldn’t be surprised.

So I made this other game... (Nonaga)

via Elm - Latest posts by @axelbdt Axel on Wed, 23 Feb 2022 17:14:36 GMT

Hello dear people,

I learned a lot from you last time when I submitted code for a Tic-Tac-Toe, so I present you an implementation of Nonaga. The code is bit more involved (500 LOC), but the game is much more fun.
I would really appreciate some feedback on the implementation, so thanks in advance :slight_smile:

The rules : https://steffen-spiele.de/fileadmin/media/Spiele/Nonaga/Nonaga_EN.pdf
The code : https://ellie-app.com/gLNNFbBtdk3a1

Specifically, a few interrogations that I had while writing this :

  • I found domain modelling a bit awkward: I tried modelling my tokens as type alias Tokens = Dict Player Set but was surprised to find that Union Types weren’t comparable. How would you have modeled the tokens?

  • Defining type alias Tokens = Dict Platform Player and using Dict-specific functions on data of type Tokens felt wrong somehow, like I am breaking encapsulation or something. And indeed, my experiments changing the underlying data structure to Tokens = List Token involved quite a few modifications (although the compiler helped a lot, of course). How do you cope with this?

  • I still ended up duplicating code (a little) when dealing with “If I have this condition, I will pipe into this function, otherwise I don’t”, see line 380-388 for an example. My guess is the GraphicsSVG API makes it a bit awkward by relying so much on piping and not on functions arguments. Do you face similar “problems” while using e.g elm-html?

  • Because of the duplication problem, I considered sending Message at inappropriate times (e.g during the wrong phase of the turn, or after the game is over), but ignored in the update. Instead, I chose to not have event handlers in the view when the Message would be appropriate, but it sometimes felt like “putting business logic in presentation layer”. What approach do you favor?

  • Surprisingly, a single file project of 500 LOC felt ok, what is your personal limit before breaking it into modules?

Wow, so many questions about 500 LOC! Hopefully you don’t dread too much the first time I hit 1k :grin:

Cheers

Help, how to coerce an Int into a Number?

via Elm - Latest posts by @allanderek Allanderek on Wed, 23 Feb 2022 13:42:09 GMT

In the playground package, Number is defined as a type alias to Float: Playground - elm-playground 1.0.3

So you need a Float rather than an Int. In this case you could just change the type signature of printDown to be Float -> String -> Shape, or you could use the toFloat : Int -> Float function.

Help, how to coerce an Int into a Number?

via Elm - Latest posts by @zvodd Zvodd on Wed, 23 Feb 2022 06:06:03 GMT

I’m using the elm Playground package for drawing an SVG.
Applying indexedMap to a list of values I am trying to render shapes and alter the shapes position with the Playground function moveDown : Number -> Shape -> Shape.
The crux of the issue is that this function accepts the Number type and that is somehow incompatible with the Int type?!
What can I do?

module Main exposing (main)

import Playground exposing (..)


main =
    picture view


type Node
    = Node Int (List Int)


view =
    let
        graph =
            [ Node 0 [ 1, 2 ]
            , Node 1 []
            , Node 2 []
            ]
    in
    graph
        |> List.map Debug.toString
        |> List.indexedMap printDown


printDown : Int -> String -> Shape
printDown i x =
    words black x
        |> moveDown i -- moveDown expects Number, got Int and fails?!

Jonathan Godbout: Evil Lies about Hash Tables

via Planet Lisp by on Wed, 23 Feb 2022 01:03:08 GMT

Greetings readers. There are lies being told in Computer Science, lies you probably believe. Today I want to discuss the lie that is the constant time lookup or insertion of our friend the hash table. Don't get me wrong, I love hash tables, some of my best functions use them, but they are far from constant time.

So, what the usual statement is: Hash tables have constant time lookups.

This is a lie. They have average case constant time lookups, worst case linear time lookups, and O is about worst case analysis. 

Let’s dig into this statement.

Faye trying to understand HashTables.

How do hash tables work?

Hash tables are key-value pairs, you tell them to store as keys some object type (for example strings), and as their value some other objects (for example a Person object).

This way we can have:

(let ((persons (make-hash-table :test #'equalp)))
  (setf (gethash "Lyra" persons) (list :name "Lyra" :height 36 :weight 34))
  (setf (gethash "Lrya" persons) (list :name "Lrua" :height 34:weight 36))
  (setf (gethash "Faye" persons) (list :name "Faye" :height 24 :weight 20))
  (print (gethash "Lyra" persons))
  ...)

So `persons` is a hash table containing a list of person attributes.

Their power is in hashing, the usage of a function that maps an object to an integer. Take strings as an example, a simple hash function could be

(defun hash-string (str)
  (reduce #'+ str :key #'char-int))

Which adds up the integer values of each character, where "a” is 97, “b” is 98...

When we run

 (gethash "Lyra" persons)

First we hash the string "Lyra" to get 408. The constant time lookup type we know of is arrays, so as one would expect hash tables could (and should) be backed by arrays. 

This leads to two problems:

  1. The possible values of our hash function are bigints, a hash table can't be backed by an array of arbitrary size.
  2. What if two keys have the same value?

The first is simple, we limit the hash table to a certain size, so it has m possible values. Then we just take (mod (string-hash "foo") m) to get the array index.

The second is also fairly simple, we create a list of elements. So "Ly" and "yL" would be in the same array index, or in hash-table parlance bucket. A value in this bucket will be the key-value pair, so in the bucket containing "Lyra" in persons we might see

(list ("Lyra" .  (list :name "Lyra" :height 36 :weight 34))
       ("Lrya" , (list :name "Lrya" :height 34 :weight 36)))

Then we are left with testing the key portion of our hash-table with our test function versus the given key, and finally returning the value.

Side note: If you have a way to compare the elements in your bucket you can use a balanced binary tree instead of a list. This takes the worst case lookup time from O(k) where k is the number of elements in your bucket, to O(log k). Java 8 did this for large bucket sizes in it's HashMap (at least some implementations).

Why is this not just O(n) or O(log n)?

Well it is, if your hash function is constant (or bad) then you will get lots of hash-collisions, and turn your nice shiny hash-table into a balanced binary tree or a list. But we really care about average lookup times.

If we fix our bucket size m, then hash-tables are back to bad... The good news is we can resize the buckets. This requires us to rehash all of the elements, and make new lists. This could be expensive, but it probably occurs rarely, and proper values for the size of our hash-table can greatly improve things. You can find the math in any CS Data Structures book, or wikipedia:

but with proper rehashing and a good hash function you’re back down to constant time lookups!

So please, don't tell me your maps are O(1) without at least alluding to the fact that this is not quite O...

Other lie:

Quicksort is not O(n log n).

it's actually O(n^2), but it almost always outperforms it's O(n log n) rivals.

 newer latest older