This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-16
Channels
- # announcements (9)
- # babashka (12)
- # beginners (60)
- # biff (2)
- # calva (4)
- # cider (4)
- # clj-commons (1)
- # clj-kondo (17)
- # clojure (2)
- # clojure-europe (17)
- # clojurescript (15)
- # emacs (18)
- # exercism (5)
- # fulcro (15)
- # holy-lambda (13)
- # joyride (1)
- # lambdaisland (2)
- # malli (1)
- # nbb (3)
- # off-topic (23)
- # polylith (6)
- # portal (59)
- # releases (1)
- # squint (1)
- # tools-deps (4)
Is there any nice REPL I can use on an Android phone? So far I've tried: • Replate REPL, but it has some serious UI problems (mishandled pasting, duplicating characters), and • Replit, but this one is not really a Clojure REPL - it's a "run your whole script" setup that kills any background REPLs too eagerly (on the free version)
The nicest REPL I have found is to simply run Linux on an Android phone, using the Termux application from the F-Droid store Then you can use a Terminal UI REPL like Rebel Readline, or Neovim, or Emacs. This even works with Clojure LSP and Clj-kondo, to give a full development environment on your phone Ideally you would use an external keyboard (I also used a keyboard for Replete, which I found an okay app for a repl) https://practical.li/neovim/termux/
Thank you! I've forgot about running Linux tools on Android. I'll try setting that up.
Termux works very well. I’ve been using a Google Pixel 2XL and a Lenovo Tab P11 plus tablet successfully. I developed some code for my current work project using Termux setup, whist I was travelling (especially each time I’ve been delayed at the airport).
I'm trying to figure out the idiosyncratic approach to this. I know how to brute force it. I'm using repeatedly to generate 3,000,000 random strings from "1111111" to "9999999" but what I really want is 3,000,000 unique random strings. I can do (distinct (repeatedly 4000000 create-new-id)) and take the first 3,000,000 but that feels just a bit odd. Ideas?
can you give more context. how are you using these? you need them all in memory or you use one at a time and don't want dupes?
I need them in memory
Basically I'm generating random data and the item I'm generating has multiple keys which need to be unique..
correct
if it matters, that sounds like you could get some easy bit based compression. if it doesn't, then maybe you could use a set over distinct
I was thinking doing a version of repeatedly with take-while.
but I didn't see how to reference the underlying coll in the take-while
something like (map str (take 3000000 (distinct (repeatedly #(+ 1111111 (rand-int 8888888))))))
?
That works. Almost wish there was a take-unique 🙂
would it be completely silly to do something like (->> (range 0 10) (partition N) (mapcat shuffle) (map str))
? that is, you take a block of N consecutive numbers and shuffle them to create some randomness but guaranteeing uniqueness
(sequence
(comp (distinct)
(take 3000000)
(map str))
(repeatedly #(+ 1111111 (rand-int 8888888))))
there’s the transducer version, if you want to do a single pass
(let [src (repeatedly #(+ 1111111 (rand-int 8888888)))]
(into #{}
(comp (distinct)
(take 3000000)
(map str))
src))
or if you want to get them into a set in memory
second is perfect
ok wow, comp is kinda cool.
yeah this is some conceptually tough stuff, comp with transducers
one sec and I can offer my “mental model” here
I'm finding some of the lazy-seq stuff challenging after coming to this with 15 yrs of common-lisp experience. so it's really quite fun.
it’s so good!
so, many of the sequence higher order functions return a “transducer” if you don’t pass the sequence argument;
at this level, you can think of these as functions that
• take an item from the source sequence
• generate 0, 1 or more items…
so these are basically scanning transformations along some sequence. (map <f>)
is shorthand for, take 1 item, apply f
to it and pass ONE item back out. (mapcat <f>)
is the more general version that can return 0 or more, and (filter <f>)
does what you’d expect
(distinct)
is basically a mapcat that passes on either nothing, or the input item, based on some internal state it keeps
right so in this case map is clear. distinct is acting as a filter.
The challenge for me is where is the state that distinct is looking at.
(defn distinct
"Returns a lazy sequence of the elements of coll with duplicates removed.
Returns a stateful transducer when no collection is provided."
{:added "1.0"
:static true}
([]
(fn [rf]
(let [seen (volatile! #{})]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (contains? @seen input)
result
(do (vswap! seen conj input)
(rf result input)))))))))
here is the definition
my first thoughts were (take-while distinct (repeatably "generator")
see (let [seen (volatile! #{})] ...)
, so the transducer function is closing over some hidden state
ok so it's in the seen
set.
much cleaner than (lambda (x) (setq seq (transducer) )
although under the covers it's conceptually similar-ish? just far more expressive.
Thanks for the mental map that really helped
if you're gonna put the results into a set (and thus don't really care about the order), perhaps you could do something like (->> (map + (range 1111111 9999999 3) (repeatedly #(rand-int 3))) (map str) set)
so you could avoid building the large intermediate state within distinct
?
I would have probably just done:
(->> (range 1111111 9999999)
(shuffle)
(take 3000000)
(map str))
Which is nice and readable in my opinion, but not fully lazy.That can have duplicates right? And the shuffle is shuffling an already random sequence?
I see what you’re trying to do but I don’t think that arity of rand-Int exists? https://clojuredocs.org/clojure.core/rand-int
Ah I think you meant range. Yes, a good idea too!
Hi guys 🙂 I have the following dependencies in my project
:dependencies [[org.clojure/clojure "1.11.1"]
[enlive "1.1.6"]
[compliment "0.3.14"]
[morse "0.4.3"]]
and I'm using them
(ns clojure-noob.test
(:require [net.cgrand.enlive-html :as html])
(:require [morse.api :as telegram])
)
but I receive an exception when I try to use the morse api
Execution error (FileNotFoundException) at clojure-noob.test/eval2760$loading (test.clj:1).
Could not locate morse/api__init.class, morse/api.clj or morse/api.cljc on classpath.
I think it's something really stupid cause I already have external libraries in my code that I use and they are working as expected
PS ah it turns out I need to restart the repl so I solved it 😄 But will leave the message in case anyone have a similar problem(ns clojure-noob.test
(:require
[net.cgrand.enlive-html :as html]
[morse.api :as telegram]))
@U11EL3P9U thank you, actually a good idea came into my mind - to try ask for a simple code review 😄 If you have time to spot some stupid things I made, I'll be really happy to address them and improve myself
Hi guys I just finished my first really small project with clojure. Since learning from your mistakes is the best way of doing it, could you make me a kind of code review?
(ns clojure-noob.test
(:require [net.cgrand.enlive-html :as html]
[morse.api :as telegram])
)
(def date (java.time.LocalDateTime/now))
(def date-map {:day (.getDayOfMon9th date) :month (.getMonthValue date) :year (.getYear date)})
(def url (str " " (:year date-map) "-" (:month date-map)))
(def website-content (html/html-resource (java.net.URL. url)))
(defn get-current-feast
[]
(->> (html/select website-content [:table :td])
(rest)
(map html/text)
(remove clojure.string/blank?)
(partition 3)
(map #(let [[e1, e2, e3] %]
{:day e1 :day-of-week e2 :content e3}))
(filter #(= (:day %) (str (:day date-map))))
(first))
)
(def current-feast (:content (get-current-feast)))
(println current-feast)
(telegram/send-text "my-token" "my-chat-id" current-feast)
Also is there a way I can make this code automatically executed every day at same time?That date
won't be "now" at every point in time. It'll always be the time when the app started up.
@U03SN3M2W0Y: When I wrote a scheduled job, some years back, I used Immutant (http://immutant.org/documentation/current/apidoc/guide-scheduling.html) to do the scheduling - mostly because it was the cleanest way of setting it up. I believe the alternative, that I didn't go for back then, was Overtone (https://github.com/overtone/overtone).
1. FYI, there is also a channel dedicated to code reviews: #code-reviews
2. One popular library to schedule repeating time-based tasks is the Java library: http://www.quartz-scheduler.org/
3. There are several Clojure bindings to (2) on github; for example, this one: https://github.com/factorhouse/cronut
4. Using any of these scheduling libraries assumes that your JVM process will keep running, so you will need to make sure if it crashes or you restart the computer, etc. that the process starts up again. If this is something that runs infrequently, you may consider instead to just write a -main
function (or convert this to a #babashka script) and run it via the operating system scheduler (eg. on linux or macos this would be cron
- https://linuxhint.com/cron_jobs_complete_beginners_tutorial/)
small note: you should require clojure.string
if you're using it. You can't always expect that it"s already loaded
most linters will warn you about missing requires
@U04290RJV0F ...hmm, I believe overtone is for music creation?
@U4VDXB2TU: Correct, and since music has to get timing right they made https://github.com/overtone/at-at.
@U04290RJV0F Ah that makes sense now. Thanks for the pointer.