Feed Aggregator Page 652
Rendered on Tue, 29 Sep 2020 02:03:40 GMT
Rendered on Tue, 29 Sep 2020 02:03:40 GMT
via Elm - Latest posts by @cmanallen C. Allen on Tue, 29 Sep 2020 01:04:29 GMT
Hi,
I’m trying to make a simple money app with Elm 1.19.1. When a user enters a value in the input I’m setting that value on the model. I’m also re-painting the input with the value that was just entered. Meaning if the user provided something invalid then it will default to something other than what they entered.
This works great for integers. But for floats something like “32.” instantly breaks because the period is removed by the update function (String.toFloat |> Maybe.withDefault model.value
). I’m wondering what is the best way to manage this?
type Model alias = { value : Float }
type Msg = SetValue String
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SetValue val ->
( { model | value = val |> String.toFloat |> Maybe.withDefault model.value }, Cmd.none )
view : Model -> Html Msg
view model =
input [ onInput SetValue, value model.value ] [ ]
I don’t want to store it as a string on the model because I feel like I lose that free validation. But I don’t know. Whats the best practice here?
via Elm - Latest posts by @jreusch Joshua on Mon, 28 Sep 2020 21:05:54 GMT
Basics.logBase
is implemented as log number / log base
, where log
is just Math.log
from Javascript. The rounding errors you are seeing comes from the floating-point division happening here.
There also exists Math.log10
in Javascript, which yields better results, but does not exist in Internet Explorer. As always, there already exists an issue matching your problem, and a pull request proposing to use said javascript function.
via Planet Lisp by on Mon, 28 Sep 2020 18:29:40 GMT
The latest SBCL handles slot
:initform
and :type
options in a new way. It’s mentioned in the
release notes.
minor incompatible change: the compiler signals a warning at compile-time when an initform of T, NIL or 0 does not match a STANDARD-CLASS slot’s declared type._
Sounds pretty benign, but it breaks dozens of projects in Quicklisp. (To be fair, most of the failures are caused by a small number of core systems on which many other systems depend.)
Here’s an example of the new behavior:
(defclass foo ()
((name :type string :initform nil)))
With the above defclass form, SBCL 2.0.9 will signal a warning at compile time:
; processing (DEFCLASS FOO ...)
; file: foo.lisp
; in: DEFCLASS FOO
; (NAME :TYPE STRING :INITFORM NIL)
; ==>
; (SB-KERNEL:THE* (STRING :SOURCE-FORM NIL :USE-ANNOTATIONS T) NIL)
;
; caught WARNING:
; Constant NIL conflicts with its asserted type STRING.
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
This compile-time warning means “failure” as far as loading with ASDF is concerned.
If you have both :type
and :initform
in your slot definitions, and
you want to be compatible with the latest SBCL, make sure the initform
type matches the slot type. If you want to use NIL as the initform,
one easy option is to set the type to (or null <actual type>)
.
via Elm - Latest posts by @stevensonmt Stevensonmt on Mon, 28 Sep 2020 19:43:16 GMT
Yes, there are other ways to approach my particular problem but the link you provided includes the method I’m using. My specific use case is orthogonal to the problem of a potentially fundamental bug in a basic arithmetic function. The appearance of a pattern suggests to me that the error is not simply “floating point math is quirky” but rather something that can be fixed. I would create an issue on github to address this if others can confirm the bug.
via Zach Beane Common Lisp by on Mon, 28 Sep 2020 18:29:40 GMT
The latest SBCL handles slot
:initform
and :type
options in a new way. It’s mentioned in the
release notes.
minor incompatible change: the compiler signals a warning at compile-time when an initform of T, NIL or 0 does not match a STANDARD-CLASS slot’s declared type._
Sounds pretty benign, but it breaks dozens of projects in Quicklisp. (To be fair, most of the failures are caused by a small number of core systems on which many other systems depend.)
Here’s an example of the new behavior:
(defclass foo ()
((name :type string :initform nil)))
With the above defclass form, SBCL 2.0.9 will signal a warning at compile time:
; processing (DEFCLASS FOO ...)
; file: foo.lisp
; in: DEFCLASS FOO
; (NAME :TYPE STRING :INITFORM NIL)
; ==>
; (SB-KERNEL:THE* (STRING :SOURCE-FORM NIL :USE-ANNOTATIONS T) NIL)
;
; caught WARNING:
; Constant NIL conflicts with its asserted type STRING.
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
This compile-time warning means “failure” as far as loading with ASDF is concerned.
If you have both :type
and :initform
in your slot definitions, and
you want to be compatible with the latest SBCL, make sure the initform
type matches the slot type. If you want to use NIL as the initform,
one easy option is to set the type to (or null <actual type>)
.
via Elm - Latest posts by @Yannick971 Yannick on Mon, 28 Sep 2020 18:47:22 GMT
That is good advice… thank you!
via Elm - Latest posts by @evancz Evan on Mon, 28 Sep 2020 16:07:54 GMT
I should add, I do not actually know what Svelte is doing specifically. I would personally be interested in seeing a little breakdown of their key techniques. Maybe there are lessons that could be applied in Elm. Would be very curious to understand more!
And maybe it’s something that could be explored in the style of elm-optimize-level-2
so that it is not blocked on compiler releases or anything.
via Elm - Latest posts by @system system on Mon, 28 Sep 2020 15:46:13 GMT
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
via Elm - Latest posts by @duncanmalashock Duncan Malashock on Mon, 28 Sep 2020 13:21:17 GMT
I was fifteen and on a trip with my family in Minocqua, Wisconsin when I heard “Slumber Song” by Glenn Miller on a local radio station one night.
I had never heard music like it before. It was intelligent and organized, with great warmth and sensitivity. It sparked my interest in the technique I now know as sectional harmony, in which most of the melodies in a piece are harmonized into multiple parts and played together by groups of instruments. In this case, these are the trumpet, trombone, saxophone, and vocal sections.
Many years later, wanting to apply these techniques to my own music, I started taking private lessons from a jazz arranger. As I began to understand the various concepts that made up this obscure and specialized field, like voicing types, approach techniques, and available tensions, I saw how much attention and mental energy is required in order to apply them.
For instance, in any given situation when harmonizing a melody, an arranger generally has to ask themselves the following questions:
None of these questions can be answered simply. Students work for years to improve their facility with arrangement techniques and develop their musical judgment.
The question of the best choice requires a musical sensibility to answer, but the others are questions of generating musical structures and validating them against certain criteria. Could those parts of this work be automated for an arranger’s benefit?
Today I’m happy to announce the initial release of elm-music-theory
, a new music theory library for the Elm language and the result of my work to answer this question.
elm-music-theory
allows you to work with musical concepts like pitches, intervals, chords, keys, and scales. This includes (but is not limited to) the tasks involved in arranging sectional harmony.
For instance, if you were an arranger trying to harmonize the melody to “Slumber Song”, you could use elm-music-theory
to generate a list of chord voicings that included the current melody note in the top voice, and sort them by various musical criteria to find the most viable options:
voicings =
Music.Chord.voiceFivePart
{ voiceOne = Music.Range.clarinet
, voiceTwo = Music.Range.altoSax
, voiceThree = Music.Range.tenorSax
, voiceFour = Music.Range.tenorSax
, voiceFive = Music.Range.baritoneSax
}
[ Music.Voicing.FivePart.close ]
(Music.Chord.majorSix Music.PitchClass.d)
|> List.filter (Music.Voicing.FivePart.containsPitchInVoiceOne Music.Pitch.d5)
This could save you time, reveal options you might not have considered, and help you focus on your high-level goals.
To my knowledge, elm-music-theory
is the first library of its kind to treat the topic of voicing chords in a structured way that reflects an arranger’s process.
I have made every effort to model the concepts I have chosen for this first release as accurately as I could. Because of this design effort, I believe elm-music-theory
provides not only a foundation for arranging harmony, but also one that supports many other potential musical applications, such as harmonic analysis, writing counterpoint, and generating music procedurally.
Take a look at the examples that cover analyzing and transposing the chord progression in a song and generating four-part chord voicings.
And if these terms are new to you, here are some learning resources for getting acquainted with the music theory concepts modeled in this library.
Music theory is a large topic, and although I feel elm-music-theory
is a solid foundation, it does not provide immediate support for more complex musical use cases.
Here are a few I am working on:
Rhythmic values and time-based structures: Right now this library does not support notes with durations, or structures for organizing them, such as measures, staves, or systems. These features will eventually allow easier generation and manipulation of musical compositions.
Melodic lines and sequences: It is possible to analyze a melodic line and generate variations on it. These variations are known in musical terms as sequences, and they are an important compositional tool for developing a melody. I’m excited for this library to support this in the future, since it has a lot of potential for compositional applications.
Chord progressions with key changes: elm-music-theory
already supports Roman numeral analysis of chords in a single key. But with a concept of harmonic movement across key changes, there will be potential to identify more harmonic relationships and to represent more sophisticated harmonic plans, which will be helpful for generating compositions procedurally.
Voicings for polyphonic instruments: This initial release has focused much attention on voicing chords for small groups of monophonic instruments. Chord voicings for polyphonic instruments (like the guitar and the piano) are subject to different principles and constraints, and these will need to be modeled separately for these cases to be well-served by this library.
I hope you enjoy elm-music-theory
! Feel free to reach out to me at @duncan
on the Elm Slack about your projects and questions.
Originally posted at dmalashock.com
via Elm - Latest posts by @rupert Rupert Smith on Mon, 28 Sep 2020 10:07:10 GMT
I don’t think it could work because even with pizzas, you still need parenthesis sometimes. For example, I recently wrote a parsing package, and as I cannot export |.
and |=
, I have to use |> ignore
or |> keep
, leading to code like this:
PR.succeed identity
|> PR.ignore PR.spaces
|> PR.keep (PR.int ExpectingInt InvalidNumber |> PR.map Just)
|> PR.ignore PR.spaces
|> PR.ignore (PR.symbol "," ExpectingComma |> PR.optional ())
|> PR.ignore PR.spaces
|> PR.forwardOrSkip Nothing [ "," ] ExpectingSpace Discarded
to work around having no parenthesis, I would need to use more let..in
blocks:
let
parseInt =
PR.int ExpectingInt InvalidNumber
|> PR.map Just
parseComma =
PR.symbol "," ExpectingComma
|> PR.optional ()
in
PR.succeed identity
|> PR.ignore PR.spaces
|> PR.keep parseInt
|> PR.ignore PR.spaces
|> PR.ignore parseComma
|> PR.ignore PR.spaces
|> PR.forwardOrSkip Nothing [ "," ] ExpectingSpace Discarded
Maybe that is actually more readable, and perhaps if I was tidying up some code I might even do that. But I could see it being very annoying at the time when you are writing a pipeline, as usually at that point you are just trying to sequence a load of stuff together in order, and don’t want the cognitive interruption of having to create another let..in
block (and then delete it again, when you realize you didn’t need it, and then put it back again when you realize you really did…).
I do agree pipelines can be harder to read sometimes, but so handy when you are just trying to figure out something complicated that need to combine sequencing and transformation.
via Elm - Latest posts by @opvasger Asger Nielsen on Mon, 28 Sep 2020 09:54:48 GMT
To me, choosing between <|
and |>
is the crux of it all, and not so much whether or not I use them.
favoring <|
means that I read function application in the same direction whether I use parenthesis or pipes. This is very important for me, as I won’t have to mentally switch reading-direction when looking at function-applications.
I get that |>
feels natural, but I don’t like the trade-off.
via Elm - Latest posts by @pdamoc Peter Damoc on Mon, 28 Sep 2020 09:51:38 GMT
I guess it should be:
main =
Browser.element
{ init = \_ -> ( initialModel, initialCmd initialModel)
It is advisable to give functions as little data as possible so. Keep the functions small and with parameters as simple as possible.
So… instead of getTimestamps: Model -> Cmd Msg
where you would extract some data from the mode, prefer getTimestamps: Int -> Cmd Msg
.
via Elm - Latest posts by @pdamoc Peter Damoc on Mon, 28 Sep 2020 09:17:35 GMT
It’s a sect of the Hindley–Milner church.
via Elm - Latest posts by @mattpiz Matthieu Pizenberg on Mon, 28 Sep 2020 06:24:03 GMT
Float arithmetic is subject to this kind of issues. If I had to count the number of digits of a number, I’d use recursive integer division by 10 such as https://www.geeksforgeeks.org/program-count-digits-integer-3-different-methods/
via Elm - Latest posts by @berend Berend de Boer on Mon, 28 Sep 2020 04:27:13 GMT
This hasn’t been released yet is it? I currently really need something like this!
via Elm - Latest posts by @Yannick971 Yannick on Mon, 28 Sep 2020 00:01:22 GMT
Alright so I tried and got stuck here:
getTimestamps: Int -> Cmd Msg
in my example the time value is in the Main Model so it would be:
getTimestamps: Model -> Cmd Msg
but its the same thing…
The compiler complains because the initialCmd should be of type Cmd
and not Model -> Cmd Msg
in main:
main =
Browser.element
{ init = \_ -> ( initialModel, initialCmd )
via Elm - Latest posts by @stevensonmt Stevensonmt on Sun, 27 Sep 2020 22:55:48 GMT
I’m using Basics.logBase
and am getting a surprising result.
logBase 10 1000
returns 2.9999999999999996
. This is problematic for my overall algorithm as I am expecting to be able to use floor
to accurately find how many digit “places” I need. Any way I can get logBase 10 1000
to return 3
as expected?
On further investigation, this issue appears to affect every value of 10^x
where x%3 == 0
.
via Elm - Latest posts by @system system on Sun, 27 Sep 2020 21:04:40 GMT
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
via Elm - Latest posts by @DullBananas on Sun, 27 Sep 2020 20:25:29 GMT
If there were no parenthesis, let statements would be used more. Might be a good thing but things like map3
wouldn’t work well with this
via Elm - Latest posts by @Chadtech Chadtech on Sun, 27 Sep 2020 20:07:02 GMT
Since pipes and parentheses are substitutes, it seems like teams have to agree on one or the other to avoid having different ways of doing the same thing. And, I think parentheses usually win because everyone is familiar with them, while only a smaller and more hardcore group is addicted to the pizza operators.
So, I have wondered, what would that look like if a team went 100% pizza. And “No parentheses” was their style. What if Elm removed parentheses? Could it work?