Re: [?] Adding my own function to clojure.core namespace

2018-02-27 Thread Kurt Harriger
You might also have a look at a library called vinyasa
 

> https://github.com/ardumont/vinyasa
>

You can can add it to your lein profile to copy functions into clojure.core 
and prefix them.  
The prefix makes it very clear that these are not part of standard 
clojure.core. 

(inject 'clojure.core '>> '[[clojure.repl doc [source source]]]) 

;; => will create the var #'clojure.core/>>doc and #'clojure.core/source
 


-- 
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: [ANN] Git Deps for Clojure!

2018-01-15 Thread Kurt Harriger

>
>
>  
>
>> I’d really like a dependency system that makes each dep’s transitive 
>> dependencies only visible to itself, so there would never be any reason to 
>> resolve dependencies.
>>
>
> You need classloader support for this and indeed this is what OSGi and 
> some early versions of the Java module system do. Working in that kind of 
> environment is very constraining. A lot of discipline is required with 
> respect to your interfaces between loaders and in general I think it's way 
> too much of a burden to use as the normal operating mode (which is one 
> reason you don't see it in the Java module system of java 9). It is a good 
> option for systems where you want users to plug in functionality and the 
> scope of those interface points is small and highly controlled.
>

I have run into incompatible transitive dependencies a lot throughout my 
career.  In many cases its not that big a deal but for cross cutting 
libraries such as data serialization etc it can be hard to get all of your 
dependencies to agree on a common version.  Here is a concrete example I 
ran into just today: https://github.com/thheller/shadow-cljs/issues/177 and 
the library that caused the issue is non-other than core.async!

I second the idea of private dependencies.  I have had the displeasure of 
working with OSGI and I think the reason its complex is not so much because 
the required metadata is hard to figure out... the complexity mostly comes  
from the starting, stopping and restarting bundles within a running jvm in 
non deterministic order.  

Another issue is that the dependency metadata needs to be included within 
each jar and since most library authors don't see the value of OSGI they 
don't provide it to users to rebundle the jar with the required metatata. 
This problem is similar to that of cljsjs, most javascript devs do not see 
any value in any significant value is using closure compile over uglyify 
(myself included as externs are a pain to maintain, minified stacktraces 
are useless, and errors are subtle and hard to debug), but the 
clojurescript community does see value in this so they do their best to 
maintain this metadata even if it means rebuilding projects. 

So what is the alternatives:  
1. Don't upgrade (common solution when there are breaking changes)
2. Try to get upstream maintainer to upgrade (most common when changes are 
not breaking and/or maintainer willing to do the work)
3. Fork the upstream project and maintain your own release using the 
desired version
4. Split your app into multiple pieces so they can run in different JVM 
instances (enter the microservice)

I think the idea that everything can use the same version is oversimplified 
and creating microservice shouldn't be necessary just because you can't get 
all your dependencies to agree.

-- 
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: Doseq, map-style

2012-06-18 Thread Kurt Harriger
On Jun 18, 2012, at 2:09 AM, Christophe Grand christo...@cgrand.net wrote:

On Sun, Jun 17, 2012 at 8:59 PM, Kurt Harriger kurtharri...@gmail.comwrote:


 Data structure is an implementation detail...


 It's not. Not in clojure. It is in OO, but clojure is not an OO language,
 so it's not an implementation detail in clojure.


 That is my point, representations SHOULD be considered implementation
 details, because representations change... if you treat them as contracts
 your code will break everywhere, if you wrap them with abstractions your
 code will only need to change in one place...



Representations are values in Clojure, they are not mixed with behaviors
like in mainstream OO. It follows that, if your representation need to
change, you can write a converter function (or two if you want to convert
from and to the old representation), that's easy, easier than writing an
adapter class in Java because the adapter class must implement new
behaviors on top of old ones (or the other way round).


Isnt that just creating an api? Everywhere the old model exists you need to
call a function to create the desired data structure and this adds another
layer of complexity that needs maintained.  Not all conversions are
straight forward, may require additional context of whatever introducing
the need for deferred computation.



Christophe

 --
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: Doseq, map-style

2012-06-18 Thread Kurt Harriger
 

I did not know about lazy map either… This might be exactly what I was 
needed.  Maps with referentially transparent properties rather than fields. 
 A way to make minor changes to map representation without adding an api in 
advance, introducing breaking changes, redundant properties, or converters 
and still work with the clojure core apis.  This might make the simple 
refactoring a bit easier.  

On Monday, June 18, 2012 8:48:37 AM UTC-6, Vinzent wrote:

 Yeah, I'm waiting for concrete example too.

 By the way, if you really need to change :area from value to deferred 
 computation then you can just change your data structure implementation 
 from hash-map to lazy map (i.e. a map whose values are delays deref'd on 
 access). This would require changing code only in one place.


-- 
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: Doseq, map-style

2012-06-18 Thread Kurt Harriger


On Monday, June 18, 2012 8:01:47 AM UTC-6, tbc++ wrote:

  Isnt that just creating an api? Everywhere the old model exists you need 
 to 
  call a function to create the desired data structure and this adds 
 another 
  layer of complexity that needs maintained.  Not all conversions are 
 straight 
  forward, may require additional context of whatever introducing the need 
 for 
  deferred computation. 

 Can you provide a concrete example (with code perhaps)? I guess I'm 
 not seeing where the problems arise. In this situation I normally 
 either, 1) create a new fetch function to create a new map of data 
 in the new format 2) provide duplicate data in the map that's computed 
 differently, 3) update the old code to the new map. 

 Here at work we have a 20 year old application that is almost 100% 
 backwards compatible (the server can talk to much older clients). And 
 it does so by using pure data. The server has setup contracts saying 
 this is what Project data looks like, this is what Company Data looks 
 like and those contracts never change. The 3D Software Blender 
 (blender.org) operates on this same principle. After almost a decade, 
 their latest software can open 1.0 .blend files, and vice versa. All 
 these applications work off of unchanging data contracts. 

 So I'm interested in seeing concrete examples of how your application 
 differs. 


Its not the external contracts that are changing but the internal contracts 
between namespaces... as I add features I add new requirements clarify my 
understanding and decide to replace them with new ones.  I wish I could say 
just don't change them, but the internal contracts are implementation 
details no one uses them but me.  If I decide to change them stuff breaks 
and that would be true in OO too, but in I know how to go about these 
refactorings incrementally in OO until the old abstractions fall away and 
become dead code, in clojure new abstractions mean lots of breaking changes 
and nothing works until everything works.   

I wouldn't mind sitting down with someone in the Denver area and getting 
some feedback on my code, eventually I would like to open source the code 
but I don't expect that to happen anytime in the near future.  
 


 Timothy 


-- 
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: Doseq, map-style

2012-06-18 Thread Kurt Harriger
On Jun 18, 2012, at 5:35 PM, Softaddicts lprefonta...@softaddicts.ca wrote:

 Lets talk a bit about my world here.

 We created a product to link medical equipments
 using a variety of protocols, some talk HL7, DICOM, others have proprietary 
 means to
 access data from various places.

 From the start we chose the richest data representation, some of it came from
 a few medical standards and another part is our own creation to carry stuff 
 that is outside the scope of the business field (non medical data).

 We did not define specific records, instead we factored out the protocol
 definition (the contract) from the representation(s) and created its 
 definition using
 persistent data structures and Clojure protocols

 The profile is being augmented often, new fields are added to keep up with
 support of new devices, new standards,...

 We never remove stuff from protocol definitions and we always aim to generate
 fully populated messages from the data available at a specific end point.

 It's all data (above 10k lines for as profile using our custom DSL) and less 
 than
 500 lines of code to define and handle.

 We have three message representations more or less equivalent, one is string 
 based
 (HL7-enabled devices accept this representation), another one is
 for serialization and the last one is a full representation with each data
 component populated with all its attributes from the profile (name, relative
 position, ...)

 All the above representation allow you to switch from one to the other.
 We even have a pretty print so we can decipher message when investigating
 bugs.

 We also have a DSL to create messages from code to promoto some
 brevity when creating messages and lax us fro having to precisely order
 fields when writing code.

Couldn't one say that a dsl is yet another more domain specific
representation of the medical record?  Why did you code against the
medical record rather than the dsl? My assumption is that the dsl is
just a subset but just curious.


 None of the above uses defrecord or deftype. We use
 Clojure's persistent structures and protocols to implement how to handle
 these various formats. Roughly we do this in less than 1000 lines splitted
 in 4 namespaces. This code never refers to a specific piece of data by its
 name.

