Lisplog

Blogging in Lisp

Search

Feed Aggregator Page 645

Rendered on Thu, 10 Sep 2020 10:03:17 GMT  newer latest older 

Extracting type metadata from Elm code?

via Elm - Latest posts by @miniBill Leonardo Taglialegne on Thu, 10 Sep 2020 08:55:46 GMT

Work in progress, this works-ish but it will need more complex types to transform oneOf into the custom/variant style from elm-codec

https://ellie-app.com/9WkhnsWqzgDa1

How to simulate a select

via Elm - Latest posts by @francescortiz Francesc Ortiz on Thu, 10 Sep 2020 08:19:40 GMT

In selects you get an input event as if the user had typed something. If you want to know which is the selected option you will have write an event decoder that checks for all the options to see if the selected one is the last one, or simply make a decoder that in case of a select returns index of the selected option and the option count.

Check this example:
https://ellie-app.com/9WjXB3WJQ9Ca1

Keep in mind that the options of a select have very different implementation in mobile than in the browser, so I don’t recommend looking at them as regular HTML entities.

Elm Radio Episode 12 - elm-spa

via Elm - Latest posts by @P.Wadsworth Peter T Wadsworth on Thu, 10 Sep 2020 07:16:39 GMT

Great podcast! Thanks for all the work you put into keeping it fresh and relevant. It’s an invaluable help for newcomers.

How to simulate a select

via Elm - Latest posts by @Brian_Carroll Brian Carroll on Wed, 09 Sep 2020 22:13:44 GMT

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

Elm-deque 1.2.0 released!

via Elm - Latest posts by @system system on Wed, 09 Sep 2020 20:15:06 GMT

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

Alexander Artemenko: function-cache

via Planet Lisp by on Wed, 09 Sep 2020 19:41:05 GMT

Yesterday I've reviewed fare-memoization and decided to tell you about the library I'm using for memoization instead.

The main features are ability to set TTL and an extendable caching protocol which allows to use different kinds of caches.

For example, here we'll use LRU cache which will remember only 3 results:

POFTHEDAY> (function-cache:defcached (foo :cache-class 'function-cache:lru-cache
                                          :capacity 3)
               (param)
             (format t "Not cached, returning the value: ~A~%" param)
             param)

POFTHEDAY> (foo 1)
Not cached, returning the value: 1
1

;; Now the value returned from the cache:
POFTHEDAY> (foo 1)
1

;; Let's fill the cache:
POFTHEDAY> (foo 2)
Not cached, returning the value: 2
2
POFTHEDAY> (foo 3)
Not cached, returning the value: 3
3
POFTHEDAY> (foo 4)
Not cached, returning the value: 4
4
POFTHEDAY> (foo 5)
Not cached, returning the value: 5
5

;; Value for 1 was evicted from the cache:
POFTHEDAY> (foo 1)
Not cached, returning the value: 1
1

And here is how we can set TTL and make the function result remembered for 5 seconds:

POFTHEDAY> (function-cache:defcached (foo :timeout 5)
               ()
             (let ((ts (local-time:now)))
               (format t "Not cached, returning the value: ~A~%" ts)
               ts))

POFTHEDAY> (foo)
Not cached, returning the value: 2020-09-09T22:36:05.630085+03:00
@2020-09-09T22:36:05.630085+03:00

POFTHEDAY> (foo)
@2020-09-09T22:36:05.630085+03:00

POFTHEDAY> (foo)
@2020-09-09T22:36:05.630085+03:00

POFTHEDAY> (foo)
@2020-09-09T22:36:05.630085+03:00

POFTHEDAY> (foo)
Not cached, returning the value: 2020-09-09T22:36:10.767777+03:00
@2020-09-09T22:36:10.767777+03:00

Sometimes it can be very convenient to cache rarely changed data this way.

How to simulate a select

via Elm - Latest posts by @marciofrayze Marcio Frayze on Wed, 09 Sep 2020 19:49:25 GMT

