I am trying to remove left recursion from following grammar:
S -> id = E
S -> id [ E ] = E
E -> E [ E ]
E -> id
I tried to follow the left recursion removal algorithm that is presented at https://en.wikipedia.org/wiki/Left_recursion, but the E -> E [ E ] line gives me problems, how should it be handled?
I do not want to get a complete solution to this, just some hints so I can actually learn how this works.
What I have tried so far is this:
E -> E [ E ]
E -> id
becomes:
E -> id E'
E' -> [ E ] E'
Which is incorrect. Am I even on the right track here ?
Following the algorithm you linked to, you want A -> Aα | β and you have
E -> E [ E ] | id
so A is E, α is [ E ] and β is id. The result of removing left recursion is A -> β A' and A' -> ε | α A', so you get the rules:
E -> id E'
E' -> ε | [ E ] E'
So it looks like you got the right result, you just left out the E' -> ε rule...
Related
I am new to Elm. I am not able to call the update function once the dropdown value changes.
Scenario:
I have two dropdowns Grade and Environment. What I want is when Grade dropdown values change, the options of Environment dropdown will dependently change.
For example, if Grade dropdown value is 3 then the options of Environment should change to Imagine Math
gradeDropdown : String -> List String -> Html Msg
gradeDropdown grade grades =
let
buildOption =
gradeOption grade
in
select [ class "importWizard--gradeSelection", name "gradeSelection", onChange (UpdateStudent Grade) ]
(map buildOption grades)
gradeOption : String -> String -> Html Msg
gradeOption optSelectedVal temp =
let
optSelected =
temp == optSelectedVal
in
option [ value temp, selected optSelected ] [ text temp ]
environmentDropdown : Model -> String -> List String -> String -> Html Msg
environmentDropdown model learningEnvironment learningEnvironments selectedGrade =
let
buildOption =
environmentOption model learningEnvironment
blueprint_grades = ["PreKindergarten", "Kindergarten", "1"]
environmentDropdownOption =
if (selectedGrade == "" || (List.member selectedGrade blueprint_grades)) then
["Blueprint"]
else if (selectedGrade == "2") then
learningEnvironments
else
["Imagine Math"]
in
select [
class "importWizard--learningEnvironmentSelection"
, name "learningEnvironmentSelection"
, onChange (UpdateStudent LearningEnvironments)
]
(map buildOption environmentDropdownOption)
environmentOption : Model -> String -> String -> Html Msg
environmentOption model optSelectedVal temp =
let
optSelected =
temp == optSelectedVal
in
option [ value temp, selected optSelected ] [ text temp ]
And in Update
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
update flags message model =
case message of
UpdateStudent updateType newValue ->
let
validate =
validateStudent flags validatableFieldsForScreen
in
case updateType of
LastName ->
( validate { model | lastName = newValue } <| Just LastNameField, Cmd.none )
FirstName ->
( validate { model | firstName = newValue } <| Just FirstNameField, Cmd.none )
Sin ->
( validate { model | sin = newValue } <| Just SinField, Cmd.none )
Grade ->
( validate { model | grade = newValue, selectedGrade = newValue } Nothing, Cmd.none )
LearningEnvironments ->
( validate { model | learningEnvironments = newValue } Nothing, Cmd.none )
View:
, td [ class wizardTableInput ] [ gradeDropdown model.grade flags.grades ]
, td [ class wizardTableInput ] [ environmentDropdown model model.learningEnvironments flags.learningEnvironments model.selectedGrade ]
In this code, the environment dropdown's value is changing, however the model's value is not updated. From what I understand, I can see is environment dropdown's id re-rendered, but it is not updating the model's value of learningEnvironments. This means it is not executing the update function matching LearningEnvironments.
select widgets where the options change is one of the use cases for Html.Keyed.node
Use a helper function like the one bellow:
keyedSelect : (String -> a) -> String -> List ( String, String ) -> Html a
keyedSelect message selectedValue kvs =
let
toOption ( k, v ) =
( k
, option
[ value k
, selected (k == selectedValue)
, disabled (k == "-1")
]
[ text v ]
)
in
Keyed.node "select"
[ class "form-control", onChange message ]
(List.map toOption kvs)
I usually have a "Please select Foo" first option with the value -1 if the user never selected any of the options. This is why the code checks for -1 and disables the option. You can remove the disabled attribute if you don't need it.
I have a report which I'm using as a basis to perform a number of Http calls to get details for each row.
LoadReport ->
( model
, Http.toTask (loadReport model.token model.page)
|> Task.andThen
(\report ->
Task.map (addProductDetailsResultsToReport report) (Task.sequence (prepareRequests model.token report))
)
|> Task.map filterOnlyMissingBarcodes
|> Task.attempt ProductData
)
The calls are sequenced and perform one after another which is very slow as I need to perform 20 calls in a row. I would like to do something analogues to JavaScript
Promise.all(prepareRequests)
I used to have them being processed using Cmd.Batch but then I couldn't find a way to know when the whole batch is finished loading, I need to load another batch if there are not enough rows on the screen.
I believe the solution already posted by Murph is correct. The following code is an example that demonstrates that solution by first getting a collection of photos from flickr and then getting captions for all those photos by batching a bunch of http get tasks. Two lists are maintained in the model - untitled photos and titled photos. As the responses to the http gets come in, the appropriate photo is added to titled photos with the title assigned.
In this example the code can tell that all the gets have been responded to when the length of the titled list is the same as the length of the untitled list but it could just as easily have been done by removing photos from the untitled list until it is empty.
Here's a working demo
module Main exposing (..)
import Browser
import Html exposing (Html, div, text)
import Html.Attributes as HA
import Http
import Json.Decode as DC
import Svg
import Svg.Attributes as SA
import Task
type Msg
= SetPhotos (Result Http.Error (List Photo))
| SetDescription (Result Http.Error ( String, String ))
main : Program () Model Msg
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = \m -> Sub.none
}
type alias Model =
Result Http.Error
{ untitled : List Photo
, titled : List Photo
}
decodeUser : DC.Decoder String
decodeUser =
DC.at [ "user", "id" ] DC.string
type alias Photo =
{ id : String
, secret : String
, server : String
, farm : Int
, description : Maybe String
}
-- Create a Photo record from info retrieved from flickr api.
-- Get description later
initPhoto : String -> String -> String -> Int -> Photo
initPhoto id sec ser farm =
Photo id sec ser farm Nothing
decodePhotoList : DC.Decoder (List Photo)
decodePhotoList =
DC.list <|
DC.map4 initPhoto
(DC.at [ "id" ] DC.string)
(DC.at [ "secret" ] DC.string)
(DC.at [ "server" ] DC.string)
(DC.at [ "farm" ] DC.int)
-- Decode photos from "flickr.people.getPublicPhotos" request.
decodePhotos : DC.Decoder (List Photo)
decodePhotos =
DC.at [ "photos", "photo" ] decodePhotoList
-- Decode descripion of photo from "flickr.photos.getInfo" request.
decodePhotoDescription : DC.Decoder String
decodePhotoDescription =
DC.at [ "photo", "description", "_content" ] DC.string
-- api key from flickr. Anyone who clones this project should
-- get their own api key.
apiKey : String
apiKey =
"e9d3fdd5c2e26f9ebd13f4983cf727db"
flickrRestServices : String
flickrRestServices =
"https://api.flickr.com/services/rest/?"
noJsonCallback : String
noJsonCallback =
"&format=json&nojsoncallback=1"
userUrl : String -> String
userUrl name =
flickrRestServices
++ "&method=flickr.people.findByUserName"
++ "&api_key="
++ apiKey
++ "&username="
++ name
++ noJsonCallback
publicPhotosUrl : String -> String
publicPhotosUrl uid =
flickrRestServices
++ "&method=flickr.people.getPublicPhotos"
++ "&api_key="
++ apiKey
++ "&user_id="
++ uid
++ noJsonCallback
photoInfoUrl : String -> String
photoInfoUrl photo =
flickrRestServices
++ "&method=flickr.photos.getInfo"
++ "&api_key="
++ apiKey
++ "&photo_id="
++ photo
++ noJsonCallback
-- Cmd to get photo description from flickr.
-- Package results as SetDescription message.
-- Save the photo id with Task.map to apply the description to the right photo
setDescriptionCmd : Photo -> Cmd Msg
setDescriptionCmd dp =
case dp.description of
Nothing ->
Task.attempt SetDescription (Task.map (\s -> ( dp.id, s )) <| Http.toTask <| Http.get (photoInfoUrl dp.id) decodePhotoDescription)
Just des ->
Cmd.none
-- Cmd to get users public photos from flickr.
-- Package results as SetPhotos message.
getPhotosCmd : String -> Cmd Msg
getPhotosCmd name =
let
req =
Http.get (userUrl name) decodeUser
userTask =
Http.toTask req
publicPhotosTask uid =
Http.toTask (Http.get (publicPhotosUrl uid) decodePhotos)
userPhotosTask =
userTask |> Task.andThen publicPhotosTask
in
Task.attempt SetPhotos userPhotosTask
init : () -> ( Model, Cmd Msg )
init _ =
( Ok
{ untitled = []
, titled = []
}
, getPhotosCmd "elmDemo" -- flickr user name
)
-- UPDATE
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SetPhotos (Ok photos) ->
( Ok
{ untitled = photos
, titled = []
}
, Cmd.batch <| List.map setDescriptionCmd photos
)
SetPhotos (Err e) ->
( Err e
, Cmd.none
)
-- Update description of the photo with matching id.
SetDescription (Ok ( photoId, desc )) ->
case model of
Ok photos ->
let
justTitled =
photos.untitled
|> List.filter (\ph -> ph.id == photoId)
|> List.map (\ph -> { ph | description = Just desc })
newTitled = photos.titled ++ justTitled
newPhotos = { photos | titled = newTitled }
in
( Ok newPhotos
, if
List.length newPhotos.titled
== List.length newPhotos.untitled
then
Cmd.none -- Could do something else here.
else
Cmd.none
)
Err e ->
( Err e
, Cmd.none
)
SetDescription (Err e) ->
( Err e
, Cmd.none
)
-- Compute a photo URL from a Photo record.
-- per: https://www.flickr.com/services/api/misc.urls.html
photoUrl : Photo -> String
photoUrl ps =
"https://farm"
++ String.fromInt ps.farm
++ ".staticflickr.com/"
++ ps.server
++ "/"
++ ps.id
++ "_"
++ ps.secret
++ "_b.jpg"
-- show an image and description if available.
viewPhoto : Photo -> Html Msg
viewPhoto ps =
div
[ HA.style "height" "20%"
, HA.style "width" "20%"
, HA.style "margin" "0"
]
[ div
[ HA.style "height" "90%"
, HA.style "width" "100%"
, HA.style "margin" "0"
]
[ Svg.svg
[ SA.version "1.1"
, SA.width "100%"
, SA.height "100%"
, SA.viewBox "-1 -0.6 2 1.2"
, SA.preserveAspectRatio "none"
]
[ Svg.image
[ SA.xlinkHref (photoUrl ps)
, SA.x "-1"
, SA.y "-0.6"
, SA.width "2"
, SA.height "1.2"
]
[]
]
]
, div
[ HA.style "height" "10%"
, HA.style "width" "100%"
, HA.style "margin" "0"
]
[ div
[ HA.style "text-align" "center" ]
[ text <| Maybe.withDefault "" ps.description ]
]
]
-- Draw an image or display the reason the image is not available.
view : Model -> Html Msg
view model =
case model of
Err s ->
text "Error: "
Ok photos ->
div []
[ div [] [ text "UNTITLED" ]
, div [] (List.map viewPhoto photos.untitled)
, div [] [ text "TITLED" ]
, div [] (List.map viewPhoto photos.titled)
]
Random thought:
Given that you will get a response back for each call you can keep track of the calls received by creating a collection of expected responses before calling batch and then removing the appropriate item from the collection each time a response is received.
At the point at which that collection is empty you've received all the responses and can fire off the next batch.
There are any number of variations on this pattern that should achieve the desired result. (And probably other patterns that would work just as well.)
I have an array containing several dictionaries. How can I sorted them using a key that each dictionary have like age?
an Array((a Dictionary('age'->'20' 'ID'->1254))(a Dictionary('age'->'35' 'ID'->1350))(a Dictionary('age'->'42' 'ID'->1425)))
You can sort by providing a comparator block; the block takes two arguments (two elements from the array) and is expected to return boolean.
data := {
{ 'age' -> '20'. 'ID' -> 1254 } asDictionary.
{ 'age' -> '35'. 'ID' -> 1350 } asDictionary.
{ 'age' -> '42'. 'ID' -> 1425 } asDictionary
}.
sorted := data sorted: [ :a :b | (a at: 'age') > (b at: 'age') ].
sorted: will return a sorted collection without changing the receiver
sort: will perform the sorting in-place and return itself
You can also use asSortedCollection: which will create a new collection that always upholds the sorting invariant.
sc := data asSortedCollection: [ :a :b | (a at: 'age') > (b at: 'age') ].
"automatically inserted between age 42 and 35"
sc add: {'age' -> '39'. 'ID' -> 1500} asDictionary.
sc "a SortedCollection(a Dictionary('ID'->1425 'age'->'42' ) a Dictionary('ID'->1500 'age'->'39' ) a Dictionary('ID'->1350 'age'->'35' ) a Dictionary('ID'->1254 'age'->'20' ))"
Let's say I have a select element to choose a person, and I want to have a certain person, say with id = 3, to be initially selected. How do I pass this id down into my options, and then set the selected attribute to True in that options?
Some sample code:
personSelect : List Person -> String -> Html Msg
personSelect : personList selectedId =
div []
[ select [] (List.map personOption personList) ]
personOption : Person -> Html Msg
personOption : person =
option [ value (toString person.id) ] [ text person.name ]
Specifically, how do I get "selectedId" passed to "personOption"? Can I even do this using List.map?
Thanks very much!
Provide selectedId as an argument to personOption and exploit that you can partially apply functions in Elm. That is, when you give a function some but not all of the arguments that it needs, you get back a function waiting for the remaining arguments.
First, add selectedId to personOptions and render the option as selected if it matches.
personOption : String -> Person -> Html Msg
personOption selectedId person =
option
[ selected (selectedId == person.id)
, value (toString person.id)
]
[ text person.name ]
Then partially apply personOption by giving it its first argument before passing it on to map:
personSelect : List Person -> String -> Html Msg
personSelect personList selectedId =
div []
[ select []
(List.map (personOption selectedId) personList)
-- personOption selectedId : String -> Html Msg
]
I'm trying to create a dispatcher of functions in Rebol 3, so that for each string the program receives there's an associated function to be called.
For example:
handlers: make map! [
"foo" foo-func
"bar" bar-func
]
where foo-func and bar-func are functions:
foo-func: func [ a b ] [ print "foo" ]
bar-func: func [ a b ] [ print "bar" ]
The idea is to select the function starting from the string, so:
f: select handlers "foo"
so that executing f is the same as executing foo-func and then call f with some arguments:
f param1 param2
I tried quoting the words in the map!, or using get-words but without success.
Using a get-word! at the console, without passing through a map! it works:
>> a: func [] [ print "Hello world!" ]
>> a
Hello world!
>> b: :a
>> b
Hello world!
Any help appreciated.
select handlers "foo" only get the word foo-func:
f: select handlers "foo"
probe f ;will get: foo-func
You need to get its content:
f: get f
f 1 2 ;will print "foo"
Or more compact:
f: get select handlers "foo"
It's better to actually have the reference to the function in the map, rather than a word that refers to the function. If you store a word then you have to make sure the word is bound to an object which has a reference to that function, like this:
handlers: object [
foo-func: func [ a b ] [ print "foo" ]
bar-func: func [ a b ] [ print "bar" ]
]
handler-names: map [
"foo" foo-func
"bar" bar-func
]
apply get in handlers select handler-names name args
But if you just have a reference to the function in your map, you don't have to do the double indirect, and your code looks like this:
handlers: map reduce [
"foo" func [ a b ] [ print "foo" ]
"bar" func [ a b ] [ print "bar" ]
]
apply select handlers name args
Cleaner code, and more efficient too. Or if you're careful enough, like this:
handlers/(name) a b
The path method above will also work if you want the code to do nothing if there is no handler - common in cases where you have optional handlers, such as in GUIs.
You can even have more than one reference to the same function with different key names. You don't have to assign functions to words, they're just values. You can also use the path method to collect the handlers in the first place, saving a reduce.
handlers: make map! 10 ; preallocate as many entries as you expect
handlers/("foo"): func [ a b ] [ print "foo" ]
handlers/("bar"): func [ a b ] [ print "bar" ]
handlers/("baz"): select handlers "bar" ; multiple references
That path syntax is just another way to call poke, but some prefer it. We have to put the string values in parens because of a (hopefully temporary) syntax conflict, but within those parens the string keys work. It's a faster alternative to do select or poke.
foo-func in your map is just an unevaluated word
>> type? select handlers "foo"
== word!
You should first create your functions and then reduce the block, you use for creating your handler map so
handlers: make map! reduce [
"foo" :foo-func
"bar" :bar-func
]
then you have functions inside your map
>> type? select handlers "foo"
== function!
Try:
....
f: do select handlers "foo"
....