A bit confused.  So you have profile that describes how to convert
from the medical record to the preferred internal representation which
allows you to support multiple medical record representations?

How might you handle the situation where a new medical record contains
an abbreviation or medical code but you need the full value and to get
the complete value you need to perform a web service query, so you
want to avoid this unless the value is required... Ideally, the
internal representation would know that the value is expensive and to
request it only if necessary.  So This would probably change the
contract, but for your boss needs this to process this non-standard
record format tomorrow if the client likes what he sees youll have
time to support it properly, if not then you can just rip the code
put.  How would you go about this change 1 if you needed it functional
tomorrow and 2 the ideal/best way?




 It's all data driven, the contract is data in our internal protocol profile 
 definition.
 Validation, searching the metadata of the profile, ... is done within the 
 profile definition.


So do you have one function that takes the profile, record and desired property?

 The name spaces allowing us to  support the different representations all 
 rely on the
 profile definition. They never refer to specific data items.

 Some devices do not support all the fields or are using older versions
 of protocols compared to what we implemented internally.

 We have a rule engine and rules attached to specific device profiles to
 alter the common format message so we can spit out a valid message that
 can be understood by the device. We implemented a Clojure protocol that lets
 us manipulate a message using Clojure generic fns to strip items,
 swap items from one spot to the other, 

 These rules are applied on top of a generic message just before sending or 
 just
 after receiving to/fro  the device. We do not have to recode messages for 
 each device
 type. This is the only place aside from message generation that will ever 
 refer
 to specific data items.


 What about maintenance ? Why remove a data item from the profile ?
 If ever necessary, we can flag it as unusable and the rest will carry on.

 Any attempt to refer to it will trigger an exception.
 Searching the code base to find references to it is no more difficult than
 finding getters. And we know it's a required change. Either it disappeared or
 the data item changed. We can remove it somewhere in the future, no need
 rushing.

 It eases the maintenance of the device specific rules, if they do not
 refer to the disabled data item, they are still working.

 We get a uniform way of dealing 

Re: Doseq, map-style

2012-06-17 Thread Kurt Harriger


On Sunday, June 17, 2012 8:48:58 AM UTC-6, Vinzent wrote:

 Well, if those assertions are violated, you can't do anything with it 
 anyway - you program is written wrong and you have to release new version 
 which'll fix it.


Yes, but if data in your database become corrupt then you may need to do 
more than just release a code fix
 


 воскресенье, 17 июня 2012 г., 1:41:17 UTC+6 пользователь Alex Baranosky 
 написал:

 To test for violations of those assertions, possibly due to wonky data 
 that only occurs in certain production-only circumstances. 



-- 
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: Doseq, map-style

2012-06-17 Thread Kurt Harriger


On Sunday, June 17, 2012 9:09:23 AM UTC-6, Vinzent wrote:

 This still requires changing your code to @(:emails contact).  If you use 
 (emails contact) you need change your code in only one place. 


 The name emails implies that it's a sequence. Lazy sequence. 


Yes it is... emails was not the best example in this case.. think the 
area example instead as this is single value rather than collection. Lazy 
sequences also introduce additional problems... they maybe realized when 
bindings are no longer in effect which causes all sorts of non-local errors 
with stacktraces that are completely non-intuitive. 


 

 Property is just the OO word for function, semantically they are the 
 same. OO doesn't have functions they have properties and methods.  


 I thought the concept similar to function in OO-world is method. Ok, so 
 if property is a function, then you want to get rid of data structures at 
 all and have only functions?


Yes, always access a map value via a function, this provides a seam (see 
Feathers, Working Effectively with Legacy Code 
http://www.informit.com/articles/article.aspx?p=359417) where alternative 
behavior could be introduced. Keywords are functions, but their behavior 
cannot changed therefore they do not make for useful seams.  The data still 
needs to be stored some where so you will have maps and will still need to 
use keywords to access that data... but that keyword usage should be in 
only one place so that when you do change the data structure eventually you 
will need to only update that one function.
 


 Agreed, clojure has a much stronger emphasis on immutability than 
 traditional OO programming and is what I like about it... but it is 
 possible to write OO code using immutable data structures but is not as 
 idiomatic.


 Well, it's kind of idiomatic in scala, for example. But not in clojure, 
 yes.


Agreed, I did not like scala's excessive use of operators, implicit 
conversions and other syntax tricks.  Plus the compiler is painfully slow.
 

  

  I don't want clojure to be like CLOS, but I also don't think that we 
 should ignore more than 50 years of lessons learned and SOLID programming 
 principles.


 SOLID is about object-oriented design. 50 years of lessons learned tell us 
 that objects have failed :) 


I disagree.  I don't think OO has failed us...MOST software is written in 
OO languages.  Lisp and various functional languages are much older than 
OO, yet were not widely adopted for commercial use. I'm not saying OO is 
perfect or that there is no room for improvement, thats why I tried clojure 
in the first place, but perhaps OO has been far more successful then you 
give it credit for and certainly more successful in practice then these so 
called academic languages.

 

-- 
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: Doseq, map-style

2012-06-17 Thread Kurt Harriger
On Jun 17, 2012, at 10:45 AM, Vinzent ru.vinz...@gmail.com wrote:

Yes it is... emails was not the best example in this case.. think the
 area example instead as this is single value rather than collection.


Well, I thought we've already came to the agreement that area is a
(polymorphic) function and it has nothing to do with structure of your
data, no?


Yes, what I am also saying is that width, height, radius etc may also be
functions, if they are used by the domain they are should be a function.
 If they are not used by the domain they are an implementation detail and
should not be accessed via keywords except of course by the single function
that provides the seem.

Lazy sequences also introduce additional problems... they maybe realized
 when bindings are no longer in effect which causes all sorts of non-local
 errors with stacktraces that are completely non-intuitive.


Use bound-fn and similar tools to preserve the context. Use contract
programming https://github.com/dnaumov/clojure-contracts to get rid of
ugly stacktraces :) Anyway, these are other problems not related to the
topic.


Yes there is that, but this is doesnt resolve all problems with bindings...
Perhaps a different topic, but arent we already off topic :)



