Fork me on GitHub

Anyone playing with IONS? I’ve found myself pretty far down the road with set-up and deployment but finding myself in uncharted waters with very little to go on deploying this web app. I’m beyond simple tutorial fodder.

👍 4

is that the clojure world's best take at the serverless fad right now? :hugging_face:


Basically yeah, sure is 😄


I bet they've given it a different opinionated azimuth though 😉


Might be interesting in the long run. Hope cognitect remains afloat with these commercial projects

Alex Miller (Clojure team)04:07:39

please ask in #datomic and the Datomic team can help you out there


Hi, working on a clojure talk for Scala devs here ...


Trying to think of a crisp example for why prefix notation is necessary for homoiconicity.... there's bound to be some cognitive resistance to the lisp syntax for some of the crowd.. that dissolves as much as rationale is provided


Anyone care to demonstrate how couldn't we write func(args) and have the interpreter turn it into (func args) without running into trouble? :grinning_face_with_one_large_and_one_small_eye:


it's not really prefix notation that's required (you could envision a lisp that does (1 + 1) instead); prefix notation just makes everything more simple and consistent it's the fact that in a lisp, the code you write is directly represented by data structures. it's certainly possible to have some of the features of homoiconicity without it [1], but lisps make it effortless - there is no difference between what you write, and what the compiler sees, so there's no extra cognitive overhead of a translation step [1] see elixir: note how different the syntax is to its internal representation, while in lisps (+ 1 1) is exactly what it appears to be. this means that macros in elixir essentially have to go through the quote/unquote dance, while in Clojure, syntax-quote/unquote are just for convenience, and it's still easy to write macros without them: just use normal Clojure functions that return data! for example, this macro:

🙏 4

actually, how are macros evaluated? does the 'compiler' endlessly apply macros until the expression no longer matches any macro name? or does it have a weaker iteration algorithm that only considers macros from each package once?


@sundarj in case you might know ...


when the compiler sees a form representing a macro, it recursively macroexpands it until it no longer does

👍 4

