Re: Default values

2015-02-21 Thread Jeremy Heiler

On 2/21/15 4:57 AM, Cecil Westerhof wrote:

I want to work with default values. For this I use:
 [& nr]

This gives the value null to nr. So far so good.

But I want to propagate the value, because I want to fill the default at a
higher level.

​I have:
 (defn test-lucky-numbers-all
   "Test all lucky number performance"
   [& nr]
 (printf "all: %s\n\n" nr)
   (time
(do (test-lucky-numbers-first   nr)
and:
 (defn test-lucky-numbers-first
   "Performance test of lucky numbers (first)"
   [& nr]
 (printf "first: %s\n\n" nr)

>

When I do:
 (test-lucky-numbers-all)
The first prints:
 all: null
but the second prints:
 first: (nil)

And when I do:
 (test-lucky-numbers-all 1)​
​The first prints:
 all: (1)
and the second prints:
 first: ((1))

What is happening here and what can I do about it?



You can "unwrap" the varargs by destructuring them like so:

  (defn foo [a b & [c d]]
(list a b (+ c d)))

  (foo 1 2 3 4) ;; => (1 2 7)

This is possible because the varargs are provided as a seq.

--
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/d/optout.


Re: Default values

2015-02-21 Thread Cecil Westerhof
2015-02-21 11:03 GMT+01:00 Ulises :

> What's happening is that you have multiple optional arguments chained
> together. Optional arguments are passed as a list (or seq?) of arguments,
> so if you pass them down to another function that also takes optional
> arguments they get wrapped in yet another list. An option to stop this is
> to use apply, e.g.:
>
> user=> (defn foo [& stuff] stuff)
> #'user/foo
> user=> (defn bar [& things] (apply foo things))
> #'user/bar
> user=> (bar 1 2 3)
> (1 2 3)
>

​That works, but the problem is that the function also accepts two
parameters. (I understood optional parameters wrongly.) I should probably
go back to my first option of a multi-arity function.

Would a be possibly to define a value that is only known in the local
source file?



> On Sat Feb 21 2015 at 9:58:00 AM Cecil Westerhof 
> wrote:
>
>> I want to work with default values. For this I use:
>> [& nr]
>>
>> This gives the value null to nr. So far so good.
>>
>> But I want to propagate the value, because I want to fill the default at
>> a higher level.
>>
>> ​I have:
>> (defn test-lucky-numbers-all
>>   "Test all lucky number performance"
>>   [& nr]
>> (printf "all: %s\n\n" nr)
>>   (time
>>(do (test-lucky-numbers-first   nr)
>> and:
>> (defn test-lucky-numbers-first
>>   "Performance test of lucky numbers (first)"
>>   [& nr]
>> (printf "first: %s\n\n" nr)
>>
>> When I do:
>> (test-lucky-numbers-all)
>> The first prints:
>> all: null
>> but the second prints:
>> first: (nil)
>>
>> And when I do:
>> (test-lucky-numbers-all 1)​
>> ​The first prints:
>> all: (1)
>> and the second prints:
>> first: ((1))
>>
>> What is happening here and what can I do about it?
>>
>> I could write a general function to translate the nil, but I was
>> wondering if there is a better option.​
>>
>
-- 
Cecil Westerhof

-- 
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/d/optout.


Re: Default values

2015-02-21 Thread Ulises
What's happening is that you have multiple optional arguments chained
together. Optional arguments are passed as a list (or seq?) of arguments,
so if you pass them down to another function that also takes optional
arguments they get wrapped in yet another list. An option to stop this is
to use apply, e.g.:

user=> (defn foo [& stuff] stuff)
#'user/foo
user=> (defn bar [& things] (apply foo things))
#'user/bar
user=> (bar 1 2 3)
(1 2 3)


On Sat Feb 21 2015 at 9:58:00 AM Cecil Westerhof 
wrote:

> I want to work with default values. For this I use:
> [& nr]
>
> This gives the value null to nr. So far so good.
>
> But I want to propagate the value, because I want to fill the default at a
> higher level.
>
> ​I have:
> (defn test-lucky-numbers-all
>   "Test all lucky number performance"
>   [& nr]
> (printf "all: %s\n\n" nr)
>   (time
>(do (test-lucky-numbers-first   nr)
> and:
> (defn test-lucky-numbers-first
>   "Performance test of lucky numbers (first)"
>   [& nr]
> (printf "first: %s\n\n" nr)
>
> When I do:
> (test-lucky-numbers-all)
> The first prints:
> all: null
> but the second prints:
> first: (nil)
>
> And when I do:
> (test-lucky-numbers-all 1)​
> ​The first prints:
> all: (1)
> and the second prints:
> first: ((1))
>
> What is happening here and what can I do about it?
>
> I could write a general function to translate the nil, but I was wondering
> if there is a better option.​
>
> --
> Cecil Westerhof
>
> --
> 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/d/optout.
>

-- 
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/d/optout.


Default values

2015-02-21 Thread Cecil Westerhof
I want to work with default values. For this I use:
[& nr]

This gives the value null to nr. So far so good.

But I want to propagate the value, because I want to fill the default at a
higher level.

​I have:
(defn test-lucky-numbers-all
  "Test all lucky number performance"
  [& nr]
(printf "all: %s\n\n" nr)
  (time
   (do (test-lucky-numbers-first   nr)
and:
(defn test-lucky-numbers-first
  "Performance test of lucky numbers (first)"
  [& nr]
(printf "first: %s\n\n" nr)

When I do:
(test-lucky-numbers-all)
The first prints:
all: null
but the second prints:
first: (nil)

And when I do:
(test-lucky-numbers-all 1)​
​The first prints:
all: (1)
and the second prints:
first: ((1))

What is happening here and what can I do about it?

I could write a general function to translate the nil, but I was wondering
if there is a better option.​

-- 
Cecil Westerhof

-- 
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/d/optout.


Re: defrecord with default values

2010-09-07 Thread anthonyghr
Awesome! Thanks so much!

Anthony


On Sep 7, 2:10 am, Meikel Brandmeyer  wrote:
> Hi,
>
> first of all we should start with the form we finally want to have:
>
> (defrecord Foo [a b c])
>
> (defn make-Foo
>   [& {:keys [a b c] :or {a :x c :z}}]
>   (Foo. a b c))
>
> ; Use as: (make-Foo :b :f) => (Foo. :x :f :z)
>
> The only annoying part is the boilerplate of defining make-Foo.
> What we would like to write is:
>
> (defrecord+ Foo [[a :x] b [c :z]])
>
> So how do we get from the lower form to the upper form? Basically
> you have that already, but you should not make the constructor
> a macro, but a function.
>
> General note: You want to use almost always vectors instead of lists
> to group things. Vectors are the Right Tool here. Lists are much less
> in important in Clojure than in other Lisp-like languages. Besides
> their
> role in code representation. (Note: a seq is not a list)
>
> Then we have to define the constructor function. Here we exploit
> the "old" new operator to save us from modifying the type symbol.
> Well, and that's basically it. There is no need for eval and related
> dark magic.
>
> (defmacro defrecord+
>   [record-name fields-and-values & record-body]
>   (let [fields-and-values (map #(if (vector? %) % [% nil]) fields-and-
> values)
>         fields            (vec (map first fields-and-values))
>         default-map       (into {} fields-and-values)]
>     `(do
>        (defrecord ~record-name
>          ~fields
>         �...@record-body)
>        (defn ~(symbol (str "make-" (name record-name)))
>          [& {:keys ~fields :or ~default-map}]
>          (new ~record-name ~...@fields)
>
> And the result:
>
> user=> (defrecord+ Foo [[a :x] b [c :z]])
> #'user/make-Foo
> user=> (make-Foo :b :f)
> #:user.Foo{:a :x, :b :f, :c :z}
> user=> (macroexpand-1 '(defrecord+ Foo [[a :x] b [c :z]]))
> (do
>   (clojure.core/defrecord Foo [a b c])
>   (clojure.core/defn make-Foo
>     [& {:or {a :x, b nil, c :z}, :keys [a b c]}]
>     (new Foo a b c)))
>
> (macroexpand output formatted for readability)
>
> This can be easily extended, that the constructor also allows
> arbitrary
> other keywords, besides the usual defined fields. This is left to the
> astute reader as an excerise. ;) Hint: there is also :as in
> destructuring.
>
> Bottom line: Avoid macros at all cost! If a function does the job, use
> a function! They are easier to write, can be passed around, can be
> apply'd, ...
>
> Hope this helps.
>
> Sincerely
> Meikel

-- 
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


Re: defrecord with default values

2010-09-06 Thread Meikel Brandmeyer
Hi,

first of all we should start with the form we finally want to have:

(defrecord Foo [a b c])

(defn make-Foo
  [& {:keys [a b c] :or {a :x c :z}}]
  (Foo. a b c))

; Use as: (make-Foo :b :f) => (Foo. :x :f :z)

The only annoying part is the boilerplate of defining make-Foo.
What we would like to write is:

(defrecord+ Foo [[a :x] b [c :z]])

So how do we get from the lower form to the upper form? Basically
you have that already, but you should not make the constructor
a macro, but a function.

General note: You want to use almost always vectors instead of lists
to group things. Vectors are the Right Tool here. Lists are much less
in important in Clojure than in other Lisp-like languages. Besides
their
role in code representation. (Note: a seq is not a list)

Then we have to define the constructor function. Here we exploit
the "old" new operator to save us from modifying the type symbol.
Well, and that's basically it. There is no need for eval and related
dark magic.

(defmacro defrecord+
  [record-name fields-and-values & record-body]
  (let [fields-and-values (map #(if (vector? %) % [% nil]) fields-and-
values)
fields(vec (map first fields-and-values))
default-map   (into {} fields-and-values)]
`(do
   (defrecord ~record-name
 ~fields
 ~...@record-body)
   (defn ~(symbol (str "make-" (name record-name)))
 [& {:keys ~fields :or ~default-map}]
 (new ~record-name ~...@fields)

And the result:

user=> (defrecord+ Foo [[a :x] b [c :z]])
#'user/make-Foo
user=> (make-Foo :b :f)
#:user.Foo{:a :x, :b :f, :c :z}
user=> (macroexpand-1 '(defrecord+ Foo [[a :x] b [c :z]]))
(do
  (clojure.core/defrecord Foo [a b c])
  (clojure.core/defn make-Foo
[& {:or {a :x, b nil, c :z}, :keys [a b c]}]
(new Foo a b c)))

(macroexpand output formatted for readability)

This can be easily extended, that the constructor also allows
arbitrary
other keywords, besides the usual defined fields. This is left to the
astute reader as an excerise. ;) Hint: there is also :as in
destructuring.

Bottom line: Avoid macros at all cost! If a function does the job, use
a function! They are easier to write, can be passed around, can be
apply'd, ...

Hope this helps.

Sincerely
Meikel

-- 
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


defrecord with default values

2010-09-06 Thread anthonyghr
Disclamer: I'm a Clojure noob, so bad code follows...

I have been putzing around with implementing a Simple Temporal Network
(a graph structure for scheduling problems) in Clojure. In the
process, I wanted to generate records that had default values.
I ran into this blog post by cemerick (http://cemerick.com/2010/08/02/
defrecord-slot-defaults/), but it doesn't do exactly what I needed.
I wanted a macro where I could optionally define defaults (rather than
forcing me to define defaults), and I wanted the 'constructor' to
accept key-value pairs that would be used instead of the defaults when
given.
So I toyed around with the code and came up with the following:

-
(defn ensure-key-params
  "Makes sure the arguments are keys - (:a 1 :b 2)"
  [key-vals]
  (->> key-vals
   (map (fn [[key val]]
  [(keyword key) val]))
   (apply concat)))

(defmacro make-instance
  "Creates an instance of a record based on the passed arguments and
the default arguments"
  [cname fields user-vals default-vals]
  `(let [user-map# (apply hash-map ~user-vals)
 default-map# (apply hash-map ~default-vals)
 record-vals# (list*
   (for [rawkey# '~fields]
 (let [key# (keyword rawkey#)]
   (get user-map# key# (default-map# key#)]
 (eval (conj record-vals# ~cname 'new

(defmacro defrecord+
  "Defines a new record, along with a make-RecordName factory function
that
   returns an instance of the record initialized with the default
values
   provided as part of the record's slot declarations.  e.g.
   (defrecord+ foo
 [(a 5) b c])
   (make-foo :b 4)
   => #user.foo{:a 5, :b 4, :c nil}"
  [name slots & etc]
  (let [slots+ (for [slot slots]
 (if (list? slot)
   slot
   (list slot nil)))
fields (->> slots+ (map first) vec)
default-vals (ensure-key-params slots+)]
`(do
   ;;Create the record with the given name and fields
   (defrecord ~name
 ~fields
 ~...@etc)

   ;;Define the constructor macro
   (defmacro ~(symbol (str "make-" name))
 ~(str "A factory function returning a new instance of " name
   " initialized with the defaults specified in the corresponding
defrecord+ form.")
 [& user-vals#]
 (let [name# ~name
   fields# '~fields
   default-vals# '~default-vals]
   `(make-instance ~name# ~fields# '~user-vals# '~default-vals#)))
   ~name)))
-
So now I can do this:
(defrecord+ foobar
   [(a (ref {})) b (c 5)])

and
(make-foobar :c "foobar")
and get
#:user.foobar{:a #, :b nil, :c "foobar"}

So it works as intended, but it seems to me that the code could be
made cleaner. I'd appreciate suggestions for improvements.

Thanks much,

Anthony

-- 
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


Re: Default values for fields of a defrecord?

2010-08-27 Thread Stuart Sierra
No, constructor functions are the correct way to accomplish this.
-S

On Aug 27, 5:16 pm, Darren Austin  wrote:
> Hi folks,
>
> Is there a way to specify default values for the fields of a
> defrecord?  Or barring that, is there a way to override or augment the
> constructor for the record?
>
> That is, if I have:
>
> (defrecord Foo [a b c d e f g])
>
> I want to be able to create a new Foo with:
>
> (Foo.)
>
> and have default values assigned to each of the fields (a, b, c, etc).
>
> Right now I am just creating my own new-foo function that calls the
> constructor with the default values, but I would like to have
> something more self contained.
>
> Thanks,
> --Darren

-- 
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


Default values for fields of a defrecord?

2010-08-27 Thread Darren Austin
Hi folks,

Is there a way to specify default values for the fields of a
defrecord?  Or barring that, is there a way to override or augment the
constructor for the record?

That is, if I have:

(defrecord Foo [a b c d e f g])

I want to be able to create a new Foo with:

(Foo.)

and have default values assigned to each of the fields (a, b, c, etc).

Right now I am just creating my own new-foo function that calls the
constructor with the default values, but I would like to have
something more self contained.

Thanks,
--Darren

-- 
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


Re: Maps with functions for default values

2010-07-12 Thread Steve Purcell
On 12 Jul 2010, at 16:13, aria42 wrote:

> Is there a way to set up a map so that there is a default function
> which depending on the key returns a value if one is not present in
> the map. I can obviously write this with a deftype and have it
> implement Associative, Seqable, etc. so it behaves like a built-in
> map, but just wondering if there was a way to get this out-of-the-box.


I imagine fnmap would make this easy to do:

 http://richhickey.github.com/clojure-contrib/fnmap-api.html

-Steve

-- 
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


Maps with functions for default values

2010-07-12 Thread aria42
Is there a way to set up a map so that there is a default function
which depending on the key returns a value if one is not present in
the map. I can obviously write this with a deftype and have it
implement Associative, Seqable, etc. so it behaves like a built-in
map, but just wondering if there was a way to get this out-of-the-box.

Thanks, Aria

-- 
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


Re: more constructors (to support default values) for deftype?

2010-01-29 Thread Rich Hickey
On Fri, Jan 22, 2010 at 5:41 PM, Raoul Duke  wrote:
> hi,
>
> if i have (deftype map-db [next-id id-to-item-map]) i have to then do
> (map-db 0 {}) any time i want to make a new one. it would be nice to
> be able to add a function in my deftype so i could use (map-db) to get
> the same effect.
>
> ?

You can just write ordinary functions for that.

Rich

-- 
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


more constructors (to support default values) for deftype?

2010-01-22 Thread Raoul Duke
hi,

if i have (deftype map-db [next-id id-to-item-map]) i have to then do
(map-db 0 {}) any time i want to make a new one. it would be nice to
be able to add a function in my deftype so i could use (map-db) to get
the same effect.

?

-- 
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


Re: hashmap default values

2009-04-27 Thread Meikel Brandmeyer

Hi Mark,

Am 27.04.2009 um 23:42 schrieb Mark Volkmann:


Is there something in core or contrib that supports creating a map
where gets on undefined keys return a specified default value? For
example, I'd like to create a hashmap where the default value for
missing keys is zero.


You can specify the default value when retrieving the value:

(def m {:a 1 :b 2})
(get m :c 0) => 0
(m :c 0) => 0 (untested)
maybe also: (:c m 0) => 0 (also untested)

Sincerely
Meikel

smime.p7s
Description: S/MIME cryptographic signature


hashmap default values

2009-04-27 Thread Mark Volkmann

Is there something in core or contrib that supports creating a map
where gets on undefined keys return a specified default value? For
example, I'd like to create a hashmap where the default value for
missing keys is zero.

-- 
R. Mark Volkmann
Object Computing, Inc.

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---