Yes, always access a map value via a function, this provides a seam (see
 Feathers, Working Effectively with Legacy Code
 http://www.informit.com/articles/article.aspx?p=359417) where alternative
 behavior could be introduced. Keywords are functions, but their behavior
 cannot changed therefore they do not make for useful seams.  The data still
 needs to be stored some where so you will have maps and will still need to
 use keywords to access that data...


Well, accessing a map value via a function is what object-oriented
programming is about. So your concern is about the fact that clojure isn't
object-oriented?

I thought you was talking about using functions to model all other data
structures, which is a good idea in theory, but is not very practical.

but that keyword usage should be in only one place so that when you do
 change the data structure eventually you will need to only update that one
 function.


Changing data structure == changing API. If you change an interface in Java
how many updates you'd have to do?


Data structure is an implementation detail... interfaces are contracts, if
the data representation changes in OO you need only change one class... In
clojure, you need to change every usage.  This is speaking from first hand
experience when I made trivial changes that would be a one liner in java
took hours and introduced simple bugs, wring usage, typo whatever. This is
exactly the point of my post, if you wrap keywords and treat them as one
does properties this could be a one liner in clojure too...


I disagree.  I don't think OO has failed us...MOST software is written in
 OO languages.


A million lemmings can't be wrong. Sure.


I'm not blindly advocating the use of simple abstractions just because that
what some/many OO programmer suggests is best practice...  but because
personal experience has given me enough conviction to believe they add
value even if they add a few LOC... And that it is worth arguing about a
bit... even if this means I am not following idiomatic clojure practices
that I disagree with.  I don't agree with all OO practices either..mutable
collection types, excessive over engineering... All patterns have some
trade offs, but one LOC for a seam is well worth it imo.




 Lisp and various functional languages are much older than OO, yet were not
 widely adopted for commercial use.


That's not true - they were.


 I'm not saying OO is perfect or that there is no room for improvement,
 thats why I tried clojure in the first place, but perhaps OO has been far
 more successful then you give it credit for and certainly more successful
 in practice then these so called academic languages.


Java is successful for commercial reasons, not because it's the best
language ever written.


-- 

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: Doseq, map-style

2012-06-17 Thread Kurt Harriger


On Sunday, June 17, 2012 1:41:22 PM UTC-6, Vinzent wrote:

 That is my point, representations SHOULD be considered implementation 
 details, because representations change... if you treat them as contracts 
 your code will break everywhere, if you wrap them with abstractions your 
 code will only need to change in one place... 

  
 As I mentioned above, this will lead us to objects instead of data. Also, 
 many people write code without (def foo :foo) and their code isn't breaking 
 (or at least they are hiding it carefully!), so this statement does not 
 match the reality, isn't it?

 But I have made this point before and starting to feel like the 
 conversation is going in circles.


  Yeah, it definitely is.

 I have made several reasoned arguments for getter functions...


 Which arguments? We found that :emails is a lazy seq and area is a 
 function... Could you provide a certain examples where plain maps don't 
 work, so we could highlight pros and cons and figure out the best way to 
 work around it?
  

 If you disagree thats fine.  But the only well reasoned argument why one 
 should not use them except that it adds an extra lines of code to maintain 
 and imo LOC is a poor metric for maintainability. 


 No, the argument is that it replaces data with unstructured objects, 
 making clojure sequence api inapplicable. Also, it's impossible to use 
 destructing, pattern matching, testing frameworks functionality and walkers 
 anymore. Moreover, since clojure doesn't support this approach out of the 
 box, you'd have to write and maintain some macros in order to avoid 
 duplication. Generally, I think it can make reading the code more difficult 
 for other people.




This is actually the most compelling argument which I didn't give you 
credit for.  However, if you follow the hollywood principle you don't need 
a seq abstraction.  Instead you use pipes and filters and this enables 
distributing computation across multiple machines without the 
synchronization bottleneck introduced by list concatenation.  

Ruby and python make this easy with first class functions and each() 
blocks.  Clojure however might be the worst case, because it requires 
making seq abstraction part of the contract and in turn creates a 
dependency on the data structure which in turn creates the need for the 
getter abstraction in the first place.  The need for getters is often an 
indication that the hollywood principle has been violated, and in clojure 
this principle is violated more often than it is not in the name of 
side-effect free functions.  

Haskell uses monads and this makes functions not only pure but also applies 
the hollywood principle.  I would love to use more Haskell... but I don't 
think Haskell will ever run on the JVM and even if it ever did the Java 
libraries would pretty much need to be blacklisted and it wouldn't be all 
that useful...  I thought clojure had potential due to its focus on 
immutability, but I think the hollywood principle is more important than 
side-effect free and this was the point of my original reply before we got 
off topic about abstracting implementation details.  If you follow the 
hollywood principle you don't need getters... but you do need side-effects. 
 

It actually seems silly in retrospective to go on and on about the value of 
getters in OO programs I avoid them like the plauge... but in OO I have the 
hollywood principle in clojure getters are the only abstraction to protect 
my code from changes to data representations. 

 

-- 
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: Doseq, map-style

2012-06-17 Thread Kurt Harriger


On Sunday, June 17, 2012 6:31:34 PM UTC-6, Sean Corfield wrote:

 On Sun, Jun 17, 2012 at 11:59 AM, Kurt Harriger kurtharri...@gmail.com 
 wrote: 
  That is my point, representations SHOULD be considered implementation 
  details, because representations change... if you treat them as 
 contracts 
  your code will break everywhere, if you wrap them with abstractions your 
  code will only need to change in one place... 

 Have you watched Stu Halloway's talk about the design of Datomic? 
 Evident Code, at Scale: 
 http://www.infoq.com/presentations/Evident-Code-at-Scale 

 You said earlier in this thread that Clojure is your first Lisp so 
 it's possible (likely?) you don't yet realize how different it is to 
 the languages you're used to. If you watch several of the 
 presentations by Stu Halloway and Rich Hickey and some of the other 
 Clojure/core folks, you should get an appreciation of why data-as-API 
 is reasonable in Clojure, in the same way that interface-as-API is 
 reasonable in Java. It's an immutable contract. It can be operated on 
 by all the standard Clojure functions but it's still a contract. It is 
 not necessarily the representation - it is the API you present to the 
 world. You can change the representation any way you want and if the 
 API does not change (in the same way that an interface wouldn't change 
 in Java), then you continue to present the same data structure to 
 client code, even if it is now a projection of the representation, 
 rather than the representation itself. 


I didn't get a chance to see it, before but watching it now and he says a 
couple interesting about abstractions right off at the beginning ideal 
number of abstractions 0.  We abstract to much interfaces are too large 
etc... 

One of the sayings I hear reiterated is it is better to have 100 methods 
that operate on one data structure than 10 methods that operate on 10 data 
structures.  Yet how is this different from one large interface with a 
hundred methods? Now if you want to change a map so that :area which was 
previously an precomputed value to a deferred computation you now need to 
override ILookup, ISeq IMapEntry, perhaps others to ensure keyword lookups 
and destructuring works etc... so while some see clojure as removing 
unnecessary abstractions I see it as adding creating one bloated 
abstraction around a persistent map which is hard to change due to the 
number and complexity of the built-in abstractions then 1 function that is 
relevant to my problem domain.   I have also found that clojure code lacks 
cohesion we hate objects so we are just going to throw everything into one 
large namespace and say we have none... In OO I might call this a god 
class?  I don't know, I'm not sold yet... but I'll keep watching.

I like the data as api idea in theory, as it 
encourages declarative programming and really thinking about the problem. I 
don't disagree that many java abstractions could be considered premature 
and could be added later if needed... but sometimes they really are 
needed. I discussed this before in regards to HTML that dependance on 
representation can limit the ability to quickly implement new features... 
In the beginning html probably didn't need any additional abstractions but 
as the usage and domain complexity increased it turned into a mess that 
requires apis to both read and write those data structures.  

I was very excited about using clojure a year ago and now that I've spent a 
few months with it I've been very frustrated... Its possible something just 
hasn't quite clicked yet, but I'm also beginning to notice issues in other 
apis.  Many libraries have been deprecated, replaced and rewritten due to 
breaking changes to clojure core or other libraries and that worries me a 
bit.. but clojure is still maturing and no one gets the abstractions 
exactly right the first time so I'm kinda going back into a wait and see 
mode...but I can't sit on the side lines entirely cause I just wrote a 
reasonably complex clojure program that I need to maintain still :)



 I have made several reasoned arguments for getter functions... If you 
  disagree thats fine. 

 Your arguments are reasoned for Java and its ilk because in those 
 languages, data structures are just representation details - and they 
 are mutable, so they can't possibly be an API. Your arguments are not 
 reasoned for Clojure because data structures cannot be modified by 
 client code - they _can_ be the API, and an API that can be used 
 directly by map / filter / reduce and all the sequence functions and 
 so on. 

 Vincent said: 

  Well, but if interfaces change? That's the same as data representation 
  change in clojure. 

 This is the fundamental shift in thinking that immutable data-as-API 
 requires. It's how you get some of the real benefits from Clojure. 
 -- 
 Sean A Corfield -- (904) 302-SEAN 
 An Architect's View -- http://corfield.org/ 
 World Singles, LLC. -- http://worldsingles.com

Re: Doseq, map-style

2012-06-17 Thread Kurt Harriger
On Jun 17, 2012, at 9:38 PM, Timothy Baldridge tbaldri...@gmail.com wrote:

 I have also found that clojure code lacks cohesion we hate objects so we 
 are just going to throw everything into one large namespace and say we have 
 none... In OO I might call this a god class?  I don't know, I'm not sold 
 yet... but I'll keep watching.

 That depends. In OOP we might call it a God Class if it was 100
 functions on a single mutable class. However, that's not what we're
 doing in Clojure. The analogy to OOP would would be a class with 100
 static public members, and no private variables. This exact
 methodology is used in .NET for example:
 http://msdn.microsoft.com/en-us/library/system.linq.enumerable.aspx


 Now if you want to change a map so that :area which was previously an 
 precomputed value to a deferred computation you now need to override ILookup

 I hear this argument at work dealing with Stored Procs in the SQL
 database. If you don't let me do ad-hoc queries, then when you change
 the sproc, you're going to break all our code!. But the correct
 answer to this complaint is: I won't. If you need to change area
 from pre-computed to defered execution, then you are changing the
 actual semantics of the code. In that case, yes, you will either need
 to define a different data api, or update all your old code to agree
 with the new computation method. Most of the time, if you have code in
 production, sticking with the first is the better route.

