Re: Dynamic args in delayed function calls

2014-12-05 Thread Steven Yi
Hi All,

Just following up, I've been contemplating the idea of dynamic 
values/time-varying state a lot in the context of my previous email.  If 
something that is deref-able (IDeref) is considered something that is 
time-varying, then it also leaks that what uses it is impure. 

If IDeref becomes something representing a time-varying value, then we 
could have something like:

(def input (r!*! read-line))

(defn process [src]
  (loop [v @src]
(when v 
  (println Read:  v) 
  (recur @src

With (process input), this ends up blocking on the deref of input, awaiting 
on the read-line.  If on the other hand, we don't use a IDeref, but a 
0-arity function:

(defn process [func]
  (loop [v (func)]
(when v 
  (println Read:  v) 
  (recur (func)

We get the notion with (process read-line) that func is impure and returns 
different values over time, but it's not as visible IMO as compared to 
@src.  

Extending this line of thought, I then thought about core.async's channels 
as just another source of values over time.  For example, if channels were 
deref-able, then this:

(*go* (*while* true
(*let* [v (! ch)]
  (println Read:  v


could be rewritten as:


(*go* (*while* true
(*let* [v @ch]
  (println Read:  v


If the code above was not written in a go block, then it would look very 
similar to the process function earlier.  It would also mean you could pass in 
ch as a channel, or pass in the (r!*! read-line), or pass in a deref-able such 
as:

*(*defn seq-iter *[*s*]**(let* *[*head *(**atom* s*)]*  
*(*reify IDeref 
   *(**deref* *[*_*]* *(let* *[[*x ** xs*]* *@*head*]* 
 *(**reset!* head xs*)* 
x*)*
(process (seq-iter [a b c))


And the process code would work with all three sources of time-varying values.  
(The last could be useful for mocking changes in values over time). It also 
doesn't matter to the process function whether the passed in IDeref is an atom, 
ref, channel, or some other source of value; or whether it blocks or not.  The 
code then becomes generalized to code that works with mutable data, and we can 
pass in arbitrary data sources.  


Something I both like and dislike about the !*! notation is that it is highly 
visible in the code.  I don't know if it is as clear as something like the 
conventions of *earmuffs* on a var to show something dynamic is used, but at 
least the code using it signifies: this function and code is not like the 
others, it is impure and deals with mutable values.  Using @ also denotes 
working with something involving change and time, which seems to make the @ and 
r!*! blocks have a natural fit.  


On the one hand, I'm not sure if generalizing IDeref to time-varying values, 
and the things mentioned above, would make things more complicated or less. On 
the other hand, IDeref also has multiple meanings as it is (i.e. get me the 
current value in time of a thing, get me the one and only value but when it's 
ready).  This is to just to say, I'm not sure about all this yet, still just 
very curious.  


Thanks!

steven



On Wednesday, December 3, 2014 12:21:54 AM UTC-5, Steven Yi wrote:

 Hi All, 

 I was working on a music notation issue with my music libraries Pink 
 and Score and came upon a solution I thought was curious. It certainly 
 solved a real problem I had with delayed function calls, and I thought 
 maybe others might find a use for it too. 

 The scenario I had is that in writing events, I needed to find a way 
 to have certain arguments be dynamic at the time of application of the 
 function, rather than the time of event creation.  For example: 

 [fm 2.5 0.3 (env [0.0 500 0.5 1000]) 0.3] 

 when processed by Score and Pink, would yield an event data structure 
 where the 3rd argument to the fm function would be a stateful function 
 generated by (env ...).  That would be fine if that the event was used 
 once, but if the event was reused (i.e. I want to listen to that block 
 of score again...), the function returned by (env) would have already 
 been processed. 

 The code I came up with is at [1].  It allowed so that I could use: 

 [fm 2.5 0.3 (!*! env [0.0 500 0.5 1000]) 0.3] 

 and everytime the fm was applied, the code within the !*! was run at 
 apply time. This ends up using the apply!*! function from [1] instead 
 of apply to resolve that argument when applying the fm function. 

 I found this curious as it meant that I didn't have to write a new 
 wrapper function just to dynamically create arguments to call the fm 
 function, such as: 

 [#(fm 0.3 (env [0.0 500 0.5 1000]) 0.3) 0.25] 

 which seemed a bit more noisy and less clear to the intent of the event 
 code. 

 I tried to think of a more general scenario where this might be 
 useful.  I came up 

Re: Dynamic args in delayed function calls

2014-12-03 Thread Fluid Dynamics
The last group of examples reminds me of spreadsheet formula cells.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Dynamic args in delayed function calls

2014-12-02 Thread Steven Yi
Hi All,

I was working on a music notation issue with my music libraries Pink
and Score and came upon a solution I thought was curious. It certainly
solved a real problem I had with delayed function calls, and I thought
maybe others might find a use for it too.

The scenario I had is that in writing events, I needed to find a way
to have certain arguments be dynamic at the time of application of the
function, rather than the time of event creation.  For example:

[fm 2.5 0.3 (env [0.0 500 0.5 1000]) 0.3]

when processed by Score and Pink, would yield an event data structure
where the 3rd argument to the fm function would be a stateful function
generated by (env ...).  That would be fine if that the event was used
once, but if the event was reused (i.e. I want to listen to that block
of score again...), the function returned by (env) would have already
been processed.

The code I came up with is at [1].  It allowed so that I could use:

[fm 2.5 0.3 (!*! env [0.0 500 0.5 1000]) 0.3]

and everytime the fm was applied, the code within the !*! was run at
apply time. This ends up using the apply!*! function from [1] instead
of apply to resolve that argument when applying the fm function.

I found this curious as it meant that I didn't have to write a new
wrapper function just to dynamically create arguments to call the fm
function, such as:

[#(fm 0.3 (env [0.0 500 0.5 1000]) 0.3) 0.25]

which seemed a bit more noisy and less clear to the intent of the event code.

I tried to think of a more general scenario where this might be
useful.  I came up with two examples, the first was composing a
logging function:

user= (def logger (partial apply!*! println [ (!*! #(str (new
java.util.Date))) ]))
#'user/logger
user= (logger testing2)
[ Tue Dec 02 22:22:44 EST 2014 ] testing2
nil
user= (logger testing3)
[ Tue Dec 02 22:22:50 EST 2014 ] testing3

Not too exciting, I know.  On the other hand, I thought about FRP, and
came up with:

user= (defn r!*! [func  args]
  #_= (reify IDeref
  #_= (deref [_] (apply!*! func args)))
  #_= )
#'user/r!*!
user= (def a (atom 45))
#'user/a
user= (def b (r!*! * (!*! deref a) 10))
#'user/b
user= @a
45
user= @b
450
user= (reset! a 50)
50
user= @b
500
user= (def c (r!*! + (!*! deref b) 6))
#'user/c
user= @c
506
user= (reset! a 10)
10
user= @a
10
user= @b
100
user= @c
106

I thought the notation of the r!*! reactive cells above looked nice to
write, and using IDeref captured a bit of the idea of working with
time-varying values. That could also be a little clearer with:

user= (def sig (partial !*! deref))
#'user/sig
user= (def c (r!*! + (sig b) 6))
#'user/c
user= @c
106

The code at [1] is pretty small, but seemed to open up a number of
interesting ways to express things that I hadn't thought about before
in terms of apply-time of functions.  Any feedback/comments/advice
very welcome!

Thanks!
steven

[1] - https://github.com/kunstmusik/pink/blob/master/src/pink/util.clj#L9-L29

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.