boot.user=> (defmacro my-when [test & body] (list* 'when test body))
boot.user=> (macroexpand-1 '(my-when true (println 42)))
(when true (println 42))
boot.user=> (macroexpand-1 *1)
(if true (do (println 42)))
boot.user=> (macroexpand '(my-when true (println 42)))
(if true (do (println 42)))


boot.user=> (source macroexpand)
(defn macroexpand
  "Repeatedly calls macroexpand-1 on form until it no longer
  represents a macro form, then returns it.  Note neither
  macroexpand-1 nor macroexpand expand macros in subforms."
  {:added "1.0"
   :static true}
    (let [ex (macroexpand-1 form)]
      (if (identical? ex form)
        (macroexpand ex))))


I am trying to connect to remote nrepl server, I am running OSX and server is ubuntu. How can I use ssh port forwarding to make it work? ✗ ssh -L 7000:theserver:7000 localhost ssh: connect to host localhost port 22: Connection refused


Also @alexmiller care to later on briefly review some slides, for any egregious comments, or points that could have taken a better twist?! ☺️


I have a function that returns

`[(ns/some-symbol ~params)] 
for later evaluation. Now I want to move the creation of the function into a macro. But I struggle with creating a macro that should include a backtick as part of its output. Can I do that or do I need to solve it some other way? So the some-symbol should be constructed when the macro runs but the params should be evaluated in run-time.


@matan interesting questions! How about ifs, var declarations etc?


I think (without having much experience so far) is that, sure, the compiler could turn infix to prefix, but then you need a parser, then your editor also needs to have a parser if you want to send forms to a repl.


@orestis thanks for liking my weird question.


wouldn't that parser be entirely CS 101 grade though?


How would macros work? The cool thing about S expressions are that your macro is the same form as my macro is the same as core stuff like if.


Okay, AST parity makes a point, though in this case too, it may seem a parser would be so benign to solve it.....


@matan see my comments in the thread above. parsing non-lispy syntax into data is what Elixir does, so it's certainly possible, but is different to what lisps do.


@sundarj Nice to know about Elixir 🙂 I'm not finding the relevant thread I suspect


What's the downside in Elixir, compared to being fully lispy?


I wouldn’t call Elixir Homoiconic. If you have a parser is that returns an ast, it’s not homoiconic


A better example @matan would be Prolog. It doesn’t use sexprs, but code is data and data is code


i didn't intend to suggest that elixir was homoiconic, just that it had some of the features typically attributed to homoiconicity. sorry if that wasn't clear

✔️ 4

another good example is Forth


It has macros, but that’s about it


hmm, i had assumed that the data structures created by quote in Elixir could be manipulated at runtime like they can in lisps, but i suppose that might not be the case (i've no experience with Elixir either way), in which case they really are just compile-time ASTs like any other language, and are thus even less powerful than i had thought. cc @matan


Ruby does the same


BTW, aside the metaprogramming does the homoiconicity provide any added value? I mean it's not that we see too many tools that leverage the metaprogramming for higher development throughput, at least I'm not seeing them.. and it's a generally good advice to keep at arms length from writing a lot of macros


Having the same syntax for data literals and data visualization is also pretty useful for the workflow


there's plenty: paredit, parinfer, sending forms to a repl from the editor, sending code across the wire (like with the socket repl and nrepl)


Thanks @sundarj! I should watch that I guess


Actually his talk about thinking in data was rather bland ... but I'll watch anyway


How would sending data across the wire relate here?


@matan in any language, you can send code across the wire as a big string, but strings are opaque and hard to work with, so all you can really do is evaluate that string wholesale, which is why people use a separate data format like JSON. in (e.g.) lisps, you can send the language's code directly across the wire as data, and then manipulate, transform, or interpret it however you like (including evaluating it wholesale). you can also send individual expressions across the wire, which you can't really do in other languages. for example, in Fulcro and Om Next, you write mutations for your application's state in data that looks like code, so [(shopping-cart/add-item! {:id 26, :quantity 4})]. that gets interpreted locally, but can also be sent to the server as a string, turned into data with clojure.edn/read-string, and interpreted there as well. in another language, you might have to send that as a string, and then call eval on it without being able to do anything else to it, or use JSON instead.


writing an interpreter for data is much easier than writing an interpreter for a string


Hey thanks. Are you into clojure as a hobby?


i'd certainly like to do it professionally, but at the moment, yeah.


On the data subject, I see homoiconicity help me when developing prototypes without databases. I just dump whatever I am working with into a text file and read it back in with clojure.edn/read-string


Similar to python's pickle or java's now depreciated Serialization, having the ability to save the data in your program without much hassle is extremely useful


this isn't really special to homoiconic languages though, its just a benefit of having serializability by default

🙏 4

Hey, can someone remind me why and and or had to be macros in clojure? (thus using apply on them being impossible)


for short circuiting

👍 12

(and false (throw (Exception. "ops"))) would throw if and were a function


you can use some/`every?` as functional equivalents


@bronsa yes I know about some/`every`? but I think the reason might run deeper


I mean, this example is a little contrived isn't it?


not really


(if (and some-flag (do-some-i/o)) then else)


is this better?


anyway, short circuiting is the only reason for and/`or` being macros


but, um, couldn't a lisp short-circuit without a macro?


a lisp (any language really) with lazy evaluation semantics


but clojure has strict evaluation semantics


so they need to be macros


some strict languages implement &&/`||` as both functions and compiler intrinsics with short-circuiting semantics


like ocaml


but then you get odd behaviours like


# false && (print_endline "oops"; true);;
- : bool = false
# (&&) false (print_endline "oops"; true);;
- : bool = false
# let f = (&&) in f false (print_endline "oops"; true);;
- : bool = false


where && only short-circuits when used in certain static ways that the compiler can recognise


That's very interesting. Meta-programming also...


Thanks. I'll suffice with that for now, as I have to call it a day


@bronsa much appreciated!


sorry. ... long day


Do you have any suggestions regarding SOAP in Clojure?


Which library to use, etc. And where to start reading?


@slawek098 My recommendation is to depend on Axis 2 (or Axis 1) libraries and use Java interop. I went down this path years ago and never found a satisfactory Clojure wrapper but using Axis directly from Clojure isn't too badly so that's what we ended up doing.


We used wsdl2java to create Java stubs, compiled those into a JAR, put it in our Archiva repo and "forgot about it" and then it was just a little bit of interop from Clojure.