Generally agree


 During the day, I work on a fairly large C# codebase, and I see these
 same problems, but they are simply ignored by most .NET programmers.
 If I call Foo.getBar(). I haven't the foggiest clue where on earth
 it's going to get the data I want. It could be computing the value, or
 simply returning a private variable, or it could be going to Mars to
 gather a soil sample and use that in its calculation (blocking me
 until it returns). That's one of the benefits of the everything is a
 map method. I know that calling (:bar data) is going to return almost
 instantly. You can re-write your data server to involve Mars trips,
 but once the data is in my program, my code will remain snappy, no
 matter how long it took to compute that data.

Forget about getters, OO should be event driven in which case you dont
call getFoo(), foo is given to you when your method is invoked making
getters unnecessary. The clojure problem is different because events
imply side effects.  Although, I have never seen a program that does
not have side effcts. I tried to write one once but it had no output
so im not sure if it actually worked :)


 So I guess what I'm saying is that if you're deciding to switch area
 from pre-computed to lazy execution, that's such a major change
 semantically that you better reevaluate your code before simply
 abstracting it and calling it a day.

True too.


 But then again, I'm biased. I deal with so many layers of abstraction
 at my day job sometimes I just want to stand up from my desk and shout
 A hashmap! My kingdom for a hashmap!.


I programmed in C# for years but changed to JVM cause windows isnt a
good platform for web apps. I turned to clojure for many of these same
reasons, i love that clojure values are immutable, serializable, and
implement meaningful equality with basicaly no code.  Pojos/message
types should have these things :) but i think services classes should
be event driven and emit new events rather than return values and
delegate much of the work to the domain.  I guess i feel like clojure
consists only of pojos and god classes...


 Timothy Baldridge

 --
 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 a
 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: Doseq, map-style

2012-06-17 Thread Kurt Harriger
On Jun 17, 2012, at 9:46 PM, Sean Corfield seancorfi...@gmail.com wrote:

 On Sun, Jun 17, 2012 at 8:06 PM, Kurt Harriger kurtharri...@gmail.com wrote:
 One of the sayings I hear reiterated is it is better to have 100 methods
 that operate on one data structure than 10 methods that operate on 10 data
 structures.  Yet how is this different from one large interface with a
 hundred methods?

 You've misunderstood the intent behind the quote. By using a generic
 data structure, you have more functions available to you - and you
 don't have to duplicate each function for each different data type (10
 methods that operate on 10 data structures is 100 methods but really
 only 10 different ones). By using a generic map, all functions that
 work on maps are available to you. By choosing a specific data
 structure for your object, you are forced to write a new version of
 every function you might need. Your one line getters might be trivial
 enough (one for every property) but now you can't use your object with
 any function that takes an associative data structure and you have to
 write adapter functions for each of those functions too.

  Now if you want to change a map so that :area which was
 previously an precomputed value to a deferred computation you now need to
 override ILookup, ISeq IMapEntry, perhaps others to ensure keyword lookups..

 This is an API change, just like changing a Java interface. In OO-land
 folks get very blasé about changing data structures because they
 obsessively wrap everything up and they seem to ignore all the extra
 code they have to write to do anything with these objects. By
 designing an API based on a data structure, there's a lot less code
 needed to interact with it. If you change the API, yes, client code
 needs to change, just like in Java. If your object's API changes so
 that area is not precomputed and becomes a deferred computation, that
 is still a change to the contract (because the performance of
 accessing area changes - and calling getArea() repeatedly now becomes
 expensive rather than a trivial operation). If you're designing a
 data-based API, you need to consider what to provide and what the
 characteristics of each part of the data structure are, just as you
 need to with a Java interface. What's missing in Java interfaces are
 any consideration about performance and what the abstraction really
 means.

A fair point, getters dont really solve the problem they just change
it.  The problem i had was generating large complex data structures as
input to other functions made me realise the representation was not
ideal, changing it however was much more work than I expected. I find
that what i am doing is creating a new namespace, copying the code,
change it then go about replacing the old namespace with the new and
this isnt working well for me I need seams for refactoring
otherwise small changes take forever.  I wish i could say that my code
improves each time i rewrite it but as the complexity increases the
more things change and the worse everything else gets. In oo i know
how to handle this complexity, in clojure the refactoring patterns are
less clear to me.



 Its possible something just hasn't quite clicked yet

 Quite possible. If you have a long history of OO thinking, FP can be
 really hard to get into. I find it much easier to teach FP to folks
 who've had little or no OO experience. Getting OO folks away from
 thinking about state as something inside an object that they can just
 poke at can take a while :)

 Many libraries have been deprecated, replaced and rewritten due to
 breaking changes to clojure core or other libraries and that worries me a

 To be fair, the shift in contrib from 1.2 to 1.3 was more about
 getting rid of unmaintained code and ad hoc experiments and focusing
 instead on well-maintained libraries that are useful to real world
 developers. Several of the authors of the abandoned parts of
 monolithic contrib will be very quick to tell you not to use their old
 code because it was half-baked or otherwise flawed...

 I can't sit on the side lines entirely cause I just wrote a reasonably
 complex clojure program that I need to maintain still :)

 And I have thousands of lines of Clojure in production too, and a
 database with millions of users - and thousands more signing up every
 day. We started on Clojure 1.2 but switched to 1.3 early on and went
 to production with Alpha 7 (or 8) and now we're on Clojure 1.4 (and
 testing on nightly builds of 1.5, just to be sure we're future proof).
 Where we needed libraries from 1.2 that were not 1.3 compatible, we
 made them compatible and worked with the library maintainers as much
 as we could. clojure.contrib.sql moved to clojure.java.jdbc and is
 actively maintained because of that.
 --
 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

Re: Doseq, map-style

2012-06-16 Thread Kurt Harriger


On Wednesday, June 13, 2012 2:52:15 AM UTC-6, Vinzent wrote:

 I do use pre-conditions where the test condition is simple, ie is this a 
 string? does the map have a :field-type? however I get a lot of my input 
 data from http requests as json which have similar structures but different 
 semantics, so I often do not have preconditions where type is not 
 explicit. For example a string could be an list id or a contact id or an 
 encoded json document. While it is possible to try to parse a string for 
 json to verify its type this is seems very computationally expensive and 
 therefore usually inferred from the context. 


 Why do you care about computational expensiveness of pre and post 
 conditions? They'll be turned off in production anyway.


How does one turn off pre/post conditions in production?  I agree with Sean 
however and generally think that assertions in production a bad thing.
 

  

 For example, my first contact model I had {... :fields [{:field-type 
  :email :value  ...}]}  I later realized that the endpoint to get the 
 contact information provided them grouped and I was filtering a lot based 
 on field-type anyway so a more effective data structure was {:emails 
 [{:value  ...}]}, :field-type was just an implementation detail, the 
 email object still has a value and associated behavior but the map no 
 longer contains a :field-type.  However, phone numbers have exactly the 
 same {:value } structure so the only way to determine if it is an email 
 or a phone number is from context or by parsing the string.


 I believe using records or adding :type metadata would be an ideal fit in 
 this case. 


