Fork me on GitHub
#clojurescript
<
2022-02-11
>
lilactown04:02:38

inspired by Clojure's new iteration fn, I've been thinking through consuming paginated APIs in ClojureScript, and came up with this as an idea: https://github.com/lilactown/async-seq

lilactown05:02:56

the idea is a seq-like abstraction that represent sequential async processes, allowing transformations of them just like seqs

tianshu19:02:27

I want to use bundle target with webpack, and target to node. My code depends on a library which requires fs in its namespace, like this

(ns macchiato.fs
  (:refer-clojure :exclude [exists?])
  (:require ["fs" :as fs]))
When compile with cljs.main, it said
No such namespace: fs, could not locate fs.cljs, fs.cljc, or JavaScript source providing "fs" in file /home/tianshu/.cljs/.aot_cache/1.10.914/A5608AE/macchiato/fs.cljs
But I think fs is builtin for node. What happened here and how can I make it to work?

mfikes20:02:40

@doglooksgood Hrm. If you just do (require 'fs) at a Node REPL, you generally get access to the fs builtin

mfikes20:02:52

Hunch is that you need to specify the node target in order to make this work... (this has been a while for me)

tianshu21:02:30

I think I just made it work. I don't have to use bundle target, node target works well for my case.

Colin P. Hill21:02:16

Does the arity of macros behave differently in cljs than it does in clj? I tried to define a macro with a [s] overload and a [s & ss] overload (typical pattern where the latter just invokes the former in a loop), and when I tried to invoke it with multiple arguments, I got an error saying Wrong number of args (1). Best I can figure is that it successfully expanded the 1+n-ary overload, which then invokes the 1-ary overload, and it complained because the 1-ary overload got clobbered or something.

p-himik21:02:18

What does the macro look like?

Colin P. Hill21:02:06

(defmacro my-macro
 ([s]
  ;; proprietary stuff here, seems to work fine)
 ([s & ss]
  (for [s2 (cons s ss)]
     (my-macro s))))

Colin P. Hill21:02:18

I suppose I might be blundering my reasoning about compilation steps somewhere in that second overload...

p-himik22:02:24

It won't work on CLJ either. A nice explanation: https://stackoverflow.com/a/25569059/564509

Colin P. Hill22:02:30

Oh right okay. What I attempted to write amounts to attempting to evaluate the first overload while the second is still expanding. If it ran, it would execute the for loop immediately, yielding a lazy sequence as the "syntax". Which clearly isn't right. I need to yield the code that will invoke the first overload, so that it expands on the next pass. Is that right?

Colin P. Hill22:02:56

Ah, and the reason it blew up instead of doing that wrong thing is that it lacks those hidden arguments.

Colin P. Hill22:02:04

Okay, got it. Thank you!

👍 1
Colin P. Hill22:02:18

I'm mildly curious why it can't insert those arguments in this context the way it would in other contexts, but the answer to that probably involves a deeper dive into macro internals than I want to wrap my head around right now 😆

p-himik22:02:45

I'd love to answer but I myself don't know. :)

Colin P. Hill22:02:55

Happen to know any good resources that elaborate on this bit? Feels like a good idea to familiarize myself with other macro pitfalls before I learn about them the hard way, and while I can see an intuitive sense to this I struggle to see the concrete reasons. > Instead, consider a helper function to do most of the work on behalf of the macro. Indeed, this is often a good practice for other macros as well.

p-himik22:02:45

Mm, not really sure why that would be a good practice for regular macros. clojure.core itself doesn't use that approach.

p-himik22:02:04

Off the top of my head, I know only of one other pitfall that's not immediately obvious with its fix - if you need your macro to generate code with specific symbols, you have to quote-unquote them. So e.g. to end up with just a after macro expansion, you'll have to use ~'a within a syntax quote.