I’m trying to do some TDD with Elm. To test events, I do something like this:
|> Query.find [ Selector.id “someId” ]
|> Event.simulate Event.click
|> Event.expect SomeEvent

That works fine to simulate a click. But I can’t figure out how to test a html Select/option.

What I want to test: when user selects the last option from a select, should dispatch a specific message with a specific value.

Any tips?

Donating to esf

via Elm - Latest posts by @system system on Wed, 09 Sep 2020 14:25:09 GMT

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

Parsers with Error Recovery

via Elm - Latest posts by @rupert Rupert Smith on Wed, 09 Sep 2020 09:59:32 GMT

On the chunking - I looked into doing it with elm/regex which is easy to do:

Regex.fromString "\\n(?=\\w)"
    |> Maybe.withDefault Regex.never
    |> (\r -> Regex.split r source)

But for interactive work, I will also need to know the start and end positions of each chunk. For that reason, I think it will make sense to write the initial chunker using elm/parser.

Parsers with Error Recovery

via Elm - Latest posts by @rupert Rupert Smith on Wed, 09 Sep 2020 08:25:42 GMT

Thanks for all of these most helpful replies.

This will work nicely for what I am trying to do. The file is a series of ‘declarations’. I can either chunk on newline followed by a letter, as you suggest. Or I could chunk on newline followed by ‘name =’, as all the declarations start that way - that would allow subsequent lines of the declaration to also be at the start of the line.

I am aiming to do the parsing on the file as it is being edited. Chunking will mean that the parsing does not have to be re-done on parts of the file already parsed. I can track where the edits are, figure out which chunks that overlaps with, and then re-chunk and parse just those.

I am trying to comprehend whether this scheme can be supported by elm/parser. I guess its going to be supported by whatever goes in the ‘context’ of a Parser.Advanced.

I think studying this will probably answer what I am wondering about above.

Beyond a first pass implementation with chunking of ‘declarations’, it would nice if I could have tolerant parsing that goes deeper into the syntax for the purpose of offering context sensitive help. For example, my ‘declarations’ can take a list of properties (name/value pairs), and the possible properties depend on which code generator the model is going to be passed to. Some properties are optional, some are required. If I can parse the property list as it is being edited but skip over any malformed parts of it, then I should be able to see what properties are already defined, and offer up suggestions for those that are not yet defined.

Parsers with Error Recovery

via Elm - Latest posts by @mdgriffith Matthew Griffith on Tue, 08 Sep 2020 20:10:34 GMT

Elm Markup does parsing with recovery and it sounds like it takes roughly the same approach as @klazuka describes.

This module is likely relevant: Tolerant Parser though not well documented because it’s internal :sweat_smile:

Alexander Artemenko: fare-memoization

via Planet Lisp by on Tue, 08 Sep 2020 19:44:20 GMT

This library is used by cl-vcr, reviewed yesterday.

Previously I've used another library for caching function results and fare-memoization seems interesting because it allows to "memoize" any function unless it is inlined.

Also, this "memoization" effect can be undone:

POFTHEDAY> (defun foo (a b)
             "Waits 5 seconds and multiplies a and b."
             (sleep 5)
             (* a b))

POFTHEDAY> (time (foo 2 3))
Evaluation took:
  5.003 seconds of real time

6

POFTHEDAY> (time (foo 2 3))
Evaluation took:
  5.005 seconds of real time
  
6

