{"id":19468442,"url":"https://github.com/fr33m0nk/optional","last_synced_at":"2026-05-13T13:39:42.513Z","repository":{"id":57749817,"uuid":"524879145","full_name":"fr33m0nk/optional","owner":"fr33m0nk","description":"A Clojure library that wraps over java.util.Optional","archived":false,"fork":false,"pushed_at":"2022-08-28T06:02:43.000Z","size":88,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-08T04:41:20.206Z","etag":null,"topics":["clojure","interop","java","optional"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fr33m0nk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-15T06:31:21.000Z","updated_at":"2023-09-08T18:36:57.000Z","dependencies_parsed_at":"2022-08-28T09:21:58.674Z","dependency_job_id":null,"html_url":"https://github.com/fr33m0nk/optional","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fr33m0nk%2Foptional","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fr33m0nk%2Foptional/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fr33m0nk%2Foptional/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fr33m0nk%2Foptional/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fr33m0nk","download_url":"https://codeload.github.com/fr33m0nk/optional/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240682319,"owners_count":19840485,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","interop","java","optional"],"created_at":"2024-11-10T18:41:09.847Z","updated_at":"2025-11-19T13:04:49.676Z","avatar_url":"https://github.com/fr33m0nk.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"## optional [![Clojars Project](https://img.shields.io/clojars/v/net.clojars.fr33m0nk/optional.svg)](https://clojars.org/net.clojars.fr33m0nk/optional)\n\n`optional` is a simple library that wraps over `java.util.Optional` and offers convenience methods for easy implementation in Clojure code.\n\n### How to use the library\nAll functions are available through the `fr33m0nk.optional` and `fr33m0nk.utility` namespaces. Add the following to your project dependencies:\n- CLI/deps.edn dependency information:\n```clojure\nnet.clojars.fr33m0nk/optional {:mvn/version \"0.1.7\"}\n```\n- Leningen/Boot\n```clojure\n[net.clojars.fr33m0nk/optional \"0.1.7\"]\n```\n- Maven:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003enet.clojars.fr33m0nk\u003c/groupId\u003e\n    \u003cartifactId\u003eoptional\u003c/artifactId\u003e\n    \u003cversion\u003e0.1.7\u003c/version\u003e\n\u003c/dependency\u003e\n```\nRequire at the REPL with:\n\n```clojure\n(require \n  '[fr33m0nk.optional :as optional]\n  '[fr33m0nk.utility :as optional-util])\n```\n\nOr in your namespace as:\n\n```clojure\n(ns mynamespace\n  (:require [fr33m0nk.optional :as optional]\n    [fr33m0nk.utility :as optional-util]))\n```\n\n## Functions and macros:\n\n| Name                                                          | Description                                                                                                                                                                    |\n|---------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| [`fr33m0nk.optional/optional-of`](#optional-of)               | Returns Optional of supplied value                                                                                                                                             |\n| [`fr33m0nk.optional/wrap-fn`](#wrap-fn)                       | Wraps Clojure fn `try catch` block to return Optional values                                                                                                                   |\n| [`fr33m0nk.optional/has-value?`](#has-value?)                 | Returns boolean based on whether Optional has value or is empty                                                                                                                |\n| [`fr33m0nk.optional/=`](#=)                                   | Like `core/=` for Optionals                                                                                                                                                    |\n| [`fr33m0nk.optional/get`](#get)                               | Retrieves the value boxed in Optional                                                                                                                                          |\n| [`fr33m0nk.optional/filter`](#filter)                         | Returns Optional value satisfying predicate                                                                                                                                    |\n| [`fr33m0nk.optional/map`](#map)                               | Transforms value boxed in Optional by applying supplied mapping function and returns `Optional\u003cT\u003e`                                                                             |\n| [`fr33m0nk.optional/flat-map`](#flat-map)                     | Transforms value boxed in Optional by applying supplied mapping function that themselves returns `Optional\u003cT\u003e`.\u003cbr/\u003eUn-nests `Optional\u003cOptional\u003cT\u003e\u003e` and returns `Optional\u003cT\u003e` |\n| [`fr33m0nk.utility/fn-\u003epredicate`](#fn-\u003epredicate)            | Takes a Clojure predicate function and returns a `java.util.function.Predicate` instance                                                                                       |\n| [`fr33m0nk.utility/fn-\u003efunction`](#fn-\u003efunction)              | Takes a Clojure function for mapping and returns a `java.util.function.Function` instance                                                                                      |\n\n## API Docs\n- Detailed usages of below functions can be found in [tests](https://github.com/fr33m0nk/optional/blob/master/test/fr33m0nk/optional_test.clj)\n- **Collections should not be wrapped in an optional as any collection by itself could represent the absence of data by being empty.** \n- **If the control flow of code (or it's part) is driven by Exception (or it's subclasses), refrain from using Optionals or this library in them.**\n- Read [this](https://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type/26328555#26328555) and [this](https://stackoverflow.com/a/73097167/19613290) for right practices of using Optional.\n- ### namespace\n```clojure \n(ns fr33m0nk.optional)\n```\n\n### `optional-of`\n- Returns an Optional \n- Zero arity version returns an empty Optional \n- Single arity version returns an Optional of value\n- If `nil` is supplied as value, returns an empty Optional\n#### Usage:\n```clojure\n(require '[fr33m0nk.optional :as optional])\n\n(optional/optional-of 10)\n;;=\u003e #object[java.util.Optional 0x21bf3689 \"Optional[10]\"]\n\n(optional/optional-of)\n;;=\u003e #object[java.util.Optional 0x1341289b \"Optional.empty\"]\n```\n\n### `wrap-fn`\n- Take a Clojure Fn `f` and returns a Clojure Fn that is wrapped in try catch block \n- Returned fn when executed returns Optional of value if application was successful or empty Optional when execution of supplied function throws an Exception\n- Multi arity versions also take a exception handler which can be a logger function\n- If logger is a macro e.g. clojure.tools.logging, create a logger-fn and supply that as argument\n- e.g.\n```clojure\n(def logger-fn #(clojure.tools.logging/info % \"Exception occurred\"))\n```\n- The reason is Clojure functions can't take macros as argument\n#### Usage:\n```clojure\n(require '[fr33m0nk.optional :as optional]\n         '[fr33m0nk.utility :as optional-util]\n         '[clojure.tools.logging :as log])\n\n(inc \"10\")\n;;Execution error (ClassCastException) at user/eval1972 (form-init6918060955066684574.clj:1).\n;;class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')\n\n;; Example without logger\n(let [wrapped-inc (optional/wrap-fn inc)]\n  (wrapped-inc 1))\n;;=\u003e #object[java.util.Optional 0x57226b51 \"Optional[2]\"]\n\n;; Example with logger\n(let [log-fn #(clojure.tools.logging/info %)\n      wrapped-inc (optional/wrap-fn inc log-fn)]\n  (wrapped-inc \"1\"))\n;; Aug 15, 2022 12:32:04 PM clojure.tools.logging$eval2267$fn__2270 invoke\n;; INFO: {:msg class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap'), :type java.lang.ClassCastException, :exception {:via [{:type java.lang.ClassCastException, :message \"class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')\", :at [clojure.lang.Numbers inc \"Numbers.java\" 139]}], :trace [[clojure.lang.Numbers inc \"Numbers.java\" 139] [clojure.core$inc invokeStatic \"core.clj\" 929] [clojure.core$inc invoke \"core.clj\" 924] [clojure.lang.AFn applyToHelper \"AFn.java\" 154] [clojure.lang.AFn applyTo \"AFn.java\" 144] [clojure.core$apply invokeStatic \"core.clj\" 667] [clojure.core$apply invoke \"core.clj\" 662] [fr33m0nk.optional$warp_return_in_optional$fn__1959 doInvoke \"optional.clj\" 114] [clojure.lang.RestFn invoke \"RestFn.java\" 408] [user$eval2280 invokeStatic \"form-init16753772140548043809.clj\" 3] [user$eval2280 invoke \"form-init16753772140548043809.clj\" 1] [clojure.lang.Compiler eval \"Compiler.java\" 7194] [clojure.lang.Compiler eval \"Compiler.java\" 7149] [clojure.core$eval invokeStatic \"core.clj\" 3215] [clojure.core$eval invoke \"core.clj\" 3211] [nrepl.middleware.interruptible_eval$evaluate$fn__968$fn__969 invoke \"interruptible_eval.clj\" 87] [clojure.lang.AFn applyToHelper \"AFn.java\" 152] [clojure.lang.AFn applyTo \"AFn.java\" 144] [clojure.core$apply invokeStatic \"core.clj\" 667] [clojure.core$with_bindings_STAR_ invokeStatic \"core.clj\" 1990] [clojure.core$with_bindings_STAR_ doInvoke \"core.clj\" 1990] [clojure.lang.RestFn invoke \"RestFn.java\" 425] [nrepl.middleware.interruptible_eval$evaluate$fn__968 invoke \"interruptible_eval.clj\" 87] [clojure.main$repl$read_eval_print__9206$fn__9209 invoke \"main.clj\" 437] [clojure.main$repl$read_eval_print__9206 invoke \"main.clj\" 437] [clojure.main$repl$fn__9215 invoke \"main.clj\" 458] [clojure.main$repl invokeStatic \"main.clj\" 458] [clojure.main$repl doInvoke \"main.clj\" 368] [clojure.lang.RestFn invoke \"RestFn.java\" 1523] [nrepl.middleware.interruptible_eval$evaluate invokeStatic \"interruptible_eval.clj\" 84] [nrepl.middleware.interruptible_eval$evaluate invoke \"interruptible_eval.clj\" 56] [nrepl.middleware.interruptible_eval$interruptible_eval$fn__999$fn__1003 invoke \"interruptible_eval.clj\" 152] [clojure.lang.AFn run \"AFn.java\" 22] [nrepl.middleware.session$session_exec$main_loop__1067$fn__1071 invoke \"session.clj\" 202] [nrepl.middleware.session$session_exec$main_loop__1067 invoke \"session.clj\" 201] [clojure.lang.AFn run \"AFn.java\" 22] [java.lang.Thread run \"Thread.java\" 1534]], :cause class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')}}\n;;=\u003e #object[java.util.Optional 0x200c7eac \"Optional.empty\"]\n```\n\n### `has-value?`\n- Returns a boolean\n- Checks if supplied Optional has a value or is empty\n#### Usage:\n```clojure\n(require '[fr33m0nk.optional :as optional])\n\n(optional/has-value? (optional/optional-of 10))\n;;=\u003e true\n\n(optional/has-value? (optional/optional-of))\n;;=\u003e false\n```\n\n### `=`\n- Returns a boolean\n- Checks equality for Optionals\n#### Usage:\n```clojure\n(require '[fr33m0nk.optional :as optional])\n\n(optional/= (optional/optional-of 10) (optional/optional-of 10) (optional/optional-of 10))\n;;=\u003e true\n\n(optional/= (optional/optional-of 10) (optional/optional-of))\n;;=\u003e false\n```\n\n### `get`\n- Return `nil` for empty Optional\n- Returns value contained in Optional\n- Two arity version also takes another value that would be returned if Optional is empty\n#### Usage:\n```clojure\n(require '[fr33m0nk.optional :as optional])\n\n(optional/get (optional/optional-of 10))\n;;=\u003e 10\n\n(optional/get (optional/optional-of))\n;;=\u003e nil\n```\n\n### `filter`\n- Returns empty Optional if predicate evaluates to false or predicate throws Exception \n- Returns Optional with value if predicate evaluates to true \n- Multi arity versions also take a exception handler which can be a logger function \n- If logger is a macro e.g. clojure.tools.logging, create a logger-fn and supply that as argument\n- e.g.\n```clojure\n(def logger-fn #(clojure.tools.logging/info % \"Exception occurred\"))\n```\n- The reason is Clojure functions can't take macros as argument\n#### Usage:\n```clojure\n(require '[fr33m0nk.optional :as optional]\n         '[fr33m0nk.utility :as optional-util]\n         '[clojure.tools.logging :as log])\n\n(optional/filter (partial \u003c 9) (optional/optional-of 10))\n;;=\u003e #object[java.util.Optional 0x21e87e90 \"Optional[10]\"]\n\n(optional/filter (partial \u003e 9) (optional/optional-of 10))\n;;=\u003e #object[java.util.Optional 0x200c7eac \"Optional.empty\"]\n\n;; Example with logger and exception message\n(let [log-fn #(clojure.tools.logging/info % \"Uh-Oh!!\")]\n  (optional/filter (partial \u003e 9) (optional/optional-of \"10\") log-fn))\n;;Aug 15, 2022 12:48:14 PM clojure.tools.logging$eval2267$fn__2270 invoke\n;;INFO: Uh-Oh!! {:msg class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap'), :type java.lang.ClassCastException, :exception {:via [{:type java.lang.ClassCastException, :message \"class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')\", :at [clojure.lang.Numbers gt \"Numbers.java\" 261]}], :trace [[clojure.lang.Numbers gt \"Numbers.java\" 261] [clojure.core$_GT_ invokeStatic \"core.clj\" 1079] [clojure.core$_GT_ invoke \"core.clj\" 1072] [clojure.core$partial$fn__5908 invoke \"core.clj\" 2641] [fr33m0nk.utility$fn$reify__1939 test \"utility.clj\" 42] [java.util.Optional filter \"Optional.java\" 218] [fr33m0nk.optional$filter invokeStatic \"optional.clj\" 59] [fr33m0nk.optional$filter invoke \"optional.clj\" 46] [user$eval2420 invokeStatic \"form-init16753772140548043809.clj\" 2] [user$eval2420 invoke \"form-init16753772140548043809.clj\" 1] [clojure.lang.Compiler eval \"Compiler.java\" 7194] [clojure.lang.Compiler eval \"Compiler.java\" 7149] [clojure.core$eval invokeStatic \"core.clj\" 3215] [clojure.core$eval invoke \"core.clj\" 3211] [nrepl.middleware.interruptible_eval$evaluate$fn__968$fn__969 invoke \"interruptible_eval.clj\" 87] [clojure.lang.AFn applyToHelper \"AFn.java\" 152] [clojure.lang.AFn applyTo \"AFn.java\" 144] [clojure.core$apply invokeStatic \"core.clj\" 667] [clojure.core$with_bindings_STAR_ invokeStatic \"core.clj\" 1990] [clojure.core$with_bindings_STAR_ doInvoke \"core.clj\" 1990] [clojure.lang.RestFn invoke \"RestFn.java\" 425] [nrepl.middleware.interruptible_eval$evaluate$fn__968 invoke \"interruptible_eval.clj\" 87] [clojure.main$repl$read_eval_print__9206$fn__9209 invoke \"main.clj\" 437] [clojure.main$repl$read_eval_print__9206 invoke \"main.clj\" 437] [clojure.main$repl$fn__9215 invoke \"main.clj\" 458] [clojure.main$repl invokeStatic \"main.clj\" 458] [clojure.main$repl doInvoke \"main.clj\" 368] [clojure.lang.RestFn invoke \"RestFn.java\" 1523] [nrepl.middleware.interruptible_eval$evaluate invokeStatic \"interruptible_eval.clj\" 84] [nrepl.middleware.interruptible_eval$evaluate invoke \"interruptible_eval.clj\" 56] [nrepl.middleware.interruptible_eval$interruptible_eval$fn__999$fn__1003 invoke \"interruptible_eval.clj\" 152] [clojure.lang.AFn run \"AFn.java\" 22] [nrepl.middleware.session$session_exec$main_loop__1067$fn__1071 invoke \"session.clj\" 202] [nrepl.middleware.session$session_exec$main_loop__1067 invoke \"session.clj\" 201] [clojure.lang.AFn run \"AFn.java\" 22] [java.lang.Thread run \"Thread.java\" 1534]], :cause class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')}}\n;;=\u003e #object[java.util.Optional 0x200c7eac \"Optional.empty\"]\n```\n\n### `map`\n- Returns empty Optional if `f` throws Exception \n- Returns Optional with transformed value if `f` was applied successfully\n- Multi arity versions also take a exception handler which can be a logger function\n- If logger is a macro e.g. clojure.tools.logging, create a logger-fn and supply that as argument\n- e.g.\n```clojure\n(def logger-fn #(clojure.tools.logging/info % \"Exception occurred\"))\n```\n- The reason is Clojure functions can't take macros as argument\n#### Usage:\n```clojure\n(require '[fr33m0nk.optional :as optional]\n         '[fr33m0nk.utility :as optional-util]\n         '[clojure.tools.logging :as log])\n\n(-\u003e\u003e 9\n     optional/optional-of\n     (optional/map inc))\n;;=\u003e #object[java.util.Optional 0x6af3fba3 \"Optional[10]\"]\n\n(-\u003e\u003e \"9\"\n     optional/optional-of\n     (optional/map inc))\n;;=\u003e #object[java.util.Optional 0x200c7eac \"Optional.empty\"]\n\n;; Example with logger and exception message\n(let [log-fn #(clojure.tools.logging/info % \"Uh-Oh!!\")]\n  (-\u003e\u003e \"9\"\n       optional/optional-of\n       (#(optional/map inc % log-fn))))\n;;Aug 15, 2022 12:51:46 PM clojure.tools.logging$eval2267$fn__2270 invoke\n;;INFO: Uh-Oh!! {:msg class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap'), :type java.lang.ClassCastException, :exception {:via [{:type java.lang.ClassCastException, :message \"class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')\", :at [clojure.lang.Numbers inc \"Numbers.java\" 139]}], :trace [[clojure.lang.Numbers inc \"Numbers.java\" 139] [clojure.core$inc invokeStatic \"core.clj\" 929] [clojure.core$inc invoke \"core.clj\" 924] [fr33m0nk.utility$fn$reify__1942 apply \"utility.clj\" 61] [java.util.Optional map \"Optional.java\" 260] [fr33m0nk.optional$map invokeStatic \"optional.clj\" 73] [fr33m0nk.optional$map invoke \"optional.clj\" 61] [user$eval2442$fn__2445 invoke \"form-init16753772140548043809.clj\" 4] [user$eval2442 invokeStatic \"form-init16753772140548043809.clj\" 4] [user$eval2442 invoke \"form-init16753772140548043809.clj\" 1] [clojure.lang.Compiler eval \"Compiler.java\" 7194] [clojure.lang.Compiler eval \"Compiler.java\" 7149] [clojure.core$eval invokeStatic \"core.clj\" 3215] [clojure.core$eval invoke \"core.clj\" 3211] [nrepl.middleware.interruptible_eval$evaluate$fn__968$fn__969 invoke \"interruptible_eval.clj\" 87] [clojure.lang.AFn applyToHelper \"AFn.java\" 152] [clojure.lang.AFn applyTo \"AFn.java\" 144] [clojure.core$apply invokeStatic \"core.clj\" 667] [clojure.core$with_bindings_STAR_ invokeStatic \"core.clj\" 1990] [clojure.core$with_bindings_STAR_ doInvoke \"core.clj\" 1990] [clojure.lang.RestFn invoke \"RestFn.java\" 425] [nrepl.middleware.interruptible_eval$evaluate$fn__968 invoke \"interruptible_eval.clj\" 87] [clojure.main$repl$read_eval_print__9206$fn__9209 invoke \"main.clj\" 437] [clojure.main$repl$read_eval_print__9206 invoke \"main.clj\" 437] [clojure.main$repl$fn__9215 invoke \"main.clj\" 458] [clojure.main$repl invokeStatic \"main.clj\" 458] [clojure.main$repl doInvoke \"main.clj\" 368] [clojure.lang.RestFn invoke \"RestFn.java\" 1523] [nrepl.middleware.interruptible_eval$evaluate invokeStatic \"interruptible_eval.clj\" 84] [nrepl.middleware.interruptible_eval$evaluate invoke \"interruptible_eval.clj\" 56] [nrepl.middleware.interruptible_eval$interruptible_eval$fn__999$fn__1003 invoke \"interruptible_eval.clj\" 152] [clojure.lang.AFn run \"AFn.java\" 22] [nrepl.middleware.session$session_exec$main_loop__1067$fn__1071 invoke \"session.clj\" 202] [nrepl.middleware.session$session_exec$main_loop__1067 invoke \"session.clj\" 201] [clojure.lang.AFn run \"AFn.java\" 22] [java.lang.Thread run \"Thread.java\" 1534]], :cause class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')}}\n;;=\u003e #object[java.util.Optional 0x200c7eac \"Optional.empty\"]\n```\n\n### `flat-map`\n- Returns empty Optional if `f` throws Exception \n- Returns Optional with transformed value if `f` transforms value \n- Un-nests Optionals and returns a single Optional e.g. `Optional\u003cOptional\u003cT\u003e\u003e -\u003e Optional\u003cT\u003e`\n- This is useful when working with fn that return Optional values\n- Multi arity versions also take a exception handler which can be a logger function\n- If logger is a macro e.g. clojure.tools.logging, create a logger-fn and supply that as argument\n- e.g.\n```clojure\n(def logger-fn #(clojure.tools.logging/info % \"Exception occurred\"))\n```\n- The reason is Clojure functions can't take macros as argument\n#### Usage:\n```clojure\n(require '[fr33m0nk.optional :as optional]\n         '[fr33m0nk.utility :as optional-util]\n         '[clojure.tools.logging :as log])\n\n;; optional/map returns Optional\u003cOptional\u003cT\u003e\u003e when the mapping fn return Optional\u003cT\u003e\n(-\u003e\u003e 9\n     optional/optional-of\n     (optional/map (optional/wrap-fn inc)))\n;;=\u003e #object[java.util.Optional 0x38629e44 \"Optional[Optional[10]]\"]\n\n;; optional/flat-map returns Optional\u003cT\u003e even when the mapping fn return Optional\u003cT\u003e\n(-\u003e\u003e 9\n     optional/optional-of\n     (optional/flat-map (optional/wrap-fn inc)))\n;;=\u003e #object[java.util.Optional 0x244313a4 \"Optional[10]\"]\n\n;; optional/map returns Optional\u003cOptional\u003cT\u003e\u003e when the mapping fn return Optional\u003cT\u003e\n(-\u003e\u003e \"9\"\n     optional/optional-of\n     (optional/map (optional/wrap-fn inc)))\n;;=\u003e #object[java.util.Optional 0x1278dd1b \"Optional[Optional.empty]\"]\n\n;; optional/flat-map returns Optional\u003cT\u003e even when the mapping fn return Optional\u003cT\u003e\n(-\u003e\u003e \"9\"\n     optional/optional-of\n     (optional/flat-map (optional/wrap-fn inc)))\n;;=\u003e #object[java.util.Optional 0x200c7eac \"Optional.empty\"]\n\n;; Example with logger and exception message when mapping function is returns unboxed value\n(let [log-fn #(clojure.tools.logging/info % \"Uh-Oh!!\")]\n  (-\u003e\u003e \"9\"\n       optional/optional-of\n       (#(optional/flat-map inc % log-fn))))\n;;Aug 15, 2022 12:59:06 PM clojure.tools.logging$eval2267$fn__2270 invoke\n;;INFO: Uh-Oh!! {:msg class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap'), :type java.lang.ClassCastException, :exception {:via [{:type java.lang.ClassCastException, :message \"class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')\", :at [clojure.lang.Numbers inc \"Numbers.java\" 139]}], :trace [[clojure.lang.Numbers inc \"Numbers.java\" 139] [clojure.core$inc invokeStatic \"core.clj\" 929] [clojure.core$inc invoke \"core.clj\" 924] [fr33m0nk.utility$fn$reify__1942 apply \"utility.clj\" 61] [java.util.Optional flatMap \"Optional.java\" 289] [fr33m0nk.optional$flat_map invokeStatic \"optional.clj\" 89] [fr33m0nk.optional$flat_map invoke \"optional.clj\" 75] [user$eval2488$fn__2491 invoke \"form-init16753772140548043809.clj\" 4] [user$eval2488 invokeStatic \"form-init16753772140548043809.clj\" 4] [user$eval2488 invoke \"form-init16753772140548043809.clj\" 1] [clojure.lang.Compiler eval \"Compiler.java\" 7194] [clojure.lang.Compiler eval \"Compiler.java\" 7149] [clojure.core$eval invokeStatic \"core.clj\" 3215] [clojure.core$eval invoke \"core.clj\" 3211] [nrepl.middleware.interruptible_eval$evaluate$fn__968$fn__969 invoke \"interruptible_eval.clj\" 87] [clojure.lang.AFn applyToHelper \"AFn.java\" 152] [clojure.lang.AFn applyTo \"AFn.java\" 144] [clojure.core$apply invokeStatic \"core.clj\" 667] [clojure.core$with_bindings_STAR_ invokeStatic \"core.clj\" 1990] [clojure.core$with_bindings_STAR_ doInvoke \"core.clj\" 1990] [clojure.lang.RestFn invoke \"RestFn.java\" 425] [nrepl.middleware.interruptible_eval$evaluate$fn__968 invoke \"interruptible_eval.clj\" 87] [clojure.main$repl$read_eval_print__9206$fn__9209 invoke \"main.clj\" 437] [clojure.main$repl$read_eval_print__9206 invoke \"main.clj\" 437] [clojure.main$repl$fn__9215 invoke \"main.clj\" 458] [clojure.main$repl invokeStatic \"main.clj\" 458] [clojure.main$repl doInvoke \"main.clj\" 368] [clojure.lang.RestFn invoke \"RestFn.java\" 1523] [nrepl.middleware.interruptible_eval$evaluate invokeStatic \"interruptible_eval.clj\" 84] [nrepl.middleware.interruptible_eval$evaluate invoke \"interruptible_eval.clj\" 56] [nrepl.middleware.interruptible_eval$interruptible_eval$fn__999$fn__1003 invoke \"interruptible_eval.clj\" 152] [clojure.lang.AFn run \"AFn.java\" 22] [nrepl.middleware.session$session_exec$main_loop__1067$fn__1071 invoke \"session.clj\" 202] [nrepl.middleware.session$session_exec$main_loop__1067 invoke \"session.clj\" 201] [clojure.lang.AFn run \"AFn.java\" 22] [java.lang.Thread run \"Thread.java\" 1534]], :cause class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')}}\n;;=\u003e #object[java.util.Optional 0x200c7eac \"Optional.empty\"]\n\n;; Example with logger and exception message when mapping function is returns Optional\u003cT\u003e\n(let [log-fn #(clojure.tools.logging/info % \"Uh-Oh!!\")\n      mapping-fn (optional/wrap-fn inc log-fn)]\n  (-\u003e\u003e \"9\"\n       optional/optional-of\n       (optional/flat-map mapping-fn)))\n;;Aug 15, 2022 12:57:43 PM clojure.tools.logging$eval2267$fn__2270 invoke\n;;INFO: Uh-Oh!! {:msg class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap'), :type java.lang.ClassCastException, :exception {:via [{:type java.lang.ClassCastException, :message \"class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')\", :at [clojure.lang.Numbers inc \"Numbers.java\" 139]}], :trace [[clojure.lang.Numbers inc \"Numbers.java\" 139] [clojure.core$inc invokeStatic \"core.clj\" 929] [clojure.core$inc invoke \"core.clj\" 924] [clojure.lang.AFn applyToHelper \"AFn.java\" 154] [clojure.lang.AFn applyTo \"AFn.java\" 144] [clojure.core$apply invokeStatic \"core.clj\" 667] [clojure.core$apply invoke \"core.clj\" 662] [fr33m0nk.optional$warp_return_in_optional$fn__1959 doInvoke \"optional.clj\" 114] [clojure.lang.RestFn invoke \"RestFn.java\" 408] [fr33m0nk.utility$fn$reify__1942 apply \"utility.clj\" 61] [java.util.Optional flatMap \"Optional.java\" 289] [fr33m0nk.optional$flat_map invokeStatic \"optional.clj\" 89] [fr33m0nk.optional$flat_map invoke \"optional.clj\" 75] [fr33m0nk.optional$flat_map invokeStatic \"optional.clj\" 84] [fr33m0nk.optional$flat_map invoke \"optional.clj\" 75] [user$eval2478 invokeStatic \"form-init16753772140548043809.clj\" 5] [user$eval2478 invoke \"form-init16753772140548043809.clj\" 1] [clojure.lang.Compiler eval \"Compiler.java\" 7194] [clojure.lang.Compiler eval \"Compiler.java\" 7149] [clojure.core$eval invokeStatic \"core.clj\" 3215] [clojure.core$eval invoke \"core.clj\" 3211] [nrepl.middleware.interruptible_eval$evaluate$fn__968$fn__969 invoke \"interruptible_eval.clj\" 87] [clojure.lang.AFn applyToHelper \"AFn.java\" 152] [clojure.lang.AFn applyTo \"AFn.java\" 144] [clojure.core$apply invokeStatic \"core.clj\" 667] [clojure.core$with_bindings_STAR_ invokeStatic \"core.clj\" 1990] [clojure.core$with_bindings_STAR_ doInvoke \"core.clj\" 1990] [clojure.lang.RestFn invoke \"RestFn.java\" 425] [nrepl.middleware.interruptible_eval$evaluate$fn__968 invoke \"interruptible_eval.clj\" 87] [clojure.main$repl$read_eval_print__9206$fn__9209 invoke \"main.clj\" 437] [clojure.main$repl$read_eval_print__9206 invoke \"main.clj\" 437] [clojure.main$repl$fn__9215 invoke \"main.clj\" 458] [clojure.main$repl invokeStatic \"main.clj\" 458] [clojure.main$repl doInvoke \"main.clj\" 368] [clojure.lang.RestFn invoke \"RestFn.java\" 1523] [nrepl.middleware.interruptible_eval$evaluate invokeStatic \"interruptible_eval.clj\" 84] [nrepl.middleware.interruptible_eval$evaluate invoke \"interruptible_eval.clj\" 56] [nrepl.middleware.interruptible_eval$interruptible_eval$fn__999$fn__1003 invoke \"interruptible_eval.clj\" 152] [clojure.lang.AFn run \"AFn.java\" 22] [nrepl.middleware.session$session_exec$main_loop__1067$fn__1071 invoke \"session.clj\" 202] [nrepl.middleware.session$session_exec$main_loop__1067 invoke \"session.clj\" 201] [clojure.lang.AFn run \"AFn.java\" 22] [java.lang.Thread run \"Thread.java\" 1534]], :cause class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')}}\n;;=\u003e #object[java.util.Optional 0x200c7eac \"Optional.empty\"]\n```\n\n### `optional-\u003esequence`\n- Returns Clojure sequence from `Optional\u003cT\u003e`\n#### Usage:\n```clojure\n(-\u003e\u003e 10\n     optional/optional-of\n     (optional/map inc)\n     (optional/optional-\u003esequence))\n;;=\u003e (11)\n```\n- ### namespace\n```clojure \n(ns fr33m0nk.utility)\n```\n\n### `fn-\u003epredicate`\n- Takes a clojure predicate fn and returns a `java.util.function.Predicate` instance which is used with `optional/filter`\n- Multi arity versions also take a exception handler which can be a logger function\n- If logger is a macro e.g. clojure.tools.logging, create a logger-fn and supply that as argument\n- e.g.\n```clojure\n(def logger-fn #(clojure.tools.logging/info % \"Exception occurred\"))\n```\n- The reason is Clojure functions can't take macros as argument\n#### Usage:\n```clojure\n(require \n  '[fr33m0nk.utility :as optional-util]\n  '[clojure.tools.logging :as log])\n\n(def log-fn #(clojure.tools.logging/info % \"Uh-Oh!!\"))\n\n(optional-util/fn-\u003epredicate inc log-fn)\n;;=\u003e #object[fr33m0nk.utility$fn$reify__1939 0x72489d41 \"fr33m0nk.utility$fn$reify__1939@72489d41\"]\n```\n\n### `fn-\u003efunction`\n- Takes a clojure fn for mapping and returns a `java.util.function.Function` instance which is used with `option/map` and `option/flat-map`\n- Multi arity versions also take a exception handler which can be a logger function\n- If logger is a macro e.g. clojure.tools.logging, create a logger-fn and supply that as argument\n- e.g.\n```clojure\n(def logger-fn #(clojure.tools.logging/info % \"Exception occurred\"))\n```\n- The reason is Clojure functions can't take macros as argument\n#### Usage:\n```clojure\n(require \n  '[fr33m0nk.utility :as optional-util]\n  '[clojure.tools.logging :as log])\n\n(def log-fn #(clojure.tools.logging/info % \"Uh-Oh!!\"))\n\n;; For map operations\n(optional-util/fn-\u003efunction inc log-fn false)\n\n;; For flat-map operations\n(optional-util/fn-\u003efunction inc log-fn true)\n;;=\u003e #object[fr33m0nk.utility$fn$reify__1942 0x37917038 \"fr33m0nk.utility$fn$reify__1942@37917038\"]\n```\n\n## Why would you WANT this?\n\nLook, this is a judgement-free zone, OK? We all have our reasons.\n\n## License\n\nCopyright © 2022 **fr33m0nk** (Prashant Sinha)\n\nDistributed under the BSD 3-Clause License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffr33m0nk%2Foptional","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffr33m0nk%2Foptional","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffr33m0nk%2Foptional/lists"}