Re: Default values
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 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
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
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
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
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
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?
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?
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
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
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?
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?
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
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
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 -~--~~~~--~~--~--~---