Re: def partially done when used in if

2017-06-30 Thread Sean Corfield
You can see it at work in this:

user=> foo
(unable to resolve foo)
user=> (when nil (def foo 42))
nil
user=> foo
(unbound var foo)

When a ‘def’ form is _compiled_ -- which happens in the above case because the 
whole form must be compiled – then it interns the var.

The ‘def’ form is parsed in DefExpr$Parser.parse() and it calls lookupVar(sym, 
true) – which interns the symbol if it is new (i.e., not yet seen). See various 
parts of:


https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java


Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

On 6/30/17, 11:28 AM, "Didier"  wrote:

I admit, this is very surprising. It looks like evaluation happens in two 
pass, like first it finds all defs and declares them, interning the symbol and 
creating an unbound var. And on a second pass it evaluates the full form.

Can someone more informed confirm or explain in more details what's 
responsible for this behavior?

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



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


Re: def partially done when used in if

2017-06-30 Thread Didier
I admit, this is very surprising. It looks like evaluation happens in two pass, 
like first it finds all defs and declares them, interning the symbol and 
creating an unbound var. And on a second pass it evaluates the full form.

Can someone more informed confirm or explain in more details what's responsible 
for this behavior?

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


Re: def partially done when used in if

2017-06-29 Thread Justin Smith
It creates an "undefined" var if the def gets compiled but doesn't get run.
This isn't the same as an "undefined behavior" as is documented for
languages that have formal specifications (clojure of course has none). I
did qualify that def / defn inside other forms are "generally" a sign of
bad design. There are of course special cases where they might be the least
bad option.

On Thu, Jun 29, 2017 at 3:15 PM Kaiming Yang  wrote:

