Re: Copying (immigrating) macros from namespace to namespace

2013-01-07 Thread the80srobot
Stuart,

You're right that it breaks identity. How about a different approach then - 
I can get the list of referred vars from a namespace, and vars can cary 
metadata. A natural way to add more flexibility would be to add a flag - 
let's call it :export - to referred vars that I'd like for namespaces that 
subsequently use mine to also refer. A var marked with :export would 
effectively propagate through any number of calls to (use).

I've thrown together a quick POC that seems to work (although it's 
obviously limited and far from optimal in how it works). The full code of 
the example is on Gist . Ideally, I'd like 
to have either (use) or (refer) propagate :export'd vars in a similar 
fashion.

Can you see problems with this?

- Adam

On Monday, January 7, 2013 3:17:55 AM UTC+1, Stuart Sierra wrote:
>
> I've said it before and I will keep saying it: copying symbols by 
> interning vars breaks the identity of the original vars. It breaks dynamic 
> binding, with-redefs, and the ability to redefine functions at the REPL.
>
> Clojure has a two perfectly good mechanisms for making vars available in 
> other namespaces: 
>
> 1. `refer`. Define a public function that `refer`s all the symbols you 
> want. It's an extra step for the user, but that's good because it makes it 
> evident that extra symbols are being added.
>
> 2. `load`. If you have N namespaces with no clashing symbols, then you 
> only need one namespace. If you want to split it across multiple files, use 
> `load`. `clojure.core` does this.
>
> -S
>

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

Re: Copying (immigrating) macros from namespace to namespace

2013-01-06 Thread Vedang
I remembered bookmarking a library that did something similar, so I
looked at my bookmarks. Here is Zach Tellman's "potemkin" library, you
might be interested in checking it out:
https://github.com/ztellman/potemkin

>From the README :

"Clojure’s namespaces conflate how you implement your code and how
it’s consumed by other code. This isn’t always a bad thing, but in
practice this means that large projects either have surprisingly large
source files (e.g. clojure.core) or a surprising number of namespaces
that have to all be used in concert to accomplish complex tasks (e.g.
Ring).

The former approach places an onus on the creator of the library; the
various orthogonal pieces of his library all coexist, which can make
it difficult to keep everything straight. The latter approach places
an onus on the consumers of the library, forcing them to remember
exactly what functionality resides where before they can actually use
it.

import-fn and import-macro decouple the structure of the code from the
structure of the API, allowing the library creator to structure the
code however he likes, without necessarily requiring that the
consumers have the same intimate understanding of that structure.

As someone who spends a fair amount of time worrying both about the
structure of the code and the presentation of the API, it’s helpful
not to have to think about how one affects the other. You might find
it helpful, too."

/vedang

