In Scala, PartialFunction is a trait, which in Clojure I'd represent using
a protocol:

(defprotocol Partial
  (defined-at? [x]))

(defn partial-fn [guard f]
  (reify
    Partial
    (defined-at? [x] (guard x))
    clojure.lang.IFn
    (invoke [f x]
      {:pre [(guard x)]}
      (f x))))

And then, when I have a mechanism to create a partial function, I'd then
work on a macro to transform:

(pfn [x :guard even?] (/ x 2))

Into:

(partial-fn even? (fn [x] (/ x 2)))

I'm not sure how much benefit you'd get out of partial functions that are
not part of the core language. You'd need to write a fair bit of
infrastructure around them, but it might be worth it.

In Clojure, it seems quite common to use functions that return nil to
achieve the same effect as partial functions, and there are several
functions and macros, like some-> and keep, that support that idiom.

- James



On 25 May 2013 17:14, David Pollak <feeder.of.the.be...@gmail.com> wrote:

> Hello,
>
> This is my first post to this group. If my post or the tone of my post is
> not up to this communities standards, please give me feedback so that I can
> integrate with the community.
>
> I'm coming from Scala-land.
>
> In Scala, there's a PartialFunction:
> http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/index.html#scala.PartialFunction
>
> The key take-away for PartialFunctions is "... is a unary function where
> the domain does not necessarily include all values of type A."
>
> The ability to test a PartialFunction to see if the domain includes a
> particular value is very helpful. pf.isDefinedAt(x) allows testing to see
> if the function is defined at a given value of x.
>
> But a PartialFunction is a subclass of Function, so PartialFunctions can
> be applied:
>
> pf(x)
>
> The Scala compiler will take a pattern and turn it into a PartialFunction:
>
> def pf: PartialFunction[String, Number] =
> {
>   case "" => 0 // special case blank to zero
>   case x if isInt(x) => x.toInt
>   case x if isDouble(x) => x.toDouble
>   case x if isBigInt(x) => asBigInt(x)
> }
>
> Another property of PartialFunction is they can be composed:
>
> pf = pf1 orElse pf2 orElse pf3 // pf isDefinedAt any place any of the
> partial functions are defined
>
> We use PartialFunctions extensively in Lift to allow choosing if a
> particular URL should be served by Lift, if it should be served by a
> particular REST handler, etc. For example, defining a REST route in Lift:
>
> serve {
>   case "api" :: "user" :: AsLong(userId) :: _ GetJson _ =>
> User.find(userId).map(_.toJson)
> }
>
> As I've been learning Clojure in preparation for a presentation at Strange
> Loop and as part of a new project I've been working on (
> http://blog.goodstuff.im/plugh), I am looking to bring the best things in
> Lift into the Clojure code I write.
>
> Clojure's pattern matching stuff is pretty nifty. I especially like how
> you can extract values out of a Map (this is *so* much more powerful that
> Scala's pattern matching, even with unapply... but I digress).
>
> So, I wrote a macro (it's my first, so feedback on the style for the macro
> itself):
>
> (defmacro match-func [& body] `(fn [~'x] (match [~'x] ~@body)))
>
> This creates a function that is the application of the match to a
> parameter, so:
>
> ((match-func [q :guard even?] (+ 1 q) [z] (* 7 z)) 33)
> ;; 231
>
> I am struggling with the right style for how to create something that's
> both a function:
>
> (def my-test (match-func [q :guard even?] (+ 1 q) [z] (* 7 z)))
>
> (my-test 33)
>
> And also something that can be tested for definition at a given value.
>
> Put another way, if Clojure had something that's both a function and a
> thing that could be asked if it's defined for a given input, how would one
> in Clojure apply that thing and also ask that thing if it was defined?
>
> Thanks for reading my long question and I look forward to feedback.
>
> David
>
>
> --
> Telegram, Simply Beautiful CMS https://telegr.am
> Lift, the simply functional web framework http://liftweb.net
> Follow me: http://twitter.com/dpp
> Blog: http://goodstuff.im
>
>  --
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to