What is the idiomatic way to concatenate strings? Here are some things
that I expected to work, but didn't
(+ "foo" "bah")
(conj "foo" "bah")
(into "foo" "bah")
For the moment I am doing
(.concat "foo" "bah")
But it seems wrong
Thanks
P
> Is there a good reason that + can't do the right thing as with other
> Java and scripting languages? I think this would be popular with
> non-LISPers.
Putting a type check in + would slow down basic math, and there is a
class of user who will complain loudly if basic math slows
down. However, this also means that > and < also don't work on strings,
which is pretty lousy.
One approach that's been proposed in #clojure is to make these functions
more capable by default, but then provide a fast-math library that could
redefine them in terms of numerics-only. I'm a big fan of functions
doing the most helpful thing by default but being able to offer better
speed when you need it.
Convenience vs speed is always a trade-off, but I think convenience
should win in the default case. What do others think about this?
-Phil
> > Concatenation is not addition. I'm almost opposed to numeric operators
> > all together. If we wrote (add 2 3), there would be no confusion at
> > all about what (add "foo" 2) should do, because you'd be writing (conj
> > "foo" (str 2))
>
> Agree
I agree regarding concatenation as well, but I think the case for
comparison of non-numerics is still pretty strong.
-Phil
>> I agree regarding concatenation as well, but I think the case for
>> comparison of non-numerics is still pretty strong.
>
> Are you referring to using <, >, =, with objects that implement
> java.lang.Comparable?
>
> i.e. given x.compareTo(y) == -1
> (< x y)
> => true
>
> I would find that useful.
I'm not sure of the details since I don't know much about Java, but that
sounds about right. I'm working on a date library, and having to use
functions like earlier? and later? rather than >, <, <=, and >= feels
awkward.
-Phil
You are probably thinking of dates as numerical longs rather than
actual "dates". If you take a step back from how the date is
represented, it is much clearer to say
(earlier? date1 date2)
than
(< date1 date2)
The latter is open to interpretation and would force any good
programmer to look up what less-than does on the dates in order to get
an intuition about what it *actually* means, whereas most everyone
would agree with what the former is intended to mean. '<' could be
defined as "happened after" and be a *valid* function definition. If
"earlier?" was defined as "happened after" it would be considered a
bug.
I realize this is just one use case, but overloading operators can
often decrease readability. That said, it can also be extremely
convenient and make for more flexible libraries, so perhaps the
argument about a fast math library and convenient non-math behavior by
default is the way to go...
Btw, if you are implementing a date library, I would strongly
recommend looking at Joda Time. You could probably just write some
clojure wrappers for the library and be done with it (of course, that
would require that the Joda Time jar be on the classpath...).
--Eric Tschetter
> One approach that's been proposed in #clojure is to make these
> functions
> more capable by default, but then provide a fast-math library that
> could
> redefine them in terms of numerics-only. I'm a big fan of functions
> doing the most helpful thing by default but being able to offer better
> speed when you need it.
>
> Convenience vs speed is always a trade-off, but I think convenience
> should win in the default case. What do others think about this?
My first reaction was "I agree". Speaking in purely abstract terms, I
also prefer convenience to speed as a default. But then I started
thinking a bit about the concrete case you are proposing.
First of all, it's a minor point in Lisp languages. There is nothing
special to functions like +. If you want another + than the one in
clojure.core, all it takes is some manipulation of the use, require,
and refer declarations at the top of your library or script. We are
not in the same situation as languages where there is a small number
of special operators. Nor is + so frequently used in other core
functions that having a second implementation would be pointless.
Second, it is not at all trivial to come up with good scheme for
polymorphic arithmetic operators. Given
(+ a b c d)
with a b c d of four different types, how do you dispatch to a
specific implementation? Dispatch on the type of the first argument?
The first two, with longer argument lists handled by reduction?
Introduce a priority hierarchy in the implementations? Or a
capability list? Among other criteria, it depends on what features of
addition you want to guarantee. Many people would expect
commutativity, based on their daily life experience with numbers, but
that's not easy to guarantee, and it would rule out using addition
for string concatenation, for example. (This is not to say that I am
in favour of string "addition", quite on the contrary, it's just a
nice illustration.)
I propose that instead of discussing that the default implementation
should be, we first start writing a "generic arithmetic" library
module in clojure.contrib and see how it works out in practice. I
expect the main effort to be test-driving the module rather than
implementing it, as the design choices are critical and probably much
harder than the implementation. Any volunteers?
Konrad.
>> Are you referring to using <, >, =, with objects that implement
>> java.lang.Comparable?
>>
>> i.e. given x.compareTo(y) == -1
>> (< x y)
>> => true
>>
>> I would find that useful.
>
> I think having <, >, <=, >= be based on Comparable has been discussed before.
>
> And the conclusion was that it was a bad idea, because in Java:
>
> user=> (.compareTo (Integer. "10") (Long. "10"))
> java.lang.ClassCastException: java.lang.Long cannot be cast to
> java.lang.Integer (NO_SOURCE_FILE:0)
>
> And:
>
> user=> (.equals (Integer. "10") (Long. "10"))
> false
Curses, Java! Foiled again.
> Given these consequences, I think the current behavior is the best compromise.
Agreed. Am curious as to what the idiomatic way to check to see if one
string is alphabetically greater than another is though.
-Phil
Agreed. Am curious as to what the idiomatic way to check to see if one
string is alphabetically greater than another is though.
> What about something like:
>
> (defn gt [str1 str2]
> (first (sort [str1 str2])))
>
> (gt "Zoe" "Bob") ; -> "Bob"
If nothing exists yet, defining <, >, <=, and >= in str-utils might work.
-Phil