Temperature converter #125
Replies: 4 comments 1 reply
-
I also made a web version. Requires Bottle. (hissp.basic.._macro_.prelude)
(defmacro compile (: :* forms)
`',(enstr
#"<script type='text/python'>\n"
(.join #"\n" (map hissp.compiler..readerless forms))
"</script>"))
(define brython "
<script src='https://cdn.jsdelivr.net/npm/brython@3/brython.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/brython@3/brython_stdlib.js'></script>
")
(define form "
<input id='Fahrenheit' onkeyup='Fahrenheit()'><label for='Fahrenheit'>°F</label>
<br>
<input id='Celsius' onkeyup='Celsius()'><label for='Celsius'>°C</label>
")
(define temperature
((.route bottle. "/temperature")
(lambda :
(enstr
brython
"<body onload='brython()'>"
(compile
(hissp.basic.._macro_.prelude)
(define get-val-of
(lambda (id)
(-> browser..document (.getElementById id) (getattr 'value))))
(define set-to-val-of
(lambda (val id)
(-> browser..document (.getElementById id) (setattr 'value val))))
(define C->F
(lambda c
(-> c (float) (mul 1.8) (add 32))))
(define F->C
(lambda f
(-> f (float) (sub 32) (truediv 1.8))))
(attach browser..window
: Fahrenheit
(lambda : (-> "Fahrenheit" (get-val-of) (F->C) (set-to-val-of "Celsius")))
Celsius
(lambda : (-> "Celsius" (get-val-of) (C->F) (set-to-val-of "Fahrenheit")))))
form
"</body>"))))
(.run bottle. : host "localhost" port 8080 debug True) Does it really need to be that much longer? Perhaps a better design would be shorter. |
Beta Was this translation helpful? Give feedback.
-
Here's a somewhat more compact version. (hissp.basic.._macro_.prelude)
(define tag
(lambda (tag : :* contents)
(enstr "<"tag">"(enstr : :* contents)"</"(getitem (.split tag) 0)">")))
(defmacro <\# (form)
`(tag ,@form))
(defmacro script (: :* forms)
`',<#("script type='text/python'" #"\n"
(.join #"\n" (map hissp.compiler..readerless forms))))
(define BRYTHON
(let (s <#("script src='https://cdn.jsdelivr.net/npm/brython@3/brython{}.js'"))
(enstr (.format s ".min") (.format s "_stdlib"))))
(define FORM
(let (row (enstr <#("input id='{0}' onkeyup='{0}()'")
<#("label for='{0}'" "°{1}")))
(enstr (.format row "Fahrenheit" "F")"<br>"(.format row "Celsius" "C"))))
(define temperature
((bottle..route "/temperature")
(lambda :
(enstr
BRYTHON
<#("body onload='brython()'"
(script
(hissp.basic.._macro_.prelude)
(define getE (lambda (id) (.getElementById browser..document id)))
(define get@v (lambda (id) (getattr (getE id) 'value)))
(define set@v (lambda (val id) (setattr (getE id) 'value val)))
(define C->F (lambda c (-> c (float) (mul 1.8) (add 32))))
(define F->C (lambda f (-> f (float) (sub 32) (truediv 1.8))))
(attach browser..window
: Fahrenheit (lambda : (-> (get@v "Fahrenheit") (F->C) (set@v "Celsius")))
Celsius (lambda : (-> (get@v "Celsius") (C->F) (set@v "Fahrenheit")))))
FORM)))))
;; https://localhost:8080/temperature
(bottle..run : host "localhost" port 8080 debug True) Even a few function and macro definitions can make the language much more expressive. But is it more readable than before, or less? |
Beta Was this translation helpful? Give feedback.
-
New bottle version with new bundled macros (Hissp 0.4.dev2022-05-14) (hissp.._macro_.prelude)
(define enjoin en#X#(.join "" (map str X)))
(define tag
(lambda (tag : :* contents)
(enjoin "<"tag">"(enjoin : :* contents)"</"(get#0 (.split tag))">")))
(defmacro script (: :* forms)
`',(tag "script type='text/python'" #"\n"
(.join #"\n" (map hissp.compiler..readerless forms))))
(define temperature
((bottle..route "/temperature")
&#(enjoin
(let (s (tag "script src='https://cdn.jsdelivr.net/npm/brython@3/brython{}.js'"))
(enjoin (.format s ".min") (.format s "_stdlib")))
(tag "body onload='brython()'"
(script
(define getE X#(.getElementById browser..document X))
(define getf@v X#(float (@#value (getE X))))
(define set@v XY#(setattr (getE Y) 'value X))
(attach browser..window
: Celsius &#(-> (getf@v 'Celsius) (X#.#"X*1.8+32") (set@v 'Fahrenheit))
Fahrenheit &#(-> (getf@v 'Fahrenheit) (X#.#"(X-32)/1.8") (set@v 'Celsius))))
(let (row (enjoin (tag "input id='{0}' onkeyup='{0}()'")
(tag "label for='{0}'" "°{1}")))
(enjoin (.format row "Fahrenheit" "F")"<br>"(.format row "Celsius" "C")))))))
(bottle..run : host "localhost" port 8080 debug True) More condensed, but still quite a bit longer than the tkinter version. |
Beta Was this translation helpful? Give feedback.
-
Well, maybe not that much longer, but the tkinter version was a bit duplicated. This new tkinter version has most of that removed: (hissp.._macro_.prelude)
(define root (tkinter..Tk))
(define fields (dict))
(define make-field
(lambda (in-units out-units conversion row)
(setitem fields in-units (tkinter..StringVar))
(doto (tkinter.ttk..Entry : textvariable (get#in-units fields))
(.bind "<Any-KeyRelease>" X#(.set (get#out-units fields)
(-> fields (get#in-units) (.get) (float) (conversion))))
(.grid : row row column 0))
(.grid (tkinter.ttk..Label root : text in-units)
: row row column 1)))
(make-field "°F" "°C" X#.#"(X-32)/1.8" 0)
(make-field "°C" "°F" X#.#"X*1.8+32" 1)
(.mainloop root) Still seems to be about half the length of the Bottle version. |
Beta Was this translation helpful? Give feedback.
-
Type in a Celsius or Fahrenheit temperature, and see it get converted automatically. Requires
tkinter
(in the standard Python distribution, but omitted from some packages).The code looks a bit duplicated. Perhaps it could be improved?
Beta Was this translation helpful? Give feedback.
All reactions