Skip to content

Commit 612bc0c

Browse files
committed
Update jank-test-suite-initial-run-restuls.md
1 parent a42fb8e commit 612bc0c

File tree

1 file changed

+24
-46
lines changed

1 file changed

+24
-46
lines changed

docs/jank-test-suite-initial-run-results.md

Lines changed: 24 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static public short shortCast(short x){
5858
// etc. for the remaining primitive numeric types
5959
```
6060

61-
Now, is it turns out, ClojureCLR is missing the overloads for `shortCast`, having only the one taking an `object`. This is an efficiency matter, and I will fix it. (For the majore conversions, `intCast`, `longCast`, `doubleCast`, and `floatCast`, the overloads are present.)
61+
Now, is it turns out, ClojureCLR is missing the overloads for `shortCast`, having only the one taking an `object`. This is an efficiency matter, and I will fix it. (For the major conversions, `intCast`, `longCast`, `doubleCast`, and `floatCast`, the overloads are present.)
6262

6363
The variant of interest here is for the `Object` case. In ClojureCLR, this is
6464

@@ -189,7 +189,7 @@ The root cause here is that on the CLR, `System.String` implements `IConvertible
189189
ClojureCLR was failing the test for `(parse-double "Infinity")` and `(parse-double "-Infinity")`.
190190
`parse-double` mostly is a wrapper for `Double.Parse`. Upon reading the doc for that method, one finds that it is indeed supposed to handle strings representing positive and negative infinity. However, the values it looks for are culture-dependent, specifically the values of `NumberFormatInfo.PositiveInfinitySymbol` and `NumberFormatInfo.NegativeInfinitySymbol`. In the `InvariantCulture`, these are "Infinity" and "-Infinity". However, in my culture (en-US), they are "∞" and "-∞". This is not the first time I've been bitten by this. In fact, take a close look through the code above to see it in use.
191191

192-
> Change the `Parse` calls to use `InvariantCulture`.
192+
> Change the `Parse` calls to use `InvariantCulture`. (DONE!)
193193
194194
## Quot-idian problems
195195

@@ -244,7 +244,7 @@ In both instances, `*math-context*` is null, so the difference will be found in
244244

245245
`java.math.BigDecimal` is defined by the JVM. We can look at its doc:
246246

247-
> Returns a BigDecimal whose value is the integer part of (this / divisor). Since the integer part of the exact quotient does not depend on the rounding mode, the rounding mode does not affect the values returned by this method. The preferred scale of the result is (this.scale() - divisor.scale()). An ArithmeticException is thrown if the integer part of the exact quotient needs more than mc.precision digits.
247+
> Returns a BigDecimal whose value is the integer part of (this / divisor). Since the integer part of the exact quotient does not depend on the rounding mode, the rounding mode does not affect the values returned by this method. The preferred scale of the result is (this.scale() - divisor.scale()). An ArithmeticException is thrown if the integer part of the exact quotient needs more than mc.precision digits. (DONE!)
248248
249249
For ClojureCLR, it defines its own `BigDecimal` class. We can look at the source. Bizarrely, or perhaps just ironically, I took the implementation of `DivideInteger` from the OpenJDK algorithm!
250250

@@ -312,7 +312,7 @@ should be:
312312
if (quotient._exp < 0)
313313
```
314314

315-
> BUG: Fix the error.
315+
> BUG: Fix the error. (DONE!)
316316

317317
## Rationalize this
318318

@@ -376,7 +376,7 @@ BigDecimal bx = x as BigDecimal
376376

377377
If you look around the code in this area, you'll see plenty of places where I do this properly. This one just slipped through.
378378

379-
> BUG: Fix the error.
379+
> BUG: Fix the error. (DONE!)
380380

381381
And while we are being rational:
382382

@@ -420,8 +420,7 @@ However, I chose to not to hid the difference in names.
420420
421421
## String tests
422422

423-
ClojureCLR fails a number of tests for functions in `clojure.string`. I argue below that these tests are semantically invalid.
424-
423+
ClojureCLR fails a number of tests for functions in `clojure.string`.
425424
These tests share the common feature that they pass into a `clojure.string` function such as `capitalize` arguments that are not strings.
426425
For example,
427426

@@ -437,46 +436,11 @@ For example,
437436
(is (= ":asdf/asdf" (str/capitalize :asDf/aSdf)))))
438437
```
439438

440-
Now I can just copy the `:cljs` tests for `:cljr` and be done. My question is whether the `:default` tests are proper.
441-
442-
I argue this based on the "Design notes for clojure.string" found in the source code. The relevant points:
443-
444-
> 1. Strings are objects (as opposed to sequences). As such, the
445-
string being manipulated is the first argument to a function;
446-
passing nil will result in a NullPointerException unless
447-
documented otherwise. If you want sequence-y behavior instead,
448-
use a sequence.
449-
450-
I argue that this implies that the functions in this library are primarily for string (with one adjustment to this statement below).
451-
452-
> 2. Functions are generally not lazy, and call straight to host
453-
methods where those are available and efficient.
454-
455-
I argue that "calling straight to host methods" is referring to methods on the implementation of the string class in the platform.
456-
457-
> 3. Functions take advantage of String implementation details to
458-
write high-performing loop/recurs instead of using higher-order
459-
functions. (This is not idiomatic in general-purpose application
460-
code.)
461-
462-
> 4. When a function is documented to accept a string argument, it
463-
will take any implementation of the correct *interface* on the
464-
host platform. In Java, this is CharSequence, which is more
465-
general than String. In ordinary usage you will almost always
466-
pass concrete strings. If you are doing something unusual,
467-
e.g. passing a mutable implementation of CharSequence, then
468-
thread-safety is your responsibility."
439+
My question is whether the `:default` tests are proper.
440+
I discussed the purpose of these test with Jeaye Wilkerson. His intention that the tests should be descriptive of the behavior of each dialect; they are not normative.
469441

470-
I argue that "in ordinary usage you will almost always pass concrete strings" is a strong hint that passing non-strings is not ordinary usage.
442+
Now I can just copy the `:cljs` tests for `:cljr` and be done.
471443

472-
It is because the JVM version accepts `CharSequence` arguments that one can get away with passing something like an integer to `capitalize`.
473-
`capitalize` first calls `toString()` on its argument hence it will work with _any_ argument.
474-
475-
There is also a an arguments from consistency. Not all functions in `clojure.string` are as permissive. ClojureJVM throws an exception on `(clojure.string/trim-newline 1)`. One has to inspect the code to determine for which functions ClojureJVM will accept non-string arguments. Thus, this is an artifact of implementation, not part of the contract for the function.
476-
477-
Given these arguments, should we be testing on non-string arguments at all? Putting in a `(is (= "1" (str/capitalize 1))` seems to normalize the behavior of passing non-string arguments. I claim that if the function implementations in `clojure.string` were to be changed to reject non-string arguments, the authors would not have broken any contract.
478-
479-
IMHO
480444

481445
## Some true breakage
482446

@@ -510,8 +474,22 @@ If instead we define
510474

511475
the call `(ok-clone (int-array 3))` works fine.
512476

513-
I'm not sure what the best solution is here. Forcing the user to know that the conversion is necessary in one call to `aset` but not the other strikes me as bad. The easiest solution is change `RT.acline` to have return type `Object` instead of `Array`. We get a dynamic callsite in the second `aset` call, but that's probably better than the reflection that takes place in `Array.SetValue`.
477+
I'm not sure what the best solution is here. Forcing the user to know that the conversion is necessary in one call to `aset` but not the other strikes me as bad.
478+
<strike>The easiest solution is change `RT.aclone` to have return type `Object` instead of `Array`. We get a dynamic callsite in the second `aset` call, but that's probably better than the reflection that takes place in `Array.SetValue`. </strike>
479+
480+
Well, that definitely did not work. The real solution has several parts.
481+
482+
- Get rid of `RT.aclone(Array)`
483+
- Add overloads for `RT.aclone` for all the basic array types used for the other operations: `object[]`, `int[]`, `long[]`, `float[]`, `double[]`, etc.
484+
- Get rid of `RT.aset(Array a, int idx, object val)`.
485+
486+
We will get reflection warnings -- can't be helped. So does ClojureJVM, on the same calls. So I think we are good to go.
487+
488+
Oh, and 'gvec.clj` compiles without any warnings. That lib has always been a problem child, particularly for the array functions. So, score.
489+
490+
Oh, and all the standard Clojure tests run successfully and with no warnings. Score again.
514491

492+
DONE!
515493

516494
### case
517495

0 commit comments

Comments
 (0)