beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Tim Robinson 2021-02-13T07:52:40.084600Z

encryption of the data across the network is normally handled by HTTPS or similar. for encryption of stored data you would normally use disk-level encryption (like windows bitlocker) which would be configured in the hosting center. you can't easily protect the data from a system administrator or DBA who knows that they are doing - you could encrypt the contents of individual fields or blobs yourself but then you'd need to store the encryption key somewhere, and the administrator would be able to find it (plus, as hiredman says, it makes it really inconvenient to use). If you want secure encryption of the data, I'd recommend putting the database engine on your own VM using disk encryption, to which only you know they password, then protecting access to the database so you know who's accessing it. Whatever you decide to do, the performance overhead of enccryption is unlikely to be significant

aratare 2021-02-13T11:46:36.088300Z

Hi there. I'm not sure if this question belongs here but I can't find another proper place for it. I'm working on a CLI Clojure app which has a hot-reload feature for certain files it's working with. I'm using https://github.com/wkf/hawk and it seems that every time I change a file there are two events fired instead of one. Looking around on StackOverflow it seems that Java's WatchService is fired twice when the content is changed and when the modification timestamp is changed. Has anyone encountered anything like this in their work? Doing double work is not really a biggie but def something I'd like to avoid. Thanks in advance.

aratare 2021-02-13T11:54:53.088700Z

It seems that only Windows is throwing double events and that's by design?

aratare 2021-02-13T11:55:14.088900Z

Anyway found a Java library to handle this for me.

Claudio Ferreira 2021-02-13T13:22:12.089200Z

Understand deeply OOP is a pre-requisite to understand and code proficiently in funcional paradigm? A beginner that is gonna work with functional languages HAS to learn deeply OOP?

Claudio Ferreira 2021-02-14T10:57:04.120200Z

Thanks all

2021-02-13T14:39:10.089300Z

I do not believe someone must deeply learn OOP as a prerequisite to learn Clojure.

2021-02-13T14:39:59.089500Z

It is useful to know a tiny bit about Java APIs, for times when you want to use a Java library, but that is nothing like "deeply learning OOP"

2021-02-13T15:02:00.089700Z

I'd argue java isn't even really oop anyway, or at least the java / c# code bases I've seen aren't. Its mostly just imperative code wrapped in classes.

grazfather 2021-02-13T16:04:04.090200Z

easy/dumb question: How can I break out of an infinite loop in the repl?

Claudio Ferreira 2021-02-14T11:07:22.120400Z

Just click that red button when u are evaluating: Did i answered your question?

tws 2021-02-14T13:23:00.125300Z

with Emacs & Cider: C-c C-b

Tim Robinson 2021-02-13T16:21:02.090900Z

hmm i had that problem just yesterday and had to kill the java process

dpsutton 2021-02-13T16:21:34.091500Z

Some repls offer a way to attempt this. What’s your repl setup?

Tim Robinson 2021-02-13T16:23:47.091600Z

I've read that those with no OOP background can find it easier to pick up functional programming, but I can't speak from personal experience. as Andy says though, familiarity with Java would be a benefit for clojure

2021-02-13T16:30:40.094300Z

