clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
2020-10-07T03:16:56.067400Z

sorry if this me failing to google before asking... anyone know if java-time can be used in closh?

/home/arthur» (cemerick.pomegranate/add-dependencies
         #_=>          :coordinates '[[clojure.java-time "0.3.2"]]
         #_=>          :repositories (merge cemerick.pomegranate.aether/maven-central
         #_=&gt;                               {"clojars" "<https://clojars.org/repo>"}))
{[clojure.java-time "0.3.2"] #{[clj-tuple "0.2.2"]}, [clj-tuple "0.2.2"] nil}
/home/arthur» (require '[java-time :as t])
Syntax error (IllegalAccessError) compiling at (java_time/temporal.clj:324:1).
tried to access field clojure.lang.APersistentVector._hash from class clojure.lang.PersistentUnrolledVector$Card1

seancorfield 2020-10-07T04:16:42.068800Z

@arthur That line in java-time.temporal in 0.3.2 is a comment so I'm wondering if closh itself already has an earlier version?

seancorfield 2020-10-07T04:19:15.070400Z

Hmm, doesn't look like it. But that does sort of feel like a compiled code/version conflict sort of issue. I've played with closh quite a bit -- but never try to add new dependencies while running -- and I did find it a bit crashy with some of the things I was doing 😐

2020-10-07T05:06:12.082800Z

I've been thinking about package dependencies and the issues happening in npm and Python world, where people name squat but also try to take advantage of typos and such to introduce vulnerabilities. Clojure recommends that you use org/package and uses namespaces, so name squatting isn't as easy, since you can't take over someone else's org, but you could still put packages of the same name in similar sounding orgs or different orgs and hope to introduce vulnerabilities by way of someone accidentally using the wrong package. Maven Central I learned does a manual verification for that purpose, where they validate that you own the domain of.your org for example. Now, in GitHub, you can verify your domain for a github organization as well, and that's actually automated. So I've been thinking, what if Clojars did something similar? It could ask to verify that you either own your domain, or your identity on some supported identity website like github. And the validation could be automated as well. For domain, do what github does, ask for a DNS TXT header secret to be there, assume your org in Clojars is the reverse domain name. Similarly, for github, could ask to create a gist that contains a secret, or a repo with a file that has the secret in it. And assume your org is your github username or org name. I don't feel this would add too much friction, and maybe if we want to be backwards compatible, Clojars could offer two repos, one verified one with such verification and one for free for all. Serious libs can do the extra work of being verified and people who need that level of trust can depend only on that repo. Thoughts? (Might post this to the reddit as well)

seancorfield 2020-10-07T05:14:53.085Z

@didibus This is probably better suited to the #clojars channel -- there used to be a two-tier system with signed JARs and unsigned JARs but it was abandoned because so few people bothered to sign JARs 😐

2020-10-07T07:07:46.090500Z

I can see Jar signing being more annoying to do. Also I don't think that validates identity, seems to be more for man in the middle. Like someone returning me a different Jar when I try to download the one from Clojars.

alexmiller 2020-10-07T12:41:46.114700Z

Signing doesn’t tell you anything about whether you trust the identity of the signer

seancorfield 2020-10-07T05:23:03.088900Z

We have so many groups on Clojars that are not either reverse domains or GitHub usernames that I don't think it would work... And Alex's blog post about qualified lib names suggested <provider>-<username>, e.g., github-seancorfield, which is not a pattern anyone uses right now but something like that would be required to avoid squatting on people's usernames on different services to sow confusion -- is seancorfield/some-lib from seancorfield on <http://github.com|github.com> (me!) or seancorfield on some other servicer provider? (potentially not me, but mostly I'm the only seancorfield everywhere as far as I know)

2020-10-07T07:21:53.090700Z

Hum, ya that would be the problem, and maybe the reason for having two repos? I wonder if you verify your domain or github on a Clojars account. Even if the Clojars account is different in name. And if by doing so, that somehow also prevented on Clojars anyone else from creating a user of the domain name or github user you verified? Maybe that be sufficient

2020-10-07T07:23:01.090900Z

Someone couldn't then come and have a org.corfield/next.jdbc since seancorfield verified that it owned the domain.

2020-10-07T07:24:18.091100Z

And then the next step would be preventing accounts that don't have a domain or identity verified with their Clojars user from being allowed to publish to it (maybe grandfather existing).

2020-10-07T07:31:16.091300Z

Hum, ok well, rereading how groups work in Clojars. I guess it would mean that groups wouldn't be created automatically when pushing. You'd need to create the group, attach an indentity or domain to it that Clojars would validate, and then it would allow users to push to the group.

2020-10-07T07:40:26.091800Z

Okay, one more idea 😝, kind of brainstorming here. Maybe all Clojars does is, if the groupId pushed is a reverse domain name, or of the form github-... or gitlab-... or bitbucket-... then it will validate it by either checking for a header on the DNS of the domain that has as value the Clojars groupId when a reverse domain, or by checking for a special repo with a readme that contains a file with the groupId in from the repo managers if it was a github-... style groupId

2020-10-07T07:42:50.092500Z

So at least, going forward, as a user, you know if you depend on a lib with a reverse domain name, that it was validated to be from the owner of the domain, or if a lib with a github-user that it was validated to be coming for sure from that user on github

2020-10-07T07:43:33.092700Z

And people who want to publish without wanting to validate can use groupId that are not of those format

seancorfield 2020-10-07T16:43:11.124700Z

Like I said, take it up in #clojars and see how receptive the maintainers are to these suggestions.

seancorfield 2020-10-07T05:26:34.090Z

Also, there's no obvious connection between the domain I own <http://corfield.org|corfield.org> and the username I have on almost every service seancorfield so I'm not sure how domain verification would even work in that case?

2020-10-07T07:07:46.090500Z

I can see Jar signing being more annoying to do. Also I don't think that validates identity, seems to be more for man in the middle. Like someone returning me a different Jar when I try to download the one from Clojars.

2020-10-07T07:21:53.090700Z

Hum, ya that would be the problem, and maybe the reason for having two repos? I wonder if you verify your domain or github on a Clojars account. Even if the Clojars account is different in name. And if by doing so, that somehow also prevented on Clojars anyone else from creating a user of the domain name or github user you verified? Maybe that be sufficient

2020-10-07T07:23:01.090900Z

Someone couldn't then come and have a org.corfield/next.jdbc since seancorfield verified that it owned the domain.

2020-10-07T07:24:18.091100Z

And then the next step would be preventing accounts that don't have a domain or identity verified with their Clojars user from being allowed to publish to it (maybe grandfather existing).

2020-10-07T07:31:16.091300Z

Hum, ok well, rereading how groups work in Clojars. I guess it would mean that groups wouldn't be created automatically when pushing. You'd need to create the group, attach an indentity or domain to it that Clojars would validate, and then it would allow users to push to the group.

Karol Wójcik 2020-10-07T07:38:11.091700Z

Is it possible to add default implementation for protocol method?

2020-10-07T07:40:26.091800Z

Okay, one more idea 😝, kind of brainstorming here. Maybe all Clojars does is, if the groupId pushed is a reverse domain name, or of the form github-... or gitlab-... or bitbucket-... then it will validate it by either checking for a header on the DNS of the domain that has as value the Clojars groupId when a reverse domain, or by checking for a special repo with a readme that contains a file with the groupId in from the repo managers if it was a github-... style groupId

2020-10-07T07:41:14.092Z

I think you can by extending it for type Object

2020-10-07T07:42:50.092500Z

So at least, going forward, as a user, you know if you depend on a lib with a reverse domain name, that it was validated to be from the owner of the domain, or if a lib with a github-user that it was validated to be coming for sure from that user on github

2020-10-07T07:43:33.092700Z

And people who want to publish without wanting to validate can use groupId that are not of those format

Karol Wójcik 2020-10-07T07:47:30.092900Z

That's seems kinda nasty.

Karol Wójcik 2020-10-07T07:48:02.093100Z

Is it possible to extend the type in record?

Karol Wójcik 2020-10-07T07:48:29.093300Z

That would be better since I would not have to mess with Object.

2020-10-07T07:54:06.094Z

Hum, I mean it's not any nastier than if there was a default. Though I guess Object would not work for nil, where a default would since protocols can extend nil.

2020-10-07T07:54:58.094200Z

You want it implemented for all record types?

2020-10-07T07:55:55.094400Z

I'm sure there's some similar parent that all record belongs too that you could use?

2020-10-07T07:57:26.094600Z

Wait, could it be you just want to use the same functions as the implementation for multiple record types?

2020-10-07T07:59:19.094800Z

If so you can use extend it takes a map from method name (as a keyword) to the function that implements it. So you can extend all your record and give them the same map

Karol Wójcik 2020-10-07T08:03:31.097100Z

@didibus I would like to have some of the records to implement IEventSourceable interface and I don’t want to specify the same function implementation over and over again.

2020-10-07T08:08:27.097300Z

Ya you should be able to do that with extend. You'd still need to list out each record you want it for, but at least you won't have to type the implementation of the methods over and over

Karol Wójcik 2020-10-07T08:21:14.097800Z

Thank you @didibus. This is great! Do you know whether it's possible to get record function by keyword?

kwrooijen 2020-10-07T08:26:29.098Z

Seems like it. I had some trouble getting it to work. Also I'm not sure why they need to open a port (I guess for remote sessions). I'm going to build a project using membrane for now and see how well it works

borkdude 2020-10-07T08:31:32.098200Z

I asked in #lambdaisland. It's far from ready, it's more like a hobby status and no release on the horizon

borkdude 2020-10-07T08:31:42.098400Z

trikl

borkdude 2020-10-07T08:32:01.098600Z

probably forking lanterna and updating it might be a worthwhile effort

borkdude 2020-10-07T08:32:07.098800Z

(clojure-lanterna)

kwrooijen 2020-10-07T08:35:43.099Z

Yeah that would be beneficial for sure. But contributing back might be a problem https://github.com/MultiMUD/clojure-lanterna/issues/24

kwrooijen 2020-10-07T08:36:47.099400Z

We could have a graalvm compatible fork possibly. Then provide clojure-lanterna with bb, which I think would be a nice balance between low / high level functionality

kwrooijen 2020-10-07T08:37:53.099600Z

Possibly fork to the babashka github org?

borkdude 2020-10-07T08:38:51.099800Z

Yes

borkdude 2020-10-07T08:40:41.100Z

forked here: https://github.com/babashka/clojure-lanterna and invited you

2020-10-07T08:50:24.100400Z

Not sure what you mean?

Setzer22 2020-10-07T09:03:23.101100Z

hi! any way to mix expound's human-readable spec errors with orchestra instrumentation?

Setzer22 2020-10-07T09:06:18.102Z

I tried setting s/*explain-out* to expound/printer , but when there's a spec error I'm still getting the normal explain output

bbrinck 2020-10-13T14:47:22.405700Z

Hm, this should work. If you post your code in #expound I may be able to spot the issue

kwrooijen 2020-10-07T09:15:18.102100Z

Thanks 👍

kwrooijen 2020-10-07T09:24:53.102400Z

I'll update my bb branch to use this version, then create a WIP PR

grounded_sage 2020-10-07T10:43:43.106Z

Trying to grok when macroexpansion occurs in a dependency. We have a dynamic var that we wish to alter downstream. So that we can alter the behaviour of the macro dynamically.

alexmiller 2020-10-08T12:41:16.188500Z

I think it depends on whether you alter the dynamic var before or after the require? Although I’m not entirely sure what happens in the aot case.

Mikko Harju 2020-10-07T10:51:34.107500Z

What would be the best way to declare for a local dependency in deps.edn (`{:local/root "checkouts/project"`}} that it uses a certain alias that has extra source paths? Or is it customary to just add that source path directly to deps.edn directly?

Mikko Harju 2020-10-07T10:52:28.107800Z

I'd like to have the possibility to omit one source directory, that needs to be specified by the dependency user to include/not include it

Mikko Harju 2020-10-07T10:53:33.108200Z

The reason is that if you choose to have that directory, you must have add additional dependencies that not every project using the dependency needs at all

kwrooijen 2020-10-07T12:11:40.108600Z

Having trouble compiling a simple example with 3.0.3. I keep getting undefined reference to Java_java_util_prefs_FileSystemPreferences_chmod. Which might be related to this issue: https://github.com/mabe02/lanterna/issues/499

kwrooijen 2020-10-07T12:12:19.109Z

And possibly fixed in Graal recently https://github.com/oracle/graal/issues/2063

kwrooijen 2020-10-07T12:16:00.109400Z

oh, hm. compiling with java8 graalvm does work :thinking_face:

borkdude 2020-10-07T12:17:01.109600Z

@kevin.van.rooijen I also had this issue with 20.2.0 JDK 11 with the tetris repo, but it started working when I avoided the Swing stuff

borkdude 2020-10-07T12:17:24.109800Z

So avoid all awt references

borkdude 2020-10-07T12:17:46.110Z

See https://github.com/oracle/graal/issues/2898

kwrooijen 2020-10-07T12:19:04.110400Z

Ah I guess the DefaultTerminal class is automatically including swing stuff

kwrooijen 2020-10-07T12:19:16.110600Z

That's a pain

borkdude 2020-10-07T12:19:30.110800Z

Ah really, then maybe not use that class?

kwrooijen 2020-10-07T12:20:13.111Z

Yeah I'd have to look into it. Basically it does all the heavy lifting in terms of OS / terminal / capabilities

kwrooijen 2020-10-07T12:20:40.111200Z

It figures out what you need related to your platform

borkdude 2020-10-07T12:20:50.111400Z

OK, you can try to compile with 20.3.0-dev and see what happens

kwrooijen 2020-10-07T12:22:40.111800Z

Cool thanks, installing now

kwrooijen 2020-10-07T12:27:19.112Z

Sadly that crashes with something new.

Fatal error:com.oracle.svm.core.util.VMError$HostedError: Option name "TruffleMultiThreaded" has multiple definitions: com.oracle.svm.truffle.api.SubstrateTruffleOptions.TruffleMultiThreaded and com.oracle.svm.truffle.api.SubstateTruffleOptions.TruffleMultiThreaded
	at com.oracle.svm.core.util.VMError.shouldNotReachHere(VMError.java:68)
	at com.oracle.svm.hosted.option.HostedOptionParser.collectOptions(HostedOptionParser.java:89)
	at com.oracle.svm.hosted.option.HostedOptionParser.&lt;init&gt;(HostedOptionParser.java:62)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:238)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:509)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:115)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:541)
Error: Image build request failed with exit status 1
com.oracle.svm.driver.NativeImage$NativeImageError: Image build request failed with exit status 1
	at com.oracle.svm.driver.NativeImage.showError(NativeImage.java:1632)
	at com.oracle.svm.driver.NativeImage.build(NativeImage.java:1382)
	at com.oracle.svm.driver.NativeImage.performBuild(NativeImage.java:1343)
	at com.oracle.svm.driver.NativeImage.main(NativeImage.java:1302)
	at com.oracle.svm.driver.NativeImage$JDK9Plus.main(NativeImage.java:1814)

kwrooijen 2020-10-07T12:27:47.112200Z

Can't find much about this

borkdude 2020-10-07T12:29:11.112400Z

Are you using the reflector fix library?

borkdude 2020-10-07T12:29:20.112600Z

That only works for a specific version

borkdude 2020-10-07T12:29:56.112800Z

I'm not sure what you're compiling here

borkdude 2020-10-07T12:36:11.113100Z

are you compiling bb or the fork of the lib?

borkdude 2020-10-07T12:36:15.113300Z

or some other thing?

kwrooijen 2020-10-07T12:37:42.113500Z

Compiling my own project, and yeah that was the problem. Still no results though. I'm just trying to get a minimal build going

kwrooijen 2020-10-07T12:37:51.113700Z

I can host the code

borkdude 2020-10-07T12:38:07.113900Z

OK. I'll be out for an hour and then I can take a look

alexmiller 2020-10-07T12:41:46.114700Z

Signing doesn’t tell you anything about whether you trust the identity of the signer

alexmiller 2020-10-07T12:45:07.115500Z

I think you are outside the bounds of what deps.edn supports

alexmiller 2020-10-07T12:46:42.116700Z

It happens whenever code using the macro is compiled. That could be at aot compile time, or load time.

Mikko Harju 2020-10-07T13:13:04.117100Z

Yeah, I thought so too – and it was trivial to just add the source path to :paths declaration in the project using the dependency (it's included as a submodule in checkouts)

Mikko Harju 2020-10-07T13:13:30.117300Z

I'm not sure if this is idiomatic, but works for our use case just fine!

kwrooijen 2020-10-07T13:24:21.117500Z

https://github.com/kwrooijen/test-lanterna If getting defaultterminal to work then maybe it is a good idea to avoid it and all swing stuff (For now)

2020-10-07T13:52:24.118100Z

http://clojure.com seems to be down

Day Bobby 2020-10-07T13:53:16.118500Z

isn't it http://clojure.org, or does it have another domain i dont know

2020-10-07T13:53:58.119300Z

ohhh you're right. I think the dot com used to redirect somewhere at least? I clicked a dead link somewhere

1👍
alexmiller 2020-10-07T13:57:08.119800Z

.com has not existed for a long time

abdullahibra 2020-10-07T16:18:19.120300Z

Hi everyone,

abdullahibra 2020-10-07T16:18:41.120800Z

is there a way to parse timestamp with whatever format ?

abdullahibra 2020-10-11T06:31:17.328300Z

but you still need the format as input, i have wrote another function which check the predicated format.

p-himik 2020-10-11T06:43:55.328500Z

No you don't - there are two arities, the second one accepts only a single string.

dharrigan 2020-10-07T16:21:25.121Z

Sure, what do you have in mind?

2020-10-07T16:21:34.121100Z

Clojure folks tend to rely on existing Java libraries for this, I believe.

abdullahibra 2020-10-07T16:22:24.121300Z

what java libs you may suggest that helps here?

abdullahibra 2020-10-07T16:22:31.121600Z

what do you mean?

dharrigan 2020-10-07T16:23:58.121900Z

Java, since version 8, has very good build-in time support, under the java.time package

2020-10-07T16:25:38.122100Z

Several different classes for different purposes, many with Java methods whose name contains "parse"

abdullahibra 2020-10-07T16:26:11.122300Z

i think the most worth here is java.text.SimpleDateFormat

abdullahibra 2020-10-07T16:26:18.122500Z

but that takes format

abdullahibra 2020-10-07T16:26:37.122700Z

maybe i need to write another function to determine the date format at first

abdullahibra 2020-10-07T16:26:41.122900Z

then parse it

abdullahibra 2020-10-07T16:27:06.123200Z

anyway thanks guys

2020-10-07T16:27:29.123400Z

There are so many date/time formats in text, that saying "whatever" format is unlikely to produce a list that ends if you start writing it this year.

2020-10-07T16:27:53.123600Z

Any given application you have hopefully you can limit them to a small set of acceptable formats.

2020-10-07T16:28:11.123800Z

If your goal is "recognize dates/times in any way a human might recognize", then you are in AI/machine-learning territory.

abdullahibra 2020-10-07T16:28:52.124Z

yeah i got that, maybe you can use CRF model to do that, stanford NLP has that feature, but i'm not seeking dates extraction from text

abdullahibra 2020-10-07T16:29:49.124300Z

i think i'll define some regexp for specific number of timestamp format, then search which regexp is right for it

abdullahibra 2020-10-07T16:30:01.124500Z

after determine the format i'll parse it

seancorfield 2020-10-07T16:43:11.124700Z

Like I said, take it up in #clojars and see how receptive the maintainers are to these suggestions.

Daniel Stephens 2020-10-07T16:43:47.124900Z

Is the aim to parse any individual timestamp or to recognise a format given many date strings? Plenty of dates are ambiguous if you don't know the format, 01-01-2020T... could be day first or month first so very few programs would do anything beyond telling you which format to provide timestamps in

abdullahibra 2020-10-07T16:45:20.125100Z

the ultimate goal is parsing timestamps, so the problem now as you addressed "the format", so i'll limit that to a set of formats then i'll need method to determine the format before the parse step

Ray Grant 2020-10-07T16:56:16.126100Z

I'm wondering if there is a commonly adopted clojure framework used for building backend routes and services for a web app. Or is there a list that could help me know what one to use?

abdullahibra 2020-10-07T16:56:42.126300Z

reitit

abdullahibra 2020-10-07T16:57:00.126500Z

https://github.com/metosin/reitit

Ray Grant 2020-10-07T17:02:18.126800Z

Thanks!

1👍
isak 2020-10-07T18:30:32.127400Z

http://pedestal.io/

p-himik 2020-10-07T19:00:57.127900Z

That's exactly what clj-time does - it tries to guess the format based on its own list of formats: https://github.com/clj-time/clj-time/blob/master/src/clj_time/format.clj#L156-L165

borkdude 2020-10-07T19:32:06.128200Z

Sorry, had something else on my mind.

borkdude 2020-10-07T19:35:53.130Z

So you are trying to use lanterna 3 directly. Why not try to update the clojure-lanterna lib and e.g. build the tetris one?

borkdude 2020-10-07T19:39:16.131200Z

It seems clojure-lanterna isn't using that class directly: https://github.com/MultiMUD/clojure-lanterna/blob/master/src/lanterna/terminal.clj#L1-L10 so maybe this is why compiling does work with that code

kwrooijen 2020-10-07T19:45:47.133Z

While trying to port clojure-laterna I noticed a lot of things are either renamed / deprecated. e.g. the Facade no longer exists. It felt a bit like a rabbit hole so I decided to first get a minimal snippet working

kwrooijen 2020-10-07T19:46:56.134Z

My lack of Java knowledge is really testing me right now, hopefully someone can point out the obvious for me. I instantiated a new com.googlecode.lanterna.gui2.MultiWindowTextGUI Object (https://github.com/mabe02/lanterna/blob/lanterna-3.0.3/src/main/java/com/googlecode/lanterna/gui2/MultiWindowTextGUI.java) using (new MultiWindowTextGUI screen wm x). I then want to tall the getFocusedInteractable method. When I check the source file https://github.com/mabe02/lanterna/blob/lanterna-3.0.3/src/main/java/com/googlecode/lanterna/gui2/MultiWindowTextGUI.java#L364 and also the API documentation https://mabe02.github.io/lanterna/apidocs/3.0/com/googlecode/lanterna/gui2/MultiWindowTextGUI.html#getFocusedInteractable-- then it looks like there should be a getFocusedInteractable method. However when I try to call it with (.getFocusedInteractable gui) I get the following error

Exception in thread "async-dispatch-1" java.lang.IllegalArgumentException: No matching field found: getFocusedInteractable​ for class com.googlecode.lanterna.gui2.MultiWindowTextGUI
        at clojure.lang.Reflector.getInstanceField(Reflector.java:397)
        at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:440)
        at trader.core$_main$fn__10988$state_machine__8040__auto____11009$fn__11011$fn__11013.invoke(core.clj:158)
        at trader.core$_main$fn__10988$state_machine__8040__auto____11009$fn__11011.invoke(core.clj:155)
        at trader.core$_main$fn__10988$state_machine__8040__auto____11009.invoke(core.clj:155)
        at clojure.core.async.impl.ioc_macros$run_state_machine.invokeStatic(ioc_macros.clj:978)
        at clojure.core.async.impl.ioc_macros$run_state_machine.invoke(ioc_macros.clj:977)
        at clojure.core.async.impl.ioc_macros$run_state_machine_wrapped.invokeStatic(ioc_macros.clj:982)
        at clojure.core.async.impl.ioc_macros$run_state_machine_wrapped.invoke(ioc_macros.clj:980)
        at trader.core$_main$fn__10988.invoke(core.clj:155)
        at clojure.lang.AFn.run(AFn.java:22)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at clojure.core.async.impl.concurrent$counted_thread_factory$reify__1811$fn__1812.invoke(concurrent.clj:29)
        at clojure.lang.AFn.run(AFn.java:22)
        at java.lang.Thread.run(Thread.java:748)
I'm using the latest version, so I assume this method should be avaiable [com.googlecode.lanterna/lanterna "3.0.3"] If someone could point out what I'm doing wrong I'd appreciate it

phronmophobic 2020-10-07T20:04:01.134400Z

the only things I can think to try are: 1. trying the call in repl on a non async thread. 2. making the reflection call yourself to see what methods exist. maybe that can point to false assumption

borkdude 2020-10-07T20:04:28.134600Z

:thumbsup:

phronmophobic 2020-10-07T20:04:41.134800Z

based on your description, it seems like it should work

borkdude 2020-10-07T20:04:46.135Z

Is it possible to not use the DefaultTerminal but something like a TextTerminal instead?

p-himik 2020-10-07T20:06:57.135200Z

Indeed, it worked for me in REPL just fine:

(import com.googlecode.lanterna.terminal.DefaultTerminalFactory)
=&gt; com.googlecode.lanterna.terminal.DefaultTerminalFactory
(def tf (DefaultTerminalFactory.))
=&gt; #'user/tf
(def term (.createTerminal tf))
=&gt; #'user/term
(import com.googlecode.lanterna.gui2.MultiWindowTextGUI)
=&gt; com.googlecode.lanterna.gui2.MultiWindowTextGUI
(import com.googlecode.lanterna.screen.TerminalScreen)
=&gt; com.googlecode.lanterna.screen.TerminalScreen
(def screen (TerminalScreen. term))
=&gt; #'user/screen
(def gui (MultiWindowTextGUI. screen))
=&gt; #'user/gui
(.startScreen screen)
=&gt; nil
(.getFocusedInteractable gui)
=&gt; nil

kwrooijen 2020-10-07T20:07:46.135400Z

What does it mean to "make the reflection call yourself" ?

p-himik 2020-10-07T20:09:40.135600Z

Something like this, only for MultiWindowTextGUI.

phronmophobic 2020-10-07T20:11:32.135800Z

make the reflection call yourself

(require 'clojure.reflect)
(clojure.reflect/reflect com.googlecode.lanterna.gui2.MultiWindowTextGUI)

1👍
phronmophobic 2020-10-07T20:12:03.136Z

just to list what methods come up. it probably won't say anything too surprising, but it will at least let you know that the method does or doesn't exist

p-himik 2020-10-07T20:13:12.136300Z

I would also check the class path to make sure that 3.0.3 is indeed the version that gets loaded.

phronmophobic 2020-10-07T20:14:42.136500Z

one other thing that can happen if you're calling from weird threads is that thread's class loader isn't the right one. not sure if that applies here, but in your top level, you can do :

(def main-class-loader @clojure.lang.Compiler/LOADER)
then right before you make the getFocusedInteractable call, do
(.setContextClassLoader (Thread/currentThread) main-class-loader)

phronmophobic 2020-10-07T20:15:48.137100Z

I think clojure.core.aync handles a lot of those weird issues for you, but if nothing else is working, it's worth a shot

JAtkins 2020-10-07T20:15:58.137400Z

random shooting the breeze - I think as a community we under-utilize the fact that clojure code is data. Why spend so much time organizing code if code is data? Currently we view our (code/data) from only one perspective - file based. Maybe open multiple files. Jump around with stuff like `go-to-definition`.  But why do we constrain ourselves like that? Data science people have workflows designed around producing alternate views of the data. Maybe a tool that we are missing as programmers is a tool that looks at our code as data and re-formats it for our use based on the problem at hand? Does this even make sense? 😜

2020-10-09T02:55:42.247300Z

I'll argue something here, the issue is 2D visualization are too limited, so text can convey more complicated graphs

2020-10-09T02:58:05.247500Z

Something like: `(let [a (foo) b (bar a) c (baz a :with-option) d (biz b c)] (buz d))`

2020-10-09T02:59:19.247800Z

What visualization here would make this clearer?

JAtkins 2020-10-09T03:19:11.248900Z

It’s just a different angle. Also, I’m thinking here of code->alt code visualizations.

JAtkins 2020-10-09T03:19:45.249900Z

Reorganizing events, hiding ui stuff, joining attributes by a key, etc

JAtkins 2020-10-09T03:20:17.250900Z

If specs are widespread, maybe using that info about the code in interesting g ways

phronmophobic 2020-10-09T03:20:20.251100Z

not the best sketch, but I think this type of graphic could emphasize the dependencies

2020-10-09T03:24:39.251700Z

Maybe, but I don't know, personally I'd rather look at the let then such a graph, but I can't tell for sure. I used to program a bit in Max/MSP, which was just everything as nodes connected by lines visually, and I wouldn't say it was any easier to read and follow. I think its because most real life use case, there will be too many dependencies and then you just have to many lines going to too many places

phronmophobic 2020-10-09T03:25:56.251900Z

you don't have to pick just one

phronmophobic 2020-10-09T03:26:40.252100Z

you can multiple representations and work with the ones that are most convenient for the purpose you're trying to accomplish

2020-10-09T03:28:08.252300Z

Ya true, but a part of the question is if it is worth the effort to build such alternate visualizations to begin with. And so the question would be, how often would I switch away from the text representation? 50% of the time? 10%? 0.5%

2020-10-09T03:29:59.252500Z

And I feel for me, its say... ok when do I struggle to read code in a way that an alternate representation would make it obvious, and what would that even be?

phronmophobic 2020-10-09T03:32:54.252700Z

It's very difficult to tell how good a tool, method, or workflow is until you try it which means that's it's very difficult to predict ahead of time how effective it would be

phronmophobic 2020-10-09T03:33:39.252900Z

I think software development still has a long way to go before we start running out of improvements.

JAtkins 2020-10-09T03:37:46.253300Z

Yup

seancorfield 2020-10-09T04:28:55.253500Z

Anyone remember Together/J? It was a Java IDE that was also a UML drawing system and it could round-trip between code and UML diagrams for certain diagrams. You could modify the code and the diagrams would update or modify the diagrams and the code would update. I loved it, but there was definitely a limit to how far you could go in each direction.

2020-10-09T04:34:31.253700Z

Was it good because the UML view allows you to avoid typing all the Java boilerplate?

seancorfield 2020-10-09T04:39:51.253900Z

It was good because it allowed for multiple "views" of the code at different levels of abstraction. I hadn't thought about it for a while but this thread triggered by memory...

seancorfield 2020-10-09T04:42:34.254100Z

But they weren't really just "views" -- it wasn't just visualization of code -- it was different levels of abstraction that you could "edit" the program at.

2020-10-09T04:50:45.255100Z

Ya, that seems neat, especially in Java, like if I could just move class arounds, nest them, unnest them, etc. All through some visual view.

2020-10-09T04:57:38.255500Z

I guess I hadn't thought what the other views could allow in terms of editing the code. I was thinking just in terms of reading it

zilti 2020-10-09T11:51:25.259400Z

I think on the low level, plain-text code is the way to go. But I think it is interesting to have alternatives for the higher-level where you connect stuff. https://en.wikipedia.org/wiki/DRAKON was, at first glance, seemingly an interesting take on this

JAtkins 2020-10-09T17:02:23.277Z

That's really cool. I'll have to look into both of those.

Jose Varela 2020-10-09T17:05:30.277200Z

GToolkit deals with the concept mentioned by @seancorfield the idea is that as you browse your codebase you can query constructs like classes, methods, modules, etc and generate custom views of queries and individual componentes in the codebase Youn can then clickthrough these until you end up in the actual code for the class and/or method

phronmophobic 2020-10-07T20:17:01.137500Z

it makes sense, but there's a lot of inertia regarding text based source formats (editors, IDEs, version control, etc)

kwrooijen 2020-10-07T20:18:12.137700Z

Interesting, I was also calling this within a go-loop, maybe that's the issue

unbalanced 2020-10-07T20:18:43.137900Z

Totally. Check out the end of @jimmy’s talk on Meander for a really inspired vision on this topic: https://www.youtube.com/watch?v=9fhnJpCgtUw&amp;m=7

JAtkins 2020-10-07T20:19:58.138200Z

ive not thought it through fully, but I don't think those are by necessity deal breakers. Storing code in the files is sensible (though unison may be an interesting alternative look - http://unisonweb.org). Perhaps it would be more clear if I put out an example... e.g.

(defattr :a {:t1 value
             :t2 value
             ...}

(defattr :b {:t1 value
             :t2 value
             ...}

JAtkins 2020-10-07T20:20:45.138500Z

maybe you want to see only :t1 for each attr. could be done by creating a view of the code

JAtkins 2020-10-07T20:22:07.138700Z

@goomba oo, I've seen that before. Forgot that he talked about this though 🙂

kwrooijen 2020-10-07T20:22:59.138900Z

Ok, that seems to be the issue. So I can't call this method within a different thread?

phronmophobic 2020-10-07T20:24:22.139100Z

you just need to set the thread's context class loader to match the clojure compiler's class loader

kwrooijen 2020-10-07T20:24:59.139300Z

So within the go-loop call (.setContextClassLoader (Thread/currentThread) main-class-loader) ?

phronmophobic 2020-10-07T20:25:11.139500Z

right

phronmophobic 2020-10-07T20:25:28.139700Z

although, I thought clojure.core.async did that for you

phronmophobic 2020-10-07T20:25:40.139900Z

which thread are you starting the go-loop from?

kwrooijen 2020-10-07T20:25:48.140100Z

The main thread

kwrooijen 2020-10-07T20:26:08.140300Z

But this doesn't seem to resolve it. I'll try creating a new thread normally

p-himik 2020-10-07T20:27:41.140500Z

There have been many attempts to create something along those words. I believe some ideas originated from Engelbart and some things were even implemented in Xerox Alto. But it never had any serious traction. There are still undergoing attempts though, I know of http://www.andrewbragdon.com/codebubbles_site.asp and https://github.com/JJ-Atkinson/Fisher

JAtkins 2020-10-07T20:28:24.140800Z

oh, lol, that's my repo

JAtkins 2020-10-07T20:28:43.141Z

I'm actually thinking about this as a feature for Fisher

JAtkins 2020-10-07T20:29:06.141200Z

not quite the same as code bubbles

p-himik 2020-10-07T20:31:37.141400Z

Oh, oops. :D

p-himik 2020-10-07T20:32:15.141600Z

Yeah, I get that. I just mentioned that because the overall concept is the same - being able to focus on something in particular, no matter what the "lens" looks like.

JAtkins 2020-10-07T20:33:28.141800Z

true. I guess I've been thinking along these lines for a while 🙂

p-himik 2020-10-07T20:36:46.142Z

IntelliJ IDEA has some interesting features as well that are somewhat relevant. Namely, analyzing data flow: https://www.jetbrains.com/help/idea/analyzing-data-flow.html But all such focusing/lensing/analysis goes out of the window as soon as there's anything dynamic going on. Even a simple (keyword n) would mess things up.

JAtkins 2020-10-07T20:37:26.142200Z

that's really cool

kwrooijen 2020-10-07T20:37:32.142400Z

I am so lost, I had it working in the main thread, now this doesn't work anymore

(defn -main [&amp; _args]
  (let [terminal (.createTerminal (DefaultTerminalFactory.))
        screen (TerminalScreen. terminal)
        gui (MultiWindowTextGUI. screen)]
    (.startScreen screen)
    (.getFocusedInteractable​ gui)))

JAtkins 2020-10-07T20:38:28.142600Z

Reminds me of https://futureofcoding.org/essays/dctp#d-is-for-denotative

phronmophobic 2020-10-07T20:40:00.142900Z

how are you running it?

phronmophobic 2020-10-07T20:43:04.143100Z

can you add:

(prn "thread: " (Thread/currentThread) )

zilti 2020-10-07T20:43:14.143300Z

The problem is also that not everything in a Clojure sourcecode file is data. ;; comments are not. Empty lines for separation are not. Neither is formatting.

p-himik 2020-10-07T20:44:17.143500Z

@jatkin I guess. And you can go all the way to the pure lambda calculus. :) The issue is that any useful program written using lambda calculus would almost certainly be incomprehensible. So far it seems that practicality demands sacrifices that, in turn, beget other, indirect, sacrifices.

kwrooijen 2020-10-07T20:45:19.143700Z

well... I found the issue

JAtkins 2020-10-07T20:45:44.143900Z

@zilti 3 possibilities. make comments data (metadata even?), enforce a standard formatting rule, and re-implement the original use of custom formatting by creating custom views of the code ... though if you are breaking a formatting rule it's typically a boutique case and maybe not possible to create general rules for

JAtkins 2020-10-07T20:45:59.144100Z

@p-himik yup

kwrooijen 2020-10-07T20:46:14.144300Z

So I think there's some kind of special character in 1 of my example codes

kwrooijen 2020-10-07T20:46:30.144500Z

I have 2, one works, the other doesn't, and they are literally equal

phronmophobic 2020-10-07T20:47:07.144800Z

doh!

kwrooijen 2020-10-07T20:47:29.145Z

This is so stupid 😕

kwrooijen 2020-10-07T20:47:56.145200Z

Thanks for helping out though. Can't believe I spent so much time with this

p-himik 2020-10-07T20:47:58.145400Z

Yeah, a common case of "those two bytes just cost me 8 hours", quite frustrating.

kwrooijen 2020-10-07T20:49:15.145600Z

I think I copied @p-himik code, which was pretty much the same as what I did, but his actually worked. Then later I must've copied back the bad text and it broke again

phronmophobic 2020-10-07T20:51:05.145900Z

:bananadance:

kwrooijen 2020-10-07T20:51:27.146100Z

I can't believe this 😂

1😡
kwrooijen 2020-10-07T20:51:55.146500Z

Hidden space, great stuff. I guess copied from API docs or something. I have no idea

kwrooijen 2020-10-07T20:52:11.146800Z

Thanks again, friends!

2👍
kwrooijen 2020-10-07T20:56:28.147400Z

Yeah that's probably the best option for now. Building my app right now so I'll get to it eventually, then move it to the babashka repo

zilti 2020-10-07T20:57:31.147600Z

@jatkin What would you do when you want to, e.g. have a long map where the entries are aligned such that the values all start in the same column? Do you add metadata to the map?

phronmophobic 2020-10-07T20:59:20.147800Z

I don't think formatting is that big a deal. gofmt let's go users not have to worry about formatting which seems like a good thing

JAtkins 2020-10-07T20:59:22.148Z

I dunno. I kind of think formatting is a moot point most of the time. I'd like to see the editor try to maintain formatting rules to show to the programmer, and maybe when saving the file to git put the file back in the default formatting. Would allow each programmer to see code how they want, and not have tons of formatting clashes on the way out

phronmophobic 2020-10-07T21:00:31.148200Z

I think the tougher challenges are around all the other tooling that expects files: packaging, making jars, version control, code editors, grep, etc.

grounded_sage 2020-10-07T21:31:10.148600Z

When you require in a macro to a ns is that classified as load time?

JAtkins 2020-10-07T21:36:57.148900Z

right. I'm just wondering if it's possible (or, more accurately if it's useful), to use transformations to create views of our code for debugging or project exploration.

subsaharancoder 2020-10-07T21:38:08.150500Z

Does anyone have experience using Jib https://cloud.google.com/java/getting-started/jib to build Clojure containers for GCP? There's very little info online and the only example I have is for a lein project and none with CLI and deps.edn

dominicm 2020-10-13T13:34:05.394800Z

Yeah, pack has a jib builder you can use!

dominicm 2020-10-13T13:34:17.395Z

JUXT/pack.alpha

zilti 2020-10-07T21:39:51.150700Z

These challenges have been solved basically. There have been languages in the past that didn't use files, but instead an "image". The one language today doing that I am aware of is Pharo. The code you see there is merely a serialization of the image / VM state.

zilti 2020-10-07T21:55:27.151900Z

Sometimes I wonder where we'll stop. At how many levels deep. After packing a VM into a pseudo-VM into a VM using a config file that's been generated by a config file plus a tool, in turn generated from another config file plus tool...

seancorfield 2020-10-07T21:57:35.152Z

The original proof of concept for LightTable was focused on functions and call trees but when they tried it with focus groups, folks complained it was too hard/unfamiliar and wanted something more file-based... so really only the auto-eval/inline-results survived from that early concept.

alexmiller 2020-10-07T21:58:14.152800Z

When you load the ns that does the require, yes

seancorfield 2020-10-07T21:58:50.153Z

Well, I guess some of the ideas of visualizing data in the editor did too (something that ProtoREPL offered for Atom -- but that's no longer maintained). Now folks are using REBL and Reveal alongside "regular editors" as a way to do that sort of visualization and data navigation.

isak 2020-10-07T22:01:16.153300Z

I like the idea. I think all of the problems people have brought up so far (except for the text editor) could be solved by just saving all the code into 1 file. I think having multiple views is useful. These days even the worst editors, like one one in visual studio supports more than one "vertical view" (like emacs), and this sounds like it would be even better. Having project scaffolding with default view definitions that people can commit to the codebase would help with the on-boarding. One challenge is what properties should you automatically assign to a function/class/etc based on the view it is typed into? Could probably think of something reasonable, though.

p-himik 2020-10-07T22:01:21.153600Z

As soon as we finally implement "Turtles all the way down". :)

zilti 2020-10-07T22:04:36.153800Z

I think what Pharo does is that you actively have to add a property/method/whatever to a class

isak 2020-10-07T22:04:38.154Z

Another challenge would be how to deal with imports/requires. You would need something way better than the stuff in Clojure, for example. I guess imports/requires would need to be global, and the way "`rf/dispatch`" expands to re-frame.core/dispatch being controlled by another view-like definition.

isak 2020-10-07T22:06:08.155100Z

@zilti Hmm, wouldn't that mean your functions could disappear on you from your view if you forgot something? Seems like an easy mistake

zilti 2020-10-07T22:06:38.155800Z

Meanwhile, for our company, I've just created a short Ansible script that deploys the server. And all the CI pipeline for our project does is to build the project, scp it to that server, and send an ssh command to restart the service. I hope I can stay away from Docker for as long as possible

seancorfield 2020-10-07T22:07:50.155900Z

I was very excited about the early LT concepts -- I would have loved to try it out. It would have been interesting to see how it would scale to a really large code base. I think Clojure definitely could be a good target for an editor that treated every top-level form as a "thing" to be edited but there would need to be a huge amount of semantic support (ordering of definitions for the purpose of feeding them to the compiler/REPL for starters).

zilti 2020-10-07T22:07:51.156100Z

Well, there are just two ways to write code in Pharo, you either write and evaluate something on the "scratch pad" which just alters the image you are running; or if you want permanent code, you choose a class, then write the code inside it

1
JAtkins 2020-10-07T22:10:29.156400Z

@seancorfield That's the goal of Fisher. I've run out of time to work on it short term (startup is starting to get into sell mode :P). I plan to possibly monetize it and get a team together. Dunno, would need a proof of concept though before I do all that.

seancorfield 2020-10-07T22:20:16.156700Z

just looking over the readme sounds very cool (and a lot of work 🙂 ).

JAtkins 2020-10-07T22:20:54.157300Z

yes 🙂

xceno 2020-10-07T22:35:13.162500Z

Hey guys, weird error happening here: I've got a ring based app, deployed as a datomic ion behind an AWS API Gateway that acts as lambda proxy as described here: https://docs.datomic.com/cloud/ions/ions-tutorial.html#lambda-proxy It works so far, but when i enable ring/ring-defaults with the following config {:session true} the AWS Api Gateway (not the app itself) crashes with: Execution failed due to configuration error: Malformed Lambda proxy response However, I double-checked and my ring-reponse seems still valid. Any ideas on how to tackle this problem?

jmckitrick 2020-10-07T22:58:27.163300Z

What would be the closest thing to Scala futures in Clojure? Core async? Is it as performant?

vncz 2020-10-08T12:22:07.186200Z

What's a feature vs a promise?

jmckitrick 2020-10-08T12:50:08.188900Z

Sorry, I should have been more clear. Scala futures let you map over them, use for comprehensions to make it all readable and abstract away the future, etc.

jmckitrick 2020-10-08T12:50:53.189100Z

So you never actually ‘await’ or deref the future, that’s all part of the for/map/flatMap machinery.

jmckitrick 2020-10-08T12:51:08.189300Z

I thought maybe core.async would be the closest thing to that.

seancorfield 2020-10-08T16:08:09.192400Z

@jmckitrick As I recall, they're just one-element "containers" so the flatMap stuff always felt a bit weird to me. It's been most of a decade since I last did any Scala production work tho' so I may be misrememberinng.

seancorfield 2020-10-08T16:14:33.194100Z

Hmm, looking at them again, it seems they have a bit more functionality than that 🙂 I would likely still just use future in Clojure for most of what they show in the examples (deferring a single computation to a thread) but for composition it would really depend on what I was trying to achieve I guess. In complex composition of processes where I needed everything to potentially be computed concurrently with synchronization points, maybe I'd use core.async. But, overall, core.async isn't something I reach for a lot: it adds a lot of incidental complexity to code in my opinion.

jmckitrick 2020-10-08T17:22:33.196500Z

I just found this article today:

jmckitrick 2020-10-08T17:22:50.197100Z

Not exactly the same thing, but the same concept.

jmckitrick 2020-10-08T17:24:21.197600Z

So a simple use case in scala, is fetching several items from the db, and each query is a future. The map/flatMap/for construct lets you write a simple ‘for’ comprehension that abstracts away the future but still wraps the result as a future to pass back up the stack.

jmckitrick 2020-10-08T17:24:57.198400Z

I guess since Clojure doesn’t mess around with async db queries by default, it’s not really an issue, and regular futures and promises would do the trick.

jmckitrick 2020-10-08T17:25:28.198800Z

This makes me wonder how the Clojure aleph server works. Isn’t that the one that handles all requests asynchronously?

seancorfield 2020-10-08T18:38:29.202500Z

No idea. Never used it. I don't think it's maintained any more?

seancorfield 2020-10-08T18:41:05.202700Z

That AppsFlyer article is about a monad (the Error monad?) and working with monadic constructs in Clojure is kind of hard because monads are better suited to statically typed languages. Scala leverages monadic constructs heavily -- which is why the approach doesn't translate directly (or even at all) into Clojure 😐

jmckitrick 2020-10-08T18:47:02.202900Z

Makes sense. I just like finding similarly elegant constructs in Clojure to somewhat match what I’ve seen and liked in other languages.

seancorfield 2020-10-08T18:57:59.203100Z

Yeah, I hear you. I'm not sure what I'd turn to in Clojure as a direct translation of a monadic Future -- I don't recall ever needing to essentially map f over something in a way that I would want it to be treated as, essentially, #(future (f (deref %))) which is what the Scala Future is doing in that situation. I suppose you could (pmap (comp f deref) collection-of-derefables) but pmap is usually a Bad Idea in the first place. Back when I did Scala for a living, I hated the implicit stuff because it always felt like it only existed to "workaround" the type system -- and it made code horrible to read/reason about because you couldn't just look at it and see what it did.

seancorfield 2020-10-08T18:58:34.203300Z

I was very glad to switch from Scala to Clojure and get away from the madness that is Scala's type system 🙂

jmckitrick 2020-10-08T19:27:23.205400Z

Oh, but haven’t you heard? Dotty (scala 3) is going to fix all of that….

jmckitrick 2020-10-08T19:28:26.206200Z

And yes, I hate those things about scala as well….

seancorfield 2020-10-08T19:35:02.211800Z

Hahaha... that Dotty type system overhaul has been in the works for years... I remember a preso about it at Strange Loop... Just had to look it up: it was seven years ago!

jmckitrick 2020-10-09T11:54:57.260200Z

Well, it’s happening this time. Sometime this month?

rob 2020-10-09T16:21:22.273300Z

Hey @jmckitrick — take a look at manifold, the async library used by aleph. It sounds like the api is a bit closer to what you are looking for

rob 2020-10-09T16:23:36.273800Z

and you can do seq-like operations on “streams of deferreds” https://github.com/aleph-io/manifold/blob/master/docs/stream.md

jmckitrick 2020-10-09T16:26:52.274100Z

You’re exactly right. That’s close to what I was talking about. Thanks!

1👍
emccue 2020-10-10T02:35:07.300900Z

@jmckitrick I always feel like I am taking crazy pills when people mention it, but scala doesn't have async db queries

emccue 2020-10-10T02:35:59.301100Z

it all boils down to JDBC which is totally synchronous, there is no "explicit yield point" to take advantage of

emccue 2020-10-10T02:36:36.301300Z

So the Future[T] there is often just a lie on top of a threadpool

emccue 2020-10-10T02:39:55.301500Z

If you want to do the monadic stuff in clojure, here you go http://funcool.github.io/cats/latest/

emccue 2020-10-10T02:40:30.301700Z

but for db calls i need to stress that there is no benefit unless I am very wrong

jmckitrick 2020-10-10T11:26:57.302300Z

@emccue I did not know that. Very interesting. Which makes all that fancy syntax of little benefit. I guess the only thing it does it let you map db results back to web server responses, and I’m pretty sure those are asynchronous.

dpsutton 2020-10-07T23:09:24.164Z

how can i import a nested enum? https://github.com/apache/mina-sshd/blob/master/sshd-common/src/main/java/org/apache/sshd/common/session/SessionHeartbeatController.java#L36 i'm trying [org.apache.sshd.common.session.SessionHeartbeatController $HeartbeatType] but its not finding a class there

dpsutton 2020-10-07T23:09:32.164300Z

its an enum of an interface

dpsutton 2020-10-07T23:13:39.164800Z

[org.apache.sshd.common.session SessionHeartbeatController$HeartbeatType] is apparently it. I thought we could import nested classes but i guess we can't

2020-10-07T23:35:56.165700Z

you can, that is the name of the class

dpsutton 2020-10-07T23:44:44.166Z

[org.apache.sshd.common.session.SessionHeartbeatController $HeartbeatType]?

Jose Varela 2020-10-07T23:45:30.166100Z

Someone mentioned Pharo in the thread, thought you’d like this: https://gtoolkit.com/ I think this app may give you some ides @jatkin

JAtkins 2020-10-07T23:47:28.166500Z

yup, thanks

JAtkins 2020-10-07T23:49:46.166700Z

@joservarelaf It's actually really really cool. I'm gonna have to dig into this a bit 😉