In ClojureScript, Set multiple properties of a javascript object at once - interop

I am using doto to assign properties of a Dom element in ClojureScript, as below:
(let [img
(doto (.createElement js/document "img")
(set! -src "bunny-512.png")
(set! -height 64)
(set! -width 64))]
;...
)
Is there a way to do set all the properties at once via a map of properties+values instead?
Was thinking something like:
(let [img (.createElement js/document "img")]
(set! img {:src "bunny-512.png" :height 64 :width 64})
But that does not work ...

Try something like this:
(defn set-props [o property-map]
(doseq [[k v] property-map]
(.setAttribute o (name k) v)))
Test:
(def mg (.createElement js/document "img"))
cljs.user=> (set-props mg {:src "foo.png" :height 128 :width 128})
nil
cljs.user=> (.-src mg)
".../foo.png"
cljs.user=> (.-width mg)
128
cljs.user=> (.-height mg)
128

Related

How are assoc and assq implemented in Scheme?

How are assoc and assq implemented in Scheme?
So what is the intern code of those two procedures?
Ultimately, it doesn't matter how it's implemented as long as it adheres to the behaviour specified in the standard (see section 6.4 of r7rs small).
In Guile, it looks like assq is implemented like this:
SCM_DEFINE (scm_assq, "assq", 2, 0, 0,
(SCM key, SCM alist),
"#deffnx {Scheme Procedure} assv key alist\n"
"#deffnx {Scheme Procedure} assoc key alist\n"
"Fetch the entry in #var{alist} that is associated with #var{key}. To\n"
"decide whether the argument #var{key} matches a particular entry in\n"
"#var{alist}, #code{assq} compares keys with #code{eq?}, #code{assv}\n"
"uses #code{eqv?} and #code{assoc} uses #code{equal?}. If #var{key}\n"
"cannot be found in #var{alist} (according to whichever equality\n"
"predicate is in use), then return #code{#f}. These functions\n"
"return the entire alist entry found (i.e. both the key and the value).")
#define FUNC_NAME s_scm_assq
{
SCM ls = alist;
for(; scm_is_pair (ls); ls = SCM_CDR (ls))
{
SCM tmp = SCM_CAR (ls);
SCM_ASSERT_TYPE (scm_is_pair (tmp), alist, SCM_ARG2, FUNC_NAME,
"association list");
if (scm_is_eq (SCM_CAR (tmp), key))
return tmp;
}
SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (ls), alist, SCM_ARG2, FUNC_NAME,
"association list");
return SCM_BOOL_F;
}
#undef FUNC_NAME
Which is the C equivalent of (excluding some type checks):
(define (assq key alist)
(let loop ((ls alist))
(if (pair? ls)
(let ((tmp (car ls)))
(if (eq? (car tmp) key)
tmp
(loop (cdr ls))))
#f)))

Jess matching rule does not fire

I am having difficulties in defining matching rules.
(defrule set-current
?desAct <- (Actuator (name 0) (StrokeLength ?sl) (Force ?f)
(nominalCurrent ?c3))
(test (eq ?c3 0)) ; I have defined this to change only if value is not
; set yet
?act <- (Actuator (inputVoltage ?v1) ; actuator that has matching slots
(StrokeLength ?sl1)
(nominalCurrent ?c1))
(test (eq ?sl1 ?sl)) ; for same stroke length I want to modify
; nominalCurrent of ?desAct
=>
(modify ?desAct (nominalCurrent ?c1))
)
?desAct represent the fact which slots values I want to change according to other existing facts based on some criteria.
I am not sure why this rule doesn't fire for following facts:
f-4 (MAIN::Actuator (name 4) (inputVoltage 12) (Force 17) (StrokeLength 10) (length 62) (width 18) (height 15.1) (motorType DC) (speedAtNomLoad 25) (weight 28) (nominalCurrent 0.46) (highTemp 50) (lowTemp -10) (price 90) (dutyCycle 20))
f-9 (MAIN::Actuator (name 0) (inputVoltage 12) (Force 17) (StrokeLength 10) (length 10) (width 10) (height 10) (motorType DC) (speedAtNomLoad 0) (weight 0) (nominalCurrent 0) (highTemp 0) (lowTemp 0) (price 0) (dutyCycle 0))
I am expecting that Actuator with name 0 with this rule has nominalCurrent same as f-4, but rule doesn't fire.
The rule does fire but more than once. If you have facts of the same template, make sure to avoid multiple matches of 1 or 2 facts.
(defrule set-current
?act1 <- (Actuator (name ?n1)
(inputVoltage ?v1)
(StrokeLength ?sl1)
(nominalCurrent ?c1&0))
?act2 <- (Actuator (name ?n2&~?n1) ; avoid redundant matches
(inputVoltage ?v1) ; same input voltage
(StrokeLength ?sl1) ; same stroke length
(nominalCurrent ?c2)) ; bind current
=>
(printout t "modify actuator " ?n1 " current=" ?c2 crlf)
(modify ?act1 (nominalCurrent ?c2))
)
The constraint (name ?n2&~?n1) forces matches to occur between Actuators with different name values. Reusing a bound variable forces a match with a slot of that value.
Don't use test. Be more consistent with the names for binding variables.

Which variable is set by `search-forward` in elisp?

In elisp to replace an occurrence of a string in a buffer I would do
(search-forward "aaa" nil 't)
(replace-match "bbb")
If between the search and the replace I modify the buffer, the following seems to happen:
(match-end 1) <- (min (point-max) (match-end 1))
(match-beginning 1) <- (min (match-beginning 1) (match-end 1))
Moreover if (match-end 1)==(match-beginning 1) replace-match calls insert at (match-end 1) (both of which gets updated to point to the end of the inserted string) whereas if (match-end 1)>(match-beginning 1) replace-match updates the string between (match-beginning 1) and (match-end 1) (and they get updated to point to the beginning and end of the inserted string)
So the second question is why the different behaviours?

Modifying structure fields within function?

I am learning how to use structures with MIT-scheme and am trying to "translate" the following function from C to scheme:
static inline void
body_integrate(struct body *body, double dt)
{
body->vx += dt * body->fx / body->mass;
body->vy += dt * body->fy / body->mass;
body->rx += dt * body->vx;
body->ry += dt * body->vy;
}
With the following definitions
(define-structure body rx ry vx vy fx fy mass)
(define integrate (lambda (body dt) (
(set-body-vx! body (+ (body-vx body) (* dt (/ (body-fx body) (body-mass body)))))
(set-body-vy! body (+ (body-vy body) (* dt (/ (body-fy body) (body-mass body)))))
(set-body-rx! body (+ (body-rx body) (* dt (body-vx body))))
(set-body-ry! body (+ (body-ry body) (* dt (body-vy body))))
)))
I get:
MIT/GNU Scheme running under GNU/Linux
Type `^C' (control-C) followed by `H' to obtain information about interrupts.
Copyright (C) 2011 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO warranty; not even for
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Image saved on Thursday November 5, 2015 at 8:44:48 PM
Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/x86-64 4.118 || Edwin 3.116
;Loading "body.ss"... done
1 ]=> (define b (make-body 1.0 1.0 2.0 2.0 10.0 10.0 0.1))
;Value: b
1 ]=> (integrate b 5.0)
;The object #!unspecific is not applicable.
;To continue, call RESTART with an option number:
; (RESTART 2) => Specify a procedure to use in its place.
; (RESTART 1) => Return to read-eval-print level 1.
2 error>
I have the feeling I can't do multiple (set-body-X! ...) inside integrate. But then how should I proceed to do this?
The opening parentheses right at the end of the first line is incorrect, in Scheme when you surround an expression with () it's treated as a function application, and that's not what you want here.
Anyway, it'd be more idiomatic to create a new structure with the new values, instead of modifying a parameter - remember, Scheme encourages a functional programming style, and you should avoid mutating values; besides modifying a parameter is considered bad style in most programming languages (that's ok in C, though). Try this:
(define (integrate body dt)
(make-body (+ (body-rx body) (* dt (body-vx body)))
(+ (body-ry body) (* dt (body-vy body)))
(+ (body-vx body) (* dt (/ (body-fx body) (body-mass body))))
(+ (body-vy body) (* dt (/ (body-fy body) (body-mass body))))
(body-fx body)
(body-fy body)
(body-mass body)))

a strange error in racket "no expression after a sequence of internal definitions"

I have the following code:
(define (play-loop strat0 strat1 strat2 game-limit)
(define (play-loop-iter strat0 strat1 strat2 count history0 history1 history2 limit)
(cond ((= count limit) (print-out-results history0 history1 history2 limit))
(else (let ((result0 (strat0 history0 history1 history2))
(result1 (strat1 history0 history1 history2)
(result2 (strat2 history0 history1 history2)))
(play-loop-iter strat0 strat1 strat2 (+ 1 count)
(extend-history result0 history0)
(extend-history result1 history1)
(extend-history result2 history2)
limit)))))
(play-loop-iter strat0 strat1 strat2 0 '() '() '() game-limit)))
When I run it in racket it gives me the following error:
begin (possibly implicit): no expression after a sequence of internal definitions in:...
I seems everything is OK but there is an error and looked me very interesting.
What is the problem?
Thank you...
It's telling you that your play-loop function only contains the definition of the play-loop-iter function and no other expression in its body.
It looks like you want the call to play-loop-iter to be part of play-loop's body, but it's not - it's part of play-loop-iter's body. Check the parentheses.
You are likely missing a paren after (result1 (strat1 history0 history1 history2)

Resources