Evan Mezeske | 1 Aug 2012 01:32
Picon
Gravatar

Re: (let [a 0] (eval 'a)))

This thread on SO might be helpful: http://stackoverflow.com/questions/6221716/variable-scope-eval-in-clojure .

On Tuesday, July 31, 2012 2:02:30 PM UTC-7, Andrew wrote:

I have a value and a string. The string contains valid Clojure code and it mentions a variable. I'd like to let-bind that variable to the value and then evaluate the string. Can this be done?

As a small example, I thought this would work: (let [a 0] (eval 'a)))

Or maybe this: 
user> (let [a 0] (eval 'user/a))

My initial attempt was this: (let [a 0] (eval (read-string "a")))

These all result in an exception...

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Lee Spector | 1 Aug 2012 02:30
Gravatar

Re: (let [a 0] (eval 'a)))


An approach that doesn't involve dynamic variables is to build, evaluate, and then call a function that's
made out of the given code and takes an argument for the variable.

Assuming for the moment that the code is in symbolic form (rather than string form) like this:

=> (def exp 'a)
#<Var <at> 2dd1082f: a>

Then you can do something like:

=> (let [a 0] ((eval (list 'fn '[a] exp)) a))
0

It's easier to see why this is useful with a slightly more complex piece of code (but it could be anything):

=> (def exp '(+ a 100))
#<Var <at> 2dd1082f: (+ a 100)>

=> (let [a 0] ((eval (list 'fn '[a] exp)) a))
100

If your code really is in a string then you want to call read-string on it:

=> (def strexp "(+ a 100)")
#<Var <at> 45d1c3cd: "(+ a 100)">

=> (let [a 0] ((eval (list 'fn '[a] (read-string strexp))) a))
100

Of course the outermost "a"s here could and probably should be something else, since that'd be less
confusing (I just used "a" to better match the original question):

=> (let [foo 0] ((eval (list 'fn '[a] (read-string strexp))) foo))
100

 -Lee

On Jul 31, 2012, at 7:32 PM, Evan Mezeske wrote:

> This thread on SO might be helpful:
http://stackoverflow.com/questions/6221716/variable-scope-eval-in-clojure .
> 
> On Tuesday, July 31, 2012 2:02:30 PM UTC-7, Andrew wrote:
> I have a value and a string. The string contains valid Clojure code and it mentions a variable. I'd like to
let-bind that variable to the value and then evaluate the string. Can this be done?
> 
> As a small example, I thought this would work: (let [a 0] (eval 'a)))
> 
> Or maybe this: 
> user> (let [a 0] (eval 'user/a))
> 
> My initial attempt was this: (let [a 0] (eval (read-string "a")))
> 
> These all result in an exception...

--

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Yoshinori Kohyama | 1 Aug 2012 07:42
Picon
Gravatar

Re:

Hi Nicolas,


Thank you for teaching!
I often use very long sequences and often want to terminate in middle of folding operations of them.
With reduce, code come to be simple and abstract, but I couldn't terminate them.
So I used to use loops or wrapping functions using loop.

Throwing a throwable object is a good alternative for me.

Thank you again.

Regards,
Yoshinori Kohyama

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Ivan Koblik | 1 Aug 2012 09:05
Picon

Re: Experiences developing a crowdfunding site for open source projects in Clojure (from a Python background)

Hi Aaron,


Thank you for such an interesting post.

You wrote that you could not setup Emacs on Windows. I decided to show you an easy way to do it.
1. Download vanilla Emacs from here:
http://ftp.gnu.org/pub/gnu/emacs/windows/

Latest version at the moment is here:
http://ftp.gnu.org/pub/gnu/emacs/windows/emacs-24.1-bin-i386.zip

2. Unpack it to a directory where you'll run it from.

3. Download this configuration:
https://rapidshare.com/files/1058404111/2011-03-emacs-config-linux.tar.gz

I prepared it on Linux but it works perfectly on Windows. I used it myself to 2 windows machines with no issues.

4. Unpack it to %APPDATA% (i.e. c:\Users\YOUR_USER_NAME\AppData\Roaming). If you had .emacs or .emacs.d there already, move them somewhere else.

That's it! Your Emacs is now configured. Easiest way to use it as REPL is to launch your application with: "lein swank" and then in Emacs M-x (Alt-x), slime-connect, enter, press enter 2 more times.

Cheers,
Ivan

On Thursday, July 26, 2012 9:59:46 PM UTC+2, Aaron Lebo wrote:
Hello!

Sometime around 2 and a half months ago, I started to work on a new project using Clojure. I've been using Python heavily for about 6 six years working for a small direct mail company and before that started programming with Ruby on Rails. This new project was something out of left field, so I had different options on what technology to use. I ended up choosing Clojure, and my work on the site has been my first real experience using a lisp, Clojure, and the JVM. I'd like to share my experiences and how that has differed with my previous Python work.

Before that, I'd like to make a little plug for my site. It is called kodefund (www.kodefund.com). The basic idea is to take the familiar Kickstarter model but to really focus on applying that to open source development. I feel that previous crowdfunding efforts have shown that there is an interest by developers to fund projects that they are enthusiastic about. When this works, everyone wins: the developer working on the project can devote their full time and effort on the actual project and still make a living and others get the benefits of the open source software. I feel like it is preferable over selling licenses to proprietary software or other efforts.

So, every project on kodefund is required to be open source. This differentiates it from other crowdfunding sites, and helps to apply a filter: you know what you are getting when you go there instead of seeing dozens of projects for unrelated stuff.

One other difference is that you can also start a project which is more or less a "reverse" Kickstarter. This allows you to take an idea for a project or issue you want fixed, raise funding, and find someone who will actually implement the project. Other users get to submit "applications" and you choose from them to find the most capable candidate. Once you chose an application, that person takes over the project.

Finally, one other push I want to make is to open up proprietary software. Maybe your company has written some software in-house, but there's no real incentive to release it. What if you could crowdfund the software, get paid to release it, and the open source community as a whole could benefit from that?

I feel like crowdfunding and open source software are an ideal fit.

I'm getting off track here. I'll shift to my actual experiences using Clojure. I was more than a little nervous about using the JVM. It always seemed like some huge, scary thing, and digging into Java libraries was not something I wanted to do. Something which resolved this was leiningen. I feel like it is absolutely brilliant, and it really makes adding libraries to your project a non-issue. Things have slowly changed in Python, but it used to be that downloading dependencies was a global process and you ended up with a site-packages that was full of dozens of old libraries that you used for other projects. Being able to specify in my project.clj file exactly which libraries I need and those getting downloaded automatically is a really nice feature that I will look for similar functionality in other languages from now on.

I was also pleasantly surprised by the library availability. The vast majority of things that I needed such as oauth2 support and such already have decent Clojure wrappers. When I did drop down into Java, I found that to be painless. The JVM really does have a wide swath of functionality already available. Some of the things that I ended up using were email libraries, date formatting libraries, and an rss feed generator. There never was a point where I felt like I was going to have to just roll things by hand. Most of the hard work has been done.

Considering the language itself, one of the first things I noticed (or didn't) was the parentheses. I don't remember when, but they simply are a non-issue after a short amount of time. One slight thing I did have a problem with was that inserting a parenthesis at the wrong place could completely alter the flow of code and it was not immediately obvious. This is not an issue when you are closing off a line or two of expressions, but when you are halfway down the page, insert a paren and everything breaks, it could get frustrating. This is probably resolved through better editor usage. I unfortunately could never get emacs with clojure-mode and goodies working properly on my Windows machine, so I ended up using the counterclockwise Eclipse plugin. It was not a horrible experience but things such as auto-indenting a large block of code was something I never figured out.

Continuing on the surface, some of my favorite parts of the language are little syntax additions. I absolutely love the syntax for anonymous functions. Python obviously has limitations with lamdas anyway, but in Clojure, having a block of code like: (do (println test) (+ 3 3)) and being able to instantly convert that to an anonymous function by sticking a # on the front is really nice. Not having to explicitly name function arguments helps as well.

Destructuring syntax is amazing. Being able to break a map or a vector down and bind numerous variables in a let or function is something that simply is not easily done in Python without some magic. It was nice to have a function definition of something like (defn index [request] ...) in a view and to be able to grab relevant needed variables using the {:keys ...} syntax.

The language is full of these little bits that are really convenient, and I was constantly surprised by something new which significantly reduced the amount of code I was writing.  Having used it, it is straight up painful in my opinion to write markup in anything else. The -> operator, hash maps as functions, etc.

One thing which surprised my was the macros. Initially I didn't use a single macro in my code, and I really couldn't figure out why the were so lauded and considered important by lots of lisp developers. That changed later in the project when I noticed a familiar pattern in my code. The basic problem was that pretty much every single web request has a familiar flow:

Does the resource exist? If not, throw a 404.
Does the user have the proper permissions to access the resource? If not, redirect to login or throw up a permission denied page.
Is this a post? If not, render a form.
If it is and the post is valid, do some work and redirect. If not valid, render the form.

This got used over and over. In Django you often see this in the form of:

def index(request):
    item = get_object_or_404(...)
    form = Form(request, item)
    if request.method == 'POST' and form.valid():
        do stuff
        redirect()
    render('index.html', dict(form=form))

This isn't the worst thing in the world, but its just extra code that gets in the way of the literal intent of the code. When I noticed this pattern I ended up writing a macro which handled the resource check, the auth check, the validation check, the redirection, etc, for me. Once I got to this point, I really "got" macros and their power. You simply don't have the ability to implement your own flow control this easily in Python.

Now, to thinking and working functionally. Python is imperative in parts. One of my favorite parts in it is the list comprehensions, which can be very functional. But for loops and destructive updates abound. Coding without for and accumulators was maybe the most difficult adjustment for me. However, once I started using map (with the aforementioned excellent anon function syntax), I started wanting to use it everywhere I could, because the concept was so simple. The same goes for reduce. Much of the pain of lacking destructive updates is mitigated with things like update-in, and such.

I guess for me the real question is whether programming functionally actually reduces the number of errors as some functional advocates put forward. The problem is that it is so damn hard to objectively compare the two. Did I have more errors when I was programming in Python compared to Clojure? I'd say most of my errors actually came from unfamiliarity of libraries or functionality. The idea that errors can be reduced is interesting, but I'm not ready to fully commit to that suggestion unless we really see hard data. I do know that there are places where destructive updates would be convenient, but I can appreciate basis of programming functionally.

Was there anything I missed when using Clojure compared to Python? The libraries seem to be a wash, the languages themselves are comparable. If anything I did want maturity in some of the libraries. For example, noir has an excellent error validation library. However, compared to Python libraries which do validation and conversion, I found myself writing and debugging extra functionality that I had to implement. I found myself digging around in github repos to actual read code instead of documentation a lot more than I ever did with Python. Obviously these are just issues of time, and they'll improve. Clojure docs and the cheatsheet help a lot, though.

Stacktraces can take a while to get used to, and some of the error messages are cryptic. I can't say how many hours I spent figuring out why #([:key "test"]) wasn't working (you can't place a vector literal directly inside an anonymous function like this. Maybe that should have been obvious to me, but once I ran across these issues and understood them, the pain of understanding stacktraces was mitigated by a large margin.

I guess if there is anything I'd love to see is some kind of style guide. Python has the PEP8 style guide, which more or less suggests how code should be written, not that it has to be written that way. There were lots of times I found myself wondering whether the "right" way was to indent the if form after the conditional or first argument, or whether it was considered "bad" form to nest multiple lets, and how that should be handled. The current cheat sheet is similar, but its not very prescriptive. I'd love to see something which suggests how common tasks should be done, I feel like it might help newbies like me feel more at ease. Does such a thing like PEP 8 exist for Clojure?

Well, those are some of my notes on using Clojure. I feel a little embarrassed writing this up because I feel like someone will pick it to death, and I'm wish I could delve further into hard details instead of dwelling so much on little syntax differences. It has been a fun, useful learning experience, anyway. I feel like anyone who has not worked with a lisp or a functional programming language owes it to their own development to work with Clojure, it really does help you to understand the whats and whys of the JVM, macros, and functional programming.

I'd especially love to see, kodefund, used by the Clojure community. I feel like it is a great way to get new libraries off the ground, or to find people to fix bugs, or even to open up previously  closed software.

If there was a project that you were considering putting on Kickstarter or one of the other crowdfunding sites, please consider kodefund. Unlike the bigger sites, you will have my full attention to your project, and I'm more than willing to work with you to improve and change parts of the site which make crowdfunding more suitable to open source projects.

I've worked really hard to make things as simple as possible. You can start or fund a project no matter where you live, all that is needed to make a pledge is a credit card, and github, twitter, facebook, google are all supported to sign up. Give it a try, let me know what you think. I've tried to explain the rationale further here: http://www.kodefund.com/about/

So, if you've got any questions about kodefund or Python/Clojure, I'm happy to answer them. Thanks to those who have spent their time making this such a useful language!

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Maik Schünemann | 1 Aug 2012 10:50
Picon

Re: Experiences developing a crowdfunding site for open source projects in Clojure (from a Python background)

I very recently set up emacs on windows for work with clojure. (finally using clojure at work :))
Nowadays it is not difficult to install ist just get emacs and set the home variable of your system where you want to put your
.emacs and .emacs.d.
then downloading clojure mode and installing slime like in the instructions and you can do M-x clojure-jack-in

Your post was very interesting

On Wed, Aug 1, 2012 at 9:05 AM, Ivan Koblik <ivankoblik <at> gmail.com> wrote:
Hi Aaron,

Thank you for such an interesting post.

You wrote that you could not setup Emacs on Windows. I decided to show you an easy way to do it.
1. Download vanilla Emacs from here:

Latest version at the moment is here:

2. Unpack it to a directory where you'll run it from.

3. Download this configuration:

I prepared it on Linux but it works perfectly on Windows. I used it myself to 2 windows machines with no issues.

4. Unpack it to %APPDATA% (i.e. c:\Users\YOUR_USER_NAME\AppData\Roaming). If you had .emacs or .emacs.d there already, move them somewhere else.

That's it! Your Emacs is now configured. Easiest way to use it as REPL is to launch your application with: "lein swank" and then in Emacs M-x (Alt-x), slime-connect, enter, press enter 2 more times.

Cheers,
Ivan

On Thursday, July 26, 2012 9:59:46 PM UTC+2, Aaron Lebo wrote:
Hello!

Sometime around 2 and a half months ago, I started to work on a new project using Clojure. I've been using Python heavily for about 6 six years working for a small direct mail company and before that started programming with Ruby on Rails. This new project was something out of left field, so I had different options on what technology to use. I ended up choosing Clojure, and my work on the site has been my first real experience using a lisp, Clojure, and the JVM. I'd like to share my experiences and how that has differed with my previous Python work.

Before that, I'd like to make a little plug for my site. It is called kodefund (www.kodefund.com). The basic idea is to take the familiar Kickstarter model but to really focus on applying that to open source development. I feel that previous crowdfunding efforts have shown that there is an interest by developers to fund projects that they are enthusiastic about. When this works, everyone wins: the developer working on the project can devote their full time and effort on the actual project and still make a living and others get the benefits of the open source software. I feel like it is preferable over selling licenses to proprietary software or other efforts.

So, every project on kodefund is required to be open source. This differentiates it from other crowdfunding sites, and helps to apply a filter: you know what you are getting when you go there instead of seeing dozens of projects for unrelated stuff.

One other difference is that you can also start a project which is more or less a "reverse" Kickstarter. This allows you to take an idea for a project or issue you want fixed, raise funding, and find someone who will actually implement the project. Other users get to submit "applications" and you choose from them to find the most capable candidate. Once you chose an application, that person takes over the project.

Finally, one other push I want to make is to open up proprietary software. Maybe your company has written some software in-house, but there's no real incentive to release it. What if you could crowdfund the software, get paid to release it, and the open source community as a whole could benefit from that?

I feel like crowdfunding and open source software are an ideal fit.

I'm getting off track here. I'll shift to my actual experiences using Clojure. I was more than a little nervous about using the JVM. It always seemed like some huge, scary thing, and digging into Java libraries was not something I wanted to do. Something which resolved this was leiningen. I feel like it is absolutely brilliant, and it really makes adding libraries to your project a non-issue. Things have slowly changed in Python, but it used to be that downloading dependencies was a global process and you ended up with a site-packages that was full of dozens of old libraries that you used for other projects. Being able to specify in my project.clj file exactly which libraries I need and those getting downloaded automatically is a really nice feature that I will look for similar functionality in other languages from now on.

I was also pleasantly surprised by the library availability. The vast majority of things that I needed such as oauth2 support and such already have decent Clojure wrappers. When I did drop down into Java, I found that to be painless. The JVM really does have a wide swath of functionality already available. Some of the things that I ended up using were email libraries, date formatting libraries, and an rss feed generator. There never was a point where I felt like I was going to have to just roll things by hand. Most of the hard work has been done.

Considering the language itself, one of the first things I noticed (or didn't) was the parentheses. I don't remember when, but they simply are a non-issue after a short amount of time. One slight thing I did have a problem with was that inserting a parenthesis at the wrong place could completely alter the flow of code and it was not immediately obvious. This is not an issue when you are closing off a line or two of expressions, but when you are halfway down the page, insert a paren and everything breaks, it could get frustrating. This is probably resolved through better editor usage. I unfortunately could never get emacs with clojure-mode and goodies working properly on my Windows machine, so I ended up using the counterclockwise Eclipse plugin. It was not a horrible experience but things such as auto-indenting a large block of code was something I never figured out.

Continuing on the surface, some of my favorite parts of the language are little syntax additions. I absolutely love the syntax for anonymous functions. Python obviously has limitations with lamdas anyway, but in Clojure, having a block of code like: (do (println test) (+ 3 3)) and being able to instantly convert that to an anonymous function by sticking a # on the front is really nice. Not having to explicitly name function arguments helps as well.

Destructuring syntax is amazing. Being able to break a map or a vector down and bind numerous variables in a let or function is something that simply is not easily done in Python without some magic. It was nice to have a function definition of something like (defn index [request] ...) in a view and to be able to grab relevant needed variables using the {:keys ...} syntax.

The language is full of these little bits that are really convenient, and I was constantly surprised by something new which significantly reduced the amount of code I was writing.  Having used it, it is straight up painful in my opinion to write markup in anything else. The -> operator, hash maps as functions, etc.

One thing which surprised my was the macros. Initially I didn't use a single macro in my code, and I really couldn't figure out why the were so lauded and considered important by lots of lisp developers. That changed later in the project when I noticed a familiar pattern in my code. The basic problem was that pretty much every single web request has a familiar flow:

Does the resource exist? If not, throw a 404.
Does the user have the proper permissions to access the resource? If not, redirect to login or throw up a permission denied page.
Is this a post? If not, render a form.
If it is and the post is valid, do some work and redirect. If not valid, render the form.

This got used over and over. In Django you often see this in the form of:

def index(request):
    item = get_object_or_404(...)
    form = Form(request, item)
    if request.method == 'POST' and form.valid():
        do stuff
        redirect()
    render('index.html', dict(form=form))

This isn't the worst thing in the world, but its just extra code that gets in the way of the literal intent of the code. When I noticed this pattern I ended up writing a macro which handled the resource check, the auth check, the validation check, the redirection, etc, for me. Once I got to this point, I really "got" macros and their power. You simply don't have the ability to implement your own flow control this easily in Python.

Now, to thinking and working functionally. Python is imperative in parts. One of my favorite parts in it is the list comprehensions, which can be very functional. But for loops and destructive updates abound. Coding without for and accumulators was maybe the most difficult adjustment for me. However, once I started using map (with the aforementioned excellent anon function syntax), I started wanting to use it everywhere I could, because the concept was so simple. The same goes for reduce. Much of the pain of lacking destructive updates is mitigated with things like update-in, and such.

I guess for me the real question is whether programming functionally actually reduces the number of errors as some functional advocates put forward. The problem is that it is so damn hard to objectively compare the two. Did I have more errors when I was programming in Python compared to Clojure? I'd say most of my errors actually came from unfamiliarity of libraries or functionality. The idea that errors can be reduced is interesting, but I'm not ready to fully commit to that suggestion unless we really see hard data. I do know that there are places where destructive updates would be convenient, but I can appreciate basis of programming functionally.

Was there anything I missed when using Clojure compared to Python? The libraries seem to be a wash, the languages themselves are comparable. If anything I did want maturity in some of the libraries. For example, noir has an excellent error validation library. However, compared to Python libraries which do validation and conversion, I found myself writing and debugging extra functionality that I had to implement. I found myself digging around in github repos to actual read code instead of documentation a lot more than I ever did with Python. Obviously these are just issues of time, and they'll improve. Clojure docs and the cheatsheet help a lot, though.

Stacktraces can take a while to get used to, and some of the error messages are cryptic. I can't say how many hours I spent figuring out why #([:key "test"]) wasn't working (you can't place a vector literal directly inside an anonymous function like this. Maybe that should have been obvious to me, but once I ran across these issues and understood them, the pain of understanding stacktraces was mitigated by a large margin.

I guess if there is anything I'd love to see is some kind of style guide. Python has the PEP8 style guide, which more or less suggests how code should be written, not that it has to be written that way. There were lots of times I found myself wondering whether the "right" way was to indent the if form after the conditional or first argument, or whether it was considered "bad" form to nest multiple lets, and how that should be handled. The current cheat sheet is similar, but its not very prescriptive. I'd love to see something which suggests how common tasks should be done, I feel like it might help newbies like me feel more at ease. Does such a thing like PEP 8 exist for Clojure?

Well, those are some of my notes on using Clojure. I feel a little embarrassed writing this up because I feel like someone will pick it to death, and I'm wish I could delve further into hard details instead of dwelling so much on little syntax differences. It has been a fun, useful learning experience, anyway. I feel like anyone who has not worked with a lisp or a functional programming language owes it to their own development to work with Clojure, it really does help you to understand the whats and whys of the JVM, macros, and functional programming.

I'd especially love to see, kodefund, used by the Clojure community. I feel like it is a great way to get new libraries off the ground, or to find people to fix bugs, or even to open up previously  closed software.

If there was a project that you were considering putting on Kickstarter or one of the other crowdfunding sites, please consider kodefund. Unlike the bigger sites, you will have my full attention to your project, and I'm more than willing to work with you to improve and change parts of the site which make crowdfunding more suitable to open source projects.

I've worked really hard to make things as simple as possible. You can start or fund a project no matter where you live, all that is needed to make a pledge is a credit card, and github, twitter, facebook, google are all supported to sign up. Give it a try, let me know what you think. I've tried to explain the rationale further here: http://www.kodefund.com/about/

So, if you've got any questions about kodefund or Python/Clojure, I'm happy to answer them. Thanks to those who have spent their time making this such a useful language!

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure <at> 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+unsubscribe <at> 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 post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Vinay D.E | 1 Aug 2012 14:21
Picon

Re: swap! and atom behavior

Thanks Sean & Carlo for the detailed comments!
The gap in my understanding was exactly *how* lazy 'lazy evaluation' is, so the evaluation of 'i' is deferred until it is totally unavoidable.

Just curious, but if I chained a large number of such lazy constructs, isn't there danger of a big unpredictable spike in CPU / Memory if something deeply nested is accessed ?
Is there someplace where this is discussed in detail, pros / cons, caveats, concepts etc ? Any books that you think I should read ?

Regards
Vinay


On Tuesday, 31 July 2012 12:05:13 UTC+5:30, Sean Corfield wrote:

> I tried putting a print and it works as expected.

Because you are realizing the whole of i to print it.

> 1) I assumed that printing out [i <at> a] instead of [ <at> a i] should realize 'i'

No, [i <at> a] creates a two-element vector of a lazy-seq and a value (the
deref of a). Then, when the REPL prints that vector, it realizes the
lazy-seq.

> 2) If I put a breakpoint in the predicate for take-while, it gets hit ( I

Yes, it is hit while i is being realized.

> 3) This is the strangest observation of all: In the debugger I can see that
> 'a' is getting incremented, its changing when the breakpoint is hit!  but
> the baffling thing is, when the result is printed out, I still get 0 as the
> value for a.

Because the value of <at> a is bound before i is realized, so 0 is bound
into the vector, and then i is realized during which process you see a
being incremented.

> Isn't (print i) the same as [i <at> a] ?  since i is realized first, shouldn't
> <at> a  be correctly printed?

No, see above.

> Why is the breakpoint showing me that a is changing ?

Because it _is_ changing but _after_ the top level of the vector has
been evaluated.
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Joop Kiefte | 1 Aug 2012 14:31
Picon
Gravatar

Re: swap! and atom behavior

Just pay attention that when using later elements you don't need the
earlier elements, and you should be fine. (IIRC)

2012/8/1 Vinay D.E <devinay <at> gmail.com>:
> Thanks Sean & Carlo for the detailed comments!
> The gap in my understanding was exactly *how* lazy 'lazy evaluation' is, so
> the evaluation of 'i' is deferred until it is totally unavoidable.
>
> Just curious, but if I chained a large number of such lazy constructs, isn't
> there danger of a big unpredictable spike in CPU / Memory if something
> deeply nested is accessed ?
> Is there someplace where this is discussed in detail, pros / cons, caveats,
> concepts etc ? Any books that you think I should read ?
>
> Regards
> Vinay
>
>
>
> On Tuesday, 31 July 2012 12:05:13 UTC+5:30, Sean Corfield wrote:
>>
>> > I tried putting a print and it works as expected.
>>
>> Because you are realizing the whole of i to print it.
>>
>> > 1) I assumed that printing out [i  <at> a] instead of [ <at> a i] should realize
>> > 'i'
>>
>> No, [i  <at> a] creates a two-element vector of a lazy-seq and a value (the
>> deref of a). Then, when the REPL prints that vector, it realizes the
>> lazy-seq.
>>
>> > 2) If I put a breakpoint in the predicate for take-while, it gets hit (
>> > I
>>
>> Yes, it is hit while i is being realized.
>>
>> > 3) This is the strangest observation of all: In the debugger I can see
>> > that
>> > 'a' is getting incremented, its changing when the breakpoint is hit!
>> > but
>> > the baffling thing is, when the result is printed out, I still get 0 as
>> > the
>> > value for a.
>>
>> Because the value of  <at> a is bound before i is realized, so 0 is bound
>> into the vector, and then i is realized during which process you see a
>> being incremented.
>>
>> > Isn't (print i) the same as [i  <at> a] ?  since i is realized first,
>> > shouldn't
>> >  <at> a  be correctly printed?
>>
>> No, see above.
>>
>> > Why is the breakpoint showing me that a is changing ?
>>
>> Because it _is_ changing but _after_ the top level of the vector has
>> been evaluated.
>> --
>> Sean A Corfield -- (904) 302-SEAN
>> An Architect's View -- http://corfield.org/
>> World Singles, LLC. -- http://worldsingles.com/
>>
>> "Perfection is the enemy of the good."
>> -- Gustave Flaubert, French realist novelist (1821-1880)
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure <at> 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+unsubscribe <at> 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 post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Vinay D.E | 1 Aug 2012 14:34
Picon

Re: atom / swap! question

Thanks for your replies Marshal & Jim.
I had not understood the 'laziness' concept correctly and was expecting it to behave differently.
I thought that this post had somehow disappeared and I started another one on the same topic. Sorry about that.

--Vinay




On Tuesday, 31 July 2012 18:17:00 UTC+5:30, Marshall Vandegrift wrote:

"Vinay D.E" writes:

> I am a newbie and was doing some exercises when I ran across something that
> I don't understand.
> I am trying to count the number of elements in an array less than 100.
>
> My first attempt didn't work. The counter returns 0
>
> (let [a (atom 0)
>       i (take-while (fn[x] (swap! a inc) (< x 100))  [1 2 3 4 5])]
>   [ <at> a i])  => [0 (1 2 3 4 5)]

The primary concrete problem is laziness, but fundamentally this sort of
mutable-imperative algorithm doesn't play nice with Clojure's core
features.

The sequence returned by `take-while` is lazy, and none of the function
applications required to generate that sequence actually happen until
something forces evaluation of the sequence elements.  So when you get
the result of `[ <at> a i]` what happens is:

  (1) ` <at> a` is evaluated; nothing else has actually happened yet, so the
      result is still the initial value of `0`.

  (2) `i` is evaluated; now the sequence is forced and generated, and as
      a side-effect the atom is updated.

Instead of depending on mutating side-effects to do these sorts of
calculations, most of the Clojure standard library assumes that you'll
be working with (largely) pure functions which operate primarily in
terms of their parameters and return values.  As an aside, you probably
wanted `filter` instead of `take-while` even for what you were trying to
do in the first place -- you should be able to figure out the difference
from the docs.  So, using pure functions, we can something as simple as:

  (count (filter #(< x 100) input-sequence))

HTH,

-Marshall

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Meikel Brandmeyer (kotarak | 1 Aug 2012 14:45
Picon
Favicon
Gravatar

Re: swap! and atom behavior

Hi,

Am Mittwoch, 1. August 2012 14:21:22 UTC+2 schrieb Vinay D.E:


Just curious, but if I chained a large number of such lazy constructs, isn't there danger of a big unpredictable spike in CPU / Memory if something deeply nested is accessed ?
Is there someplace where this is discussed in detail, pros / cons, caveats, concepts etc ? Any books that you think I should read ?

I gave a talk on lazy sequences (and their history) on this year's EuroClojure conference in London. The videos are in the process of being published at vimeo.

Kind regards
Meikel

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Andrew Cheng | 1 Aug 2012 23:32
Picon

Re: (let [a 0] (eval 'a)))

Thanks Evan and Lee....  Lee's approach works in my code except for one interesting wrinkle. The item that I pass in ('a' in the example) can only really be used if a particular library is loaded.


So what I'm doing now is taking the code string from the user -- user-string -- and wrapping it like this 

(format "(do (require '[my.lib :as lib]) (try %s (catch Exception e e)))" user-string)

... bound to expr. And then I get the result...

(try ((eval (list 'fn '[a] (read-string expr))) a) (catch Exception e e))

... This is all presented to the user in a Seesaw UI form. 

Here's the wrinkle: code that uses any fn from lib throws an exception No such namespace: lib

But if I try again with just a (the value) or any other expression like 1, that succeeds. And then if I try the code from the initial attempt (the exact code that failed in the previous paragraph) it now also succeeds! Why might that be?


On Tue, Jul 31, 2012 at 8:30 PM, Lee Spector <> wrote:

An approach that doesn't involve dynamic variables is to build, evaluate, and then call a function that's made out of the given code and takes an argument for the variable.

Assuming for the moment that the code is in symbolic form (rather than string form) like this:

=> (def exp 'a)
#<Var <at> 2dd1082f: a>

Then you can do something like:

=> (let [a 0] ((eval (list 'fn '[a] exp)) a))
0

It's easier to see why this is useful with a slightly more complex piece of code (but it could be anything):

=> (def exp '(+ a 100))
#<Var <at> 2dd1082f: (+ a 100)>

=> (let [a 0] ((eval (list 'fn '[a] exp)) a))
100

If your code really is in a string then you want to call read-string on it:

=> (def strexp "(+ a 100)")
#<Var <at> 45d1c3cd: "(+ a 100)">

=> (let [a 0] ((eval (list 'fn '[a] (read-string strexp))) a))
100

Of course the outermost "a"s here could and probably should be something else, since that'd be less confusing (I just used "a" to better match the original question):

=> (let [foo 0] ((eval (list 'fn '[a] (read-string strexp))) foo))
100

 -Lee


On Jul 31, 2012, at 7:32 PM, Evan Mezeske wrote:

> This thread on SO might be helpful: http://stackoverflow.com/questions/6221716/variable-scope-eval-in-clojure .
>
> On Tuesday, July 31, 2012 2:02:30 PM UTC-7, Andrew wrote:
> I have a value and a string. The string contains valid Clojure code and it mentions a variable. I'd like to let-bind that variable to the value and then evaluate the string. Can this be done?
>
> As a small example, I thought this would work: (let [a 0] (eval 'a)))
>
> Or maybe this:
> user> (let [a 0] (eval 'user/a))
>
> My initial attempt was this: (let [a 0] (eval (read-string "a")))
>
> These all result in an exception...

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure <at> 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+unsubscribe <at> 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 post to this group, send email to clojure <at> 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+unsubscribe <at> googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Gmane