Is it possible to create a Cmd that sends no message on completion in Elm?
Specifically, I am trying to have an element grab the focus (programmically), but I don't need to be informed of the result:
Dom.focus "element-id"
|> Task.attempt FocusReceived
...
FocusReceived result ->
model ! [] -- result ignored
Is there any way to just have the Elm "engine" not send a message after this Cmd?
I know that my code (FocusReceived result -> model ! []) is a no-op, but I would like the message not to be sent at all.
No, a Msg is always required. It is a common idiom in typical Elm projects to include a Msg type constructor that does nothing named NoOp.
type Msg
= NoOp
| ...
The update function does what FocusReceived in your example does, namely, nothing.
case msg of
NoOp ->
model ! []
...
Related
Can I use antlr v4 for syntax check before I actually run the code?
Example :
I defined syntax: select * from table, I want to know the statement is correct or not before actually executing it.
Following is my code :
val listener = new SQLListener()
val loadLexer = new SQLLexer(new ANTLRInputStream(input))
val tokens = new CommonTokenStream(loadLexer)
val parser = new SQLParser(tokens)
val stat = parser.statement()
I tried but DefaultErrorStrategy won't throw an Exception
I tried this:
parser.addErrorListener(new BaseErrorListener {
override def syntaxError(recognizer: Recognizer[_, _ <: ATNSimulator],
offendingSymbol: scala.Any,
line: Int,
charPositionInLine: Int,
msg: String, e: RecognitionException ): Unit = {
println("==========2============"+msg)
throw new AssertionError("line: " + line + ", offset: " + charPositionInLine +
", symbol:" + offendingSymbol + " " + msg)
}
})
but get this:
Error: Note: the super classes of contain the following, non final members named syntaxError:
If the input contains any syntax errors, this will call the visitErrorNode method on the listener. So if you define that method in your listener, you'll see any errors that occur.
If your listener is directly executing the code (rather than first building an AST or other form of IR), you probably won't want your listener to even start executing when there's a syntax error. One way to achieve that would be to set the BailErrorStrategy instead of the DefaultErrorStrategy as the error handling strategy of your parser (using setErrorHandler on the parser). This will throw an exception as soon as a syntax error occurs.
If you don't want to abort on the first error and/or you want some additional checks beyond just syntax errors (like checking for certain types of semantic errors), an alternative is to have a listener just to perform those checks. Then you'd run your code-executing listener only if the error-checking listener does not find any errors.
You are on the right track here. Use your error listener to store the errors in a list while parsing. Afterwards you can then check that list.
That requires however not to do any action during the parsing process (e.g. in a parse listener) other than stuff related to the parsing process itself. Any follow up action (e.g. error markup in an editor) should be done after the parse run.
If you like to see an example of an application using this approach take a look at the parser module implementation of MySQL Workbench. It also demonstrates the 2-stage parsing strategy for quicker parsing.
I've been trying to figure out a way to test the following piece of code (in Elixir):
defmacro __using__(_) do
quote do
# API functions will be used from this client
import Client.API
def list_storages do
case list_buckets do
{:ok, res} ->
case res.status_code do
200 ->
res.body
|> Friendly.find("name")
|> Enum.map(fn bucket -> bucket.text end)
_ ->
res |> show_error_message_and_code
end
{:error, reason} ->
parse_http_error reason
end
end
...
The problem is the list_buckets function is being import from the Client.API module (that's already being tested in another project which I can't really change anything there). My idea was to stub/mock/dummy the API functions so that they return just a dummy reply. I've tried using defoverridable to override the list_buckets function but that doesn't work since the function definition is happening in another module.
I've read the following post by José Valim and that has helped test the Client.API module but I don't find a way to apply those concepts to this particular problem.
My only (and stupid) idea so far is to just reimplement every function inside the macro in a test file and use a dummy API function defined there but that feels very wrong and not helpful if there are code changes in the non-testing code.
Basically I want to test if the three possible cases are correct:
Receiving {:ok, res} and code 200 -> Outputs the correct data
Receiving {:ok, res} and another code -> Output the error message and code
Receiving {:error, reason} -> parses the HTTP error and outputs the reason for failure
Can anyone help me with this?
You can still use the principles from that blog post. Instead of importing Client.Api pass it as a last variable to list_storages.
def list_storages(api \\ Client.Api) do
case api.list_buckets do
This way you don't need to change anything in your application code and you can pass dummy mock when testing the function.
I declared update function:
update : Action -> Model -> (Model, Effects.Effects Action)
And my model is:
model = Signal.foldp update init actions.signal
But Signal.foldp expects update function with Action -> Model -> Model shape.
Effect is POST call with code:
Http.post Json.Decode.string "http://localhost/tracker/link-admin/test.php" body
|> Task.toMaybe
|> Task.map SetShortenedUrl
|> Effects.task
I have two questions:
how can I run effect from update?
how can I change my model to type check?
Thanks!
If you're going to be using Effects without StartApp, at some point you'll need to use Effects.toTask, which requires a mailbox that can accept a list of actions.
Note that the documentation of Effects.toTask warns away from its explicit use except by expert hands (full disclosure: I am no expert) and at most once per app, but I'm going to pick it apart here anyways as an exercise in understanding StartApp.
Using the StartApp source code as our guide, we can pick out just the bare minimum we need to get your example running. First off, we have to deal with the pesky mailbox problem by defining a second mailbox called messages that takes a list of actions.
messages =
Signal.mailbox []
Now, we have to redefine your actions mailbox in terms of this new messages mailbox, using only the first element of the list, or NoOp in case of an empty list. (Read up on Effects.toTask to understand why it is a list, and why we're ok in this example to treat it as a singleton list)
actions : Signal.Mailbox Action
actions =
let
singleton action =
[action]
fromList list =
case list of
[] -> NoOp
(action::_) -> action
in
{ address = Signal.forwardTo messages.address singleton
, signal = Signal.map fromList messages.signal
}
We'll need a new Signal to deal with Effects so we can split out the processing in the update function from the tasks which we'll soon send to a port. Again, picking snippets from StartApp, we can define the following signal
effectsAndModel : Signal (Model, Effects.Effects Action)
effectsAndModel =
let
updateJustModel action (model,_) = update action model
in
Signal.foldp updateJustModel init actions.signal
Now that we have the above effectsAndModel signal, we can now redefine your model signal by just peeling off the Model from the first element of the tuple.
model : Signal Model
model =
Signal.map fst effectsAndModel
Likewise, we can use the effectsAndModel signal to send the tasks out a port by peeling off the Effects from the second element of the tuple:
port tasks : Signal (Task.Task Effects.Never ())
port tasks =
Signal.map (Effects.toTask messages.address << snd) effectsAndModel
The above port, tasks is where the Effects.toTask happens which required the redefining of your actions mailbox.
I've created a simple working example with an ad hoc view method to verify your requirements at this gist. I changed it to look for a local test.txt file rather than your url.
I'm trying to fetch a json from an url and parse it in elm, following the Reactivity tutorial. But for some reason my code doesn't do anything. I'm using Debug.watch to see if anything happens.
I have the following code:
emailUrl : String
emailUrl = some url
port fetchEmails : Task Http.Error ()
port fetchEmails =
Http.getString (Debug.watch "url" emailUrl) `andThen` parseEmails
parseEmails : String -> Task x ()
parseEmails json =
let result = Json.Decode.decodeString Static.emailDecoder json
in case result of
...
The code compiles, but doesn't seem to do anything. I'm very new to elm, so I'm a bit stuck here. How should this work?
Edit: turns out it was working, but as the answer stated the Debug.watch does not work with ports yet. I was also getting a 'cross-origin request blocked', which explains why it couldn't get the json.
Thanks!
The Elm time traveling debugger does not play well with ports yet.
Please use Debug.log and check you JavaScript Console.
Sometimes I want to filter out certain errors in a stream. I'd like to write something like this:
stream
.filterError (error) ->
error.type is 'foo'
But there is no filterError method.
As an alternative I thought I could use errors().mapError to map the errors into values, filter them, and then map them back into errors. However, I don't see a way to convert a value in a stream into an error.
# Filter only the errors we are interested in
errors = stream.errors()
.mapError (error) ->
error
.filter (error) ->
...
.mapValuesBackIntoErrors() # ?
The idea is that the stream in question either carries a value or an error. Both represent domain knowledge; the value means the system is in normal operation and the error means we have a domain error. Some of the domain errors are not such that we want to carry them, though, so I wish to filter them out.
The alternative works, of course, and you may use a combination of map and mapError to wrap normal values and errors in the style of the Either type in Haskell. For instance
stream.map((value) -> { value }).mapError((error) -> { error })
Now your stream would output something like this:
{ value: 1 }
{ value: 2 }
{ error: "cannot connect to host" }
On the other hand, actually implementing filterError wouldn't be too hard. Consider implementing this yourself and making a PR.