> Thanks Justin,
>
> Sadly in my case those mutable container will not work because I was
> making a monkey-patch to a bug in a macro from other package.
>
> Despite what I was doing, I think "a bad design" in clojure spec is too
> weak to fit this situation. If someone tells me "it is a bad design" I
> would think I will spend more development/computation time to make it work
> but I would still expect *correct* result. "An undefined behavior" would be
> a more suitable.
>
>
> On Thursday, June 29, 2017 at 1:15:23 PM UTC-7, Justin Smith wrote:
>
>> Clojure's compiler (there's no interpreter) creates vars for every def
>> inside a form it compiles. Before the def actually runs it's unbound (as if
>> you had used declare).
>>
>> Generally def and defn that are not top level forms are signs of a bad
>> design. If you need runtime rebinding use a proper mutable container like
>> and atom, ref, or agent, this is what they are for, and they eliminate a
>> number of gotchas that come with runtime redefinition.
>>
>> On Thu, Jun 29, 2017 at 1:07 PM Kaiming Yang  wrote:
>>
> Hi,
>>> Recently encountered a weird issue, A def in if clause declared a var
>>> but left it unbound.
>>>
>>> I encountered this issue when I was trying to implement something like
>>> "define a symbol if it is not defined yet". Naively I tried:
>>>
>>> (if (nil? (resolve 'foo))
>>>   (def foo 42))
>>> ; Cannot use (def foo (if (nil? (resolve 'foo)) foo 42)) because foo
>>> might be macro
>>>
>>> I tried in repl and the result really surprised me:
>>>
>>> user=> foo
>>>
>>> CompilerException java.lang.RuntimeException: Unable to resolve symbol:
>>> foo in this context,
>>> compiling:(/private/var/folders/1h/vhl8yb657mjf3pchm9cbc40m63f2d3/T/form-init8893781347079502941.clj:1:1062)
>>> user=> (if (nil? (resolve 'foo))
>>>   #_=>   (do (def foo 42) (prn "true-branch"))
>>>   #_=>   (prn "false-branch"))
>>> "false-branch"
>>> nil
>>> user=> foo
>>> #object[clojure.lang.Var$Unbound 0x6dc69f03 "Unbound: #'user/foo"]
>>>
>>> Seems once clojure interpreter declares the variable before really
>>> evaluate the clause with def.
>>>
>>> Is this an expected behavior? Should I ever use def in if or fn?
>>>
>>> Thanks!
>>> Kaiming
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>>
>> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.
>>
>>
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

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


Re: def partially done when used in if

2017-06-29 Thread Kaiming Yang
Thanks Justin,

Sadly in my case those mutable container will not work because I was making 
a monkey-patch to a bug in a macro from other package.

Despite what I was doing, I think "a bad design" in clojure spec is too 
weak to fit this situation. If someone tells me "it is a bad design" I 
would think I will spend more development/computation time to make it work 
but I would still expect *correct* result. "An undefined behavior" would be 
a more suitable.


On Thursday, June 29, 2017 at 1:15:23 PM UTC-7, Justin Smith wrote:
>
> Clojure's compiler (there's no interpreter) creates vars for every def 
> inside a form it compiles. Before the def actually runs it's unbound (as if 
> you had used declare).
>
> Generally def and defn that are not top level forms are signs of a bad 
> design. If you need runtime rebinding use a proper mutable container like 
> and atom, ref, or agent, this is what they are for, and they eliminate a 
> number of gotchas that come with runtime redefinition.
>
> On Thu, Jun 29, 2017 at 1:07 PM Kaiming Yang  > wrote:
>
>> Hi,
>> Recently encountered a weird issue, A def in if clause declared a var but 
>> left it unbound.
>>
>> I encountered this issue when I was trying to implement something like 
>> "define a symbol if it is not defined yet". Naively I tried:
>>
>> (if (nil? (resolve 'foo)) 
>>   (def foo 42))  
>> ; Cannot use (def foo (if (nil? (resolve 'foo)) foo 42)) because foo 
>> might be macro
>>
>> I tried in repl and the result really surprised me:
>>
>> user=> foo
>>
>> CompilerException java.lang.RuntimeException: Unable to resolve symbol: 
>> foo in this context, 
>> compiling:(/private/var/folders/1h/vhl8yb657mjf3pchm9cbc40m63f2d3/T/form-init8893781347079502941.clj:1:1062)
>> user=> (if (nil? (resolve 'foo))
>>   #_=>   (do (def foo 42) (prn "true-branch"))
>>   #_=>   (prn "false-branch"))
>> "false-branch"
>> nil
>> user=> foo
>> #object[clojure.lang.Var$Unbound 0x6dc69f03 "Unbound: #'user/foo"]
>>
>> Seems once clojure interpreter declares the variable before really 
>> evaluate the clause with def. 
>>
>> Is this an expected behavior? Should I ever use def in if or fn?
>>
>> Thanks!
>> Kaiming
>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>

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


Re: def partially done when used in if

2017-06-29 Thread Justin Smith
Clojure's compiler (there's no interpreter) creates vars for every def
inside a form it compiles. Before the def actually runs it's unbound (as if
you had used declare).

Generally def and defn that are not top level forms are signs of a bad
design. If you need runtime rebinding use a proper mutable container like
and atom, ref, or agent, this is what they are for, and they eliminate a
number of gotchas that come with runtime redefinition.

On Thu, Jun 29, 2017 at 1:07 PM Kaiming Yang  wrote:

> Hi,
> Recently encountered a weird issue, A def in if clause declared a var but
> left it unbound.
>
> I encountered this issue when I was trying to implement something like
> "define a symbol if it is not defined yet". Naively I tried:
>
> (if (nil? (resolve 'foo))
>   (def foo 42))
> ; Cannot use (def foo (if (nil? (resolve 'foo)) foo 42)) because foo
> might be macro
>
> I tried in repl and the result really surprised me:
>
> user=> foo
>
> CompilerException java.lang.RuntimeException: Unable to resolve symbol:
> foo in this context,
> compiling:(/private/var/folders/1h/vhl8yb657mjf3pchm9cbc40m63f2d3/T/form-init8893781347079502941.clj:1:1062)
> user=> (if (nil? (resolve 'foo))
>   #_=>   (do (def foo 42) (prn "true-branch"))
>   #_=>   (prn "false-branch"))
> "false-branch"
> nil
> user=> foo
> #object[clojure.lang.Var$Unbound 0x6dc69f03 "Unbound: #'user/foo"]
>
> Seems once clojure interpreter declares the variable before really
> evaluate the clause with def.
>
> Is this an expected behavior? Should I ever use def in if or fn?
>
> Thanks!
> Kaiming
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

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


def partially done when used in if

2017-06-29 Thread Kaiming Yang
Hi,
Recently encountered a weird issue, A def in if clause declared a var but 
left it unbound.

I encountered this issue when I was trying to implement something like 
"define a symbol if it is not defined yet". Naively I tried:

(if (nil? (resolve 'foo)) 
  (def foo 42))  
; Cannot use (def foo (if (nil? (resolve 'foo)) foo 42)) because foo might 
be macro

I tried in repl and the result really surprised me:

user=> foo

CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo 
in this context, 
compiling:(/private/var/folders/1h/vhl8yb657mjf3pchm9cbc40m63f2d3/T/form-init8893781347079502941.clj:1:1062)
user=> (if (nil? (resolve 'foo))
  #_=>   (do (def foo 42) (prn "true-branch"))
  #_=>   (prn "false-branch"))
"false-branch"
nil
user=> foo
#object[clojure.lang.Var$Unbound 0x6dc69f03 "Unbound: #'user/foo"]

Seems once clojure interpreter declares the variable before really evaluate 
the clause with def. 

Is this an expected behavior? Should I ever use def in if or fn?

Thanks!
Kaiming

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