Fork me on GitHub
#beginners
<
2021-03-11
>
mwolf01:03:46

how do I map a lazy sequence? suppose I have a function that generates a lazy sequence, e.g. if (ints) generates 1, 2, 3 ..., but I want to map each returned value by inc, so something like (take 5 (some-function-here inc (ints))) generates [2 3 4 5 6], how would I code that?

aratare01:03:07

perhaps (map inc (ints)) is what you’re looking for?

mwolf01:03:05

yeah, I was over-complicating it in my head. thx.

👍 6
Alex Miller (Clojure team)01:03:37

you already wrote it! :)

clojure-spin 3
👆 3
Adrian Imanuel06:03:55

Hi, I'm using (clojure.string/replace "yes we use clojure" " " "...") or (clojure.string/replace "NULL" "NULL" "...") if i want to specify " " or "NULL" to replace with "..." how to write the syntax? There won't be both " " & "NULL" in one string

andarp07:03:46

#"( |NULL)" should work. Note the leading # - that means it’s a regular expression.

3
Adrian Imanuel11:03:07

Thank you @anders152, bullseye solution!

🙌 3
Stuart11:03:30

Can I update the CLI tools from the CLI tools or do I need to re-install the newer verswion over the top?

Stuart11:03:54

nevrmind, just installed latest.

Adrian Imanuel11:03:33

I'm wondering why this become nil

(def myvar
{:converted_date "5/31/2011", :SubTotal "6122.082", :TaxAmt "587.5603", :Freight "867.2389", :TotalDue "7576.8812", :sales_name "Michael Blythe", :AreaName "Others", :CountryName "Others"})
when i use
(myvar :converted_date)
=> nil
it supposed to show 5/31/2011, anyone can explain why?

dharrigan11:03:37

That's strange, for it works for me...

dharrigan11:03:42

