I just started hating Java
1
2
3
4
5
6
7
8
9
10
11
12
| private static String joinObjectFields(final List<SomeObject> objects, final Character seperator, final SomeObject exclude) { String result = ""; for (SomeObject object: objects) { if (!object.equals(exclude)) { result += object.someField + seperator; } } // Strip last ; (and see edit3) return result.substring(0, result.length() - 1); } |
1
2
3
4
| def joinObjectFields(objects, seperator, exclude): fields = [object.someField for object in objects if object != exclude] return seperator.join(fields) |
To prevent "these pieces of code don't do the same thing", an alternate Java implementation, more like the Python one:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| private static String joinObjectFields(final List<SomeObject> objects, final Character seperator, final SomeObject exclude) { final String[] fields = new String[objects.size()]; for (int i = 0; i < fields.length; i++) { if (!object.get(i).equals(exclude)) { fields[i] = object.someField; } else { fields[i] = ""; } } return StringUtils.join(fields, ';'); } |
Doesn't get much better, even if you would initialize the array to contain "" in every field using a utility method.
For extra hatred, consider the necessary changes to the code to enable the same method to join the contents of a different object field.
Edit: A colleague noted that cloning the list and removing the 'exclude' would make matters slightly better.
Edit2: And before someone starts calling me a Python fanboy: you can also do this in a much shorter fashion in Scheme, Ruby, Perl, Scala, Lisp/Clojure, etc.
Edit3: And of course I stupidly forgot to check whether result.length() is actually > 0 in the first implementation.
Edit4: As JanDM rightly points out, I shouldn't use curly braces in Python

Edit 5: This version in Java, posted by Markus in the comments, is far superior: I wasn't making any sense here: the code does a different thing.
01-'10 Harvesting energy from WiFi and GSM networks?
11-'09 Debian, aptitude update: segmentation fault.
Comments
Java:
1
2
3
4
5
6
7
8
9
10
| private static String joinObjectFields(final List<SomeObject> objects, final Character seperator, final SomeObject exclude) { StringBuilder builder = new StringBuilder(); for (SomeObject object : objects) { if (object.equals(exclude)) continue; if (builder.length() > 0) builder.append(separator); builder.append(object.someField); } return builder.toString(); } } |
Shoter and more efficient. Also, some notes:
* The Python implementation is not declared private or static. From the example, I can't see who can access it and from what scope.
* The Python implementation's parameters are not declared final, although they may be final by default in Python, not sure.
* The second Java implementation adds a semicolon even if the field isn't empty - as far as I can see (read: expect, I don't know Python), the Python implementation doesn't do this.
* Python doesn't have types, so that one is less safe. What if I call joinObjectFields with an object of type Henk that doesn't have a property someField? Type error.
imo, verbose is good. Non-verbose (and uncompiling) java version without types or verbose additional method and parameter keywords:
Java:
1
2
3
4
5
6
7
8
9
| joinObjectFields(objects, seperator, exclude) { builder = new StringBuilder(); for (object : objects) { if (object.equals(exclude)) continue; if (builder.length() > 0) builder.append(separator); builder.append(object.someField); } return builder.toString(); } |
Thus. Not saying Java's better than Python, it just works differently. And verboseness isn't something bad per sé - it gives you much more control when you need it.
Also, it makes little sense to me to have a join() method on a character / string object that uses the object itself as separator between the elements of a list. That, or I don't get it.
(Although it's true that I would like a syntactic sugar feature added to Java that allows you to iterate through a certain field (accessor) of a list of objects)
[Comment edited on Thursday 7 January 2010 16:09]
http://commons.apache.org...ject,%20java.lang.Object)

C#:
1
2
3
4
5
6
7
8
| private static string joinObjectFields(List<SomeObject> objects, string separator, SomeObject exclude) { return String.Join(separator, objects .Where(obj => !obj.Equals(exclude)) .Select(obj => obj.SomeField).ToArray()); } |
[Comment edited on Thursday 7 January 2010 16:26]
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| private static String joinObjectFields(final List<SomeObject> objects, final Character seperator, final SomeObject exclude) { StringBuilder builder = new StringBuilder(); for (SomeObject object : objects) { if (object.equals(exclude)) { continue; } if (builder.length() > 0) { builder.append(separator); } builder.append(object.someField); } return builder.toString(); } } |
This is required for readability, but uses costly vertical screen real estate. The point is not just number of lines that is annoying: also the number of characters and operations/keywords/constructs required. A page of Java looks like a mess and is harder to understand than an page of Python or Scheme, once you get used to the syntax.
As for efficiency: I doubt it's more efficient. AFAIK, a moderately recent JVM will use a StringBuilder/StringBuffer anyway.
Very often I don't care, especially not with these kinds of utility methods. A single visibility of 'public' is just fine with me. If a method should not be called, I'll mark it as such.* The Python implementation is not declared private or static. From the example, I can't see who can access it and from what scope.
In effect they are (because you can't change what the original variable points to), but variables being final isn't very interesting, as the problem is usually the contents of lists, maps and objects being altered. Moreover, 'final' should have been the default in java.* The Python implementation's parameters are not declared final, although they may be final by default in Python, not sure.
Python most definitely does have types, though no compile-time typechecking. However, appropriate unit-tests will catch that, without explicitly checking the type.* Python doesn't have types, so that one is less safe. What if I call joinObjectFields with an object of type Henk that doesn't have a property someField? Type error.
I will present a Scala example shortly, to show that type-safety, clarity and terseness can go hand-in-hand.
[Comment edited on Thursday 7 January 2010 17:30]
Python:
1
2
3
| def joinObjectFields(objects, seperator, exclude): fields = [object.someField for object in objects if object != exclude] return seperator.join(fields) |
I agree with your point though, Python is a great language and it still surprises me how clear and concise it looks compared to most other languages.
The last line from your Java code, for example:
Java:
1
| return result.substring(0, result.length() - 1); |
could be written in Python as:
Python:
1
| return result[:-1] |

[Comment edited on Thursday 7 January 2010 17:25]
PHP:
1
2
3
| function joinObjectFields($objects, $separator, $exclude) { return implode($separator, array_diff($objects, $exclude)); } |
Unfortunately this requires the magic reflection method __tostring to be set on the objects in the array, returning the someField string. Otherwise the example will be much more verbose, even with the quite powerful array manipulation methods that PHP posesses.
[Comment edited on Thursday 7 January 2010 17:25]
Which also has the nice property that, as long as result was initialized, it doesn't throw an exception, but does what you want in the majority of situations: return an empty stringcould be written in Python as:
Python:
1 return result[:-1]
[Comment edited on Thursday 7 January 2010 17:29]
And this is example scenario shows it. Your original joinObjectFields does several things:For extra hatred, consider the necessary changes to the code to enable the same method to join the contents of a different object field.
- Filtering (not processing the exclude value)
- Mapping (mapping SomeObject instances to a value that's showable)
- Folding or reducing a list of values to a single value (in this case, a String)
Haskell:
1
2
3
4
5
6
7
| joinFields exclude field sep = intercalate sep . map (show . field) . filter (/= exclude) {- ^ ^ ^ | | step 1, filtering | step 2, mapping step 3, reducing the list to a single value -} |
This function takes 4 arguments, namely the value to exclude, a field selection function, a String seperator (not a character as in your original function), and finally the list containing the objects.
In case you're wondering where the 4th argument is being mentioned in the above definition, well, it isn't. It has been eta-reduced:
Haskell:
1
2
3
| -- equivalent definition without eta-reduction joinFields exclude field sep objects = (intercalate sep . map (show . field) . filter (/= exclude)) objects |
(Things of form f x = e x can be eta-reduced to f = e, provided that x does not appear in e)
For completeness' sake, but not necessary in a language with type inference, the type of this function is:
Haskell:
1
| joinFields :: (Eq a, Show b) => a -> (a -> b) -> String -> [a] -> String |
[Comment edited on Thursday 7 January 2010 18:07]
Personally I'd rather read and maintain the java code than your python code.



ABAP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| FORM join_objf USING pt_objects TYPE ltt_someobject pc_separator TYPE c. po_exclude TYPE lt_someobject CHANGING ps_return TYPE string. DATA lo_object LIKE LINE OF pt_objects. LOOP AT pt_objects INTO lo_object. IF NOT lo_object = lo_exclude. IF ps_return IS NOT INITIAL. CONCATENATE ps_return lo_object INTO ps_return SEPARATED BY pc_separator. ELSE. ps_return = lo_object. ENDIF. ENDIF. ENDLOOP. ENDFORM. |
[Comment edited on Thursday 7 January 2010 19:21]
Ruby:
1
2
3
| def join_object_fields(objects, separator, exclude) objects.delete_if{|o| o == exclude }.join(separator) end |

I strongly disagree. List comprehensions are not a "little use case". Why do you think things like set-builder notation, LINQ, SQL, etc. exist? We'd like to be able to clearly and succinctly express operations over collection-like structures.The python code is a nice example of overuse of syntactic sugar in a language. Creating separate syntax for every little use case leads to this.
I'd classify Python as an imperative OO language with a few functional features, rather than a functional language.It's rather typical for functional languages.
Anyway, I'd like to know how you came to the conclusion that syntactic sugar is typical for functional languages? Syntactic sugar can also be found in imperative languages (e.g. string literals in C, foreach in Java, yield in C# and Python).
Excel is the most popular functional language.May also be one of the reasons why functional languages aren't popular.
You're feel free to do so, but I'd rather read something likePersonally I'd rather read and maintain the java code than your python code.
Haskell:
1
| intercalate sep . map (show . field) . filter (/= exclude) |
that clearly shows the function is composed of three simpler things.
[Comment edited on Thursday 7 January 2010 20:26]
The python example accepts a string as well.quote: RayNbowThis function takes 4 arguments, namely the value to exclude, a field selection function, a String seperator (not a character as in your original function), and finally the list containing the objects.
I must say that after the haskell colleges, I started using python a lot more. List comprehesion, lambda functions, higher order functions. Haskell can do those better thanks to currying the arguments, but I like that python can do this stuff as well. Something I really really miss in Java. Just like the example in this blog.
And to add to the language comparison:
Ruby:
1 2 3 def join_object_fields(objects, separator, exclude) objects.delete_if{|o| o == exclude }.join(separator) end
Ruby:
1
2
3
| def join_object_fields(objects, separator, exclude) objects.select{|o| o != exclude }.join(separator) end |
Anders raak je waarschijnlijk objecten kwijt die je niet wil kwijt raken. In ruby is alles een reference

It may very well be easy to understand f you're used to Haskell, but at the moment, it's gibberish to me. In Python you could also write
Python:
1
2
3
4
| field = operators.attrgetter('field') def joinObjectFields(objects, seperator, exclude): def notExclude(x): return x != exclude return seperator.join(map(field, filter(notExclude, objects))) |
But then I really prefer the list comprehension

@Neverwinterx
Scheme is a functional language. You can hardly accuse it of overusing syntactic sugar, now can you?

[Comment edited on Thursday 7 January 2010 21:21]
Of course, but there's a tradeoff of the increased complexity. Which is arguably worth it.I strongly disagree. List comprehensions are not a "little use case". Why do you think things like set-builder notation, LINQ, SQL, etc. exist? We'd like to be able to clearly and succinctly express operations over collection-like structures.
I'm aware of that, didn't say it was a purely functional language.I'd classify Python as an imperative OO language with a few functional features, rather than a functional language.
Notice the link made by "It's" in my sentence. It should be read as "overuse of syntactic sugar is typical ...". I'd like to add that by this i mean obscure syntactic sugar with all sorts of special symbols.Anyway, I'd like to know how you came to the conclusion that syntactic sugar is typical for functional languages? Syntactic sugar can also be found in imperative languages (e.g. string literals in C, foreach in Java, yield in C# and Python).
For example this scala code:
code:
1
2
3
| for(tpTerm <- typeOf(term); (from, to) <- isTArr(tpTerm); _ <- isEqual(from, to, "some text")) yield from |
Add any more syntactic sugar and your language starts to resemble Brainfuck.
Name the most popular languages of recent decennium/decennia:
C
C++
Java
C#
(and even older stuff that has to be maintained, can be ignored further)
See what they have in common?
The C-like syntax amongst other things. Ever noticed how the C-like syntax is easy to read? It's almost English. Try to read functional languages (or the parts of other languages with functional features) out loud: you'll understand what i mean.
The right amount of sugar is the key to a good language: not too much, not too little, not too verbose, not too symbollic.
You are well aware of the fact that this is ridiculous. 99% of the functions in Excel is just basic math and doesn't even come close to what a functional programming language does differently from imp languages. A3 = A2 * 5/9 works in a non-functional imp language as well.Excel is the most popular functional language.
Give people a course in Java and Haskell and show them that code and the java equivalent. Have a guess which version will be understood faster. I am willing to bet plenty of money on java.Haskell example

@Confusion
typical != always
[Comment edited on Thursday 7 January 2010 21:14]
Of course typical != always, but I doubt whether Python really has a relatively large amount of syntactic sugar. When considering all 'common' languages (in which I include things like Haskell, OCaml, AWK and R), then I expect Python to be in the lower regions qua amount of syntactic sugar. Also, I wonder whether there is truly a clear difference between functional and non-functional languages (as far as that difference can be made). If anything, a functional language generally needs less syntactic sugar to attain the same level of expressivity?
[Comment edited on Thursday 7 January 2010 21:25]
I'm also a fulltime J2EE developer and there is a lot more that makes java interesting to do, the frameworks for example. High quality, nice concepts, flexibility, dotnet just seems to get poor ripoff's of what java has (nhibernate?) ...
And the tooling is also good, eclipse and all the plugins/projects they offer, mylyn rocks and has no equivalent. (afaik)
Nice architectures with ESB's, fault tolerant clustered systems, combined with nice powerfull databases, usually pretty fancy hardware, focussing on stuff like this just seems a bit too nitpicky, even for my taste

(btw java7 will get some more advanced methods for collections)
It is syntactic sugar, and it is a good thing. Whether or not it is overuse bepends on your expectations of a language. If your applications do a lot of list manipulation (or even do things to arrays) this function is not bloated, it may be too easy on you, but it is very useful.>The python code is a nice example of overuse of syntactic sugar in a language. Creating
>separate syntax for every little use case leads to this.
I strongly disagree. List comprehensions are not a "little use case". Why do you think things like set-builder notation, LINQ, SQL, etc. exist? We'd like to be able to clearly and succinctly express operations over collection-like structures.
I might say that call-by-reference in c++ is an overuse of syntactic sugar, because the very same thing can be accomplished using dereferenced call-by-value (ie.: use &a to feed int* pa to a function works just as fine as feeding "a" to a function expecting int& a).
I might say that SQL overuses syntactic sugar because it supports JOIN, which could be done using lookup loops in my frondend on a table retrieval. But it being overuse is not an opinion you're gaining much friends with.
I'm doubting the added value of all these popular frameworks more and more. I spend way too much time figuring out how to do a certain thing in a framework, when I could have written the necessary code in half the time. Spring, Hibernate, Struts: these aren't flexible enough. If you want something nonstandard, you can only do it through an arcane invocation, instead of providing the ability to drop back to a lower level to do it. I've started preferring more lightweight frameworks.
Tooling? Did you work with Visual Studio? Not the crappy 2001 version, but 2003 and up.
And a 'nice powerfull database' has what to do with the language/framework you're working with?
Regarding the Frameworks: every language has it's own framework. They all do cool stuff. I've been working with Silverlight a year or more and all frameworks I've tested and tried look cool at first, but whenever you want to do that little extra: give up, drop the framework, do it yourself, skip the framework and conclude it's faster than the awesome cool framework you're using.
One of the basic principles: the right tool for the job!
BigDecimal pct = item1.multiply( new BigDecimal( "100" ) ).
divide( item2 ).
setScale( 2, BigDecimal.ROUND_HALF_UP );
Why don't they include a decimal type in the language? And why don't they allow numbers to be used as parameters (so you don't have to wrap the string "100" in a BigDecimal)?
public void testJoinExclude(){
assertEquals("1, 2, 4", joinExclude(Arrays.asList(1,2,3,4), 3, ", "));
}
public <T> String joinExclude(final List<T> objects, final T exclude, final String separator){
List<T> rs = new ArrayList<T>(objects); // don't touch the original
rs.remove(exclude);
return StringUtils.join(rs, separator);
}
That's not just better: it's far superior. Originally, I excluded one item based on a field value, so I needed to iterate over the list anyway. I later changed that (by implenting a proper equalsI() on SomeObject) , but didn't reconsider to realize that would allow simpler version. I guess I was too busy thinking how easy it would be in other languages

I'm not making any sense: your version concatenates the object(.toString)s, while the original problem is concatenating field values.
[Comment edited on Friday 8 January 2010 13:58]
In Haskell list comprehensions are also possible:It may very well be easy to understand f you're used to Haskell, but at the moment, it's gibberish to me. In Python you could also write
*snip*
But then I really prefer the list comprehension. I'm not at all convinced that purely functional code, involving the usual maps, filters and reductions, is in fact usually easier to understand.
Haskell:
1
| intercalate sep [show (field obj) | obj <- objects, obj /= exclude] |
It depends on the situation whether you want list comprehensions or explicitly use filter and map. In Python list comprehensions are often preferred since you can't do function composition in a clean way like in math or Haskell:
code:
1
2
3
4
5
6
7
8
9
| -- usual math notation: (f . g)(x) = f (g(x)) -- Haskell eschews parentheses and uses -- juxtaposition instead for function application: (f . g) x = f (g x) -- (Math on the other hand eschews multiplication -- operators and uses juxtaposition instead) |
Since you don't have function composition in Python, you are forced to write things like f(g(h(x))) when you want to glue 3 functions together. In Haskell you can write (f . g . h) which is much cleaner. Or in case you don't want to read from right to left, you could use a flipped composition operator (from the Arrow module):
code:
1
| (h >>> g >>> f) x |
Now, if you also want the argument to appear on the left side, you could easily write a flipped function application operator:
code:
1
2
| infixl 0 |> x |> f = f x -- NB: this pipeline operator is predefined in F# |
And then you could write the following code:
code:
1
| x |> h >>> g >>> f |
@Neverwinterx
With all due respect, but that's not syntactic sugar. Syntactic sugar are constructs that can be desugared to a "simpler" constructs that already exist in the language. Some Haskell examples:Notice the link made by "It's" in my sentence. It should be read as "overuse of syntactic sugar is typical ...". I'd like to add that by this i mean obscure syntactic sugar with all sorts of special symbols.
Haskell:
1
2
3
4
5
6
7
8
9
| -- Syntactic sugar Desugared ---------------------------------------------- [1,2,3,4] = 1:(2:(3:(4:[]))) [1..4] = enumFromTo 1 4 [1..] = enumFrom 1 (+4) = (\x -> x+4) (4+) = (\x -> 4+x) -- (NB: the slash stands for lambda) |
A simple C# example:
C#:
1
2
3
4
5
6
7
| var foo = from n in ns from m in ms select n + m; // is equivalent to: var foo = ns.SelectMany(n => ms, (n, m) => n + m); |
I'm not familiar with Scala, but that code reads perfectly fine. Parentheses and semicolons are not uncommon in C-style languages, so that can't be the problem if you don't understand the code. All that remains is the <- symbol. It doesn't take too much imagination to see it represents a left arrow. Arrows have been used in plenty of languages and computer science textbooks to mean some form of assignment.For example this scala code:
*snip*
Add any more syntactic sugar and your language starts to resemble Brainfuck.
Without any given criteria and sources, I'm not convinced that your list is a faithful representation of popular languages.Name the most popular languages of recent decennium/decennia:
C
C++
Java
C#
(and even older stuff that has to be maintained, can be ignored further)
See what they have in common?
It isn't. I can quite remember well from my youth (coming from BASIC) that I despised the C syntax at first. It takes time to get used to a different syntax, but then again, it might be human nature to be afraid of unknown things.The C-like syntax amongst other things. Ever noticed how the C-like syntax is easy to read?
Nice try, but BASIC and Python resemble English more than C-style languages.It's almost English.
Sure, let's try this example:Try to read functional languages (or the parts of other languages with functional features) out loud: you'll understand what i mean.
code:
1
| [show (field obj) | obj <- objects, obj /= exclude] |
"The list containing the values show (field obj), for which obj comes from objects and obj is not equal to exclude."
Really, it is just an ASCII version of math.
First of all, a program written in a purely functional language like Haskell is nothing more than a bunch of equations. An Excel spreadsheet is, guess what, nothing more than a bunch of equations.You are well aware of the fact that this is ridiculous. 99% of the functions in Excel is just basic math and doesn't even come close to what a functional programming language does differently from imp languages. A3 = A2 * 5/9 works in a non-functional imp language as well.
Secondly, while you could write "A3 = A2 * 5/9" in an imperative language, variables in imperative languages often have a different meaning. In imperative languages variables are a name for a memory location, a box to store stuff in. That line written in an imperative language would be a statement: "The box labeled A3 now contains the value obtained by taking the contents of box A2 and multiplying it by 5/9".
In math and in purely functional languages, that line is an equation. No matter what the value of A2 is, A3 will always be equal to 5/9 of A2.
People who have been taught Haskell ought to know what function composition is. With a blink of an eye they can see the three transformations that take place. The only difficulty of my code example is when your vocabulary is lacking and you don't know what the word intercalate means. In that case, I could use the fact that the following equation holdsGive people a course in Java and Haskell and show them that code and the java equivalent. Have a guess which version will be understood faster. I am willing to bet plenty of money on java.
code:
1
| intercalate x = concat . intersperse x |
and substitute this into my original code fragment:
code:
1
| concat . intersperse sep . map (show . field) . filter (/= exclude) |
Assuming intersperse and concat are well-known words, this piece of code is even easier to read than my original version.
@Herko_ter_Horst
When?Don't worry: closures are coming in Java 7.

http://code.google.com/p/...jFeatures#Joining_strings
Using Markus code as a base, I think something like this should work using lambdaj:
public <T> String joinExclude(final List<T> objects, final T exclude, final String separator){
List<T> rs = new ArrayList<T>(objects); // don't touch the original
rs.remove(exclude);
return joinFrom(rs, separator).getSomeField();
}
Comments are closed