Re: the semantic of if-let macro

2013-01-31 Thread Stuart Halloway
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 mimmo.cose...@gmail.comwrote:


 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.




the semantic of if-let macro

2013-01-30 Thread Mimmo Cosenza
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.




Re: the semantic of if-let macro

2013-01-30 Thread James Xu
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 mimmo.cose...@gmail.com 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.




Re: the semantic of if-let macro

2013-01-30 Thread Mimmo Cosenza
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 xumingming64398...@gmail.com 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 mimmo.cose...@gmail.com 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

2013-01-30 Thread Mimmo Cosenza
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 mimmo.cose...@gmail.com 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 xumingming64398...@gmail.com 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 mimmo.cose...@gmail.com 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

2013-01-30 Thread James Xu
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 mimmo.cose...@gmail.com 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 xumingming64398...@gmail.com
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 mimmo.cose...@gmail.com 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.




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

Re: the semantic of if-let macro

2013-01-30 Thread Mimmo Cosenza
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 xumingming64398...@gmail.com 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 mimmo.cose...@gmail.com 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 xumingming64398...@gmail.com
 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 mimmo.cose...@gmail.com 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

Re: the semantic of if-let macro

2013-01-30 Thread Ben Smith-Mannschott
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 mimmo.cose...@gmail.comwrote:

 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 xumingming64398...@gmail.com
 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 mimmo.cose...@gmail.com 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 xumingming64398...@gmail.com
  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 mimmo.cose...@gmail.com 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

Re: the semantic of if-let macro

2013-01-30 Thread Gary Verhaegen
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 
 mimmo.cose...@gmail.comwrote:

 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 xumingming64398...@gmail.com
 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 mimmo.cose...@gmail.com 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 xumingming64398...@gmail.com
  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 mimmo.cose...@gmail.com 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.comjavascript:_e({}, 'cvml', 
 '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 javascript:_e({}, 'cvml',
 'clojure%2bunsubscr...@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 javascript:_e({}, 'cvml

Re: the semantic of if-let macro

2013-01-30 Thread Mimmo Cosenza
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 gary.verhae...@gmail.com 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 mimmo.cose...@gmail.com 
 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 xumingming64398...@gmail.com 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 mimmo.cose...@gmail.com 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 xumingming64398...@gmail.com
  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 mimmo.cose...@gmail.com 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

Re: the semantic of if-let macro

2013-01-30 Thread Sean Corfield
  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 mimmo.cose...@gmail.com 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

2013-01-30 Thread Mimmo Cosenza
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

2013-01-30 Thread Mimmo Cosenza

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.