user=> (def myvar
  #_=> {:converted_date "5/31/2011", :SubTotal "6122.082", :TaxAmt "587.5603", :Freight "867.2389", :TotalDue "7576.8812", :sales_name "Michael Blythe", :AreaName "Others", :CountryName "Others"})
#'user/myvar
user=> (:converted_date myvar)
"5/31/2011"
user=> (myvar :converted_date)
"5/31/2011"
user=> 

confusedparrot 3
3
dharrigan11:03:20

Have you eval'ed myvar yet?

Adrian Imanuel11:03:23

cleaning-adv.core> (eval myvar)
;; => {:converted_date "5/31/2011", :SubTotal "6122.082", :TaxAmt "587.5603", :Freight "867.2389", :TotalDue "7576.8812", :sales_name "Michael Blythe", :AreaName "Others", :CountryName "Others"}

dharrigan11:03:35

not quite like that

dharrigan11:03:48

I mean, did you type this into a repl and try first?

dharrigan11:03:58

or are you doing this in an editor?

Adrian Imanuel11:03:26

in editor, then i run it into repl

dharrigan11:03:46

Right, okay, so most editors allow you to eval the var in their editing pane and then in the same window pane to do (myvar :converted_date) and evalutate that. For what I think could be happening is that your repl is in one namespace (user?) and your editor window pane is in another namespace

dharrigan11:03:02

and vars are local to each namespace.

dharrigan11:03:15

Only a guess, as I can't see what you're doing 🙂

dharrigan11:03:43

you see in my example above, I'm in the user namespace

Adrian Imanuel11:03:04

no, i work in 1 namespace cleaning-adv.core , i've also c-x c-e in the editor as well, return into nil but

(:SubTotal myvar)
"6122.082"

dharrigan11:03:06

if you type (keys myvar) what do you get?

Adrian Imanuel11:03:34

this is all the keys

cleaning-adv.core> (keys myvar)
;; => (:converted_date :SubTotal :TaxAmt :Freight :TotalDue :sales_name :AreaName :CountryName)

dharrigan11:03:52

and what happens if you do (:converted_date myvar)?

Adrian Imanuel11:03:29

nil ... I wonder if it because i pull those data from .csv, does it have some effect?

(def csvopener
 (with-open [reader (io/reader "resources/AdvWorks_Sales_Report_Dirty_sample.csv")]
  (doall
   (csv/read-csv reader))))

(defn csv-data->maps
  [csv-data]
  (map zipmap
       (->> (first csv-data)
            (map keyword)
            repeat)
        (rest csv-data)))

(def dirtydata (into [](csv-data->maps csvopener)))

(def myvar (get dirtydata 3))

javahippie12:03:48

I’m wondering if there are any strange characters in your keyword? What happens if you try this: (map #(% myvar) (keys myvar)), or better: (map #(= :converted_date %) (keys myvar)) ?

Adrian Imanuel12:03:22

i checked with class, only the converted_date return nil

cleaning-adv.core> (class (myvar :converted_date))
;; => nil
cleaning-adv.core> (class (myvar :SubTotal))
;; => java.lang.String
cleaning-adv.core> (class (myvar :sales_name))
;; => java.lang.String 

dharrigan12:03:30

Could there be something screwy with the quotes on the date field? Sometimes those quotes aren't real quotes - a few times I ran in that on other things.

Adrian Imanuel12:03:25

@javahippie here's the result,

cleaning-adv.core> (map #(% myvar) (keys myvar))
;; => ("5/31/2011" "6122.082" "587.5603" "867.2389" "7576.8812" "Michael Blythe" "Others" "Others")
cleaning-adv.core> (map #(= :converted_date %) (keys myvar))
;; => (false false false false false false false false)
@dharrigan hmm... what format should I change the date? the / symbol might messing up the string?

javahippie12:03:15

Your keyword :converted_date is not what it seems, the first entry would have been true otherwise in the second call

dharrigan12:03:39

yes, perhaps the _ is not a real underscore?

javahippie12:03:39

There are some chars in there, so that (= :converted_date :converted_date) is false

Adrian Imanuel12:03:29

that's really confusing, I've changed it without _ then re-type it become ConvertedDate1 still showing nil i'll rename the header, and change the column from 1st to 2nd or 3rd column... let's see or my csv is saved in CSV UTF-8 comma delimited, does it have any effect? should I save it to another format?

andarp12:03:18

I am quite convinced at this point that your input data has some type of strange character. A zero width space perhaps?

andarp12:03:34

Try opening the csv in a byte editor or some such

andarp12:03:52

Is the column you have issues with the first column in the csv?

andarp12:03:43

If that’s the case I think it’s some kind of encoding issue related to byte order marks or some such. Sorry for the handwaving explanation, on a phone at the moment!

Adrian Imanuel12:03:25

it solved my problems after change CSV UTF-8 (comma delimited) into only csv (comma delimited), i wonder what's the difference between those? thanks a lot @dharrigan @javahippie @anders152, it wasn't because of _ or different/hanging <space> characters, but this also an alert, it's better to rename it without any symbols https://donatstudios.com/CSV-An-Encoding-Nightmare

andarp12:03:16

Then it was probably an encoding issue with the first character in the file, or some other strange character artifact

Mark Wardle17:03:47

Hi all. Really enjoying using deps.edn, aliases and a standard main -M. I've also been experimenting with -X to execute arbitrary functions. In many cases, it seems possible to avoid parsing command-line arguments at all and remove a load of unnecessary code. It's turtles functions all the way down. Sometimes one simply needs one or two little configuration options. Is there any clever way of avoiding having to escape strings? eg clj -X:download :db /var/tmp/wibble is just so much nicer than clj -X:download :db '"/var/tmp/wibble"', particularly for non-clojure users of tools. I see non-escaped strings are passed as symbols so could I do something clever in the function itself? Or am I best sticking to -M:alias and parsing the command line arguments with tools.cli? Advice appreciated.

grazfather17:03:03

if you’re writing cli consider using #babashka

Mark Wardle18:03:43

Thanks. This is for running or starting a number of applications (that include a number of java libraries) from the command line, rather than scripting tools per se.

Alex Miller (Clojure team)18:03:32

I would stick with -X for now, we're continuing to think about the annoyance of string args and best answer there

Alex Miller (Clojure team)18:03:38

in the code you could use (name arg) - name works with both strings and symbols so would work with either

👍 6
Mark Wardle18:03:02

That's a great idea. Thank you. It is only a minor annoyance - I must have deleted a page of redundant code because this is so convenient....

Alex Miller (Clojure team)18:03:03

yep, hoping to continue adding to the convenience factor :)

seancorfield18:03:04

For my deps-based apps that can be invoked via -X, I generally allow any argument that is expected to be a string to also be a symbol where that is legal but it's still a bit of a pain point. It would be nice to see changes in the underlying machinery to improve this. I can imagine that if the argument is unparsable, perhaps it could just be passed as a literal string and left for the executed function to validate/deal with?

Mark Wardle20:03:47

I tried using name, but of course, there are special characters which are interpreted before being passed to the fn - so anything illegal as a symbol I guess is ruled out. e.g.

➜  clods git:(dev) ✗ clj -X:download :db ods-2021-03
test: got params {:db ods-2021-03}
Installing ODS index in  ods-2021-03
➜  clods git:(dev) ✗ clj -X:download :db \var\tmp\ods-2021-03
test: got params {:db vartmpods-2021-03}
Installing ODS index in  vartmpods-2021-03
➜  clods git:(dev) ✗ clj -X:download :db /var/tmp/ods-2021-03
Unreadable arg: "/var/tmp/ods-2021-03"

Mark Wardle20:03:47

It’s fine. I’ll switch to using -M for a bit and I can print some help text etc… and I can see why this might be tricky. But I guess it depends on whether you think of this as tool for the developer of the software, or actually useful to a user of that software. If the latter, perhaps a simple options map to go along with exec-fn might work to help inform parsing/coercion? But just thinking out loud… perhaps I’m misusing the feature 🙂

Alex Miller (Clojure team)20:03:08

I don’t think you’re using it wrong

Alex Miller (Clojure team)20:03:32

It bugs me too, still thinking about it

🙂 3
fsd20:03:48

Hi There, I have this function, when I (println places) it prints an array but when I print inside the loop after [idx park] (println park) it does not println any objects. Can someone please tell me what is wrong with my code? Thanks

(defn featuresList[places]
;; (println places)
  (map-indexed (fn [idx park] (println park)  {:type "Feature" :geometry {:type "Point" :coordinates [(:Longitude park),(:Latitude park)]}} )places)
  )

dpsutton20:03:03

> when i print inside the loop you don't have a loop. That's a lazy sequence that is unrealized so nothing is computed

fsd20:03:37

Ohh I see @dpsutton Thanks. My goal is to create objects like below for the mapbox so that it can display Marks on the map dynamic depending on geo coordinates. Would please guide what could I use to get this working. I would like to loop through the array of object and set dynamic coordinates [(:Longitude park),(:Latitude park)] like this.

#js {:type "Feature" :geometry #js {:type "Point" :coordinates #js [-122.5257173,38.55322304]}}
#js {:type "Feature" :geometry #js {:type "Point" :coordinates #js [-121.6984631,38.11059503]}}
#js {:type "Feature" :geometry #js {:type "Point" :coordinates #js [-122.3400331,37.2016849]}}
#js {:type "Feature" :geometry #js {:type "Point" :coordinates #js [ -122.379692,37.713693]}}

dpsutton20:03:10

if you change your verbiage a bit you're doing that. From a collection of places, return a collection of that has this shape using the original collection. I think you've accomplished that right?

dpsutton20:03:33

unless you're asking how to get these as js types rather than the clojurescript immutable types?

fsd20:03:21

correct, i am trying to get as js types because I created a sample app using reactjs and it worked on there. Following code in js

const featuresLst = data.map(
    park => ({
        "type": 'Feature',
        "geometry":
        {
            "type": 'Point',
            "coordinates": [park.Longitude, park.Latitude]
        }
    }))

fsd20:03:58

let geojson = {
    type: 'FeatureCollection',
    features: featuresLst
}

fsd20:03:22

Source id="my-data" type="geojson" data={geojson}>
<Layer />
</Source>

fsd21:03:44

This is how I did it JavaScript, First created separate function variable just for mapping over array.

oconn20:03:31

(defn features-list [places]
  ;; idx is unused (here) so you could use map
  (map-indexed (fn [idx park] 
                 (println park) ;; => {:Longitude -77.0364, :Latitude 38.8951}
                 #js {:type "Feature" 
                      :geometry #js {:type "Point" 
                                     :coordinates #js [(:Longitude park)
                                                       (:Latitude park)]}})
               places))