I agree, an explicit type field makes dispatching easy.  However this data 
structure returned by (http/get ... :as json) so if I want to add type 
information I need to walk the tree and rewrite it.  Not necessarily a bad 
idea, but in some cases the only thing I need is the eTag and so the 
additional processing may in some cases unnecessary. One could easily make 
data conversions lazy by doing something like (defrecord Contact [contact]) 
(defmethod emails Contact [contact] (map map-Email (:emails contact)) to 
delay the computation until the values are actually requested.  However, 
note that emails is now a multimethod method not a value and the consumer 
needs to use (emails contact) rather than (:emails contact)... Thus as I 
was saying previously is that (def emails :emails) gives you the 
flexibility to delay computation if desired.  


 I also tried using multimethods instead of protocols, but I still found I 
 needed to restart the JVM frequently.  I think whenever I would re-eval the 
 namespace with the record type and (defmethod ...) a new class file would 
 be emitted and the objects in my swank session need to be recreated.   


 defmulti has defonce semantic; you can use (def foo nil) (defmulti foo 
 ...) to workaround this. A topic about this problem was recently created in 
 dev mail list, so it'll probably be fixed soon. 

 I disagree.  Ironically, if you told a java developer that getters were a 
 premature optimization and he should use fields instead he would look at 
 you funny.  Getters are not an optimization and if anything have a minor 
 performance penalty.  However, using fields makes one very dependent on 
 implementation details doing so is considered bad practice. I don't see how 
 this is any different in clojure.  


 In clojure, structure of your map is a part of the contract. It's not an 
 implementation detail - it's the same as getters\setters in java.


EXACTLY my point!  Clojure does not distinguish between properties and data 
representation and these are NOT the same thing.  There are many different 
ways to represent data. For example the area of a shape can be represented 
in many different ways, square inches, square miles, a rectangle, circles, 
polygons, or perhaps complex geometry requiring calculus all of which could 
be asked what is your area in square feet.  Area is a property of the 
object, the width, radius, number of sides, etc is an implementation 
detail. 

You may then ask so why don't you just pass in {:area } as square feet 
instead of the radius of the circle?  Because the value may not be used by 
the function.  If its not used then why is it part of the contract? 
 Because it may be used conditionally, for example, maybe the function 
needs to find the first shape that will fit within a region once that limit 
is reached it no longer requires the area for any other shapes.  So if the 
shape requires complex calculus which has been written in another 
programming language and thus requires a rpc call to a network service to 
compute the value that is only used sometimes seems wasteful and 
inefficient if the value is only sometimes computed.  This example is 
somewhat contrived, but it is not that different from what I am doing.

For each contact record I need to perform data enrichment, normalization, 
cleansing, and 

Re: Doseq, map-style

2012-06-16 Thread Kurt Harriger


On Saturday, June 16, 2012 12:26:34 PM UTC-6, Sean Corfield wrote:

 On Sat, Jun 16, 2012 at 10:58 AM, Kurt Harriger kurtharri...@gmail.com 
 wrote: 
  How does one turn off pre/post conditions in production? 

 (binding [*assert* false] (call-my-code)) 
  

 I agree with Sean 
  however and generally think that assertions in production a bad thing. 

 I didn't say that. I said the question was a philosophical one. 

 

 I actually think assertions should stay _on_ in production (so I would 
 care about computationally intensive assertions - and I would prefer 
 those to be in a test suite). 



Sorry, I mistyped that.  I too agree that assertions should remain on 
in production. Sometimes my fingers don't keep up and I miss a word or two 
when that word is not the results can be disastrous. 


 (and I don't agree with you on using accessor functions vs data-as-API 
 either) 


I think there is a difference between data as an api and using data as a 
programming model.  I am fond of declarative programming, say what not how. 
 But, it is my opinion that good declarative data models require extremely 
good understanding of the problem domain which develops from reflecting 
of the commonality and differences in many different 
implementations. Declarative data models done right can simplify things... 
however, the wrong data model can also introduce complexity. Ant is a data 
driven api but the data model is poorly designed, maven is a much better 
example of a declarative data api, yet a lot of people still find maven to 
be more complex and inflexible than ant for various projects that require a 
lot of plugins. A really good clojure specific example of data vs api is 
the discussion regarding if the clojurescript analyzer should contain 
children or if children should be a multimethod 
https://groups.google.com/forum/m/?fromgroups#!topic/clojure-dev/vZLVKmKX0oc

HTML is another great example of a declarative data model that has shown 
the stress of increasing complexity from poor representation for common use 
cases (its a navbar not a table) and a multiplicity of vendor specific 
additions that do the same thing in a different way.  I don't think it is a 
stretch to say that rich client side web development was significantly more 
difficult to do correctly before apis such as jquery were written to 
abstract over the differences in vendor implementations.   HTML is data as 
an api that tells the browser how to render a page it cannot be anything 
else... but I wouldn't consume or construct the data structure directly 
instead I would use an api such as jquery so that when the data 
representation changes such as new css attributes that enable the same 
effect to be accomplished more efficiently I can quickly take advantage of 
them without needing to make massive breaking code changes.   APIs allow 
you to be DRY.

I'm not suggesting that the api for a program should not be 
a declarative data structure, what I am saying is that we should not 
consume the data structure directly without abstractions. Publish your api 
as a data structure...consume that the data structure through an api. 

Kurt

 

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


On Saturday, June 16, 2012 12:26:34 PM UTC-6, Sean Corfield wrote:

 On Sat, Jun 16, 2012 at 10:58 AM, Kurt Harriger kurtharri...@gmail.com 
 wrote: 
  How does one turn off pre/post conditions in production? 

 (binding [*assert* false] (call-my-code)) 

  I agree with Sean 
  however and generally think that assertions in production a bad thing. 

 I didn't say that. I said the question was a philosophical one. 

 I actually think assertions should stay _on_ in production (so I would 
 care about computationally intensive assertions - and I would prefer 
 those to be in a test suite). 

 (and I don't agree with you on using accessor functions vs data-as-API 
 either) 
 -- 
 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: Doseq, map-style

2012-06-16 Thread Kurt Harriger


On Saturday, June 16, 2012 1:28:21 PM UTC-6, Vinzent wrote:

 I agree, an explicit type field makes dispatching easy.  However this data 
 structure returned by (http/get ... :as json) so if I want to add type 
 information I need to walk the tree and rewrite it.  Not necessarily a bad 
 idea, but in some cases the only thing I need is the eTag and so the 
 additional processing may in some cases unnecessary. One could easily make 
 data conversions lazy by doing something like (defrecord Contact [contact]) 
 (defmethod emails Contact [contact] (map map-Email (:emails contact)) to 
 delay the computation until the values are actually requested.  However, 
 note that emails is now a multimethod method not a value and the consumer 
 needs to use (emails contact) rather than (:emails contact)... Thus as I 
 was saying previously is that (def emails :emails) gives you the 
 flexibility to delay computation if desired.  


 You have delays and lazy sequences for delaying computation.


This still requires changing your code to @(:emails contact).  If you use 
(emails contact) you need change your code in only one place. 


 Clojure does not distinguish between properties and data representation 
 and these are NOT the same thing. 


 Properties is OOP concept; clojure is not an object-orinted language.

 

  There are many different ways to represent data. For example the area of 
 a shape can be represented in many different ways, square inches, square 
 miles, a rectangle, circles, polygons, or perhaps complex geometry 
 requiring calculus all of which could be asked what is your area in square 
 feet.  Area is a property of the object, the width, radius, number of 
 sides, etc is an implementation detail. 


 No, area is a function.


Property is just the OO word for function, semantically they are the same. 
OO doesn't have functions they have properties and methods.  
 

  

 You may then ask so why don't you just pass in {:area } as square feet 
 instead of the radius of the circle?  Because the value may not be used by 
 the function.  If its not used then why is it part of the contract? 
  Because it may be used conditionally, for example, maybe the function 
 needs to find the first shape that will fit within a region once that limit 
 is reached it no longer requires the area for any other shapes.  So if the 
 shape requires complex calculus which has been written in another 
 programming language and thus requires a rpc call to a network service to 
 compute the value that is only used sometimes seems wasteful and 
 inefficient if the value is only sometimes computed.  This example is 
 somewhat contrived, but it is not that different from what I am doing.


 If getting a 'property' requires such computations, then it's clearly 
 should be a function.


Agree.  

  

 My point is that properties with getter functions allow you to defer 
 computation, keywords do not.  Keywords are not like java getters they are 
 like java fields.  


 Keywords are just one of clojure's data structures (see 
 http://clojure.org/data_structures#Data 
 Structures-Keywords) 

 

 Instead of (:property themap), one should use (def property :property) 
 (property themap). 


 No, one shouldn't.


I disagree... but I will continue to recommend otherwise.  
 


 Actually this is only somewhat contrived.  It is not uncommon for a user 
 to the same nickname in his email nickn...@domain.com and in twitter 
 handle, and this is a useful similarity feature when this computation is 
 performed for each *pair* of field in each *pair* of contacts this 
 computation may need to be performed millions of times.


 Well, you can use memoization or choose to structure your data in some 
 other way.
  

 Perhaps lisp programmers already did? CLOS and OO was born?


 Clojure is not Common Lisp. 


Agreed, clojure has a much stronger emphasis on immutability than 
traditional OO programming and is what I like about it... but it is 
possible to write OO code using immutable data structures but is not as 
idiomatic.  I don't want clojure to be like CLOS, but I also don't think 
that we should ignore more than 50 years of lessons learned and SOLID 
programming principles.


-- 
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: Doseq, map-style

2012-06-16 Thread Kurt Harriger


-- 
Kurt Harriger
Sent with Sparrow (http://www.sparrowmailapp.com/?sig)


On Saturday, June 16, 2012 at 3:07 PM, Kurt Harriger wrote:

 
 
 On Saturday, June 16, 2012 1:28:21 PM UTC-6, Vinzent wrote:
   I agree, an explicit type field makes dispatching easy.  However this 
   data structure returned by (http/get ... :as json) so if I want to add 
   type information I need to walk the tree and rewrite it.  Not necessarily 
   a bad idea, but in some cases the only thing I need is the eTag and so 
   the additional processing may in some cases unnecessary. One could easily 
   make data conversions lazy by doing something like (defrecord Contact 
   [contact]) (defmethod emails Contact [contact] (map map-Email (:emails 
   contact)) to delay the computation until the values are actually 
   requested.  However, note that emails is now a multimethod method not a 
   value and the consumer needs to use (emails contact) rather than (:emails 
   contact)... Thus as I was saying previously is that (def emails :emails) 
   gives you the flexibility to delay computation if desired.  
  
  
  You have delays and lazy sequences for delaying computation.
 
 This still requires changing your code to @(:emails contact).  If you use 
 (emails contact) you need change your code in only one place. 
  
   Clojure does not distinguish between properties and data representation 
   and these are NOT the same thing. 
  
  Properties is OOP concept; clojure is not an object-orinted language.
   
There are many different ways to represent data. For example the area of 
   a shape can be represented in many different ways, square inches, square 
   miles, a rectangle, circles, polygons, or perhaps complex geometry 
   requiring calculus all of which could be asked what is your area in 
   square feet.  Area is a property of the object, the width, radius, number 
   of sides, etc is an implementation detail. 
   
  
  
  No, area is a function.
 
 Property is just the OO word for function, semantically they are the same. OO 
 doesn't have functions they have properties and methods.  
  
   
   You may then ask so why don't you just pass in {:area } as square feet 
   instead of the radius of the circle?  Because the value may not be used 
   by the function.  If its not used then why is it part of the contract?  
   Because it may be used conditionally, for example, maybe the function 
   needs to find the first shape that will fit within a region once that 
   limit is reached it no longer requires the area for any other shapes.  So 
   if the shape requires complex calculus which has been written in another 
   programming language and thus requires a rpc call to a network service to 
   compute the value that is only used sometimes seems wasteful and 
   inefficient if the value is only sometimes computed.  This example is 
   somewhat contrived, but it is not that different from what I am doing.
   
  
  
  If getting a 'property' requires such computations, then it's clearly 
  should be a function.
 
 Agree.  
   
   My point is that properties with getter functions allow you to defer 
   computation, keywords do not.  Keywords are not like java getters they 
   are like java fields.  
   
  
  
  Keywords are just one of clojure's data structures (see 
  http://clojure.org/data_structures#Data Structures-Keywords 
  (http://clojure.org/data_structures#Data+Structures-Keywords)) 
   
   Instead of (:property themap), one should use (def property :property) 
   (property themap). 
   
  
  
  No, one shouldn't.
 
 I disagree... but I will continue to recommend otherwise.  
 
I disagree... and I will continue to recommend otherwise.   
 
  
   Actually this is only somewhat contrived.  It is not uncommon for a user 
   to the same nickname in his email nickn...@domain.com 
   (mailto:nickn...@domain.com) and in twitter handle, and this is a useful 
   similarity feature when this computation is performed for each *pair* of 
   field in each *pair* of contacts this computation may need to be 
   performed millions of times.
  
  Well, you can use memoization or choose to structure your data in some 
  other way.
   
   Perhaps lisp programmers already did? CLOS and OO was born?
  
  
  Clojure is not Common Lisp. 
 
 Agreed, clojure has a much stronger emphasis on immutability than traditional 
 OO programming and is what I like about it... but it is possible to write OO 
 code using immutable data structures but is not as idiomatic.  I don't want 
 clojure to be like CLOS, but I also don't think that we should ignore more 
 than 50 years of lessons learned and SOLID programming principles.
 
 
 -- 
 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 
 (mailto: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

Re: Doseq, map-style

2012-06-16 Thread Kurt Harriger
On Jun 16, 2012, at 6:27 PM, Softaddicts lprefonta...@softaddicts.ca wrote:

 50 years of solid programming principles, OO being the Holy Grail ? :)

 I assume then that you programmed a lot in Simula-66 ? I did...

 For over 50 years, we made the same mistakes that Clojure attempts to
 correct. Most of the time new languages repackaged the same flawed concepts
 of the past, this has been done over and over again.

How is clojure different? I have programmed in dozens of languages,
message based and functional, static and dynamic, garbage collected
and manage it yourself.  One thing that I have realized is there is no
magic bullet and they are as you say different versions of the same
thing.

Clojure is my first lisp however and I was really excited about it
when I started but after writing a project with more than a few
thousand lines of code I found it very frustrating to change.


 Programmer's throughput have to increase somehow, any superfluous line of
 code is too many.

 Getters facades of any form are just that, superflous code lines that need to 
 be maintained later on.

 That led Java right in the russian puppet syndrom.

 In these 50 years solid principles, many failed to deliver. It's time for a 
 reset :)


I too have experienced the russian doll syndrome and logic scattered
across multiple files, but I have already started migrating away from
clojure because the code is difficult to maintain.

If the code does not need to change then maintaining it is easy,
however if it does need to change i would prefer to make that change
in only one place.  DRY.  If that only requires one more line of code
then I think it is well worth it and I certainly do not believe that
lines of code are the best metric of maintainable code.  IMHO,
Readability and good domain abstractions are FAR more important then
LOC.


 Luc





 On Saturday, June 16, 2012 1:28:21 PM UTC-6, Vinzent wrote:

 I agree, an explicit type field makes dispatching easy.  However this data
 structure returned by (http/get ... :as json) so if I want to add type
 information I need to walk the tree and rewrite it.  Not necessarily a bad
 idea, but in some cases the only thing I need is the eTag and so the
 additional processing may in some cases unnecessary. One could easily make
 data conversions lazy by doing something like (defrecord Contact [contact])
 (defmethod emails Contact [contact] (map map-Email (:emails contact)) to
 delay the computation until the values are actually requested.  However,
 note that emails is now a multimethod method not a value and the consumer
 needs to use (emails contact) rather than (:emails contact)... Thus as I
 was saying previously is that (def emails :emails) gives you the
 flexibility to delay computation if desired.


 You have delays and lazy sequences for delaying computation.


 This still requires changing your code to @(:emails contact).  If you use
 (emails contact) you need change your code in only one place.


 Clojure does not distinguish between properties and data representation
 and these are NOT the same thing.


 Properties is OOP concept; clojure is not an object-orinted language.



 There are many different ways to represent data. For example the area of
 a shape can be represented in many different ways, square inches, square
 miles, a rectangle, circles, polygons, or perhaps complex geometry
 requiring calculus all of which could be asked what is your area in square
 feet.  Area is a property of the object, the width, radius, number of
 sides, etc is an implementation detail.


 No, area is a function.


 Property is just the OO word for function, semantically they are the same.
 OO doesn't have functions they have properties and methods.




 You may then ask so why don't you just pass in {:area } as square feet
 instead of the radius of the circle?  Because the value may not be used by
 the function.  If its not used then why is it part of the contract?
 Because it may be used conditionally, for example, maybe the function
 needs to find the first shape that will fit within a region once that limit
 is reached it no longer requires the area for any other shapes.  So if the
 shape requires complex calculus which has been written in another
 programming language and thus requires a rpc call to a network service to
 compute the value that is only used sometimes seems wasteful and
 inefficient if the value is only sometimes computed.  This example is
 somewhat contrived, but it is not that different from what I am doing.


 If getting a 'property' requires such computations, then it's clearly
 should be a function.


 Agree.



 My point is that properties with getter functions allow you to defer
 computation, keywords do not.  Keywords are not like java getters they are
 like java fields.


 Keywords are just one of clojure's data structures (see 
 http://clojure.org/data_structures#Data
 Structures-Keywords)



 Instead of (:property themap), one should use (def property 

Re: Doseq, map-style

2012-06-12 Thread Kurt Harriger


On Tuesday, June 12, 2012 2:18:03 AM UTC-6, Christophe Grand wrote:

 Hi,

 To contrast our experiences of the language and the different approaches 
 to deal with some problems:

 On Sun, Jun 10, 2012 at 4:47 AM, Kurt Harriger kurtharri...@gmail.comwrote:

  Many will say that side-effecting functions are more difficult to test 
 then pure functions... However after writing about 4000 lines of clojure 
 code, I realized that things in practice are never quite as simple as they 
 seem.  As functions are composed the data structures they work with grow 
 larger and more complex and this leads to maps containing maps containing 
 lists containing maps and a minor change downstream can ripple through the 
 program.  Tests become significantly more complex and fragile as the input 
 and output structures grow in complexity.


 Do you test only the functions or do you have also introduced lint 
 functions which check the shape of your data. To me, these are pretty 
 useful: you can use them in tests, pre/postconds, middlewares to guard 
 against untrusted sources etc. 


I do use pre-conditions where the test condition is simple, ie is this a 
string? does the map have a :field-type? however I get a lot of my input 
data from http requests as json which have similar structures but different 
semantics, so I often do not have preconditions where type is not 
explicit. For example a string could be an list id or a contact id or an 
encoded json document. While it is possible to try to parse a string for 
json to verify its type this is seems very computationally expensive and 
therefore usually inferred from the context. 

I also felt that explicit type checking went against the spirit of duck 
typing, there was a couple of times I added type checks only to realize 
that the type checking was to strict... ie nil was an acceptable value and 
now the code through an assertion error. In many cases a function simply 
takes the argument and passes it to another function, so I don't really 
care what type the argument is as long as there is an implementation of the 
other function which supports that data type, maybe it doesn't know but in 
the future maybe it will should my code unnecessarily constrain the type 
based on an implementation detail?  

I have never been truely sold on duck typing however as I often find the 
time I spend debugging exceptions thrown deep down in the call stack 
because an error that could have been caught earlier when the problem was 
obvious was allowed to penetrate deep into call stack where the problem is 
no longer obvious often within a third party library that never expected 
that type of input.  In OO the argument is an interface which says nothing 
about the structure of the object, only that it provides the desired 
behavior.  Protocols are a step in this direction, however, if you extend a 
protocol to a map then (satisfy? TheProtocol {}) will return true for ALL 
maps, making satisfies? an otherwise useless precondition.  

For example, my first contact model I had {... :fields [{:field-type 
 :email :value  ...}]}  I later realized that the endpoint to get the 
contact information provided them grouped and I was filtering a lot based 
on field-type anyway so a more effective data structure was {:emails 
[{:value  ...}]}, :field-type was just an implementation detail, the 
email object still has a value and associated behavior but the map no 
longer contains a :field-type.  However, phone numbers have exactly the 
same {:value } structure so the only way to determine if it is an email 
or a phone number is from context or by parsing the string.


 

 This reminded me of another OO code smell Don't talk to strangers 
 and the Law of Demeter, instead sending and returning maps of lists of maps 
 I started returning maps of functions.  This provided additional decoupling 
 that enabled me to refactor a bit more easily additionally maps of maps of 
 lists of maps often need to be fully computed where as a map containing 
 functions allows me to defer computation until it is actually required 
 which may in many cases be never. 


 Basically you are returning a lazy map a map of keys to delayed values 
 (why not use delays instead of fns as values?), while it is sometimes a 
 necessity to do so, the implied trade-off must not be overlooked: the map 
 can't be treated as a value anymore: if you call twice the pure function 
 which generates such a lazy map twice with the same arguments, you get two 
 lazy maps which are not equals! I'm not even speaking about being equal to 
 their non-lazy counterparts (which makes them a bit harder to test)


This is an excellent point. Initially I started passing maps of functions 
into other functions as optional parameter map for testing (new-correction 
[  {:keys [get-current-date] :or [get-current-date get-current-date]). 
  This solved one problem but created others, the function was now 
completely deterministic and easy to test

Re: Doseq, map-style

2012-06-09 Thread Kurt Harriger
 
You could also (dorun (map f coll)) 

It is actually interesting you brought this up as I was recently 
contrasting the OO principle tell don't ask with the functional way of 
doing things.  In OO a void method taking a visitor is preferred over 
return values.  One could perhaps say that (dorun (map f (generator))) is 
pretty much the same thing as (each (generator) f) except that generator is 
now a pure side effect free function where as visitors generally speaking 
have side effects, although this isn't required for example (each coll 
identity) is just as easy to use and test. 

The more I thought about it the more I began to realize that the OO visitor 
approach may still have some advantages over the functional approach.  In a 
typed language the generator can overload based on the visitor's type 
signature, this makes refactoring and evolving code easier while still 
preserving backward compatibility as different versions of a visitor might 
have different method parameter types.  Of course you could do this in 
clojure explicitly but is less elegant ie (map f (generator 
:non-default-type)) and is generally considered confusing to have functions 
return different return types depending on their parameters. It is probably 
better to just choose a different function name instead.

One other difference that is not as easy to emulate functionally is when 
the generator spawns multiple threads and delegates the work where each 
worker may call the visitor back on different threads.  In clojure you can 
easily (pmap f (generator)), however this requires generator to create a 
sequence of return values from a specific thread regardless of how many 
threads are used to generate the sequence or process the sequence, 
ultimately the generator must first bring all these results together on a 
single thread creating a synchronization bottleneck that does not 
necessarily need to exist when using side effects instead of return values. 
 For example, the side effect might be to write its results to a database 
and the generator might partition the work to each visitor never expecting 
a reply from any of them, the visitor might even forward the request to a 
different machine on the network since no return value is expected or 
required.  

Many will say that side-effecting functions are more difficult to test then 
pure functions... However after writing about 4000 lines of clojure code, I 
realized that things in practice are never quite as simple as they seem. 
 As functions are composed the data structures they work with grow larger 
and more complex and this leads to maps containing maps containing lists 
containing maps and a minor change downstream can ripple through the 
program.  Tests become significantly more complex and fragile as the input 
and output structures grow in complexity.

This reminded me of another OO code smell Don't talk to strangers and 
the Law of Demeter, instead sending and returning maps of lists of maps I 
started returning maps of functions.  This provided additional decoupling 
that enabled me to refactor a bit more easily additionally maps of maps of 
lists of maps often need to be fully computed where as a map containing 
functions allows me to defer computation until it is actually required 
which may in many cases be never. Although very idiomatic to use keywords 
to get from maps, I have started to think of this as a code smell and 
instead prefer to (def value :value) and use this var instead of the 
keyword because it allows me to later replace the implementation or rename 
properties if it is necessary to refactor and I want to minimize changes to 
existing code or make changes to the existing code in small incremental 
units rather than all at once.  

It is also very hard to write a useful program that does not contain 
side-effects or reads data from an impure datasource and I used midje to 
mock functions that such as (get-current-time), many times my function did 
not use that function directly but was used by another function that my 
function called.  I began to see this as a code smell in OO I would mock 
the object that uses get-current-time not get-current-time itself which 
then gave me the idea to start passing the functions used by the function 
under test to the function as additional parameters, for testing I could 
pass in an alternative function such as (constantly true) or (identity). 
 However, some functions required many functions so I began to group these 
into maps and began to realize that I was reinventing OO programming... 
perhaps there is a good reason lisp programmers invented CLOS in the first 
place.  

I'm starting to go off topic, and don't mean to troll, but your question as 
innocent as it seems is perhaps one of the most important differences 
between OO and functional programming (Tell don't ask).  Perhaps the 
functional solution is monads... but most find these confusing for some 
reason and are hardly idiomatic.  I 

defrecord serialization and *data-readers*

2012-05-14 Thread Kurt Harriger
When I first started my project I tried using defrecord and defprotocol for 
various data structurs and when I wanted an easy serialization function I 
used pr-str and read-string, this worked great!... until I wanted to do 
some refactoring and move some types to another namespace.  After changing 
the namespace name, I could no longer read the serialized data structures 
since the serialized data included namespace and record type 
#namespace.Record{:prop value   }.  Ideally, I would just be able to 
redefine the reader literal for #namespace.Record so that I could define a 
custom function or perhaps alias it to an equivalent record type in a 
different namespace via *data-readers*, but this didn't seem to work for 
me.  It appears that data-readers can't override the reader literals for 
record types and instead read-string throws a class not found exception.  I 
have since stopped using record types for serialization and saving 
everything as maps, but this has increased the complexity of the 
deserialization logic as I need to store the type information in fields and 
restore these types after deserialization.  I liked using record types, but 
I don't like not being able to rename these types later if I change my 
mind.  

It seems to me that I should perhaps be able to override the reader 
literals for record types? 

-- 
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: Clojure 1.3+ and JRebel

2012-05-06 Thread Kurt Harriger


On Sunday, May 6, 2012 5:08:51 PM UTC-6, Anton Arhipov wrote:

 Tried both: 

 java -javaagent:... -jar clojure.jar  and  java -javaagent:... - 
 cp ... clojure.main -r 

 Both seem to work fine. What does java -version print? 

 

 java version 1.6.0_31

 Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3646)

 Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)


  

-- 
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: Clojure 1.3+ and JRebel

2012-05-06 Thread Kurt Harriger
Done. Thanks. 

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

Clojure 1.3+ and JRebel

2012-05-05 Thread Kurt Harriger
I'm attempting to start a swank-clojure session within a grails 
application.  This part is easy and works fine.  However, whenever I change 
a groovy class clojure does not see this change until I restart the jvm.  I 
mucked around a bit with classlojure and pomegranate trying to figure out 
if I could shadow the default class loader to force clojure to relaod the 
groovy class files on demand, but at the moment it seems beyond me.  I've 
heard of JRebel for reloading class files in an existing jvm and ran across 
a few posts where people have had success using JRebel to reload classes in 
clojure.  I was able to get this to work with clojure 1.2.1 however I can't 
get it to work with clojure 1.3 or 1.4.  

The simplest reproducible test case I could think of was just to start the 
repl as follows:

java -javaagent:/Applications/ZeroTurnaround/JRebel/jrebel.jar -cp 
lib/clojure-1.4.0.jar clojure.main -r 
JRebel: Starting logging to file: /Users/kurtharriger/var/jrebel.log
[2012-05-05 16:19:40] 
[2012-05-05 16:19:40] 
#
[2012-05-05 16:19:40] 
[2012-05-05 16:19:40]  JRebel 4.6.2 (201205021440)
[2012-05-05 16:19:40]  (c) Copyright ZeroTurnaround OU, Estonia, Tartu.
[2012-05-05 16:19:40] 
[2012-05-05 16:19:40]  Over the last 1 days JRebel prevented 
[2012-05-05 16:19:40]  at least 1 redeploys/restarts saving you about 0 
hours.
[2012-05-05 16:19:40] 
[2012-05-05 16:19:40]  This product is licensed to Kurt Harriger 
(FullContact) 
[2012-05-05 16:19:40]  until June 4, 2012
[2012-05-05 16:19:40] 
[2012-05-05 16:19:40] 
*
[2012-05-05 16:19:40]  Your license is about to EXPIRE!
[2012-05-05 16:19:40] 
*
[2012-05-05 16:19:40] 
[2012-05-05 16:19:40]  This license will expire in 29 days and JRebel will
[2012-05-05 16:19:40]  stop working after that. Renew your license at:

[2012-05-05 16:19:40] http://sales.zeroturnaround.com/?1338842936
[2012-05-05 16:19:40] 
[2012-05-05 16:19:40]  The following plugins are disabled at the moment: 
[2012-05-05 16:19:40]  * Apache MyFaces plugin (set 
-Drebel.myfaces_plugin=true to enable)
[2012-05-05 16:19:40] Reloads JSF configuration and reconfigures managed 
beans.
[2012-05-05 16:19:40]  * Click plugin (set -Drebel.click_plugin=true to 
enable)
[2012-05-05 16:19:40] Reloads menu.xml menu definitions of Apache Click 
projects.
[2012-05-05 16:19:40]  * JRuby Plugin (set -Drebel.jruby_plugin=true to 
enable)
[2012-05-05 16:19:40]  * Jersey plugin (set -Drebel.jersey_plugin=true to 
enable)
[2012-05-05 16:19:40] Reloads Jersey configuration from Java annotations.
[2012-05-05 16:19:40]  * Oracle ADF Core plugin (set 
-Drebel.adf_core_plugin=true to enable)
[2012-05-05 16:19:40] JRebel ADF Core Plugin
[2012-05-05 16:19:40]  * Oracle ADF Faces plugin (set 
-Drebel.adf_faces_plugin=true to enable)
[2012-05-05 16:19:40] JRebel ADF Faces Plugin
[2012-05-05 16:19:40]  * Seam-Wicket plugin (set 
-Drebel.seam_wicket_plugin=true to enable)
[2012-05-05 16:19:40] Integration with load time weaving seam annotations 
to wicket classes
[2012-05-05 16:19:40] (-javaagent:path-to-jboss-seam-wicket-jar)
[2012-05-05 16:19:40]  * WebObjects plugin (set 
-Drebel.webobjects_plugin=true to enable)
[2012-05-05 16:19:40] WebObjects JRebel Plugin
[2012-05-05 16:19:40] 
[2012-05-05 16:19:40] 
#
[2012-05-05 16:19:40] 
Exception in thread main java.lang.ExceptionInInitializerError
at clojure.main.clinit(main.java:20)
Caused by: java.lang.IllegalStateException: Attempting to call unbound fn: 
#'clojure.core/first, compiling:(clojure/core.clj:55)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6462)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:518)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyze(Compiler.java:6223)
at clojure.lang.Compiler.eval(Compiler.java:6515)
at clojure.lang.Compiler.load(Compiler.java:6952)
at clojure.lang.RT.loadResourceScript(RT.java:359)
at clojure.lang.RT.loadResourceScript(RT.java:350)
at clojure.lang.RT.load(RT.java:429)
at clojure.lang.RT.load(RT.java:400)
at clojure.lang.RT.doInit(RT.java:436)
at clojure.lang.RT.clinit(RT.java:318)
... 1 more
Caused by: java.lang.IllegalStateException: Attempting to call unbound fn: 
#'clojure.core/first
at clojure.lang.Var$Unbound.throwArity(Var.java:43)
at clojure.lang.AFn.invoke(AFn.java:39)
at clojure.core$fn.doInvoke(core.clj:3999)
at clojure.lang.RestFn.invoke(RestFn.java:490)
at clojure.lang.Var.invoke(Var.java:431)
at clojure.lang.AFn.applyToHelper(AFn.java:178)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.lang.Compiler.macroexpand1(Compiler.java:6366

clojure-1.4.0.jar missing in ~/.m2

2012-05-05 Thread Kurt Harriger
When i first upgraded to clojure 1.4 i had a similar issue with lein not 
downloading updated dependencies. It tirned out to be an invalid version range 
dependency spec in midje that caused it to fail silently. Perhaps try removing 
all other dependencies first and try again. 

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


LinkedHashMap not well supported

2012-04-29 Thread Kurt Harriger
I am using a groovy library that returns a LinkedHashMap containing ArrayLists 
and nested LinkedHashMaps.  I did not expect any issues working with this in 
clojure since this type implements java.util.Map I figured everything would 
just work. However the first thing I tried to do was apply 
clojure.set/keywordize-keys which didn't keywordize the keys as expected.  I 
then tried map? which returned false, I figured I would then try to convert to 
clojure map using apply hash-map which threw an illegalargumentexception. into 
{} however did work. I then attempted to use clojure.walk/postwalk to convert 
LinkedHashMaps to clojure maps which only visited the top node.  However using 
prewalk did work, so I ended up with the following helper function.  

(defn- convert-types
  [groovy-result]
  (walk/prewalk
   (fn [x]
 (cond (instance? java.util.LinkedHashMap x) (into {} x)
   (instance? java.util.ArrayList x)  (vec x)  ;; probably not required 
but I wanted to pr-str to print as vectors rather than #ArrayList ...
   :else x)) groovy-result))


clojure map? is defined as:
 (fn ^:static map? [x] (instance? clojure.lang.IPersistentMap x)))

Is there any reason map? checks explicitly for clojure.lang.IPersistentMap 
rather than java.util.Map? 

also clojure.walk/walk contains: 
..
  (instance? clojure.lang.IMapEntry form)
..

but (first m) returns java.util.LinkedHashMap$Entry which extends 
java.util.Map$Entry and java.util.HashMap$Entry.

I'm not sure why into {} works but apply hash-map doesn't, seems to have to do 
with first and next don't work on java.util.LinkedHashMap$Entry either.

Seems like many of these functions could be improved to work with java.util.Map 
and  java.util.Map$Entry?  
Should a JIRA be created for these?

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