Re: the semantic of if-let macro
The docs are clear that the test occurs before the bindings: (doc if-let) - clojure.core/if-let ([bindings then] [bindings then else & oldform]) Macro bindings => binding-form test If test is true, evaluates then with binding-form bound to the value of test, if not, yields else Cheers, Stu On Thu, Jan 31, 2013 at 2:43 AM, Mimmo Cosenza wrote: > > On Thursday, January 31, 2013 1:49:40 AM UTC+1, Sean Corfield wrote: > >> but now that you've posted this, I >> can see some potential for confusion when folks first encounter >> if-let... Presumably the same confusion could arise for when-let? >> > > yes, this is the confusion that you can incur in. > > mimmo > > -- > -- > 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: the semantic of if-let macro
On Thursday, January 31, 2013 1:49:40 AM UTC+1, Sean Corfield wrote: > but now that you've posted this, I > can see some potential for confusion when folks first encounter > if-let... Presumably the same confusion could arise for when-let? > yes, this is the confusion that you can incur in. mimmo -- -- 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: the semantic of if-let macro
On Wednesday, January 30, 2013 8:51:47 PM UTC+1, Gary Verhaegen wrote: > For your particular use-case, what you want is more along the lines of > > (if-let [errors (:password (fn-returning-errors))] > ...) > yes, precisely! mimmo -- -- 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: the semantic of if-let macro
ant to select just the email errors I would write something like >> >> that >> >> >> >> (if-let [{errors :email} (function-returning-error email password)] >> >> true >> >> false) >> >> >> >> Reading the above code you're led to believe that if there are email >> >> errors, errors local binding will be true. Instead, it returns true >> >> even >> >> if the are no email errors but there are password errors and you never >> >> get the false branch. >> >> >> >> An if you want to catch password errors you would write something like >> >> >> >> (if-let [{errors :password} (function-returning-errors email password)] >> >> true >> >> false) >> >> >> >> In either case you never get the false branch when >> >> function-returning-errors return an error which is not the one you're >> >> looking for >> >> >> >> Mimmo >> >> >> >> >> >> On Jan 30, 2013, at 10:05 AM, James Xu >> >> wrote: >> >> >> >>> From the expansion we can see that if-let determine the result based >> >>> on >> >>> the second param, in your case: {:key2 "a string"}, not the local >> >>> binding >> >>> you assumed(key1), and >> >>> I think it is reasonable, for example, if we have the following code: >> >>> >> >>> (if-let [{key1 key2} {:key2 "a string"}] >> >>> true >> >>> false)) >> >>> >> >>> >> >>> Should if-let determine the result based on key1? key2? IMO {key1 >> >>> key2} >> >>> in >> >>> a whole is more reaonable. And {key1 key2} == {:key2 "a string"}, then >> >>> the >> >>> result is true. >> >>> >> >>> >> >>> >> >>> On 13-1-30 下午4:51, "Mimmo Cosenza" wrote: >> >>> >> >>>> Hi all, >> >>>> I'm a little bit confused about the semantic of if-let macro. >> >>>> >> >>>> Suppose to call it as follows with map destructoring: >> >>>> >> >>>> (if-let [{key1 :key1} {:key2 "a string"}] >> >>>> true >> >>>> false)) >> >>>> >> >>>> It returns true. >> >>>> >> >>>> But, >> >>>> >> >>>> (let [{key1 :key1} {:key2 "a string"}] >> >>>> (if key1 >> >>>> true >> >>>> false)) >> >>>> >> >>>> returns false. >> >>>> >> >>>> >> >>>> The macro expansion of the former explains why >> >>>> >> >>>> (macroexpand-1 '(if-let [{key1 :key1} {:key2 "a string"}] true >> >>>> false)) >> >>>> >> >>>> returns >> >>>> (clojure.core/let [temp__3971__auto__ {:key2 "a string"}] (if >> >> >> >> >> -- >> -- >> 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. > > > > > -- > -- > 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. > > -- 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@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: the semantic of if-let macro
Perhaps I've been a little bit rude with if-let, but I really do not see how (if-let [{erros :email} (function-returning-errors email password)] true false) is not misleading. I now that the tested value is the one returning from the function call and not the value assigned to errors local, but exactly this is misleading in reading the code. What I'm saying is that in such a case (i.e. if-let + sequence destructoring) you're just coding wrong. I'm not say that if-let is wrong. So I prefer not to use if-let when I'm restructuring because I could easily create a subtle bug. I don't like complexity when is not needed. You already have the if-let limitation in the number of locals you can use. Now you have this subtle behaviour to pay attention to. If I now that something is dangerous I prefer to stay a little bit apart from it. Mimmo On Jan 30, 2013, at 8:51 PM, Gary Verhaegen wrote: > If-let does the right thing. What would your intuition expect for > > (if-let [{a :a b :b} {:a 1 :b nil}] > true > false) > > For your particular use-case, what you want is more along the lines of > > (if-let [errors (:password (fn-returning-errors))] > ...) > > On Wednesday, January 30, 2013, Ben Smith-Mannschott wrote: > I find it helpful to view if-let as a minor variation on if, with the only > difference being that you choose to bind the results of the test-expression > to some name(s). if-let doesn't care about the values bound to the variables > named in binding-target (which might be an arbitrarily complex > destructuring). If that's not what you want, then if-let isn't the right tool > for the job. > > (if test-expression > expression-evaluated-when-test-expression-is-truthy > expression-evaluated-otherwise) > > is similar to > > (if-let [ binding-target test-expression ] > expression-evaluated-when-test-expression-is-truthy > expression-evaluated-otherwise) > > expands to roughly this, except that test-expression is evaluated only once: > > (if test-expression > (let [binding-target test-expression] > expression-evaluated-when-test-expression-is-truthy) > expression-evaluated-otherwise) > > It took me a little while to understand that this is how it worked when I > began with clojure, but it seems pretty natural now. if-let is really > simple-minded. don't over-think it. > > // ben > > > On Wed, Jan 30, 2013 at 10:42 AM, Mimmo Cosenza > wrote: > that means never use if-let with sequential destructoring, which brings me to > say: never use if-let, because I don't' like to remember such thing while > coding and then become crazy to catch my error because of a misleading > language feature. > > mimmo > > > On Jan 30, 2013, at 10:32 AM, James Xu wrote: > > > Agree with you that it is very misleading when using map-destructure in > > if-let, the same applies to sequential-destructure: > > > > user=> (if-let [[_ x] [1 nil]] true false) > > true > > > > > > > > On 13-1-30 下午5:23, "Mimmo Cosenza" wrote: > > > >> Uhm, I do not agree. > >> > >> Suppose tha you have a function returning a map of errors (a valip > >> validator lib real case) like the following > >> > >> {:email ["Email can't be empty"] :password ["Password can't be empty"]} > >> > >> If I want to select just the email errors I would write something like > >> that > >> > >> (if-let [{errors :email} (function-returning-error email password)] > >> true > >> false) > >> > >> Reading the above code you're led to believe that if there are email > >> errors, errors local binding will be true. Instead, it returns true even > >> if the are no email errors but there are password errors and you never > >> get the false branch. > >> > >> An if you want to catch password errors you would write something like > >> > >> (if-let [{errors :password} (function-returning-errors email password)] > >> true > >> false) > >> > >> In either case you never get the false branch when > >> function-returning-errors return an error which is not the one you're > >> looking for > >> > >> Mimmo > >> > >> > >> On Jan 30, 2013, at 10:05 AM, James Xu > >> wrote: > >> > >>> From the expansion we can see that if-let determine the result based on > >>> the second param, in your case: {:key2 "a string"}, not the loc
Re: the semantic of if-let macro
If-let does the right thing. What would your intuition expect for (if-let [{a :a b :b} {:a 1 :b nil}] true false) For your particular use-case, what you want is more along the lines of (if-let [errors (:password (fn-returning-errors))] ...) On Wednesday, January 30, 2013, Ben Smith-Mannschott wrote: > I find it helpful to view if-let as a minor variation on if, with the only > difference being that you choose to bind the results of the test-expression > to some name(s). if-let doesn't care about the values bound to the > variables named in binding-target (which might be an arbitrarily complex > destructuring). If that's not what you want, then if-let isn't the right > tool for the job. > > (if test-expression > expression-evaluated-when-test-expression-is-truthy > expression-evaluated-otherwise) > > is similar to > > (if-let [ binding-target test-expression ] > expression-evaluated-when-test-expression-is-truthy > expression-evaluated-otherwise) > > expands to roughly this, except that test-expression is evaluated only > once: > > (if test-expression > (let [binding-target test-expression] > expression-evaluated-when-test-expression-is-truthy) > expression-evaluated-otherwise) > > It took me a little while to understand that this is how it worked when I > began with clojure, but it seems pretty natural now. if-let is really > simple-minded. don't over-think it. > > // ben > > > On Wed, Jan 30, 2013 at 10:42 AM, Mimmo Cosenza > wrote: > > that means never use if-let with sequential destructoring, which brings me > to say: never use if-let, because I don't' like to remember such thing > while coding and then become crazy to catch my error because of a > misleading language feature. > > mimmo > > > On Jan 30, 2013, at 10:32 AM, James Xu > wrote: > > > Agree with you that it is very misleading when using map-destructure in > > if-let, the same applies to sequential-destructure: > > > > user=> (if-let [[_ x] [1 nil]] true false) > > true > > > > > > > > On 13-1-30 下午5:23, "Mimmo Cosenza" wrote: > > > >> Uhm, I do not agree. > >> > >> Suppose tha you have a function returning a map of errors (a valip > >> validator lib real case) like the following > >> > >> {:email ["Email can't be empty"] :password ["Password can't be empty"]} > >> > >> If I want to select just the email errors I would write something like > >> that > >> > >> (if-let [{errors :email} (function-returning-error email password)] > >> true > >> false) > >> > >> Reading the above code you're led to believe that if there are email > >> errors, errors local binding will be true. Instead, it returns true even > >> if the are no email errors but there are password errors and you never > >> get the false branch. > >> > >> An if you want to catch password errors you would write something like > >> > >> (if-let [{errors :password} (function-returning-errors email password)] > >> true > >> false) > >> > >> In either case you never get the false branch when > >> function-returning-errors return an error which is not the one you're > >> looking for > >> > >> Mimmo > >> > >> > >> On Jan 30, 2013, at 10:05 AM, James Xu > >> wrote: > >> > >>> From the expansion we can see that if-let determine the result based on > >>> the second param, in your case: {:key2 "a string"}, not the local > >>> binding > >>> you assumed(key1), and > >>> I think it is reasonable, for example, if we have the following code: > >>> > >>> (if-let [{key1 key2} {:key2 "a string"}] > >>> true > >>> false)) > >>> > >>> > >>> Should if-let determine the result based on key1? key2? IMO {key1 key2} > >>> in > >>> a whole is more reaonable. And {key1 key2} == {:key2 "a string"}, then > >>> the > >>> result is true. > >>> > >>> > >>> > >>> On 13-1-30 下午4:51, "Mimmo Cosenza" wrote: > >>> > >>>> Hi all, > >>>> I'm a little bit confused about the semantic of if-let macro. > >>>> > >>>> Suppose to call it as follows with map destructoring: > >>>> > >>>> (if-let [{key1 :key1
Re: the semantic of if-let macro
I find it helpful to view if-let as a minor variation on if, with the only difference being that you choose to bind the results of the test-expression to some name(s). if-let doesn't care about the values bound to the variables named in binding-target (which might be an arbitrarily complex destructuring). If that's not what you want, then if-let isn't the right tool for the job. (if test-expression expression-evaluated-when-test-expression-is-truthy expression-evaluated-otherwise) is similar to (if-let [ binding-target test-expression ] expression-evaluated-when-test-expression-is-truthy expression-evaluated-otherwise) expands to roughly this, except that test-expression is evaluated only once: (if test-expression (let [binding-target test-expression] expression-evaluated-when-test-expression-is-truthy) expression-evaluated-otherwise) It took me a little while to understand that this is how it worked when I began with clojure, but it seems pretty natural now. if-let is really simple-minded. don't over-think it. // ben On Wed, Jan 30, 2013 at 10:42 AM, Mimmo Cosenza wrote: > that means never use if-let with sequential destructoring, which brings me > to say: never use if-let, because I don't' like to remember such thing > while coding and then become crazy to catch my error because of a > misleading language feature. > > mimmo > > > On Jan 30, 2013, at 10:32 AM, James Xu > wrote: > > > Agree with you that it is very misleading when using map-destructure in > > if-let, the same applies to sequential-destructure: > > > > user=> (if-let [[_ x] [1 nil]] true false) > > true > > > > > > > > On 13-1-30 下午5:23, "Mimmo Cosenza" wrote: > > > >> Uhm, I do not agree. > >> > >> Suppose tha you have a function returning a map of errors (a valip > >> validator lib real case) like the following > >> > >> {:email ["Email can't be empty"] :password ["Password can't be empty"]} > >> > >> If I want to select just the email errors I would write something like > >> that > >> > >> (if-let [{errors :email} (function-returning-error email password)] > >> true > >> false) > >> > >> Reading the above code you're led to believe that if there are email > >> errors, errors local binding will be true. Instead, it returns true even > >> if the are no email errors but there are password errors and you never > >> get the false branch. > >> > >> An if you want to catch password errors you would write something like > >> > >> (if-let [{errors :password} (function-returning-errors email password)] > >> true > >> false) > >> > >> In either case you never get the false branch when > >> function-returning-errors return an error which is not the one you're > >> looking for > >> > >> Mimmo > >> > >> > >> On Jan 30, 2013, at 10:05 AM, James Xu > >> wrote: > >> > >>> From the expansion we can see that if-let determine the result based on > >>> the second param, in your case: {:key2 "a string"}, not the local > >>> binding > >>> you assumed(key1), and > >>> I think it is reasonable, for example, if we have the following code: > >>> > >>> (if-let [{key1 key2} {:key2 "a string"}] > >>> true > >>> false)) > >>> > >>> > >>> Should if-let determine the result based on key1? key2? IMO {key1 key2} > >>> in > >>> a whole is more reaonable. And {key1 key2} == {:key2 "a string"}, then > >>> the > >>> result is true. > >>> > >>> > >>> > >>> On 13-1-30 下午4:51, "Mimmo Cosenza" wrote: > >>> > >>>> Hi all, > >>>> I'm a little bit confused about the semantic of if-let macro. > >>>> > >>>> Suppose to call it as follows with map destructoring: > >>>> > >>>> (if-let [{key1 :key1} {:key2 "a string"}] > >>>> true > >>>> false)) > >>>> > >>>> It returns true. > >>>> > >>>> But, > >>>> > >>>> (let [{key1 :key1} {:key2 "a string"}] > >>>> (if key1 > >>>> true > >>>> false)) > >>>> > >>>> returns false. > >>>> > >
Re: the semantic of if-let macro
that means never use if-let with sequential destructoring, which brings me to say: never use if-let, because I don't' like to remember such thing while coding and then become crazy to catch my error because of a misleading language feature. mimmo On Jan 30, 2013, at 10:32 AM, James Xu wrote: > Agree with you that it is very misleading when using map-destructure in > if-let, the same applies to sequential-destructure: > > user=> (if-let [[_ x] [1 nil]] true false) > true > > > > On 13-1-30 下午5:23, "Mimmo Cosenza" wrote: > >> Uhm, I do not agree. >> >> Suppose tha you have a function returning a map of errors (a valip >> validator lib real case) like the following >> >> {:email ["Email can't be empty"] :password ["Password can't be empty"]} >> >> If I want to select just the email errors I would write something like >> that >> >> (if-let [{errors :email} (function-returning-error email password)] >> true >> false) >> >> Reading the above code you're led to believe that if there are email >> errors, errors local binding will be true. Instead, it returns true even >> if the are no email errors but there are password errors and you never >> get the false branch. >> >> An if you want to catch password errors you would write something like >> >> (if-let [{errors :password} (function-returning-errors email password)] >> true >> false) >> >> In either case you never get the false branch when >> function-returning-errors return an error which is not the one you're >> looking for >> >> Mimmo >> >> >> On Jan 30, 2013, at 10:05 AM, James Xu >> wrote: >> >>> From the expansion we can see that if-let determine the result based on >>> the second param, in your case: {:key2 "a string"}, not the local >>> binding >>> you assumed(key1), and >>> I think it is reasonable, for example, if we have the following code: >>> >>> (if-let [{key1 key2} {:key2 "a string"}] >>> true >>> false)) >>> >>> >>> Should if-let determine the result based on key1? key2? IMO {key1 key2} >>> in >>> a whole is more reaonable. And {key1 key2} == {:key2 "a string"}, then >>> the >>> result is true. >>> >>> >>> >>> On 13-1-30 下午4:51, "Mimmo Cosenza" wrote: >>> >>>> Hi all, >>>> I'm a little bit confused about the semantic of if-let macro. >>>> >>>> Suppose to call it as follows with map destructoring: >>>> >>>> (if-let [{key1 :key1} {:key2 "a string"}] >>>> true >>>> false)) >>>> >>>> It returns true. >>>> >>>> But, >>>> >>>> (let [{key1 :key1} {:key2 "a string"}] >>>> (if key1 >>>> true >>>> false)) >>>> >>>> returns false. >>>> >>>> >>>> The macro expansion of the former explains why >>>> >>>> (macroexpand-1 '(if-let [{key1 :key1} {:key2 "a string"}] true false)) >>>> >>>> returns >>>> (clojure.core/let [temp__3971__auto__ {:key2 "a string"}] (if >>>> temp__3971__auto__ (clojure.core/let [{key1 :key1} temp__3971__auto__] >>>> true) false)) >>>> >>>> the consequence, IMHO, is that I would never suggest to use map >>>> restructuring inside and if-let binding, because the syntax let me >>>> think >>>> the result its the opposite of its semantic, >>>> >>>> Am I completely wrong? >>>> >>>> mimmo >>>> >>>> >>>> -- >>>> -- >>>> 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 >>
Re: the semantic of if-let macro
Agree with you that it is very misleading when using map-destructure in if-let, the same applies to sequential-destructure: user=> (if-let [[_ x] [1 nil]] true false) true On 13-1-30 下午5:23, "Mimmo Cosenza" wrote: >Uhm, I do not agree. > >Suppose tha you have a function returning a map of errors (a valip >validator lib real case) like the following > >{:email ["Email can't be empty"] :password ["Password can't be empty"]} > >If I want to select just the email errors I would write something like >that > >(if-let [{errors :email} (function-returning-error email password)] >true >false) > >Reading the above code you're led to believe that if there are email >errors, errors local binding will be true. Instead, it returns true even >if the are no email errors but there are password errors and you never >get the false branch. > >An if you want to catch password errors you would write something like > >(if-let [{errors :password} (function-returning-errors email password)] >true >false) > >In either case you never get the false branch when >function-returning-errors return an error which is not the one you're >looking for > > Mimmo > > >On Jan 30, 2013, at 10:05 AM, James Xu >wrote: > >> From the expansion we can see that if-let determine the result based on >> the second param, in your case: {:key2 "a string"}, not the local >>binding >> you assumed(key1), and >> I think it is reasonable, for example, if we have the following code: >> >> (if-let [{key1 key2} {:key2 "a string"}] >> true >> false)) >> >> >> Should if-let determine the result based on key1? key2? IMO {key1 key2} >>in >> a whole is more reaonable. And {key1 key2} == {:key2 "a string"}, then >>the >> result is true. >> >> >> >> On 13-1-30 下午4:51, "Mimmo Cosenza" wrote: >> >>> Hi all, >>> I'm a little bit confused about the semantic of if-let macro. >>> >>> Suppose to call it as follows with map destructoring: >>> >>> (if-let [{key1 :key1} {:key2 "a string"}] >>> true >>> false)) >>> >>> It returns true. >>> >>> But, >>> >>> (let [{key1 :key1} {:key2 "a string"}] >>> (if key1 >>> true >>> false)) >>> >>> returns false. >>> >>> >>> The macro expansion of the former explains why >>> >>> (macroexpand-1 '(if-let [{key1 :key1} {:key2 "a string"}] true false)) >>> >>> returns >>> (clojure.core/let [temp__3971__auto__ {:key2 "a string"}] (if >>> temp__3971__auto__ (clojure.core/let [{key1 :key1} temp__3971__auto__] >>> true) false)) >>> >>> the consequence, IMHO, is that I would never suggest to use map >>> restructuring inside and if-let binding, because the syntax let me >>>think >>> the result its the opposite of its semantic, >>> >>> Am I completely wrong? >>> >>> mimmo >>> >>> >>> -- >>> -- >>> 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/grou
Re: the semantic of if-let macro
ah, compare > (if-let [{errors :email} (function-returning-error email password)] >true >false) with (let [{errors :email) (function-returning-errros email password)] (if errors true false)) I'm not saying that if-let is wrong, I'm saying I would never use in such a case (i.e. restructuring), because it led me think wrong. mimmo On Jan 30, 2013, at 10:23 AM, Mimmo Cosenza wrote: > Uhm, I do not agree. > > Suppose tha you have a function returning a map of errors (a valip validator > lib real case) like the following > > {:email ["Email can't be empty"] :password ["Password can't be empty"]} > > If I want to select just the email errors I would write something like that > > (if-let [{errors :email} (function-returning-error email password)] >true >false) > > Reading the above code you're led to believe that if there are email errors, > errors local binding will be true. Instead, it returns true even if the are > no email errors but there are password errors and you never get the false > branch. > > An if you want to catch password errors you would write something like > > (if-let [{errors :password} (function-returning-errors email password)] >true >false) > > In either case you never get the false branch when function-returning-errors > return an error which is not the one you're looking for > > Mimmo > > > On Jan 30, 2013, at 10:05 AM, James Xu wrote: > >> From the expansion we can see that if-let determine the result based on >> the second param, in your case: {:key2 "a string"}, not the local binding >> you assumed(key1), and >> I think it is reasonable, for example, if we have the following code: >> >> (if-let [{key1 key2} {:key2 "a string"}] >> true >> false)) >> >> >> Should if-let determine the result based on key1? key2? IMO {key1 key2} in >> a whole is more reaonable. And {key1 key2} == {:key2 "a string"}, then the >> result is true. >> >> >> >> On 13-1-30 下午4:51, "Mimmo Cosenza" wrote: >> >>> Hi all, >>> I'm a little bit confused about the semantic of if-let macro. >>> >>> Suppose to call it as follows with map destructoring: >>> >>> (if-let [{key1 :key1} {:key2 "a string"}] >>> true >>> false)) >>> >>> It returns true. >>> >>> But, >>> >>> (let [{key1 :key1} {:key2 "a string"}] >>> (if key1 >>> true >>> false)) >>> >>> returns false. >>> >>> >>> The macro expansion of the former explains why >>> >>> (macroexpand-1 '(if-let [{key1 :key1} {:key2 "a string"}] true false)) >>> >>> returns >>> (clojure.core/let [temp__3971__auto__ {:key2 "a string"}] (if >>> temp__3971__auto__ (clojure.core/let [{key1 :key1} temp__3971__auto__] >>> true) false)) >>> >>> the consequence, IMHO, is that I would never suggest to use map >>> restructuring inside and if-let binding, because the syntax let me think >>> the result its the opposite of its semantic, >>> >>> Am I completely wrong? >>> >>> mimmo >>> >>> >>> -- >>> -- >>> 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 unsubscrib
Re: the semantic of if-let macro
Uhm, I do not agree. Suppose tha you have a function returning a map of errors (a valip validator lib real case) like the following {:email ["Email can't be empty"] :password ["Password can't be empty"]} If I want to select just the email errors I would write something like that (if-let [{errors :email} (function-returning-error email password)] true false) Reading the above code you're led to believe that if there are email errors, errors local binding will be true. Instead, it returns true even if the are no email errors but there are password errors and you never get the false branch. An if you want to catch password errors you would write something like (if-let [{errors :password} (function-returning-errors email password)] true false) In either case you never get the false branch when function-returning-errors return an error which is not the one you're looking for Mimmo On Jan 30, 2013, at 10:05 AM, James Xu wrote: > From the expansion we can see that if-let determine the result based on > the second param, in your case: {:key2 "a string"}, not the local binding > you assumed(key1), and > I think it is reasonable, for example, if we have the following code: > > (if-let [{key1 key2} {:key2 "a string"}] > true > false)) > > > Should if-let determine the result based on key1? key2? IMO {key1 key2} in > a whole is more reaonable. And {key1 key2} == {:key2 "a string"}, then the > result is true. > > > > On 13-1-30 下午4:51, "Mimmo Cosenza" wrote: > >> Hi all, >> I'm a little bit confused about the semantic of if-let macro. >> >> Suppose to call it as follows with map destructoring: >> >> (if-let [{key1 :key1} {:key2 "a string"}] >> true >> false)) >> >> It returns true. >> >> But, >> >> (let [{key1 :key1} {:key2 "a string"}] >> (if key1 >> true >> false)) >> >> returns false. >> >> >> The macro expansion of the former explains why >> >> (macroexpand-1 '(if-let [{key1 :key1} {:key2 "a string"}] true false)) >> >> returns >> (clojure.core/let [temp__3971__auto__ {:key2 "a string"}] (if >> temp__3971__auto__ (clojure.core/let [{key1 :key1} temp__3971__auto__] >> true) false)) >> >> the consequence, IMHO, is that I would never suggest to use map >> restructuring inside and if-let binding, because the syntax let me think >> the result its the opposite of its semantic, >> >> Am I completely wrong? >> >> mimmo >> >> >> -- >> -- >> 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. > > -- -- 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: the semantic of if-let macro
>From the expansion we can see that if-let determine the result based on the second param, in your case: {:key2 "a string"}, not the local binding you assumed(key1), and I think it is reasonable, for example, if we have the following code: (if-let [{key1 key2} {:key2 "a string"}] true false)) Should if-let determine the result based on key1? key2? IMO {key1 key2} in a whole is more reaonable. And {key1 key2} == {:key2 "a string"}, then the result is true. On 13-1-30 下午4:51, "Mimmo Cosenza" wrote: >Hi all, >I'm a little bit confused about the semantic of if-let macro. > >Suppose to call it as follows with map destructoring: > >(if-let [{key1 :key1} {:key2 "a string"}] > true > false)) > >It returns true. > >But, > >(let [{key1 :key1} {:key2 "a string"}] > (if key1 > true > false)) > >returns false. > > >The macro expansion of the former explains why > >(macroexpand-1 '(if-let [{key1 :key1} {:key2 "a string"}] true false)) > >returns >(clojure.core/let [temp__3971__auto__ {:key2 "a string"}] (if >temp__3971__auto__ (clojure.core/let [{key1 :key1} temp__3971__auto__] >true) false)) > >the consequence, IMHO, is that I would never suggest to use map >restructuring inside and if-let binding, because the syntax let me think >the result its the opposite of its semantic, > >Am I completely wrong? > >mimmo > > >-- >-- >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.
the semantic of if-let macro
Hi all, I'm a little bit confused about the semantic of if-let macro. Suppose to call it as follows with map destructoring: (if-let [{key1 :key1} {:key2 "a string"}] true false)) It returns true. But, (let [{key1 :key1} {:key2 "a string"}] (if key1 true false)) returns false. The macro expansion of the former explains why (macroexpand-1 '(if-let [{key1 :key1} {:key2 "a string"}] true false)) returns (clojure.core/let [temp__3971__auto__ {:key2 "a string"}] (if temp__3971__auto__ (clojure.core/let [{key1 :key1} temp__3971__auto__] true) false)) the consequence, IMHO, is that I would never suggest to use map restructuring inside and if-let binding, because the syntax let me think the result its the opposite of its semantic, Am I completely wrong? mimmo -- -- 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.