(let [places [{:Longitude -77.0364 :Latitude 38.8951}]]
  ;; This will force the lazy seq to be realized
  (prn (features-list places)) ;; => (#js {:type "Feature", :geometry #js {:type "Point", :coordinates #js [-77.0364 38.8951]}})
Could also wrap the object in clj->js

fsd21:03:51

Hello @oconn 
Like this ?
(clj->js {:type "Feature" 
                      :geometry #js {:type "Point" 
                                     :coordinates #js [(:Longitude park)
                                                       (:Latitude park)]}})

oconn21:03:50

yes, but you don’t need the nested #js literals then

DoubleU21:03:29

Hi All, bit of a newbie question here, but I have a form component in my clojurescript, and that component contains a form-input as a child (code below). I’m trying to figure out how to dispatch an event back out to my component when the on-blur event is fired but not exactly sure how. With something like Angular, from within the component I could use the .emit(), in React, I could do something like onClick={someMethod} which would then call a method in my parent, but not sure how to do this in clojurescript (or if this is even possible). Can someone provide some direction?

[form-input
          (utils/merge-fn-props {:on-input #(reset! value (-> % .-target .-value))
                                 :on-focus #(reset! focus? true)
                                 :on-blur #(reset! focus? false)}...

blak3mill3r22:03:17

@jcwright04 you are using reagent, but not re-frame, is that right?

blak3mill3r22:03:03

you can call whatever code you want there... :on-blur #(dispatch-blur-event %)

blak3mill3r22:03:03

if you share a bit more of the surrounding code I might be able to offer an idea for how to connect things together

blak3mill3r22:03:49

the anonymous fn you pass as :on-blur has bindings for your lexical scope (anything you construct in a let binding in the component, for example) ... does that help?