POFTHEDAY> (fare-memoization:memoize 'foo)

;; This call will cache it's result:
POFTHEDAY> (time (foo 2 3))
Evaluation took:
  5.004 seconds of real time
  
6

;; And next call will return immediately:
POFTHEDAY> (time (foo 2 3))
Evaluation took:
  0.000 seconds of real time
  
6

;; Now we'll undone the effect:
POFTHEDAY> (fare-memoization:unmemoize 'foo)

POFTHEDAY> (time (foo 2 3))
Evaluation took:
  5.005 seconds of real time
  
6

There is also a macro to define memoized functions and apply/funcall and remember results. The only thing I miss is the ability to cache results for a given amount of time.

Read the documentation, @ngnghm did a very good job!

Alexander Artemenko: cl-vcr

via Planet Lisp by on Mon, 07 Sep 2020 20:11:19 GMT

This system provides a simple macro which will remember all HTTP requests. Results are stored to the disk and will be reused. This should be useful if you need to rerun your integration tests frequently.

The README is short and only say that cl-vcr was inspired by https://github.com/vcr/vcr

By the way, cl-vcr is not in Quicklisp. Here is the link to the repository:

https://github.com/kidd/cl-vcr

Let's try it!

;; CL-VCR stores it's data in /tmp/vcr/, but does
;; not create it itself :(
POFTHEDAY> (ensure-directories-exist "/tmp/vcr/")


POFTHEDAY> (time
            (cl-vcr:with-vcr "the-tape"
              (drakma:http-request "https://httpbin.org/delay/10")))
Evaluation took:
  10.859 seconds of real time
  0.037955 seconds of total run time (0.025274 user, 0.012681 system)
  0.35% CPU
  12 lambdas converted
  23,975,316,800 processor cycles
  5 page faults
  1,176,304 bytes consed
  
#(123 10 32 32 34 97 114 103 115 34 58 32 123 125 44 32 10 32 32 34 100 97 116
  97 34 58 32 34 34 44 32 10 32 32 34 102 105 108 101 115 34 58 32 123 125 44
  32 10 32 32 34 102 111 114 109 34 58 32 123 125 44 32 10 32 32 34 104 101 97
  100 101 114 115 34 58 32 123 10 32 32 32 32 34 65 99 99 101 112 116 34 58 32
  34 42 47 42 34 44 32 10 32 32 32 32 34 72 111 115 116 34 58 32 34 104 116 116
  112 98 105 110 46 111 114 103 34 44 32 10 32 32 32 32 34 85 115 101 114 45 65
  103 101 110 116 34 58 32 34 68 114 97 107 109 97 47 50 46 48 46 55 32 40 83
  66 67 76 32 50 46 48 46 56 59 32 68 97 114 119 105 110 59 32 49 57 46 53 46
  48 59 32 104 116 116 112 58 47 47 119 101 105 116 122 46 100 101 47 100 114
  97 107 109 97 47 41 34 44 32 10 32 32 32 32 34 88 45 65 109 122 110 45 84 114
  97 99 101 45 73 100 34 58 32 34 82 111 111 116 61 49 45 53 102 53 54 56 98 57
  48 45 98 55 102 53 56 99 98 48 52 57 57 55 51 51 53 48 100 52 48 56 52 55 55
  48 34 10 32 32 125 44 32 10 32 32 34 111 114 105 103 105 110 34 58 32 34 51
  49 46 49 55 51 46 56 48 46 55 34 44 32 10 32 32 34 117 114 108 34 58 32 34
  104 116 116 112 115 58 47 47 104 116 116 112 98 105 110 46 111 114 103 47 100
  101 108 97 121 47 49 48 34 10 125 10)

POFTHEDAY> (time
            (cl-vcr:with-vcr "the-tape"
              (drakma:http-request "https://httpbin.org/delay/10")))
; Debugger entered on #<SIMPLE-TYPE-ERROR expected-type: SB-IMPL::FUNCTION-NAME
;                     datum: (LAMBDA () :IN DRAKMA::MAKE-SSL-STREAM)>

As you can see, here we have two problems:

  • cl-vcr does not work;
  • drakma is not able to decode httpbin.org's JSON response (honestly, I tried different arguments to http-request.

Fortunately, there is cool Dexador, which "just works" and a hack to make cl-vcr use it. But "ups!" it does not work either, because cl-vcr tries to remember all returned values, including SSL stream and associated CFFI structure of the networking socket:

POFTHEDAY> (time
            (let ((cl-vcr::*http-call* 'dex:request))
              (cl-vcr:with-vcr "the-tape"
                (dex:get "https://httpbin.org/delay/10"))))
; Debugger entered on #<CL-STORE:STORE-ERROR {100C4C3E73}>

;; This is what dex:get returns as it's values:
POFTHEDAY> (dex:get "https://httpbin.org/delay/10")
"{
  \"args\": {}, 
  \"data\": \"\", 
  \"files\": {}, 
  \"form\": {}, 
  \"headers\": {
    \"Accept\": \"*/*\", 
    \"Content-Length\": \"0\", 
    \"Host\": \"httpbin.org\", 
    \"User-Agent\": \"Dexador/0.9.14 (SBCL 2.0.8); Darwin; 19.5.0\", 
    \"X-Amzn-Trace-Id\": \"Root=1-5f568fb6-f74ff20069c9dca0a0b0c760\"
  }, 
  \"origin\": \"31.173.80.7\", 
  \"url\": \"https://httpbin.org/delay/10\"
}
"
200 (8 bits, #xC8, #o310, #b11001000)
#<HASH-TABLE :TEST EQUAL :COUNT 7 {100C4BBC93}>
#<QURI.URI.HTTP:URI-HTTPS https://httpbin.org/delay/10>
#<CL+SSL::SSL-STREAM for #<FD-STREAM for "socket 192.168.43.216:64553, peer: 35.170.21.246:443" {100C4AE583}>>

We can overcome these difficulties by creating a wrapper to make HTTP requests and return only the result.

First call returns in 10 seconds:

POFTHEDAY> (defun http-get (url)
             (values (dex:get url)))

POFTHEDAY> (time
            (let ((cl-vcr::*http-call* 'http-get))
              (cl-vcr:with-vcr "the-tape"
                (http-get "https://httpbin.org/delay/10"))))
Evaluation took:
  10.175 seconds of real time
  0.020157 seconds of total run time (0.013977 user, 0.006180 system)
  0.20% CPU
  52 lambdas converted
  22,465,739,006 processor cycles
  4,203,120 bytes consed
  
"{
  \"args\": {}, 
  \"data\": \"\", 
  \"files\": {}, 
  \"form\": {}, 
  \"headers\": {
    \"Accept\": \"*/*\", 
    \"Content-Length\": \"0\", 
    \"Host\": \"httpbin.org\", 
    \"User-Agent\": \"Dexador/0.9.14 (SBCL 2.0.8); Darwin; 19.5.0\", 
    \"X-Amzn-Trace-Id\": \"Root=1-5f5692a6-fde6da521dce37dc2983bb9e\"
  }, 
  \"origin\": \"31.173.80.7\", 
  \"url\": \"https://httpbin.org/delay/10\"
}
"

But second call returns immediately:

POFTHEDAY> (time
            (let ((cl-vcr::*http-call* 'http-get))
              (cl-vcr:with-vcr "the-tape"
                (http-get "https://httpbin.org/delay/10"))))
Evaluation took:
  0.005 seconds of real time
  0.005484 seconds of total run time (0.004814 user, 0.000670 system)
  100.00% CPU
  26 lambdas converted
  12,198,056 processor cycles
  1,996,128 bytes consed
  
"{
  \"args\": {}, 
  \"data\": \"\", 
  \"files\": {}, 
  \"form\": {}, 
  \"headers\": {
    \"Accept\": \"*/*\", 
    \"Content-Length\": \"0\", 
    \"Host\": \"httpbin.org\", 
    \"User-Agent\": \"Dexador/0.9.14 (SBCL 2.0.8); Darwin; 19.5.0\", 
    \"X-Amzn-Trace-Id\": \"Root=1-5f5692a6-fde6da521dce37dc2983bb9e\"
  }, 
  \"origin\": \"31.173.80.7\", 
  \"url\": \"https://httpbin.org/delay/10\"
}
"

There is another problem with cl-vcr - it does not use unwind-protect to run unmemoize. That is why it applied memoization patch to the dex:request function, but didn't roll it back on the error.

What could I say? CL-VCR is a good example of a really bad implementation of a nice idea :)

Parsers with Error Recovery

via Elm - Latest posts by @klazuka Keith Lazuka on Tue, 08 Sep 2020 19:00:31 GMT

The approach taken by IntelliJ is two-fold:

  1. pinning: when a certain token is reached in a parse rule, commit to that rule even if subsequent tokens do not match the remaining rule
  2. recovery: when committed to a failed rule*, discard tokens until you reach some sentinel token (or arbitrary logic) which indicates a point from which you can recover.

The error recovery can be nested so you can recover from top-level declarations, as Evan described, or you can recover inside expressions, i.e. the incomplete List literal [ 1, 2,

Pinning happens when you see something that unequivocally indicates what the user intends. So if I’m writing an expression in Elm and I type [, we can be pretty sure that the user is trying to write a List literal and we commit to parsing it as a list literal at this point even though there is no matching ].

Recovery happens when you need to drop garbage tokens so that the parser can resume. If I write [1, 2, 3xyz ], the parser will fail when we reach 3xyz (because it’s not a valid expression). Assuming that we pinned (committed to parsing the list literal) when we saw the [, we can recover by dropping tokens until we consume the closing ].

Footnote *: this is a bit of a simplification. I think recovery in IntelliJ/GrammarKit used to work this way (where it would only happen when a rule failed but was pinned), but now I think the recovery is always done, even when a rule succeeds normally.

Parsers with Error Recovery

via Elm - Latest posts by @evancz Evan on Tue, 08 Sep 2020 15:49:34 GMT

The easiest way is probably to define a simple notion of “chunks” that any file can be broken into.

So with Elm code, maybe that means a chunk begins whenever you have a “fresh line” where a newline is directly followed by a letter. That indicates that we are seeing a type, type alias, type annotation, declaration, import, or port. Then you parse the chunks individually.

That approach could get confused by weirdly indented expressions I guess, but it seems like it’s a reasonable start at least! I also wouldn’t be to tied to trying to do it all in a single pass over the file at first. Just start by figuring out if it can get the error messages you’d like to see!

Elm-review 2.3.0 - "Just try it out"

via Elm - Latest posts by @MartinS on Tue, 08 Sep 2020 15:23:36 GMT

I’m looking forward to trying this out. Having withModuleNameLookupTable seems quite handy. Previously I’ve just written rules with the assumption that the user won’t do anything unusual with module imports but now the rules I make can be more robust.

Parsers with Error Recovery

via Elm - Latest posts by @rupert Rupert Smith on Tue, 08 Sep 2020 15:12:52 GMT

I’ve seen this topic mentioned a few times on Slack, but though it worth asking here so the answers are better preserved.

I want to write a parser with error recovery (for this). So as a user is inputing the source code, the parser should run and attempt to parse the input. If it fails to do so, it should recover and continue on the next part of the source that is valid.

Has anyone any links to blogs, source code, etc on doing this in Elm? Or any thoughts or experience they might care to share?

Operation that does Debug.log and returns input value

via Elm - Latest posts by @system system on Tue, 08 Sep 2020 12:43:28 GMT

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

Seeking advice on which Haskell back end frameworks/libraries to use

via Elm - Latest posts by @aforemny Alexander Foremny on Tue, 08 Sep 2020 11:09:38 GMT

Hi @ChrisWellsWood, I have recently stumbled upon Mu-Haskell and after reading through the documentation I cannot wait to give it a try!

I have not used it yet though so I cannot recommend it from experience.

Elm-review 2.3.0 - "Just try it out"

via Elm - Latest posts by @jfmengels Jeroen Engels on Tue, 08 Sep 2020 11:05:17 GMT

This is an exciting release for elm-review, for both the CLI and the Elm package!

Highlights:

  • Running elm-review without configuring it
  • Being able to select which rules to run
  • Performance improvements thanks to elm-serialize
  • Having access to more data when running a rule
  • New rule to detect unused arguments of custom type constructors

 newer latest older