Add java.util.Optional
A value class libraries return from getters (java.time, and the java.net.http client shim that aws-api's java backend builds on). Statics of/ofNullable/empty, methods isPresent/isEmpty/get/orElse/orElseGet/ifPresent/toString, value-equal so (= (Optional/of x) (Optional/of x)). Five JVM-certified corpus rows. Runtime .ss, no re-mint.
This commit is contained in:
parent
27d99db4bc
commit
9510e7663f
2 changed files with 32 additions and 0 deletions
|
|
@ -795,6 +795,33 @@
|
|||
(cons "nextFloat" (lambda (self) (random 1.0)))
|
||||
(cons "nextBoolean" (lambda (self) (fx=? 0 (random 2))))))
|
||||
|
||||
;; --- java.util.Optional -----------------------------------------------------
|
||||
;; Returned by getters across java.time / java.net.http (e.g. HttpRequest.timeout,
|
||||
;; HttpClient.connectTimeout). Value-equal so (= (Optional/of x) (Optional/of x)).
|
||||
(define (jt-optional present? value) (make-jhost "optional" (vector present? value)))
|
||||
(define jt-optional-empty (jt-optional #f jolt-nil))
|
||||
(define (opt? x) (and (jhost? x) (string=? (jhost-tag x) "optional")))
|
||||
(define (opt-present? o) (vector-ref (jhost-state o) 0))
|
||||
(define (opt-value o) (vector-ref (jhost-state o) 1))
|
||||
(let ((statics (list (cons "of" (lambda (v) (if (jolt-nil? v) (error #f "Optional.of(null)") (jt-optional #t v))))
|
||||
(cons "ofNullable" (lambda (v) (if (jolt-nil? v) jt-optional-empty (jt-optional #t v))))
|
||||
(cons "empty" (lambda _ jt-optional-empty)))))
|
||||
(register-class-statics! "Optional" statics)
|
||||
(register-class-statics! "java.util.Optional" statics))
|
||||
(register-host-methods! "optional"
|
||||
(list (cons "isPresent" (lambda (o) (opt-present? o)))
|
||||
(cons "isEmpty" (lambda (o) (not (opt-present? o))))
|
||||
(cons "get" (lambda (o) (if (opt-present? o) (opt-value o) (error #f "Optional.get() on empty Optional"))))
|
||||
(cons "orElse" (lambda (o d) (if (opt-present? o) (opt-value o) d)))
|
||||
(cons "orElseGet" (lambda (o f) (if (opt-present? o) (opt-value o) (jolt-invoke f))))
|
||||
(cons "ifPresent" (lambda (o f) (when (opt-present? o) (jolt-invoke f (opt-value o))) jolt-nil))
|
||||
(cons "toString" (lambda (o) (if (opt-present? o)
|
||||
(string-append "Optional[" (jolt-str-render-one (opt-value o)) "]")
|
||||
"Optional.empty")))))
|
||||
(register-eq-arm! (lambda (a b) (or (opt? a) (opt? b)))
|
||||
(lambda (a b) (and (opt? a) (opt? b) (eq? (opt-present? a) (opt-present? b))
|
||||
(or (not (opt-present? a)) (jolt=2 (opt-value a) (opt-value b))))))
|
||||
|
||||
;; --- minimal JVM class/interface ancestry -----------------------------------
|
||||
;; A handful of libraries reflect over the class hierarchy — e.g. core.memoize
|
||||
;; validates its first argument with (some #{IFn AFn Runnable Callable}
|
||||
|
|
|
|||
|
|
@ -560,6 +560,11 @@
|
|||
{:suite "interop / java.time chrono-fields" :label "YearMonth PROLEPTIC_MONTH" :expected "24244" :actual "(.getLong (java.time.YearMonth/of 2020 5) java.time.temporal.ChronoField/PROLEPTIC_MONTH)"}
|
||||
{:suite "interop / java.time chrono-fields" :label "ISO_OFFSET_DATE_TIME keeps fractional seconds" :expected "1594033153417" :actual "(.toEpochMilli (.toInstant (java.time.ZonedDateTime/parse \"2020-07-06T10:59:13.417Z\" java.time.format.DateTimeFormatter/ISO_OFFSET_DATE_TIME)))"}
|
||||
{:suite "interop / java.time chrono-fields" :label "ISO_OFFSET_DATE_TIME without fraction" :expected "1594033153000" :actual "(.toEpochMilli (.toInstant (java.time.ZonedDateTime/parse \"2020-07-06T10:59:13Z\" java.time.format.DateTimeFormatter/ISO_OFFSET_DATE_TIME)))"}
|
||||
{:suite "interop / java.util Optional" :label "of + get" :expected "42" :actual "(.get (java.util.Optional/of 42))"}
|
||||
{:suite "interop / java.util Optional" :label "empty isPresent" :expected "false" :actual "(.isPresent (java.util.Optional/empty))"}
|
||||
{:suite "interop / java.util Optional" :label "value equality" :expected "true" :actual "(= (java.util.Optional/of 5) (java.util.Optional/of 5))"}
|
||||
{:suite "interop / java.util Optional" :label "empty orElse" :expected "7" :actual "(.orElse (java.util.Optional/empty) 7)"}
|
||||
{:suite "interop / java.util Optional" :label "ofNullable nil is empty" :expected "true" :actual "(= (java.util.Optional/empty) (java.util.Optional/ofNullable nil))"}
|
||||
{:suite "interop / java.time shims" :label "Instant/now is current" :expected "true" :actual "(> (.toEpochMilli (Instant/now)) 1500000000000)"}
|
||||
{:suite "interop / java.time shims" :label "sql types are not" :expected "false" :actual "(instance? java.sql.Timestamp #inst \"2020-01-01T00:00:00Z\")"}
|
||||
{:suite "interop / StringReader & StringBuilder" :label "StringReader read" :expected "[97 98 -1]" :actual "(let [r (java.io.StringReader. \"ab\")] [(.read r) (.read r) (.read r)])"}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue