Re: How to try/catch Let bindings?

2017-10-08 Thread Gary Verhaegen
As others have noted, this is pretty much what monads are made for. I've
found Brian Marick's "Functional Programming for the Object-Oriented
Programmer"'s chapter on monads really good at teaching how to recognize
situations where monads would be a good fit.

For this specific use-case, you can probably, as an intermediate solution,
define a fairly simple macro that would get you almost all you want,
something like:

(defmacro mlet
  [bindings & body]
  (if (seq bindings)
(let [[b expr & r] bindings]
  `(try (let [~b ~expr]
  (mlet ~r ~@body))
(catch Exception e#
  (let [~b [:mlet/error e#]]
(let ~(->> r
   (partition 2)
   (mapcat (fn [[b _]] [b :mlet/unbound]))
   vec)
  ~@body)
`(do ~@body)))
(mlet [a (+ 1 2)
   b (- a 3)
   c (/ 10 b)
   d (inc c)]
  [a b c d]);; => [3 0 [:mlet/error #error {#_elided}] :mlet/unbound]

Depending on how much complexity you're willing to bear within that macro,
you could do smarter things like detecting which variables can still be
computed, etc.

Maybe also take a look at prismatic graph?
https://github.com/plumatic/plumbing

-- 
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.


Re: How to try/catch Let bindings?

2017-10-07 Thread Nathan Fisher
You could use exceptions, is that a hard requirement or are you working to
transition your mental model for Java code to Clojure?

If you can catch the exceptions or not throw them to begin with there’s
some other options;

Another way you could do it is using core.async and channels as some others
have mentioned.

Yet another way would be using cats.

A similar solution to what the problem you described is outlined partway
through this article (there’s a lot there):

https://blog.skyliner.io/fourteen-months-with-clojure-beb8b3e4bf00

A friend of mine used to say “get it writ, then get it right”. As long as
you encapsulate the desired behaviour in the function you can try all of
the different suggestions and take a decision of what feels more readable
to you and others on your team.

On Sat, 30 Sep 2017 at 23:14, Didier <didi...@gmail.com> wrote:

> I'm curious how others handle this use case, which I feel should be pretty
> common.
>
> Given you have a series of business process steps, where the flow is too
> complex for the arrow macros, and you also like to name the step results
> descriptively, so you use let:
>
> (let [a (do-a ...)
>   b (do-b . a . .)
>   c (do-c . a . b)]
>   (log/info "Success" {:a a
>:b b
>:c c})
>   c)
>
> Now, say each steps could possibly throw an exception. So you want to
> try/catch the let bindings:
>
> (try
>   (let [a (do-a ...)
> b (do-b . a . .)
> c (do-c . a . b)]
> (log/info "Success" {:a a
>  :b b
>  :c c})
> c)
>   (catch Exception e
> (log/error "Failed" {:a a
>      :b b
>  :c c})
> (throw e)))
>
> But, inside the catch, you need access to the let bindings a,b,c, in order
> to recover from the failure, or like in my example, just to log so that
> debugging of the issue is easier.
>
> Now the catch will not be in scope of the bindings, and this won't even
> compile: "Can not find symbol a,b,c in context...".
>
> What would be the idomatic thing to do here?
>
> Is there another way to execute a set of complex steps which does not rely
> on let and can be try/catched in the manner I describe?
>
> Or is there a way to re-write the let that satisfies my case, and remains
> idiomatic, and does not add accidental complexities?
>
> Thank You.
>
> --
> 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.
>
-- 
- sent from my mobile

-- 
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.


Re: How to try/catch Let bindings?

2017-10-07 Thread Fabrizio Ferrai
Now that bertschi mentioned Haskell and side-effects, I noticed that the
problem we have here totally looks like a monad:
we have several steps of side-effecting computation, and each of them can
fail, and when this happens you want to handle the failure while keeping
the previous bindings.

Now, when it comes to handling Java exceptions in a monadic way, we can
look at the Try monad in Scala, that is exactly what we are searching for.
We have several libraries that implement monadic sugar in Clojure, and
`cats` [1] implements the try monad [2].

Example usage with `mlet` (monadic let, aka `do` in Haskell):

=> (require '[cats.core :as m])
nil
=> (require '[cats.monad.exception :as exc])
nil
=> (m/mlet [a (exc/try-on 1)
b (exc/try-on a)] ;; a is visible in b scope of course, as in
standard let
 (m/return (str "a: " a ", b: " b)))
#
boot.user=> (m/mlet [a (exc/try-on 1)
 b (exc/try-on (+ 1 nil))] ;; when you get an exception
it blows up
  (m/return (str "a: " a ", b: " b)))
# (m/mlet [a (exc/try-on 1)
b (exc/try-or-else (+ 1 nil) a)] ;; but you have the a binding
also in case of exception
 (m/return (str "a: " a ", b: " b)))
#


[1]: https://github.com/funcool/cats
[2]: http://funcool.github.io/cats/latest/#exception

Cheers,
Fabrizio

On Mon, Oct 2, 2017 at 4:39 AM, Didier  wrote:

> I've seen this, I was still curious if the reason I was facing the issue
> was that let is simply the wrong tool for my use case or not.
>
> If let is the correct tool, I would propose that clojure.core should had a
> try/catch where the catch is in scope of the try. I feel the reason this is
> contrived is accidental complexity due to limitations of Clojure. In Java,
> this isn't an issue, because you're variables would be mutable:
>
>
> Object a;
> Object b;
> Object c;
> try {
>   a = doA(..);
>   b = doB(.., a, .., .., ..);
>   c = doC(.., .., a, .., b, ..);
> } catch {
>   // The catch is in scope of a,b,c.
> }
>
> Which I feel I can't think of any way in Clojure to do this, which does
> not add accidental complexity. In that, there's nothing to the actual
> problem which requires say the complexity of a let inside a let, a
> try/catch around each steps, binding atoms, delays, promise, volatile and
> then setting them inside the try, etc. All these seems to me like Clojure
> just adds some accidental complexity to this common use case.
>
> What do others think?
>
>
> On Saturday, 30 September 2017 16:42:48 UTC-7, Marcus Magnusson wrote:
>>
>> I've used try-let (link below) for this, it's worked great!
>>
>> https://github.com/rufoa/try-let
>>
> --
> 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.
>

-- 
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.


Re: How to try/catch Let bindings?

2017-10-06 Thread 'bertschi' via Clojure


On Monday, October 2, 2017 at 11:04:52 PM UTC+2, Didier wrote:
>
> > Even in an impure language such as Common Lisp we frown on such LET forms
>
> True, but as far as I know, in Common Lisp, the condition handler is 
> always in scope of where the error happened, so I wouldn't face this 
> problem.
>
> I also struggle to split this up into functions without making it even 
> more complicated. I'm intrigued by the interceptor pattern mentioned, I'll 
> have to try it out, I worry its overkill, but not sure.
>
> My opposition to turning this into a chain, is that it complects the order 
> of things, with the work of each step. My steps are pure functions, they 
> take inputs and return outputs. They don't know anything about the full 
> workflow, just their transformation. My orchestrating function is the one 
> which knows how to compose the smaller pure steps, so that it can fulfill 
> the business process.
>
No, your functions are not pure. Besides returning a value they can throw 
an exception, i.e. they have a side-effect!
As we know from Haskell, this forces them to be evaluated in a sequential 
order ... just ask yourself what value the variable c should be bound to if 
an exception is thrown by doB.

Both suggested solutions seem to be reasonable. While try-let ignores all 
bindings when an error occurs (check with macroexpand), the interceptor 
chain probably can see all bindings established before the error occured (I 
have not tested this though) and thus correctly imposes a sequential order.

Best,

 Nils

The interceptor chain seems to still complect this a little. At least it 
> has the steps know about each other since it relies on a common context, 
> and expects previous steps to properly assoc the data needed by later steps.
>
>

-- 
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.


Re: How to try/catch Let bindings?

2017-10-02 Thread Didier
> Even in an impure language such as Common Lisp we frown on such LET forms

True, but as far as I know, in Common Lisp, the condition handler is always in 
scope of where the error happened, so I wouldn't face this problem.

I also struggle to split this up into functions without making it even more 
complicated. I'm intrigued by the interceptor pattern mentioned, I'll have to 
try it out, I worry its overkill, but not sure.

My opposition to turning this into a chain, is that it complects the order of 
things, with the work of each step. My steps are pure functions, they take 
inputs and return outputs. They don't know anything about the full workflow, 
just their transformation. My orchestrating function is the one which knows how 
to compose the smaller pure steps, so that it can fulfill the business process.

The interceptor chain seems to still complect this a little. At least it has 
the steps know about each other since it relies on a common context, and 
expects previous steps to properly assoc the data needed by later steps.

-- 
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.


Re: How to try/catch Let bindings?

2017-10-02 Thread hiskennyness


On Saturday, September 30, 2017 at 6:14:33 PM UTC-4, Didier wrote:
>
> I'm curious how others handle this use case, which I feel should be pretty 
> common.
>
> Given you have a series of business process steps, where the flow is too 
> complex for the arrow macros, and you also like to name the step results 
> descriptively, so you use let:
>

You are almost saying what I am thinking: this beast of a calculation has 
to be broken up (into separate functions)! :)
 

>
> (let [a (do-a ...)
>   b (do-b . a . .)
>   c (do-c . a . b)]
>

Even in an impure language such as Common Lisp we frown on such LET forms. 
I believe it was Lisp legend Paul Graham who suggested we imagine a tax on 
LET. 

Sometimes while sorting out something complex I do solve it in a series of 
LET bindings, but once I understand what I am about I am able to add 
clarity by shuffling the code into a nice functional form (and yes, 
sometimes break things out into standalone functions if only to make the 
source more approachable).

I then think the exception handling will sort itself on its own.

-kt

-- 
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.


Re: How to try/catch Let bindings?

2017-10-02 Thread Luke Burton


> On Oct 1, 2017, at 9:21 PM, Didier  wrote:
> 
> I can't emphasize enough the utility of the interceptor chain pattern, as 
> employed heavily in pedestal.
> 
> Interesting... Its almost like a workflow framework, but for simpler in code 
> workflows. I'm reluctant to have a dependency on pedestal just for this 
> though.

The dependencies required are pretty minimal, you just pull in the interceptor 
stuff by itself. Those guys did a good job of breaking pedestal into reusable 
pieces.

 [io.pedestal/pedestal.interceptor "0.5.2"]
   [io.pedestal/pedestal.log "0.5.2"]  
 [io.dropwizard.metrics/metrics-core "3.1.2"]  
   [org.clojure/core.match "0.3.0-alpha4" :exclusions 
[[org.clojure/clojurescript] [org.clojure/tools.analyzer.jvm]]]   

Plus core.async.

I've rolled my own mini-interceptor too. If you don't need the "leave" 
interceptor concept and are happy with one-way execution, we're just talking 
about pushing functions onto a queue. Each function takes a context map that 
includes the queue itself. Then, implement an executor that dequeues each 
function and executes it. Capture any errors at this point and short-circuit 
execution.

Having gone down that route I just ended up using pedestal.interceptor, after 
reading the source code and realizing it's so simple. I like using other 
people's heavily debugged code :) 


-- 
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.


Re: How to try/catch Let bindings?

2017-10-02 Thread Duncan McGreggor
Didier, I've done something similar a few times just using core.async -- no
extra deps required ;-)

d


On 1 October 2017 at 23:21, Didier  wrote:

> I can't emphasize enough the utility of the interceptor chain pattern, as
>> employed heavily in pedestal.
>>
>
> Interesting... Its almost like a workflow framework, but for simpler in
> code workflows. I'm reluctant to have a dependency on pedestal just for
> this though.
>
> On Sunday, 1 October 2017 21:00:31 UTC-7, Luke Burton wrote:
>
>>
>> On Sep 30, 2017, at 3:14 PM, Didier  wrote:
>>
>> Is there another way to execute a set of complex steps which does not
>> rely on let and can be try/catched in the manner I describe?
>>
>>
>> I can't emphasize enough the utility of the interceptor chain pattern, as
>> employed heavily in pedestal.
>>
>> I use this *everywhere* now. I have code that interleaves interceptors
>> into a chain to augment them with timing information, audit logs, and more.
>> I have written code that maps a subset of an interceptor chain over a
>> cluster of machines, then reduces the results back down locally. Most
>> importantly, they are fantastically useful when it comes time to debug a
>> complex business process … you can swap interceptors in and out easily,
>> isolate stateful interceptors to enable better mocking during tests, and
>> more.
>>
>> Here's a basic application of interceptors. It's really not much code
>> considering what you get. This doesn't even scratch the surface of what
>> they can do.
>>
>> (ns interceptor.test
>>   (:require
>> [io.pedestal.interceptor.chain :as chain]))
>>
>> (def step1
>>   {:name  :step1
>>:enter (fn [ctx]
>> (let [x "sheep"]
>>   (assoc ctx :result x)))})
>>
>> (def step2
>>   {:name  :step2
>>:error (fn [ctx ex-info]
>> (println "so much for step2:" (:exception-type (ex-data
>> ex-info
>>:enter (fn [{:keys [result] :as ctx}]
>>
>> (println "time to transform" result "into a number")
>> (update ctx :result #(Long/parseLong %)))})
>>
>> (defn run []
>>   (chain/execute {} [step1 step2]))
>>
>>
>> --
> 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.
>

-- 
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.


Re: How to try/catch Let bindings?

2017-10-02 Thread Daniel Compton
Hi Didier

The interceptor pattern is pretty tiny, certainly small enough to copy from
project to project if you wanted. You can see re-frame's implementation
here:
https://github.com/Day8/re-frame/blob/master/src/re_frame/interceptor.cljc
which
is only around 100 SLOC. That doesn't handle exceptions like Pedestal, but
shows the core of the idea.

On Mon, Oct 2, 2017 at 5:22 PM Didier  wrote:

> I can't emphasize enough the utility of the interceptor chain pattern, as
>> employed heavily in pedestal.
>>
>
> Interesting... Its almost like a workflow framework, but for simpler in
> code workflows. I'm reluctant to have a dependency on pedestal just for
> this though.
>
> On Sunday, 1 October 2017 21:00:31 UTC-7, Luke Burton wrote:
>
>>
>> On Sep 30, 2017, at 3:14 PM, Didier  wrote:
>>
>> Is there another way to execute a set of complex steps which does not
>> rely on let and can be try/catched in the manner I describe?
>>
>>
>> I can't emphasize enough the utility of the interceptor chain pattern, as
>> employed heavily in pedestal.
>>
>> I use this *everywhere* now. I have code that interleaves interceptors
>> into a chain to augment them with timing information, audit logs, and more.
>> I have written code that maps a subset of an interceptor chain over a
>> cluster of machines, then reduces the results back down locally. Most
>> importantly, they are fantastically useful when it comes time to debug a
>> complex business process … you can swap interceptors in and out easily,
>> isolate stateful interceptors to enable better mocking during tests, and
>> more.
>>
>> Here's a basic application of interceptors. It's really not much code
>> considering what you get. This doesn't even scratch the surface of what
>> they can do.
>>
>> (ns interceptor.test
>>   (:require
>> [io.pedestal.interceptor.chain :as chain]))
>>
>> (def step1
>>   {:name  :step1
>>:enter (fn [ctx]
>> (let [x "sheep"]
>>   (assoc ctx :result x)))})
>>
>> (def step2
>>   {:name  :step2
>>:error (fn [ctx ex-info]
>> (println "so much for step2:" (:exception-type (ex-data
>> ex-info
>>:enter (fn [{:keys [result] :as ctx}]
>>
>> (println "time to transform" result "into a number")
>> (update ctx :result #(Long/parseLong %)))})
>>
>> (defn run []
>>   (chain/execute {} [step1 step2]))
>>
>>
>> --
> 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.
>

-- 
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.


Re: How to try/catch Let bindings?

2017-10-01 Thread Didier

>
> I can't emphasize enough the utility of the interceptor chain pattern, as 
> employed heavily in pedestal.
>

Interesting... Its almost like a workflow framework, but for simpler in 
code workflows. I'm reluctant to have a dependency on pedestal just for 
this though.

On Sunday, 1 October 2017 21:00:31 UTC-7, Luke Burton wrote:
>
>
> On Sep 30, 2017, at 3:14 PM, Didier  
> wrote:
>
> Is there another way to execute a set of complex steps which does not rely 
> on let and can be try/catched in the manner I describe?
>
>
> I can't emphasize enough the utility of the interceptor chain pattern, as 
> employed heavily in pedestal.
>
> I use this *everywhere* now. I have code that interleaves interceptors 
> into a chain to augment them with timing information, audit logs, and more. 
> I have written code that maps a subset of an interceptor chain over a 
> cluster of machines, then reduces the results back down locally. Most 
> importantly, they are fantastically useful when it comes time to debug a 
> complex business process … you can swap interceptors in and out easily, 
> isolate stateful interceptors to enable better mocking during tests, and 
> more.
>
> Here's a basic application of interceptors. It's really not much code 
> considering what you get. This doesn't even scratch the surface of what 
> they can do.
>
> (ns interceptor.test
>   (:require
> [io.pedestal.interceptor.chain :as chain]))
>
> (def step1
>   {:name  :step1
>:enter (fn [ctx]
> (let [x "sheep"]
>   (assoc ctx :result x)))})
>
> (def step2
>   {:name  :step2
>:error (fn [ctx ex-info]
> (println "so much for step2:" (:exception-type (ex-data 
> ex-info
>:enter (fn [{:keys [result] :as ctx}]
> 
> (println "time to transform" result "into a number")
> (update ctx :result #(Long/parseLong %)))})
>
> (defn run []
>   (chain/execute {} [step1 step2]))
>
>
>

-- 
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.


Re: How to try/catch Let bindings?

2017-10-01 Thread Luke Burton

> On Sep 30, 2017, at 3:14 PM, Didier  wrote:
> 
> Is there another way to execute a set of complex steps which does not rely on 
> let and can be try/catched in the manner I describe?

I can't emphasize enough the utility of the interceptor chain pattern, as 
employed heavily in pedestal.

I use this *everywhere* now. I have code that interleaves interceptors into a 
chain to augment them with timing information, audit logs, and more. I have 
written code that maps a subset of an interceptor chain over a cluster of 
machines, then reduces the results back down locally. Most importantly, they 
are fantastically useful when it comes time to debug a complex business process 
… you can swap interceptors in and out easily, isolate stateful interceptors to 
enable better mocking during tests, and more.

Here's a basic application of interceptors. It's really not much code 
considering what you get. This doesn't even scratch the surface of what they 
can do.

(ns interceptor.test
  (:require
[io.pedestal.interceptor.chain :as chain]))

(def step1
  {:name  :step1
   :enter (fn [ctx]
(let [x "sheep"]
  (assoc ctx :result x)))})

(def step2
  {:name  :step2
   :error (fn [ctx ex-info]
(println "so much for step2:" (:exception-type (ex-data ex-info
   :enter (fn [{:keys [result] :as ctx}]

(println "time to transform" result "into a number")
(update ctx :result #(Long/parseLong %)))})

(defn run []
  (chain/execute {} [step1 step2]))


-- 
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.


Re: How to try/catch Let bindings?

2017-10-01 Thread Didier
I've seen this, I was still curious if the reason I was facing the issue 
was that let is simply the wrong tool for my use case or not.

If let is the correct tool, I would propose that clojure.core should had a 
try/catch where the catch is in scope of the try. I feel the reason this is 
contrived is accidental complexity due to limitations of Clojure. In Java, 
this isn't an issue, because you're variables would be mutable:


Object a;
Object b;
Object c;
try {
  a = doA(..);
  b = doB(.., a, .., .., ..);
  c = doC(.., .., a, .., b, ..);
} catch {
  // The catch is in scope of a,b,c.
}

Which I feel I can't think of any way in Clojure to do this, which does not 
add accidental complexity. In that, there's nothing to the actual problem 
which requires say the complexity of a let inside a let, a try/catch around 
each steps, binding atoms, delays, promise, volatile and then setting them 
inside the try, etc. All these seems to me like Clojure just adds some 
accidental complexity to this common use case.

What do others think?

On Saturday, 30 September 2017 16:42:48 UTC-7, Marcus Magnusson wrote:
>
> I've used try-let (link below) for this, it's worked great!
>
> https://github.com/rufoa/try-let
>

-- 
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.


How to try/catch Let bindings?

2017-09-30 Thread Marcus Magnusson
I've used try-let (link below) for this, it's worked great!

https://github.com/rufoa/try-let

-- 
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.


How to try/catch Let bindings?

2017-09-30 Thread Didier
I'm curious how others handle this use case, which I feel should be pretty 
common.

Given you have a series of business process steps, where the flow is too 
complex for the arrow macros, and you also like to name the step results 
descriptively, so you use let:

(let [a (do-a ...)
  b (do-b . a . .)
  c (do-c . a . b)]
  (log/info "Success" {:a a
   :b b
   :c c})
  c)

Now, say each steps could possibly throw an exception. So you want to 
try/catch the let bindings:

(try
  (let [a (do-a ...)
b (do-b . a . .)
c (do-c . a . b)]
(log/info "Success" {:a a
 :b b
 :c c})
c)
  (catch Exception e
(log/error "Failed" {:a a
 :b b
 :c c})
(throw e)))

But, inside the catch, you need access to the let bindings a,b,c, in order 
to recover from the failure, or like in my example, just to log so that 
debugging of the issue is easier.

Now the catch will not be in scope of the bindings, and this won't even 
compile: "Can not find symbol a,b,c in context...".

What would be the idomatic thing to do here?

Is there another way to execute a set of complex steps which does not rely 
on let and can be try/catched in the manner I describe?

Or is there a way to re-write the let that satisfies my case, and remains 
idiomatic, and does not add accidental complexities?

Thank You.

-- 
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.


Re: Let bindings and immutability

2015-02-12 Thread Luc Préfontaine
Think about values first, symbols after.

Symbols are accessory, not values, values are the only things that exist at 
runtime.

Symbols are only there for you poor human (I include myself in this statement) 
to grasp
roughly what is going on by tracking intermediate values with names. The names 
you
choose are irrelevant except for your own comprehension.

There are no containers per se that you can alter transparently.

Some special constructs (atoms, ...)
allow you to persist other values, obviously you need to name
these constructs but they are not symbols, they are a special kind of value.

Your code will need the value they persist, not the construct itself.
(swap! is of limited interest if you never refer to the atom value).

Top level vars are like the universe of values where your code will operate, a 
frame.
Once set vars do not change. (Ok, some may use alter root but it should be 
reserved
to specific occasions).

It's all about values.

This is the semantic shift compared to most languages.

I do not even think about the underlying objects supporting values in Clojure 
unless I need to
(extending with protocols, type hints, weird stack traces, ...). Implementation 
details :)

As for interop, you enter the mutable world and the familiar rules apply here.

The above 'cosmology' sums up how I think when I dive into some Clojure code 
and it works
99.5% of the time. There's no confusion.

Luc P.

 On 12/02/2015 01:53, Ben Wolfson wrote:
  The multiple-binding form of let can be recursively transformed into
  nested lets:
 
  (let [name1 value1 name2 value2 ... name value] body)
  
  (let [name1 value1] (let [name2 value2] ...  (let [name value] body)))
 
  All you're doing with your let form is shadowing the name; there's no
  mutation. If you had something like this:
 
  (let [x 1]
  (let [x (inc x)]
(println x))  ;; prints 2
  (println x)) ;; prints 1
 
  it would be more obvious; it's less apparent in your case because
  there's no room for the extra forms.
 
 
 That explains it but I think Clojure's syntax is misleading here. 
 Without knowledge of this magic the mind doesn't readily translate:
 
 (let [x 1
  x (inc x)
  x (inc x)
  x (inc x)]
 x)
 
 
  into:
 
 (let [x 1]
(let [x (inc x)]
  (let [x (inc x)]
(let [x (inc x)]
x
 
 The single bracket pair in the original leads the unwitting newcomer to 
 assume all the x'es are in the same scope.
 
 gvim
 
 
 
 
 
 
 -- 
 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.
 
--
Luc Préfontainelprefonta...@softaddicts.ca sent by ibisMail!

-- 
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.


Re: Let bindings and immutability

2015-02-11 Thread Ben Wolfson
The multiple-binding form of let can be recursively transformed into nested
lets:

(let [name1 value1 name2 value2 ... name value] body)

(let [name1 value1] (let [name2 value2] ...  (let [name value] body)))

All you're doing with your let form is shadowing the name; there's no
mutation. If you had something like this:

(let [x 1]
   (let [x (inc x)]
 (println x))  ;; prints 2
   (println x)) ;; prints 1

it would be more obvious; it's less apparent in your case because there's
no room for the extra forms.


On Wed, Feb 11, 2015 at 5:49 PM, gvim gvi...@gmail.com wrote:

 On 12/02/2015 01:44, Laurens Van Houtven wrote:

 Hi,

 You're confusing mutation with single assignment. You're not mutating
 anything: 1 is still 1, 2 is still 2; you're just assigning the same name
 to different numbers. The numbers themselves are immutable.


 It's x that bothers me, not the values assigned to it. I don't quite get
 it as x seems to behave here like any old mutable variable in Ruby or
 Python even if it's not called mutation. I suppose I've just never really
 got this (big) one :(


 gvim

 --
 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.




-- 
Ben Wolfson
Human kind has used its intelligence to vary the flavour of drinks, which
may be sweet, aromatic, fermented or spirit-based. ... Family and social
life also offer numerous other occasions to consume drinks for pleasure.
[Larousse, Drink entry]

-- 
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.


Re: Let bindings and immutability

2015-02-11 Thread Ambrose Bonnaire-Sergeant
Local bindings are immutable.

Your example demonstrates lexical shadowing of bindings.

This is an equivalent program semantically.

(let [x   1
  x_1 (inc x)
  x_2 (inc x_1)
  x_3 (inc x_2)]
  x_3)

By the rules of lexical scoping, you cannot access the first `x` but it is
never mutated.

Thanks,
Ambrose

On Wed, Feb 11, 2015 at 8:42 PM, gvim gvi...@gmail.com wrote:

 Why is this possible in a language based on immutability:

 (let [x 1
 x (inc x)
 x (inc x)
 x (inc x)]
x)

 ;;= 4

 Maybe under the hood (ie. memory registers/pointers etc.) this isn't
 strictly mutation but as a relative newcomer to Clojure I find it goes
 against the grain of what I find elsewhere in the language.

 gvim


 --
 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.


-- 
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.


Re: Let bindings and immutability

2015-02-11 Thread Herwig Hochleitner
2015-02-12 3:06 GMT+01:00 gvim gvi...@gmail.com:


 That explains it but I think Clojure's syntax is misleading here. Without
 knowledge of this magic the mind doesn't readily translate:


In some other lisps, clojure's let is called let* for this reason. Their
let binds only in parallel, similar to clojure's (binding []) form for vars.

-- 
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.


Re: Let bindings and immutability

2015-02-11 Thread Justin Smith
(let [x 0
   f #(println x)
   x 1
   g #(println x)
   x 2]
  (f)
  (g)
  x)

there is no mutation of x, only scope shadowing hiding the other binding. Most 
functional languages (all that I know) allow shadowing.

-- 
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.


Re: Let bindings and immutability

2015-02-11 Thread gvim

On 12/02/2015 01:53, Ben Wolfson wrote:

The multiple-binding form of let can be recursively transformed into
nested lets:

(let [name1 value1 name2 value2 ... name value] body)

(let [name1 value1] (let [name2 value2] ...  (let [name value] body)))

All you're doing with your let form is shadowing the name; there's no
mutation. If you had something like this:

(let [x 1]
(let [x (inc x)]
  (println x))  ;; prints 2
(println x)) ;; prints 1

it would be more obvious; it's less apparent in your case because
there's no room for the extra forms.



That explains it but I think Clojure's syntax is misleading here. 
Without knowledge of this magic the mind doesn't readily translate:


(let [x 1
x (inc x)
x (inc x)
x (inc x)]
   x)


 into:

(let [x 1]
  (let [x (inc x)]
(let [x (inc x)]
  (let [x (inc x)]
  x

The single bracket pair in the original leads the unwitting newcomer to 
assume all the x'es are in the same scope.


gvim






--
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.


Re: Let bindings and immutability

2015-02-11 Thread Herwig Hochleitner
I think that, from a user perspective, the important difference from
mutation to shadowing is, that outer x is available even in the inner
context, if captured by a closure.
Likewise, a second thread, that runs an outer closure, would see the
original x.
Observe:

(let [x :outer
  f (fn [] x)
  x :inner]
  (println (f)) ; = :outer
  (println x))  ; = :inner

Shadowing can still be confusing to a smaller extent, so I like to call
shadowed versions x, x', x'', aso.

regards

-- 
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.


Re: Let bindings and immutability

2015-02-11 Thread gvim

On 12/02/2015 01:44, Laurens Van Houtven wrote:

Hi,

You’re confusing mutation with single assignment. You’re not mutating anything: 
1 is still 1, 2 is still 2; you’re just assigning the same name to different 
numbers. The numbers themselves are immutable.



It's x that bothers me, not the values assigned to it. I don't quite get 
it as x seems to behave here like any old mutable variable in Ruby or 
Python even if it's not called mutation. I suppose I've just never 
really got this (big) one :(


gvim

--
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.


Let bindings and immutability

2015-02-11 Thread gvim

Why is this possible in a language based on immutability:

(let [x 1
x (inc x)
x (inc x)
x (inc x)]
   x)

;;= 4

Maybe under the hood (ie. memory registers/pointers etc.) this isn't 
strictly mutation but as a relative newcomer to Clojure I find it goes 
against the grain of what I find elsewhere in the language.


gvim


--
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.


Re: Let bindings and immutability

2015-02-11 Thread Laurens Van Houtven
Hi,


 On Feb 11, 2015, at 5:42 PM, gvim gvi...@gmail.com wrote:
 
 Why is this possible in a language based on immutability:
 
 (let [x 1
x (inc x)
x (inc x)
x (inc x)]
   x)
 
 ;;= 4
 
 Maybe under the hood (ie. memory registers/pointers etc.) this isn't strictly 
 mutation but as a relative newcomer to Clojure I find it goes against the 
 grain of what I find elsewhere in the language.


You’re confusing mutation with single assignment. You’re not mutating anything: 
1 is still 1, 2 is still 2; you’re just assigning the same name to different 
numbers. The numbers themselves are immutable.


hth
lvh

 gvim
 
 
 --
 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.

-- 
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.


signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: Let bindings and immutability

2015-02-11 Thread James Reeves
On 12 February 2015 at 02:06, gvim gvi...@gmail.com wrote:

 That explains it but I think Clojure's syntax is misleading here. Without
 knowledge of this magic the mind doesn't readily translate:

 (let [x 1
 x (inc x)
 x (inc x)
 x (inc x)]
x)

  into:

 (let [x 1]
   (let [x (inc x)]
 (let [x (inc x)]
   (let [x (inc x)]
   x


It's not magic; it's just how the syntax is defined. The for and doseq
forms have the same behaviour.

Languages like Racket that are perhaps more focused on teaching do have
separate let and let* forms. However, Clojure has a more practical focus,
and there isn't much practical point in having a non-shadowing let.

- James

-- 
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.


Re: let bindings

2014-01-21 Thread Andy Smith
Excellent post, thank you for that.

-- 
-- 
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/groups/opt_out.


let bindings

2014-01-20 Thread Andy Smith
Hi,

(let bindings form) is a special form. As I understand it, let can be 
reformulated in terms of functions e.g.

 (let [x 2] (* x 20)) equivalent to ((fn [x] (* x 20)) 2)
(let [x 3 y (* x x)] (- y x)) equivalent to ((fn [x] ((fn [x y] (- y x)) x 
(* x x))) 3)
 
So if we can always reformulate in this was, why cant let be implemented as 
a macro rather than a special form?

Where have I gone wrong in my understanding here?

Andy

-- 
-- 
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/groups/opt_out.


Re: let bindings

2014-01-20 Thread Andy Smith
typo : was=way

-- 
-- 
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/groups/opt_out.


Re: let bindings

2014-01-20 Thread Jozef Wagner
Hi,

fn does additional stuff which let doesn't. fn returns an object which you
can store and later call invoke on it. This is more than let promises. From
the implementation point, fn creates java class. This is not needed for let.

JW


On Mon, Jan 20, 2014 at 9:38 PM, Andy Smith the4thamig...@googlemail.comwrote:

 Hi,

 (let bindings form) is a special form. As I understand it, let can be
 reformulated in terms of functions e.g.

  (let [x 2] (* x 20)) equivalent to ((fn [x] (* x 20)) 2)
 (let [x 3 y (* x x)] (- y x)) equivalent to ((fn [x] ((fn [x y] (- y x)) x
 (* x x))) 3)

 So if we can always reformulate in this was, why cant let be implemented
 as a macro rather than a special form?

 Where have I gone wrong in my understanding here?

 Andy

 --
 --
 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/groups/opt_out.


-- 
-- 
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/groups/opt_out.


Re: let bindings

2014-01-20 Thread Carlo Zancanaro
Hey Andy!

On Mon, Jan 20, 2014 at 12:38:23PM -0800, Andy Smith wrote:
 So if we can always reformulate in this was, why cant let be implemented as 
 a macro rather than a special form?

It can. Quite easily, in fact:

(defmacro my-let [bindings  body]
  (if (empty? bindings)
`(do ~@body)
(let [var (first bindings)
  val (second bindings)
  others (nnext bindings)]
  `((fn [~var]
  (my-let ~others ~@body))
~val

This is going to be a fair bit less efficient than the existing 'let'
implementation, though. The special form is, as far as I understand it,
an optimisation so that we're not constantly creating and destroying
function objects for the sake of local bindings (which are much simpler
than closures, which is what functions require here).

If there's another reason then I'm hoping someone will correct me, but I
can't think of any other reasons at the moment.

Carlo


signature.asc
Description: Digital signature


Re: let bindings

2014-01-20 Thread Kevin Downey
On 1/20/14, 12:38 PM, Andy Smith wrote:
 Hi,
 
 (let bindings form) is a special form. As I understand it, let can be 
 reformulated in terms of functions e.g.
 
  (let [x 2] (* x 20)) equivalent to ((fn [x] (* x 20)) 2)
 (let [x 3 y (* x x)] (- y x)) equivalent to ((fn [x] ((fn [x y] (- y x)) x 
 (* x x))) 3)
  
 So if we can always reformulate in this was, why cant let be implemented as 
 a macro rather than a special form?
 
 Where have I gone wrong in my understanding here?
 
 Andy
 

Clojure has made several choices which make implementing let via macro
expanding to function application a nonstarter:

1. Clojure is compiled.
  There is no interpreter for clojure, all clojure code is compiled to
bytecode before executing, even at the repl. So the compiler needs to be
fast for interactive work and cannot spend a lot of time in optimizing
passes typically used to avoid function call overhead for every local
name binding.

2. Debuggers
  There are a number of nice debugging tool kits for Java/the JVM. They
operating by reading metadata (like local names) from class files.
Because clojure maps let bound locals to the same JVM construct as Java,
you can re-use Java debuggers for Clojure.

3. JVM interop
  The JVM does not have TCO built in, so in order to provide general
constant space tail calls you must do extensive code transforms(breaks 1
and 2) or use your own calling convention(method call and trampoline,
instead of just a method call) which would complicate interop. Clojure
instead provides less general construct loop/recur for constant space
iteration. loop/recur is local to a function body, so if let macro
expanded to a fn call, you would not be able to recur from inside a let.

So while technically possible (there are scheme impls on the jvm that
may) Clojure does not expand let in to a fn call

-- 
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

-- 
-- 
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/groups/opt_out.


Re: let bindings

2014-01-20 Thread John Mastro
 If there's another reason then I'm hoping someone will correct me, but I
 can't think of any other reasons at the moment.

Since Clojure doesn't do tail call elimination implementing let atop fn would 
also use up stack. 

I believe many or all Schemes (which are required by the spec to eliminate all 
tail calls) do implement let in that way, but Common Lisps (where it's not 
promised by the spec, though some implementations with some settings will) does 
not, likely at least in part for the same reason. 

- John

-- 
-- 
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/groups/opt_out.


let bindings in tree-seq funciton

2013-09-05 Thread Kuba Roth
I'm currently working with tree-seq function from clojure.core and there is 
one thing I'm struggling to understand... Could you please explain why 
pretty much all of the body of the function sits within 'let binding' and 
not in the 'let body' where only (walk root) is placed?
Has it something to do with tail recursion?

Thank you,
Kuba

-- 
-- 
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/groups/opt_out.


Re: let bindings in tree-seq funciton

2013-09-05 Thread Cedric Greevey
More likely it has to do with simply naming many of the intermediate
results in a calculation. That often results in long let bindings with
short let bodies. I've written many a function that's basically

(defn foo [x]
  (let [stuff
more stuff
yet more stuff
res (Thingy. args)]
res))

or something close to that, or with a one-liner body of (Thingy. args) or
whatever instead of first naming that res. It's useful to make long and
intricate chains of operations more readable than a very long nested sexp
(and unlike the threading macros doesn't care where each result feeds into
the next operation, and does let each one have its own name that helps
document what it is or what it's for) and it's especially useful if a
single intermediate result is used in more than one place subsequently.



On Thu, Sep 5, 2013 at 2:05 AM, Kuba Roth kuba.r...@gmail.com wrote:

 I'm currently working with tree-seq function from clojure.core and there
 is one thing I'm struggling to understand... Could you please explain why
 pretty much all of the body of the function sits within 'let binding' and
 not in the 'let body' where only (walk root) is placed?
 Has it something to do with tail recursion?

 Thank you,
 Kuba

 --
 --
 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/groups/opt_out.


-- 
-- 
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/groups/opt_out.


Re: let bindings in tree-seq funciton

2013-09-05 Thread Kuba Roth
Thanks, very interesting point. It's a shame this is not available in the 
clojure docs - very useful for newcomers as me.
Is it fair to say that let bindings is good/recomended  to put all the code  
and the main body is used primarily for returning results of the function?

Cheers,
Kuba

-- 
-- 
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/groups/opt_out.


Re: let bindings in tree-seq funciton

2013-09-05 Thread Cedric Greevey
I wouldn't say that. It depends on what the function is doing, and to some
extent on your philosophy. Some would suggest breaking functions into very
small functions, though I'd mostly only break out separate functions if
they are separately useful. If naming the intermediates isn't very useful
for making the purpose of the code clearer, but writing the function body
as (last-step (late-step (middle-step something (early-step arg1 arg3))
arg5) arg2 arg4) is going to be a confusing mess, the threading macros may
be a fine alternative.

That said, most of my functions are either:

* Short;
* Long let bindings, short body;
* Mid-size;
* Mostly a (loop ...); or
* Mostly a body that mutates stuff, likely a big (doto ...) or (dosync ...)
or a series of send-off, swap!, etc.


The last and some of the others being not pure, so usually at the periphery
of the system. Controller, DAL, or other such role. In a few cases I'm
using mutable Java objects but in a somewhat functional way -- for example,
one body of code works extensively with graphics processing, and the
functions tend to all have a (let [bi (BufferedImage. ...) g (.getGraphics
bi) ...] (doto g ...)) type of structure. They don't mutate their
BufferedImage arguments, instead constructing a new instance and returning
that. Some also throw around arrays, for performance reasons, and though
these are technically mutable they also follow a builder pattern and a
pretend it's immutable pattern where functions don't mutate their array
arguments and only use aset to initially create array-valued returned
results, or to work with intermediaries that do not escape the function at
all. This avoids headaches with aliasing and concurrent mutation (as once
either a BI or an array is visible outside its creation code it's not being
mutated any more by any code) while gaining the performance and interop
benefits of using Java's mutable types (e.g. JComboBox constructor takes
array of items, JComboBox object is mutable, eschewing JComboBox is a lot
more work than using it if you need a GUI with a combo box widget in it, so
use arrays and JComboBoxes but use them in as sanitary a manner as you can;
arrays of primitives are more compact and faster when doing certain numeric
stuff; BufferedImage allows to use ImageIO instead of having to write one's
own PNG en/decoder, one's own JPEG en/decoder, and allows to use Graphics2D
instead of having to write one's own line, filled-box, circle, etc.
routines).



On Thu, Sep 5, 2013 at 3:39 PM, Kuba Roth kuba.r...@gmail.com wrote:

 Thanks, very interesting point. It's a shame this is not available in the
 clojure docs - very useful for newcomers as me.
 Is it fair to say that let bindings is good/recomended  to put all the
 code  and the main body is used primarily for returning results of the
 function?

 Cheers,
 Kuba

 --
 --
 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/groups/opt_out.


-- 
-- 
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/groups/opt_out.


Re: dynamically generated let bindings

2011-07-30 Thread Sam Aaron
Hi Ken,
On 29 Jul 2011, at 22:02, Ken Wesson wrote:

 P.S. Thanks everyone for your help so far. My brain is overheating but I am 
 learning a lot.
 
 You're welcome.
 
 To do what you're proposing you will probably need the emitted
 function to look like:
 
 (fn [ args]
  (let [foo (some logic goes here)
bar (some logic goes here)
...]
(body goes here)))
 
 where the first logic checks the args for containing the value for
 foo, if it does evaluates to that value, and if not evaluates to foo's
 default; the second does likewise for bar; and so on.

I just finished implementing a solution and it looks exactly like this. You're 
absolutely right - this is precisely the pattern I was looking for.

What I didn't do, and I think the biggest lesson I've learned from these early 
macro-fighting days, is to do exactly what you propose: sketch out what the 
macro should expand to *before* working on the macro itself.

Thanks everyone once again,

Sam

---
http://sam.aaron.name

-- 
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


Re: dynamically generated let bindings

2011-07-30 Thread Ken Wesson
On Sat, Jul 30, 2011 at 7:29 AM, Sam Aaron samaa...@gmail.com wrote:
 (fn [ args]
  (let [foo (some logic goes here)
        bar (some logic goes here)
        ...]
    (body goes here)))

 I just finished implementing a solution and it looks exactly like this. 
 You're absolutely right - this is precisely the pattern I was looking for.

 What I didn't do, and I think the biggest lesson I've learned from these 
 early macro-fighting days, is to do exactly what you propose: sketch out what 
 the macro should expand to *before* working on the macro itself.

That's generally good advice when macro-writing.

 Thanks everyone once again,

You're welcome.

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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


Re: dynamically generated let bindings

2011-07-30 Thread Alan Malloy
On Jul 29, 2:02 pm, Ken Wesson kwess...@gmail.com wrote:
 (fn [ args]
   (let [argmap__5673__auto (#'some-ns/parse-args args)
         foo (or (:foo argmap__5673__auto) 42)
         bar (or (:bar argmap__5673__auto) nil)
         ...]
     (body goes here)))
 where you define a private parse-args function in your namespace to
 turn an argument seq into a map of argument name keywords to values,
 with some omissions, and 42 and nil are the defaults which the macro
 builds right into the function.

 Of course, this has the slight issue that arguments whose values are
 false or nil will be changed to their defaults. You may need some
 trickier handling, e.g.

 (let [...
       foo (:foo argmap__5673__auto)
       foo (if (:foo argmap__5673__auto) foo 42)
       ...]
   ...)

(get :foo argmap__5673__auto 42) is the right way to solve this
problem.

Or if, as in the current example, you want to destructure a map with
lots of defaults, simply:

(let [{:keys [foo bar] :or {foo 42}} (parse-whatever)]
  ...body...)


 or

 (let [...
       foo (find argmap__5673__auto :foo)
       foo (if foo (val foo) 42)
       ...]
   ...)

 --
 Protege: What is this seething mass of parentheses?!
 Master: Your father's Lisp REPL. This is the language of a true
 hacker. Not as clumsy or random as C++; a language for a more
 civilized age.

-- 
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


Re: dynamically generated let bindings

2011-07-30 Thread Ken Wesson
On Sat, Jul 30, 2011 at 9:07 PM, Alan Malloy a...@malloys.org wrote:
 (get :foo argmap__5673__auto 42) is the right way to solve this
 problem.

Is another way to solve it, yes, and a good one.

 Or if, as in the current example, you want to destructure a map with
 lots of defaults, simply:

 (let [{:keys [foo bar] :or {foo 42}} (parse-whatever)]
  ...body...)

Or

(let [{:keys [foo bar]} (merge {:foo 42} (parse-whatever))]
  ...body...)

The defaults map can be a literal emitted by the macro and must be on
the left of the map-returning (parse-whatever) call.

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Ken Wesson
On Fri, Jul 29, 2011 at 12:49 AM, Jeff Rose ros...@gmail.com wrote:
 I don't think it's very typical to pass a form to a function, unless
 you plan on using eval at runtime.

Or it's a function called by a macro to do some processing of forms.

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Sam Aaron

On 29 Jul 2011, at 07:22, Ken Wesson wrote:

 On Fri, Jul 29, 2011 at 12:49 AM, Jeff Rose ros...@gmail.com wrote:
 I don't think it's very typical to pass a form to a function, unless
 you plan on using eval at runtime.
 
 Or it's a function called by a macro to do some processing of forms.

Yep, this is precisely what I was considering. I should have explicitly made 
mk-dynamically-bound-fn a macro in my example - a miscommunication on my part.


On 29 Jul 2011, at 02:12, Alan Malloy wrote:

 
 It's not clear how much of this is relevant to your actual problem, vs
 the simple version you're posting here. 

Sorry, I was just trying to simplify things to try and get directly to the meat 
of the problem. 

 If you want something more general, that implicitly binds things for
 you based on some code somewhere else (ew ew ew), then you need a
 macro. This implementation is pretty gross; I suspect it could be
 better, but you're trying to do something that seems weird to me.
 
 (defn binding-vec []
  ['size '(count args)])
 
 (defmacro magic-fn
  [ forms]
  `(fn [ ~'args]
 (let ~(binding-vec)
   ~@forms)))
 
 
 user ((magic-fn (+ size 10)) 1 2)
 12

Very cool, although it's not quite what I'd like. I'd like binding-vec to be a 
function of the resulting magic-fn's args. 

I'm aiming for something like this, but can't get it to quite work:

(defn binding-vec [foos]
  '[size (count ~foos)])

(defmacro magic-fn
 [ forms]
 `(fn [ ~'args]
(let ~(binding-vec ~'args)
  ~@forms)))

((magic-fn (+ size 10)) 1 2) ;= BOOM

Sam

---
http://sam.aaron.name

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Sam Aaron

On 29 Jul 2011, at 00:46, Kent wrote:

 I'm not sure what you're trying to do with this and, based on that
 ignorance, I'm not sure I think it's a great idea. Maybe you are being
 a bit crazy, and maybe your a genius.  Who am I to say?
 
 Here is a function that does what you want.  The only difference is
 that my function also takes the binding-vec function as an argument.
 
 
 (defn mdbf [form binding-func]
  (fn [ args]
(eval `(let ~(binding-func args) ~form
 
 Here it is used in your example.
 
 (defn binding-vec
  [args]
   ['size (count args)]
 
 (def a (mdbf '(+ size 10) binding-vec))
 
 (a 1 2 3 4) = 14


Very nice, thanks for this. However, using eval feels a bit too scary even for 
a crazy guy like myself!

Perhaps I need to take a different angle to solving my problem…

Sam

---
http://sam.aaron.name

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Alan Malloy
On Jul 29, 1:49 am, Sam Aaron samaa...@gmail.com wrote:
 On 29 Jul 2011, at 07:22, Ken Wesson wrote:

  On Fri, Jul 29, 2011 at 12:49 AM, Jeff Rose ros...@gmail.com wrote:
  I don't think it's very typical to pass a form to a function, unless
  you plan on using eval at runtime.

  Or it's a function called by a macro to do some processing of forms.

 Yep, this is precisely what I was considering. I should have explicitly made 
 mk-dynamically-bound-fn a macro in my example - a miscommunication on my part.

 On 29 Jul 2011, at 02:12, Alan Malloy wrote:



  It's not clear how much of this is relevant to your actual problem, vs
  the simple version you're posting here.

 Sorry, I was just trying to simplify things to try and get directly to the 
 meat of the problem.

No apologies needed - reducing to a simple case is great. But here,
the simplification was probably too severe.

  If you want something more general, that implicitly binds things for
  you based on some code somewhere else (ew ew ew), then you need a
  macro. This implementation is pretty gross; I suspect it could be
  better, but you're trying to do something that seems weird to me.

  (defn binding-vec []
   ['size '(count args)])

  (defmacro magic-fn
   [ forms]
   `(fn [ ~'args]
      (let ~(binding-vec)
        ~@forms)))

  user ((magic-fn (+ size 10)) 1 2)
  12

 Very cool, although it's not quite what I'd like. I'd like binding-vec to be 
 a function of the resulting magic-fn's args.

 I'm aiming for something like this, but can't get it to quite work:

 (defn binding-vec [foos]
   '[size (count ~foos)])

 (defmacro magic-fn
  [ forms]
  `(fn [ ~'args]
     (let ~(binding-vec ~'args)
       ~@forms)))

 ((magic-fn (+ size 10)) 1 2) ;= BOOM

(defn binding-vec [foos]
  ['size `(count ~foos)])

(defmacro magic-fn
  [ forms]
  (let [args (gensym 'args)]
`(fn [ ~args]
   (let ~(binding-vec args)
 ~@forms

((magic-fn (+ size 10)) 1 2) ;= 12

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Sam Aaron
Hi Alan,

On 29 Jul 2011, at 10:05, Alan Malloy wrote:
 
 Sorry, I was just trying to simplify things to try and get directly to the 
 meat of the problem.
 
 No apologies needed - reducing to a simple case is great. But here,
 the simplification was probably too severe.
 

Sorry, I'm English - apologies are just part of normal discourse ;-)

 
 (defn binding-vec [foos]
  ['size `(count ~foos)])
 
 (defmacro magic-fn
  [ forms]
  (let [args (gensym 'args)]
`(fn [ ~args]
   (let ~(binding-vec args)
 ~@forms
 
 ((magic-fn (+ size 10)) 1 2) ;= 12
 


Fantastic! I believe this is exactly what I'm looking for. Thank-you so much.

Out of interest, are you able to briefly describe (or able to direct me at some 
relevant literature that does) why your original solution used ~'args and why 
this version uses (gensym 'args). These subtle macro compile-time/runtime 
syntax tricks are something I'm clearly yet to master.

Sam

---
http://sam.aaron.name

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Sam Aaron
Hi there,

On 29 Jul 2011, at 10:05, Alan Malloy wrote:
 
 (defn binding-vec [foos]
  ['size `(count ~foos)])
 
 (defmacro magic-fn
  [ forms]
  (let [args (gensym 'args)]
`(fn [ ~args]
   (let ~(binding-vec args)
 ~@forms
 
 ((magic-fn (+ size 10)) 1 2) ;= 12

Actually, sadly, this still quite doesn't do what I want - and definitely 
highlights the perils of over-simplifying the question!

I'd like binding-vec to generate the binding vector entirely from foos, i.e. 
both the binding name and value. Imagine that there's a var names:

(def names ['size 'foo 'bar 'baz])

To continue in the context of the (over-simplified) question, I'd like 
binding-vec to dynamically generate me a vec of:

['size `(count ~foos)
 'foo  `(count ~foos)
 'bar  `(count ~foos)
 'baz  `(count ~foos)]

However, something like the following doesn't work:

(defn binding-vec [foos]
  `(vec (interleave ~names ~(take (count names) (repeat '`(count ~foos))

A, because the above code is probably incorrect (I just cobbled it together for 
the example) and more importantly:
B, because the code doesn't return a vec, it returns code that returns a vec. 

I really seem to be getting my brain in a knot over this. :-( Any illumination 
would be really appreciated


Sam

---
http://sam.aaron.name

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Ken Wesson
On Fri, Jul 29, 2011 at 6:57 AM, Sam Aaron samaa...@gmail.com wrote:
 However, something like the following doesn't work:

 (defn binding-vec [foos]
  `(vec (interleave ~names ~(take (count names) (repeat '`(count ~foos))

 A, because the above code is probably incorrect (I just cobbled it together 
 for the example) and more importantly:
 B, because the code doesn't return a vec, it returns code that returns a vec.

 I really seem to be getting my brain in a knot over this. :-( Any 
 illumination would be really appreciated

Why not just (vec (interleave names (take (count names) (repeat
`(count ~foos)?

Of course I assume you eventually want something more complex than
just (count foos) as the value for every variable, or why have more
than one variable?

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Sam Aaron

On 29 Jul 2011, at 12:11, Ken Wesson wrote:
 
 Why not just (vec (interleave names (take (count names) (repeat
 `(count ~foos)?
 

That seems to blow up:


(defn binding-vec [foos]
  (vec (interleave names (take (count names) (repeat `(count ~foos))

(defmacro magic-fn
 [ forms]
 (let [args (gensym 'args)]
   `(fn [ ~args]
  (let ~(binding-vec args)
~@forms

((magic-fn (+ size 10)) 1 2) ;= 12


 Of course I assume you eventually want something more complex than
 just (count foos) as the value for every variable, or why have more
 than one variable?

Yes, of course :-)

The actual end goal is to be able to define a macro (or whatever) passing in a 
body containing symbols which are yet to be defined. The macro will then return 
me function which has variable arity. When I call this function I'd like the 
values of the args be bound to a specified list of symbols (which happen to be 
the arg names) so that the original body can execute correctly. The interesting 
part is that I'd like to be able to specify defaults interleaved with the arg 
names. 

For example:

(def yo (with-arg-params [foo 0 bar 1 baz 2]
(+ foo bar baz)

a would now be bound to a fn which I could call:

(yo 1 2 3) ;= 6

I could also call it with fewer args than expected:

(yo 1 2) ;= 5

this works because bad has a default of 2.

There's a bunch of other neat tricks I can do here which would probably only 
serve to complicate this example, but this is the general gist of things.

I assume for this to work I have to dynamically create a let binding over the 
original form, so the first call would execute code like:

(let [foo 1 bar 2 baz 3] (+ foo bar baz))

and the second example would execute code like:

(let [foo 1 bar 2 baz 2] (+ foo bar baz)

this would therefore mean that this let statement's vec needs to be a function 
of the args passed to yo and the initial set of defaults.  Unfortunately I'm 
currently unable to figure out how to achieve this.

Sam

---
http://sam.aaron.name



-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Ken Wesson
On Fri, Jul 29, 2011 at 7:35 AM, Sam Aaron samaa...@gmail.com wrote:

 On 29 Jul 2011, at 12:11, Ken Wesson wrote:

 Why not just (vec (interleave names (take (count names) (repeat
 `(count ~foos)?


 That seems to blow up

How so?

 The actual end goal is to be able to define a macro (or whatever) passing in 
 a body containing symbols which are yet to be defined. The macro will then 
 return me function which has variable arity. When I call this function I'd 
 like the values of the args be bound to a specified list of symbols (which 
 happen to be the arg names) so that the original body can execute correctly. 
 The interesting part is that I'd like to be able to specify defaults 
 interleaved with the arg names.

 For example:

 (def yo (with-arg-params [foo 0 bar 1 baz 2]
    (+ foo bar baz)

 a would now be bound to a fn which I could call:

 (yo 1 2 3) ;= 6

 I could also call it with fewer args than expected:

 (yo 1 2) ;= 5

 this works because bad has a default of 2.

(defmacro with-arg-params [bindings  body]
  (let [bindings (apply array-map bindings)]
`(fn
  ~@(for [i (range (inc (count bindings)))]
  `(~(vec (take i (keys bindings)))
 (let ~(vec (mapcat identity (drop i bindings)))
   ~@body))

= (def x (with-arg-params [foo 1 bar 2 baz 3] (+ foo bar baz)))
#'user/x
= (x 4 5 6)
15
= (x 4 5)
12
= (x 4)
9
= (x)
6

= (macroexpand-1 '(with-arg-params [foo 1 bar 2 baz 3] (+ foo bar baz)))
(clojure.core/fn ([] (clojure.core/let [foo 1 bar 2 baz 3] (+ foo bar
baz))) ([foo] (clojure.core/let [bar 2 baz 3] (+ foo bar baz))) ([foo
bar] (clojure.core/let [baz 3] (+ foo bar baz))) ([foo bar baz]
(clojure.core/let [] (+ foo bar baz

=

(fn
  ([] (let [foo 1 bar 2 baz 3] (+ foo bar baz)))
  ([foo] (let [bar 2 baz 3] (+ foo bar baz)))
  ([foo bar] (let [baz 3] (+ foo bar baz)))
  ([foo bar baz] (let [] (+ foo bar baz

Note that array-map cannot be changed to hash-map here because the
order must be preserved.

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Sam Aaron

On 29 Jul 2011, at 12:56, Ken Wesson wrote:
 
 
 That seems to blow up
 
 How so?

(defn binding-vec [foos]
 (vec (interleave names (take (count names) (repeat `(count ~foos))

(defmacro magic-fn
[ forms]
(let [args (gensym 'args)]
  `(fn [ ~args]
 (let ~(binding-vec args)
   ~@forms

((magic-fn (+ size 10)) 1 2) ;= Unable to resolve symbol: size in this context

 
 (defmacro with-arg-params [bindings  body]
  (let [bindings (apply array-map bindings)]
`(fn
  ~@(for [i (range (inc (count bindings)))]
  `(~(vec (take i (keys bindings)))
 (let ~(vec (mapcat identity (drop i bindings)))
   ~@body))
 
 = (def x (with-arg-params [foo 1 bar 2 baz 3] (+ foo bar baz)))
 #'user/x
 = (x 4 5 6)
 15
 = (x 4 5)
 12
 = (x 4)
 9
 = (x)
 6

Ah, very neat :-)

However... (apologies, there always seems to be a however from me in this 
thread!)

This totally satisfies the general gist part of my description but doesn't 
allow for the bunch of other neat tricks I can do here part. The behaviour of 
with-arg-params needs to match the behaviour of other functions in my system 
for consistency. The other tricks are keyword args and even a combination of 
keyword args and normal args. I have the majority of code to implement all this 
behaviour - I can generate the correct vector of bindings given a list of 
supplied args and some defaults. However, it's the ability to dynamically 
create a let binding within a function for which the bindings themselves are a 
function of the actual function's args (and some constant(s)) which is evading 
me.

This seems the closest I can get to a solution:

(defn binding-vec [foos]
 (fn-which-returns-a-vec-of-alternating-symbols-and-vals foos)

(defmacro magic-fn
[ forms]
(let [args (gensym 'args)]
  `(fn [ ~args]
 (let ~(binding-vec args)
   ~@forms

((magic-fn (+ size 10)) 1 2)

I just don't have the magic skills to get it to actually work :-(

Sam

P.S. Thanks everyone for your help so far. My brain is overheating but I am 
learning a lot.

---
http://sam.aaron.name

-- 
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


Re: dynamically generated let bindings

2011-07-29 Thread Ken Wesson
 P.S. Thanks everyone for your help so far. My brain is overheating but I am 
 learning a lot.

You're welcome.

To do what you're proposing you will probably need the emitted
function to look like:

(fn [ args]
  (let [foo (some logic goes here)
bar (some logic goes here)
...]
(body goes here)))

where the first logic checks the args for containing the value for
foo, if it does evaluates to that value, and if not evaluates to foo's
default; the second does likewise for bar; and so on.

Alternatively, if that might result in a lot of inefficient duplication,

(fn [ args]
  (let [argmap__5673__auto (#'some-ns/parse-args args)
foo (or (:foo argmap__5673__auto) 42)
bar (or (:bar argmap__5673__auto) nil)
...]
(body goes here)))

where you define a private parse-args function in your namespace to
turn an argument seq into a map of argument name keywords to values,
with some omissions, and 42 and nil are the defaults which the macro
builds right into the function.

Of course, this has the slight issue that arguments whose values are
false or nil will be changed to their defaults. You may need some
trickier handling, e.g.

(let [...
  foo (:foo argmap__5673__auto)
  foo (if (:foo argmap__5673__auto) foo 42)
  ...]
  ...)

or

(let [...
  foo (find argmap__5673__auto :foo)
  foo (if foo (val foo) 42)
  ...]
  ...)

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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


dynamically generated let bindings

2011-07-28 Thread Sam Aaron
Hi there,

I'm trying to create a fn which does the following:

* returns a fn which takes an arbitrary number of args
* calls a helper fn, passing the incoming args returning a vector of 
alternating symbols and vals
* creates a let form using the vector of alternating symbols and vals returned 
by the helper fn as the bindings
* contains some inner form that makes use of the bindings

i.e. is it possible to implement something that allows the following to work:

(defn binding-vec 
  [args]
  ['size (count args)])

(defn mk-dynamically-bound-fn
  [form]
  ;; returns a fn with sign [ args] which
  ;; uses binding-vec to create a the vec for
  ;; which a let statement binds around form
  )

(def a (mk-dynamically-bound-fn '(+ size 10)))

(a 1 2 3 4) ;= 14 (the number of args + 10)


Please let me know if I'm being a bit crazy with the question. It's totally 
possible that I'm barking up the wrong tree with this line of enquiry.

Sam

---
http://sam.aaron.name

-- 
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


Re: dynamically generated let bindings

2011-07-28 Thread Kent
I'm not sure what you're trying to do with this and, based on that
ignorance, I'm not sure I think it's a great idea. Maybe you are being
a bit crazy, and maybe your a genius.  Who am I to say?

Here is a function that does what you want.  The only difference is
that my function also takes the binding-vec function as an argument.


(defn mdbf [form binding-func]
  (fn [ args]
(eval `(let ~(binding-func args) ~form

Here it is used in your example.

(defn binding-vec
  [args]
   ['size (count args)]

(def a (mdbf '(+ size 10) binding-vec))

(a 1 2 3 4) = 14

Kent.

On Jul 28, 3:48 pm, Sam Aaron samaa...@gmail.com wrote:
 Hi there,

 I'm trying to create a fn which does the following:

 * returns a fn which takes an arbitrary number of args
 * calls a helper fn, passing the incoming args returning a vector of 
 alternating symbols and vals
 * creates a let form using the vector of alternating symbols and vals 
 returned by the helper fn as the bindings
 * contains some inner form that makes use of the bindings

 i.e. is it possible to implement something that allows the following to work:

 (defn binding-vec
   [args]
   ['size (count args)])

 (defn mk-dynamically-bound-fn
   [form]
   ;; returns a fn with sign [ args] which
   ;; uses binding-vec to create a the vec for
   ;; which a let statement binds around form
   )

 (def a (mk-dynamically-bound-fn '(+ size 10)))

 (a 1 2 3 4) ;= 14 (the number of args + 10)

 Please let me know if I'm being a bit crazy with the question. It's totally 
 possible that I'm barking up the wrong tree with this line of enquiry.

 Sam

 ---http://sam.aaron.name

-- 
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


Re: dynamically generated let bindings

2011-07-28 Thread Ken Wesson
On Thu, Jul 28, 2011 at 6:48 PM, Sam Aaron samaa...@gmail.com wrote:
 Hi there,

 I'm trying to create a fn which does the following:

 * returns a fn which takes an arbitrary number of args
 * calls a helper fn, passing the incoming args returning a vector of 
 alternating symbols and vals
 * creates a let form using the vector of alternating symbols and vals 
 returned by the helper fn as the bindings
 * contains some inner form that makes use of the bindings

You probably want a macro rather than a normal function here, which is
used in the body of a function or else in a manner similar to defn.

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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


Re: dynamically generated let bindings

2011-07-28 Thread Alan Malloy
On Jul 28, 3:48 pm, Sam Aaron samaa...@gmail.com wrote:
 Hi there,

 I'm trying to create a fn which does the following:

 * returns a fn which takes an arbitrary number of args
 * calls a helper fn, passing the incoming args returning a vector of 
 alternating symbols and vals
 * creates a let form using the vector of alternating symbols and vals 
 returned by the helper fn as the bindings
 * contains some inner form that makes use of the bindings

 i.e. is it possible to implement something that allows the following to work:

 (defn binding-vec
   [args]
   ['size (count args)])

 (defn mk-dynamically-bound-fn
   [form]
   ;; returns a fn with sign [ args] which
   ;; uses binding-vec to create a the vec for
   ;; which a let statement binds around form
   )

 (def a (mk-dynamically-bound-fn '(+ size 10)))

 (a 1 2 3 4) ;= 14 (the number of args + 10)

 Please let me know if I'm being a bit crazy with the question. It's totally 
 possible that I'm barking up the wrong tree with this line of enquiry.

It's not clear how much of this is relevant to your actual problem, vs
the simple version you're posting here. If all you want to do is
automatically have the args counted for you, you could:

(defn wrap-counting [f]
  (fn [ args]
(apply f (count args) args)))

(def a (wrap-counting
(fn [size  args]
  (+ size 10

If you want something more general, that implicitly binds things for
you based on some code somewhere else (ew ew ew), then you need a
macro. This implementation is pretty gross; I suspect it could be
better, but you're trying to do something that seems weird to me.

(defn binding-vec []
  ['size '(count args)])

(defmacro magic-fn
  [ forms]
  `(fn [ ~'args]
 (let ~(binding-vec)
   ~@forms)))


user ((magic-fn (+ size 10)) 1 2)
12

-- 
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


Re: dynamically generated let bindings

2011-07-28 Thread Jeff Rose
I don't think it's very typical to pass a form to a function, unless
you plan on using eval at runtime.  If it doesn't need to happen at
runtime, then you'd do this with a macro approximately like this:

user= (defmacro bar [f] `(fn [ args#] (let [~'size (count args#)]
~f)))
#'user/bar
user= (bar (+ size 10))
#user$eval675$fn__676 user$eval675$fn__676@11b4c2
user= (*1 1 2 3 4)
14

~Jeff

On Jul 28, 6:48 pm, Sam Aaron samaa...@gmail.com wrote:
 Hi there,

 I'm trying to create a fn which does the following:

 * returns a fn which takes an arbitrary number of args
 * calls a helper fn, passing the incoming args returning a vector of 
 alternating symbols and vals
 * creates a let form using the vector of alternating symbols and vals 
 returned by the helper fn as the bindings
 * contains some inner form that makes use of the bindings

 i.e. is it possible to implement something that allows the following to work:

 (defn binding-vec
   [args]
   ['size (count args)])

 (defn mk-dynamically-bound-fn
   [form]
   ;; returns a fn with sign [ args] which
   ;; uses binding-vec to create a the vec for
   ;; which a let statement binds around form
   )

 (def a (mk-dynamically-bound-fn '(+ size 10)))

 (a 1 2 3 4) ;= 14 (the number of args + 10)

 Please let me know if I'm being a bit crazy with the question. It's totally 
 possible that I'm barking up the wrong tree with this line of enquiry.

 Sam

 ---http://sam.aaron.name

-- 
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