On Mon, Jan 7, 2013 at 8:12 AM, Sean Corfield  wrote:
> On Sun, Jan 6, 2013 at 6:17 PM, Stuart Sierra
>  wrote:
>> 1. `refer`. Define a public function that `refer`s all the symbols you want.
>> It's an extra step for the user, but that's good because it makes it evident
>> that extra symbols are being added.
>
> Forcing all users of a library to refer a whole slew of symbols from
> another library that they don't even know they're using is horrible
> usability and really not a useful suggestion. The user should be able
> to (:require [main-library :refer [what i want]) without being forced
> to know about a transitive dependency and know which symbols come from
> which library, if the main-library developer wishes to provide a
> single, simple API.
>
> Could you explain exactly how this "breaks dynamic binding,
> with-redefs, and the ability to redefine functions at the REPL" given
> the scenario we're discussing? Remember that the whole purpose of this
> discussion is to essentially hide the underlying namespace from which
> symbols originate, and to present a single namespace with the desired
> API.
>
>> 2. `load`. If you have N namespaces with no clashing symbols, then you only
>> need one namespace. If you want to split it across multiple files, use
>> `load`. `clojure.core` does this.
>
> Fine if you control all of the source yourself.
>
> In the case of FW/1, I want a portion of Enlive available directly and
> easily to users of FW/1. Enlive is a transitive dependency - users of
> FW/1 don't need to know about it, and shouldn't really care.
>
> Since this appears to be a relatively common use case for library
> developers, perhaps a native Clojure solution that doesn't have the
> downsides you list would be worth adding? Perhaps some sort of (export
> some-ns/some-symbol) that makes *ns*/some-symbol appear like an exact
> public alias of some-ns/some-symbol? So users of the library see those
> exported symbols exactly as if they were declared in the library
> itself, rather than the third-party dependency, and could interact
> with them as such.
> --
> 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



-- 
Unix is simple. It takes a genius to understand it's simplicity.-Anon
People think it must be fun to be a super genius, but they don't
realize how hard it is to put up with all the idiots in the world.
-Calvin.

Cheers,
Vedang.

Programmer,
Infinitely Beta.
http://twitter.com/vedang
http://vedang.me

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


Re: Copying (immigrating) macros from namespace to namespace

2013-01-06 Thread Sean Corfield
On Sun, Jan 6, 2013 at 6:17 PM, Stuart Sierra
 wrote:
> 1. `refer`. Define a public function that `refer`s all the symbols you want.
> It's an extra step for the user, but that's good because it makes it evident
> that extra symbols are being added.

Forcing all users of a library to refer a whole slew of symbols from
another library that they don't even know they're using is horrible
usability and really not a useful suggestion. The user should be able
to (:require [main-library :refer [what i want]) without being forced
to know about a transitive dependency and know which symbols come from
which library, if the main-library developer wishes to provide a
single, simple API.

Could you explain exactly how this "breaks dynamic binding,
with-redefs, and the ability to redefine functions at the REPL" given
the scenario we're discussing? Remember that the whole purpose of this
discussion is to essentially hide the underlying namespace from which
symbols originate, and to present a single namespace with the desired
API.

> 2. `load`. If you have N namespaces with no clashing symbols, then you only
> need one namespace. If you want to split it across multiple files, use
> `load`. `clojure.core` does this.

Fine if you control all of the source yourself.

In the case of FW/1, I want a portion of Enlive available directly and
easily to users of FW/1. Enlive is a transitive dependency - users of
FW/1 don't need to know about it, and shouldn't really care.

Since this appears to be a relatively common use case for library
developers, perhaps a native Clojure solution that doesn't have the
downsides you list would be worth adding? Perhaps some sort of (export
some-ns/some-symbol) that makes *ns*/some-symbol appear like an exact
public alias of some-ns/some-symbol? So users of the library see those
exported symbols exactly as if they were declared in the library
itself, rather than the third-party dependency, and could interact
with them as such.
--
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


Re: Copying (immigrating) macros from namespace to namespace

2013-01-06 Thread Leonardo Borges
On Mon, Jan 7, 2013 at 1:17 PM, Stuart Sierra
 wrote:
> I've said it before and I will keep saying it: copying symbols by interning
> vars breaks the identity of the original vars. It breaks dynamic binding,
> with-redefs, and the ability to redefine functions at the REPL.
>
> Clojure has a two perfectly good mechanisms for making vars available in
> other namespaces:
>
> 1. `refer`. Define a public function that `refer`s all the symbols you want.
> It's an extra step for the user, but that's good because it makes it evident
> that extra symbols are being added.
>

So this would be no different than having the user put an extra 'use'
call to use any additional namespaces right? In this case I'd rather
have the user explicitly perform the  "use" call instead of "refer",
like this:

(require '[bouncer.core :as b])
(use '[bouncer.validators :only [defvalidator])

Which is what I recommend at the moment.

> 2. `load`. If you have N namespaces with no clashing symbols, then you only
> need one namespace. If you want to split it across multiple files, use
> `load`. `clojure.core` does this.
>

This sounds like what I want. I'll look into it, thanks.

Leo.

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


Re: Copying (immigrating) macros from namespace to namespace

2013-01-06 Thread Stuart Sierra
I've said it before and I will keep saying it: copying symbols by interning 
vars breaks the identity of the original vars. It breaks dynamic binding, 
with-redefs, and the ability to redefine functions at the REPL.

Clojure has a two perfectly good mechanisms for making vars available in 
other namespaces: 

1. `refer`. Define a public function that `refer`s all the symbols you 
want. It's an extra step for the user, but that's good because it makes it 
evident that extra symbols are being added.

2. `load`. If you have N namespaces with no clashing symbols, then you only 
need one namespace. If you want to split it across multiple files, use 
`load`. `clojure.core` does this.

-S

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

Re: Copying (immigrating) macros from namespace to namespace

2013-01-06 Thread Leonardo Borges
+1

I was thinking of doing the same in the validation lib I published
recently [1] and this thread came in handy. I haven't implemented it
yet but having a common way in which people do this seems reasonable -
if it's in core then all the better.

Cheers,
Leo


[1] - https://github.com/leonardoborges/bouncer
Leonardo Borges
www.leonardoborges.com


On Mon, Jan 7, 2013 at 12:04 PM, Brian Marick  wrote:
>
> On Jan 6, 2013, at 3:34 PM, Sean Corfield  wrote:
>
>> Here's what I use to pull symbols from Enlive into FW/1:
>
>
> Midje plays similar tricks to make namespace abilities available via one 
> `use`.
>
> Which makes me think:
>
> 1: In the old patterns world, there was a "rule of three" which claimed that 
> something shouldn't be published as a pattern until it could be demonstrated 
> in three real systems.
>
> 2: Lispers like Gabriel and others noted that what were patterns in languages 
> like Smalltalk and C++ were built into Lisp or were easily regularized 
> in-language with macros.
>
> Therefore: to me, this email thread suggests that the ability to do such 
> consolidation should be immortalized not in email examples of patterns 
> ("here's how I accomplished X") but - in a more Lispy fashion - by writing a 
> common library and making it available to the user base. That is: functions 
> like Adam's and Sean's and mine should be in some official library close to 
> clojure.core.
>
> 
> Occasional consulting on programming technique
> Contract programming in Ruby and Clojure
> Latest book: /Functional Programming for the Object-Oriented Programmer/
> https://leanpub.com/fp-oo
>
> --
> 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 post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Copying (immigrating) macros from namespace to namespace

2013-01-06 Thread Brian Marick

On Jan 6, 2013, at 3:34 PM, Sean Corfield  wrote:

> Here's what I use to pull symbols from Enlive into FW/1:


Midje plays similar tricks to make namespace abilities available via one `use`. 

Which makes me think:

1: In the old patterns world, there was a "rule of three" which claimed that 
something shouldn't be published as a pattern until it could be demonstrated in 
three real systems. 

2: Lispers like Gabriel and others noted that what were patterns in languages 
like Smalltalk and C++ were built into Lisp or were easily regularized 
in-language with macros.

Therefore: to me, this email thread suggests that the ability to do such 
consolidation should be immortalized not in email examples of patterns ("here's 
how I accomplished X") but - in a more Lispy fashion - by writing a common 
library and making it available to the user base. That is: functions like 
Adam's and Sean's and mine should be in some official library close to 
clojure.core. 


Occasional consulting on programming technique
Contract programming in Ruby and Clojure
Latest book: /Functional Programming for the Object-Oriented Programmer/
https://leanpub.com/fp-oo

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


Re: Copying (immigrating) macros from namespace to namespace

2013-01-06 Thread Sean Corfield
Here's what I use to pull symbols from Enlive into FW/1:

(def ^:private enlive-symbols
  ['append 'at 'clone-for 'content 'do-> 'html-content 'prepend
'remove-class 'set-attr 'substitute])

(defmacro enlive-alias ^:private [sym]
  `(let [enlive-sym# (resolve (symbol (str "html/" ~sym)))]
 (intern *ns* (with-meta ~sym (meta enlive-sym#)) (deref enlive-sym#

This pulls in both functions and macros. It hard-codes the alias for
Enlive (html, for net.cgrand.enlive-html) but otherwise should serve
your needs. FW/1 uses it like this:

(doseq [sym enlive-symbols]
  (enlive-alias sym))

Sean

On Sun, Jan 6, 2013 at 12:19 PM, the80srobot  wrote:
> I have come up with a solution to a problem I don't think exists outside of
> my mind, but since I can't for the life of me figure out how Clojure 'wants'
> me to do this, I thought I would bounce this off the Google Group.
>
> The scenario: I am trying to collect a bunch of functions and macros from
> all the different namespaces in my library into a single namespace; let's
> call the namespace adams-lib.api. The idea is that the consumer of the
> library will only have to include that one API namespace, and not all of the
> little namespaces with parts of the functionality.
>
> The problem: Obviously, calling (use) doesn't cut it, because the aliased
> vars are not immigrated by subsequent calls to the (use) of the namespace
> that (used) them. You know what I mean.
>
> The "solution": For functions this is simpler, but macros pose some
> additional challenges, which is why I'm including my "solution" for
> immigrating macros. Hold on to your hats, this one is ugly:
>
> (defmacro immigrate-macro
>   [ns-sym macro-sym]
>   `(let [ nspublics# (ns-publics '~ns-sym)
>   macro-var# (nspublics# '~macro-sym)
>   macro-fn# @macro-var#
>   macro-meta# (meta macro-var#)]
> (def ~macro-sym macro-fn#)
> (. (var ~macro-sym) (setMacro))
> (reset-meta! (var ~macro-sym) macro-meta#))
> nil)
>
>
> And using it:
>
> (immigrate-macro adams-lib.some-other-ns some-macro)
>
>
> There has got to be a simpler/better/less insane way of doing this. Would
> anyone care to weigh in? For the record, I fully realize that my solution is
> not OK.
>
> -Adam
>
> --
> 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



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