Some REPLs you can type Ctrl-C and it will kill the whole JVM process. There is a stop() JVM API method that can be used to kill a thread, but it is deprecated because in the general case it can lead to a state of your JVM where locks are held and never released on objects, and leave them in an intermediate bad state. ( https://www.baeldung.com/java-thread-stop for some details and alternatives to using the stop() method, but they require that your loops that might go into an infinite loop to be modified).

2021-02-13T16:41:56.095400Z

in nrepl, control+c kills the current thread's computation, but doesn't kill the process

2021-02-13T16:47:48.096100Z

Using the stop() method probably? i.e. with its warnings about possible bad state being left behind?

2021-02-13T16:48:07.096600Z

I wonder

2021-02-13T16:48:42.097500Z

Those warnings are less commonly important the way Clojure code is usually written, I believe, but in general if you are calling arbitrary Java libraries in the thread being stopped, it could be wonky.

2021-02-13T16:48:43.097700Z

maybe the fact that they know what state is there (the state made by a REPL thread) means they can use it safely?

2021-02-13T16:48:49.098Z

right

2021-02-13T16:49:11.098600Z

the REPL will be in a namespace, killing that thread doesn't change scope of anything in that namespace

2021-02-13T16:49:43.099300Z

the only gotcha would be if something in your looping / stuck code left an object in a bad state, but you'd be unlikely to see that happen with clojure apis themselves

2021-02-13T16:50:01.099800Z

I guess? I'm realizing that's a lot of speculation and I should just read their code.

2021-02-13T16:50:26.100300Z

Yeah, I can't see using stop on a thread in a JVM running Clojure causing corruption of any of your defined functions, nor immutable collections. It is mainly the mutable stuff that you might be manipulating via Java libraries that would be most at risk.

2021-02-13T16:51:37.100800Z

the one gotcha I'm considering is if you left your IO in a bad state, with nrepl you'd be leaving that open if you don't exit the client...

Faris 2021-02-13T16:51:40.101Z

I’m playing around with Clojure by doing deaf aunty, basically it gets input from the user and returns a response depending on if the string is fully capitalised or not. To leave the conversation with “aunty” you need to say “BYE” 3 times. My code is as below

(ns deaf-aunty.core)
(require '[clojure.string :as str])


(defn is-all-capitalized? [string]
  (= string (str/upper-case string)))

(defn talk-to-aunty [string]
  (if (is-all-capitalized? string) " NO, NOT SINCE 1938!" "HUH?! SPEAK UP, SONNY!"))

(def consecutive-byes (atom 0))

(defn deaf-aunty-run []
  (case (read-line)
    "BYE"   (if (= @consecutive-byes 3)
              (println "Okay BYE!")
              (do
                (println "What!? You want to leave????")
                (reset! consecutive-byes (+ @consecutive-byes 1))
                (recur)))  
    (do
    (reset! consecutive-byes 0)  
    (println (talk-to-aunty read-line))  (recur)
    )
    )
  )

(deaf-aunty-run)
So my question is with this part
"BYE"   (if (= @consecutive-byes 3)
              (println "Okay BYE!")
              (do
                (println "What!? You want to leave????")
                (reset! consecutive-byes (+ @consecutive-byes 1))
                (recur)))  
The Rubyist in me is itching to extract that out into a function, but not sure how to run recur in the extracted function so that it reruns deaf-aunty-run. Feel free to comment/criticise other parts as well!

2021-02-13T16:52:07.101100Z

If that killed thread were manipulating a transient collection, it might be left in a bad intermediate state, but most likely the fact that the thread was killed means probably no other thread has a reference to the transient, anyway.

2021-02-13T16:53:55.101300Z

right - transients have a big "only use from one thread" warning on them :biohazard_sign:

2021-02-13T16:55:33.101500Z

you might want to cross post this to #code-reviews for starters, regarding readability, it would help a lot if you followed community conventions (no trailing ) on their own line, always indent children further than parent forms)

Faris 2021-02-13T16:56:22.101700Z

Okay! I actually didn’t know that channel existed, thanks!

2021-02-13T16:56:45.101900Z

the normal way would be for the function you run to take a parameter (defn foo [x] ... (recur (f x)) ...)

2021-02-13T16:57:55.102100Z

then the same parameter can be passed to a helper function. also, using an atom means that your code is impossible to use with threads

2021-02-13T16:58:14.102300Z

If you do use an atom, it is idiomatic to use (swap! consecutive-byes inc) instead of the call to reset! you show in your code.

2021-02-13T16:58:33.102500Z

But noisesmith's comments are spot on for how to avoid the use of an atom altogether.

2021-02-13T16:59:45.102700Z

there's a proof somewhere I've misplaced that the usage of a mutable value can always be replaced with a parameter taken by and returned from each function touching it (though this requires some amount of code restructuring to pull off in the general case, here it's trivial)

2021-02-13T17:01:46.102900Z

I have heard people who have done years of Java and object-oriented programming say that they felt when learning Clojure that it took time for them to "unlearn" some habits they had from object-oriented languages, and learn more functional/immutable-data-structure styles of doing things.

2021-02-13T17:03:17.103100Z

(Not really "unlearn" -- just learn different/new patterns and habits.)

Faris 2021-02-13T17:06:51.103300Z

I see, okay lemme try and rewrite it, thanks for the tips!

grazfather 2021-02-13T19:25:03.104200Z

Does anyone here know vega[lite]? I am trying to chart some data using oz, and I don’t know how to get it to recognize timestamps as quantifiable values

jumar 2021-02-13T19:26:29.104800Z

#data-science may be a good place to ask

grazfather 2021-02-13T20:34:25.105100Z

thank you

grazfather 2021-02-13T20:43:12.105300Z

lein repl

grazfather 2021-02-13T20:43:38.105500Z

Yep, that’s annoying. I’d like to be able to gracefully shutdown via signal or ctrl c

phronmophobic 2021-02-13T22:06:04.107Z

what's the recommended way to run a zero arity function with clj? clj -X my.ns/my-fn will give Wrong number of args (1) passed to: my.ns/my-fn

seancorfield 2021-02-13T22:15:16.107500Z

-X only runs functions with a single argument, which must be a hash map.

seancorfield 2021-02-13T22:16:02.108500Z

You could run it with -e instead but you'll need to require/resolve it -e "((requiring-resolve,'my.ns/my-fn))"

phronmophobic 2021-02-13T22:17:44.110300Z

I have several zero arity functions that would be nice to be able to invoke from the command line and I don't necessarily want to change them to just to run with -X. I can always make something to put in my deps.edn, but I was just wondering if there was already a recommended approach

dpsutton 2021-02-13T22:21:24.110700Z

you could make a single arity function which accepts information about which zero arity fn to call?

1👍
dpsutton 2021-02-13T22:22:08.111Z

requires setting up a single function rather than changing all of your zero arity versions

phronmophobic 2021-02-13T22:26:13.113Z

doesn't sound too hard. I basically just want something like -X with the same parsing rules, but instead of producing a single map to pass to a 1 arity exec function, it produces a vector to produces to apply to an exec function. Just wanted to double check that this functionality didn't already exist.